diff --git a/Win32/Blades of Exile/ACTIONS.CPP b/Win32/Blades of Exile/ACTIONS.CPP new file mode 100644 index 00000000..8b43bcda --- /dev/null +++ b/Win32/Blades of Exile/ACTIONS.CPP @@ -0,0 +1,2755 @@ +#include +#include /* for sprintf */ +#include +#include +#include "global.h" +#include "blades.h" +#include "gutils.h" +#include "graphics.h" +#include "fileio.h" +#include "dlgutils.h" +#include "locutils.h" +#include "fields.h" +#include "town.h" +#include "math.h" +#include "text.h" +#include "party.h" +#include "monster.h" +#include "specials.h" +#include "newgraph.h" +#include "combat.h" +#include "items.h" +#include "exlsound.h" +#include "infodlgs.h" +#include "itemdata.h" +#include "dlogtool.h" +#include "graphutl.h" +#include "actions.h" + +#include "globvar.h" + +extern short store_flags[3]; + +void init_screen_locs() +{ + short i,j,k,l; + RECT startup_base = {5,279,306,327}; + RECT shop_base = {12,63,267,99}; /**/ + + for (i = 0; i < 7; i++) + shopping_rects[0][i] = shop_base; + shopping_rects[0][1].right -= 35; + shopping_rects[0][2].right = shopping_rects[0][2].left + 28; + shopping_rects[0][3].top += 4; + shopping_rects[0][3].left += 28; + shopping_rects[0][4].top += 20; + shopping_rects[0][4].left += 154; + shopping_rects[0][5].top += 20; + shopping_rects[0][5].left += 34; + shopping_rects[0][6].top += 3; + shopping_rects[0][6].bottom -= 21; + shopping_rects[0][6].right -= 19; + shopping_rects[0][6].left = shopping_rects[0][6].right - 14; + for (i = 1; i < 8; i++) + for (j = 0; j < 7; j++) { + shopping_rects[i][j] = shopping_rects[0][j]; + OffsetRect(&shopping_rects[i][j],0,i * 36); + } + + + for (i = 0; i < 6; i++) { + startup_button[i] = startup_base; + OffsetRect(&startup_button[i],301 * (i / 3) - 0,48 * (i % 3)); + } + startup_top.top = 5; + startup_top.bottom = startup_button[0].top; + startup_top.left = 5; + startup_top.right = startup_button[3].right; + + for (i = 0; i < 200; i++) + for (j = 0; j < 8; j++) + for (k = 0; k < 64; k++) + { + town_maps.town_maps[i][j][k] = 0; + } + for (i = 0; i < 100; i++) + for (k = 0; k < 6; k++) + for (l = 0; l < 48; l++) + o_maps.outdoor_maps[i][k][l] = 0; + + for (i = 0; i < 7; i++) { + bottom_buttons[i].top = 383; + bottom_buttons[i].bottom = 420; + bottom_buttons[i].left = 5 + (i * 37); + bottom_buttons[i].right = bottom_buttons[i].left + 36; + town_buttons[i] = bottom_buttons[i]; + } + + for (i = 0; i < 5; i++) combat_buttons[i] = bottom_buttons[i]; + town_buttons[7] = bottom_buttons[6]; + town_buttons[5] = medium_buttons[0]; + town_buttons[6] = medium_buttons[1]; + for (i = 5; i < 9; i++) combat_buttons[i] = medium_buttons[i - 5]; + + // name, use, give, drip, info, sell/id each one 13 down + item_buttons[0][0].top = 17; + item_buttons[0][0].bottom = item_buttons[0][0].top + 12; + item_buttons[0][0].left = 3; + item_buttons[0][0].right = item_buttons[0][0].left + 185; + OffsetRect(&item_buttons[0][0],0,1); + item_buttons[0][1] = item_buttons[0][0]; + item_buttons[0][1].left = 196; + item_buttons[0][1].right = 210; + item_buttons[0][2] = item_buttons[0][0]; + item_buttons[0][2].left = 210; + item_buttons[0][2].right = 224; + item_buttons[0][3] = item_buttons[0][0]; + item_buttons[0][3].left = 224; + item_buttons[0][3].right = 238; + item_buttons[0][4] = item_buttons[0][0]; + item_buttons[0][4].left = 238; + item_buttons[0][4].right = 252; + item_buttons[0][5] = item_buttons[0][0]; + item_buttons[0][5].left = 173; + item_buttons[0][5].right = 232; + for (i = 1; i < 8; i++) + for (j = 0; j < 6; j++) { + item_buttons[i][j] = item_buttons[0][j]; + OffsetRect(&item_buttons[i][j],0,13 * i); + } + +// name, hp, sp, info, trade + pc_buttons[0][0].top = 18; + pc_buttons[0][0].bottom = pc_buttons[0][0].top + 12; + pc_buttons[0][0].left = 3; + pc_buttons[0][0].right = pc_buttons[0][0].left + 177; + pc_buttons[0][1] = pc_buttons[0][0]; + pc_buttons[0][1].left = 184; + pc_buttons[0][1].right = 214; + pc_buttons[0][2] = pc_buttons[0][0]; + pc_buttons[0][2].left = 214; + pc_buttons[0][2].right = 237; + pc_buttons[0][3] = pc_buttons[0][0]; + pc_buttons[0][3].left = 241; + pc_buttons[0][3].right = 253; + pc_buttons[0][4] = pc_buttons[0][0]; + pc_buttons[0][4].left = 253; + pc_buttons[0][4].right = 262; + for (i = 1; i < 6; i++) + for (j = 0; j < 5; j++) { + pc_buttons[i][j] = pc_buttons[0][j]; + OffsetRect(&pc_buttons[i][j],0,13 * i); + } + pc_help_button.top = 101; + pc_help_button.bottom = 114; + pc_help_button.left = 251; + pc_help_button.right = 267; + + pc_area_rect.top = PC_WIN_UL_Y; + pc_area_rect.left = PC_WIN_UL_X; + pc_area_rect.bottom = PC_WIN_UL_Y + 116; + pc_area_rect.right = PC_WIN_UL_X + 271; + item_area_rect.top = ITEM_WIN_UL_Y; + item_area_rect.left = ITEM_WIN_UL_X; + item_area_rect.bottom = ITEM_WIN_UL_Y + 143; + item_area_rect.right = ITEM_WIN_UL_X + 271; +} + +Boolean prime_time() +{ + return ((overall_mode < 2) || (overall_mode == MODE_COMBAT))? TRUE : FALSE; +} + +Boolean handle_action(POINT the_point, WPARAM wparam, LPARAM lparam ) +{ + short i,j,k,item_hit,which_t,s1,s2,s3; + Boolean are_done = FALSE; + Boolean need_redraw = FALSE, did_something = FALSE, need_reprint = FALSE; + Boolean town_move_done = FALSE,pc_delayed = FALSE; + location destination,cur_loc,loc_in_sec,cur_direction; + unsigned char storage; + short find_direction_from,ter_looked_at,button_hit = 12,store_cur_pc; + short store_sp[6]; + + char str[60]; + POINT point_in_area; + Boolean right_button = FALSE; + Boolean ctrl_key = FALSE; + unsigned char ter; + + if (lparam != -1) { + the_point.x -= ulx; + the_point.y -= uly; + } + if (lparam == -2) right_button = TRUE; + if (MK_CONTROL & wparam) + ctrl_key = TRUE; + + for (i = 0; i < 20; i++) + special_queue[i] = -1; + end_scenario = FALSE; + + // Now split off the extra stuff, like talking and shopping. + if (overall_mode == MODE_TALKING) { + handle_talk_event(the_point); + if (overall_mode != MODE_TALKING) + return FALSE; + } + if (overall_mode == MODE_SHOPPING) { + handle_shop_event(the_point); + if (overall_mode != MODE_SHOPPING) + return FALSE; + } + + + +// First, figure out where party is + switch (overall_mode) { + case 0: case 35: + cur_loc = party.p_loc; + for (i = 0; i < 7; i++) + if (PtInRect ( &bottom_buttons[i], the_point) == TRUE) { + button_hit = i; + if (spell_forced == FALSE) + main_button_click(overall_mode,bottom_buttons[i]); + } + break; + + case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 36: + cur_loc = center; + for (i = 0; i < 8; i++) + if (PtInRect (&town_buttons[i], the_point) == TRUE) { + button_hit = i; + if (spell_forced == FALSE) + main_button_click(overall_mode,town_buttons[i]); + } + break; + + case MODE_TALKING: + case MODE_SHOPPING: + break; + + default: + cur_loc = (overall_mode > MODE_COMBAT) ? center : pc_pos[current_pc]; + for (i = 0; i < 9; i++) + if (PtInRect (&combat_buttons[i], the_point) == TRUE) { + button_hit = i; + if (spell_forced == FALSE) + main_button_click(overall_mode,combat_buttons[i]); + } + break; + } + +// Then, handle a button being hit. + if (button_hit != 12) + switch(button_hit) + { + case 0: case 1: + if (someone_awake() == FALSE) { + ASB("Everyone's asleep/paralyzed."); + need_reprint = TRUE; + need_redraw = TRUE; + } + if (overall_mode == MODE_OUTDOORS) { + cast_spell(button_hit,0); + spell_forced = FALSE; + need_reprint = TRUE; + need_redraw = TRUE; + } + else if (overall_mode == MODE_TOWN) { + for (i = 0; i < 6; i++) + store_sp[i] = adven[i].cur_sp; + cast_spell(button_hit,1); + spell_forced = FALSE; + need_reprint = TRUE; + need_redraw = TRUE; + for (i = 0; i < 6; i++) + if (store_sp[i] != adven[i].cur_sp) + did_something = TRUE; + } + else if (overall_mode == 3) { + add_string_to_buf(" Cancelled. "); + overall_mode = MODE_TOWN; + } + else if (overall_mode == MODE_COMBAT) { + if (button_hit == 0) { + did_something = combat_cast_mage_spell(); + need_reprint = TRUE; + } + if (button_hit == 1) { + did_something = combat_cast_priest_spell(); + need_reprint = TRUE; + } + need_redraw = TRUE; + spell_forced = FALSE; + redraw_terrain(); + } + else if ((overall_mode == 11) || (overall_mode == 14)) { + add_string_to_buf(" Cancelled. "); + overall_mode = MODE_COMBAT; + center = pc_pos[current_pc]; + pause(10); + need_redraw = TRUE; + } + put_pc_screen(); + put_item_screen(stat_window,0); + break; + + case 2: + if (overall_mode == MODE_OUTDOORS) overall_mode = MODE_LOOK_OUTDOORS; + if (overall_mode == MODE_TOWN) overall_mode = MODE_LOOK_TOWN; + if (overall_mode == MODE_COMBAT) overall_mode = MODE_LOOK_COMBAT; + add_string_to_buf("Look: Select a space. You can also "); + add_string_to_buf(" right click to look."); + need_redraw = TRUE; + break; + + case 3: + if (overall_mode == MODE_COMBAT) { + add_string_to_buf("Parry. "); + char_parry(); + did_something = TRUE; + need_reprint = TRUE; + need_redraw = TRUE; + } + if (overall_mode == MODE_TOWN) { + overall_mode = MODE_TALK_TOWN; + add_string_to_buf("Talk: Select someone "); + need_reprint = TRUE; + } + if (overall_mode == MODE_OUTDOORS) { // Resting + i = 0; + ter = out[party.p_loc.x][party.p_loc.y]; + if (party.in_boat >= 0) + add_string_to_buf("Rest: Not in boat. "); + else if (adven.isPoisoned()) + add_string_to_buf("Rest: Someone poisoned. "); + else if (party.food <= 12) + add_string_to_buf("Rest: Not enough food. "); + else if (nearest_monster() <= 3) + add_string_to_buf("Rest: Monster too close. "); + else if ((scenario.ter_types[ter].special >= 2) && (scenario.ter_types[ter].special <= 6)) + add_string_to_buf("Rest: It's dangerous here.");//// + else if (party.isFlying()) + add_string_to_buf("Rest: Not while flying. "); + else { + add_string_to_buf("Resting... "); + print_buf(); + play_sound(20); + draw_rest_screen(); + pause(25); + party.food -= 6; + while (i < 50) { + increase_age(); + if (get_ran(1,1,2) == 2) + do_monsters(); + if (get_ran(1,1,70) == 10) + create_wand_monst(); + if (nearest_monster() <= 3) { + i = 200; + add_string_to_buf(" Monsters nearby."); + } + else i++; + } + put_pc_screen(); + } + if (i == 50) { + party.age += 1200;//// + add_string_to_buf(" Rest successful. "); + adven.heal(get_ran(5,1,10)); + adven.restoreSP(50); + put_pc_screen(); + } + need_reprint = TRUE; + need_redraw = TRUE; + } + break; + + case 4: + if (overall_mode == MODE_OUTDOORS) { + give_help(62,0,0); + display_map(); + SetCursor(sword_curs); + SetFocus(mainPtr); + } + if ((overall_mode == MODE_TOWN) || (overall_mode == MODE_COMBAT)) { + if (party.in_boat >= 0) { + j = 0; + add_string_to_buf("Get: Not while in boat. "); + } + if (overall_mode == MODE_TOWN) + j = get_item(c_town.p_loc,6,FALSE); + else { + j = get_item(pc_pos[current_pc],current_pc,FALSE); + take_ap(4); + } + if (j > 0) { + put_item_screen(stat_window, 0); + put_pc_screen(); + need_redraw = TRUE; + did_something = TRUE; + } + need_reprint = TRUE; + } + break; + + case 5: + if (overall_mode == MODE_OUTDOORS) { + save_file(0); + need_redraw = TRUE; + current_switch = 6; + break; + } + if (overall_mode == MODE_TOWN) { + add_string_to_buf("Use: Select a space or item."); + add_string_to_buf(" (Hit button again to cancel.)"); + need_reprint = TRUE; + overall_mode = 4; + } + else if (overall_mode == 4) { + overall_mode = 1; + need_reprint = TRUE; + add_string_to_buf(" Cancelled."); + } + if (overall_mode == MODE_COMBAT) { + need_reprint = TRUE; + need_redraw = TRUE; + pc_delayed = TRUE; + } + + break; + + case 6: + if (overall_mode == 0) { + do_load(); + break; + } + if (overall_mode == 1) { + give_help(62,0,0); + display_map(); + SetCursor(sword_curs); + SetFocus(mainPtr); + } + if (overall_mode == MODE_COMBAT) { + load_missile(); + need_reprint = TRUE; + redraw_terrain(); + } + else if ((overall_mode == 12) || (overall_mode == 13)) { + add_string_to_buf(" Cancelled. "); + center = pc_pos[current_pc]; + pause(10); + need_redraw = TRUE; + overall_mode = MODE_COMBAT; + } + break; + + case 7: + if (overall_mode == MODE_TOWN) { + if (party.in_boat >= 0) { + need_reprint = TRUE; + add_string_to_buf("Combat: Not while in boat. "); + } + else if (party.in_horse >= 0) { + need_reprint = TRUE; + add_string_to_buf("Combat: Not while on horseback. "); + } + else { + add_string_to_buf("Combat! "); + play_sound(18); + need_reprint = TRUE; + start_town_combat(party.direction); + need_redraw = TRUE; + current_pc = 6; + did_something = TRUE; + put_pc_screen(); + } + } + else if (overall_mode == MODE_COMBAT) { + if (which_combat_type == 0) { + if (hit_end_c_button() == TRUE) { + end_town_mode(0,c_town.p_loc); + play_sound(93); + add_string_to_buf("End combat. "); + handle_wandering_specials(1); + menu_activate(1); + put_pc_screen(); + set_stat_window(current_pc); + } + else add_string_to_buf("Can't end combat yet. "); + } + else { + party.direction = end_town_combat(); + center = c_town.p_loc; + set_stat_window(current_pc); + redraw_screen(0); + play_sound(93); + need_reprint = TRUE; + need_redraw = TRUE; + did_something = TRUE; + menu_activate(1); + } + need_redraw = TRUE; + } + break; + + case 8: + + if (overall_mode == MODE_COMBAT) { + if (combat_active_pc == INVALID_PC) { + add_string_to_buf("This PC now active. "); + combat_active_pc = current_pc; + } + else { + add_string_to_buf("All PC's now active. "); + current_pc = combat_active_pc; + combat_active_pc = INVALID_PC; + } + need_reprint = TRUE; + } + break; + + + + } + +// Begin : click in terrain + if ((PtInRect ( &world_screen,the_point)) && ((is_out()) || (is_town()) || (is_combat())) ){ + i = (the_point.x - 23) / 28; + j = (the_point.y - 23) / 36; + + destination = cur_loc; + + if ((overall_mode == 0) || (overall_mode == 1) || (overall_mode == MODE_COMBAT)) + if ((i == 4) && (j == 4) && (right_button == FALSE)) { // Pausing + if (overall_mode == MODE_COMBAT) { + char_stand_ready(); + add_string_to_buf("Stand ready. "); + if (adven[current_pc].status[STATUS_WEBS] > 0) { + add_string_to_buf("You clean webs. "); + move_to_zero(adven[current_pc].status[STATUS_WEBS]); + move_to_zero(adven[current_pc].status[STATUS_WEBS]); + put_pc_screen(); + } + check_fields(pc_pos[current_pc],2,current_pc); + } + else { + add_string_to_buf("Pause."); + for (k = 0; k < 6; k++) + if ((adven[k].isAlive()) && (adven[k].status[STATUS_WEBS] > 0)) { + sprintf((char *) str,"%s cleans webs.",adven[k].name); + add_string_to_buf((char *) str); + move_to_zero(adven[k].status[STATUS_WEBS]); + move_to_zero(adven[k].status[STATUS_WEBS]); + } + if (party.in_horse >= 0) { + if (overall_mode == 0) { + party.horses[party.in_horse].which_town = 200; + party.horses[party.in_horse].horse_loc_in_sec = party.p_loc.toLocal(); + party.horses[party.in_horse].horse_loc = party.p_loc; + party.horses[party.in_horse].horse_sector.x = party.outdoor_corner.x + party.i_w_c.x; + party.horses[party.in_horse].horse_sector.y = party.outdoor_corner.y + party.i_w_c.y; + party.in_horse = -1; + } + else if (overall_mode == 1){ + party.horses[party.in_horse].horse_loc = c_town.p_loc; + party.horses[party.in_horse].which_town = c_town.town_num; + party.in_horse = -1; + } + } + put_pc_screen(); + check_fields(c_town.p_loc,1,0); + } + + did_something = TRUE; + need_redraw = TRUE; + } + else if (right_button == FALSE) { + cur_direction = get_cur_direction(the_point); + destination.x += cur_direction.x; + destination.y += cur_direction.y; + +// Begin: Moving + if ((right_button == FALSE) && (overall_mode == MODE_COMBAT)) { + if (pc_combat_move(destination) == TRUE) { + center = pc_pos[current_pc]; + did_something = TRUE; + update_explored(destination); + } + need_redraw = TRUE; + menu_activate(1); + } + if ((right_button == FALSE) && (overall_mode == 1)) { + if (someone_awake() == FALSE) { + ASB("Everyone's asleep/paralyzed."); + need_reprint = TRUE; + need_redraw = TRUE; + } + else { + need_redraw = TRUE; + if (town_move_party(destination,0) == TRUE) { + did_something = TRUE; + center = c_town.p_loc; + update_explored(destination); + + if (loc_off_act_area(c_town.p_loc) == TRUE) { + + destination = end_town_mode(0,destination); + + + town_move_done = TRUE; + FlushEvents(2); + } + } + else need_reprint = TRUE; + menu_activate(1); + } + } + if ((right_button == FALSE) && (overall_mode == 0)) { + if (outd_move_party(destination,town_move_done) == TRUE) { + center = destination; + need_redraw = TRUE; + did_something = TRUE; + update_explored(party.p_loc); + + menu_activate(1); + } + else need_redraw = TRUE; + + storage = out[party.p_loc.x][party.p_loc.y]; + if (scenario.ter_types[storage].special == 21) {//// town entry + + if (party.direction == 0) find_direction_from = 2; + else if (party.direction == 4) find_direction_from = 0; + else if (party.direction < 4) find_direction_from = 3; + else find_direction_from = 1; + + for (i = 0; i < 8; i++) + if (same_point(party.loc_in_sec,outdoors[party.i_w_c.x][party.i_w_c.y].exit_locs[i]) == TRUE) { + which_t = outdoors[party.i_w_c.x][party.i_w_c.y].exit_dests[i]; + if (which_t >= 0) + start_town_mode(outdoors[party.i_w_c.x][party.i_w_c.y].exit_dests[i], find_direction_from); + if (is_town() == TRUE) { + need_redraw = FALSE; + i = 8; + if (party.in_boat >= 0) + party.boats[party.in_boat].which_town = c_town.town_num; + if (party.in_horse >= 0) + party.horses[party.in_horse].which_town = c_town.town_num; + } + } + } + } // End if(overall_mode == 0) + + } +// End: Moving + +// Begin: Looking at something + if ((right_button == TRUE) || (overall_mode == 35) || (overall_mode == 36) || (overall_mode == 37)) { + destination.x = destination.x + i - 4; + destination.y = destination.y + j - 4; + + need_reprint = TRUE; + +// if ((can_see(cur_loc,destination) >= 4) || ((overall_mode != 35) && (loc_off_world(destination) == TRUE))) + if ((is_combat() == FALSE) && (party_can_see(destination) == 6)) + add_string_to_buf(" Can't see space. "); + else if ((is_combat() == TRUE) && (can_see(pc_pos[current_pc],destination,0) >= 4)) + add_string_to_buf(" Can't see space. "); + else { + add_string_to_buf("You see... "); + ter_looked_at = do_look(destination); + if ((is_town()) || (is_combat())) + if (adjacent(c_town.p_loc,destination) == TRUE) + if (adj_town_look(destination) == TRUE) + need_redraw = TRUE; + if (scenario.ter_types[ter_looked_at].special == 11) { + print_buf(); + need_reprint = FALSE; + k = 0; + if (is_town()) { + while (k < 15) { + if (same_point (destination, c_town.town.sign_locs[k]) == TRUE) { + need_reprint = TRUE; + if (adjacent(c_town.town.sign_locs[k],c_town.p_loc)==TRUE) + do_sign(c_town.town_num,k,(short) ter_looked_at); + else add_string_to_buf(" Too far away to read sign. "); + } + k++; + } + } + if (is_out()) { + loc_in_sec = party.loc_in_sec; + loc_in_sec.x += i - 4; + loc_in_sec.y += j - 4; + while (k < 8) { + if (same_point (loc_in_sec, + outdoors[party.i_w_c.x][party.i_w_c.y].sign_locs[k]) == TRUE) { + need_reprint = TRUE; + if (adjacent(outdoors[party.i_w_c.x][party.i_w_c.y].sign_locs[k],party.loc_in_sec)==TRUE) + do_sign((short) (200 + get_outdoor_num()),k,(short) ter_looked_at); + else add_string_to_buf(" Too far away to read sign. "); + } + k++; + } + } + } + } + + // If option not pressed, looking done, so restore center + if ((ctrl_key == FALSE) && (right_button == FALSE)) { + if (overall_mode == 37) { + overall_mode = 10; + center = pc_pos[current_pc]; + pause(5); + need_redraw = TRUE; + } + else if (overall_mode == 36) { + overall_mode = 1; + center = c_town.p_loc; + need_redraw = TRUE; + } + else if (overall_mode == 35) + overall_mode = 0; + + } + } + +// End: looking at something + +// Begin : talking to someone + if (overall_mode == 2) { + destination.x = destination.x + i - 4; + destination.y = destination.y + j - 4; + + if ((can_see(cur_loc,destination,0) >= 4) || (loc_off_world(destination) == TRUE)) { + add_string_to_buf(" Can't see space "); + need_reprint = TRUE; + } + else { + + for (i = 0; i < T_M; i++) { + if (monst_on_space(destination,i) == TRUE) { + did_something = TRUE; + need_redraw = TRUE; + if (c_town.monst.dudes[i].attitude % 2 == 1) { + add_string_to_buf(" Creature is hostile. "); + } + else if ((c_town.monst.dudes[i].summoned > 0)//// + || (c_town.monst.dudes[i].monst_start.personality < 0)) + add_string_to_buf("Talk: No response. "); + else{ + start_talk_mode(i,c_town.monst.dudes[i].monst_start.personality,c_town.monst.dudes[i].number, + c_town.monst.dudes[i].monst_start.facial_pic); + did_something = FALSE; + need_redraw = FALSE; + } + break; + } + } + if ((did_something == FALSE) && (overall_mode != 20)){ + add_string_to_buf(" Nobody there"); + need_reprint = TRUE; + } + if (overall_mode != 20) + overall_mode = 1; + } + if (overall_mode != 20) + need_redraw = TRUE; + } +// End : talking to someone + +// Begin : Targeting a space + if ((overall_mode == 11) || (overall_mode == 12) || (overall_mode == 13) || + (overall_mode == 14) || (overall_mode == MODE_DROPPING)) { + destination.x += i - 4; + destination.y += j - 4; + if (overall_mode == 11) + do_combat_cast(destination); + if ((overall_mode == 13) || (overall_mode == 12)) + fire_missile(destination); + if (overall_mode == 14) { + place_target(destination); + need_reprint = TRUE; + } + if (overall_mode != 14) { + did_something = TRUE; + center = pc_pos[current_pc]; + } + if (overall_mode == MODE_DROPPING) { // dropping + if (adjacent(pc_pos[current_pc],destination) == FALSE) + add_string_to_buf("Drop: must be adjacent."); + else { + adven[current_pc].dropItem(store_drop_item,destination); + take_ap(1); + } + } + pause(6); + need_redraw = TRUE; + if ((overall_mode >= 10) && (overall_mode < 20) && (overall_mode != 14)) + overall_mode = 10; + put_pc_screen(); + put_item_screen(stat_window,0); + } + if ((overall_mode > 2) && (overall_mode < 6)) { + destination.x += i - 4; + destination.y += j - 4; + switch (overall_mode) { + case 3: + cast_town_spell(destination); + did_something = TRUE; + break; + case 4: + if (adjacent(destination,c_town.p_loc) == FALSE) + add_string_to_buf(" Must be adjacent. "); + else { + did_something = use_space(destination); + } + break; + case 5: + if (adjacent(c_town.p_loc,destination) == FALSE) + add_string_to_buf("Drop: must be adjacent."); + else if (get_obscurity(destination.x,destination.y) == 5) + ASB("Drop: Space is blocked."); + else adven[current_pc].dropItem(store_drop_item,destination); + break; + } + overall_mode = 1; + need_redraw = TRUE; + put_pc_screen(); + put_item_screen(stat_window,0); + } +// End : Targeting a space + + } +//End: click in terrain + +// Begin: Screen shift + if ((overall_mode == 11) || (overall_mode == MODE_FIRING) || (overall_mode == MODE_THROWING) || (overall_mode == 14) + || (overall_mode == 37) || (overall_mode == 36)) { + if ((PtInRect ( &border_rect[0],the_point)) && (center.y > c_town.town.in_town_rect.top) + && (center.y > 4)) { + center.y--; + need_redraw = TRUE; + } + if ((PtInRect ( &border_rect[1],the_point)) && (center.x > c_town.town.in_town_rect.left) + && (center.x > 4)) { + center.x--; + need_redraw = TRUE; + } + if ((PtInRect ( &border_rect[2],the_point)) && (center.y < c_town.town.in_town_rect.bottom) + && (center.y < town_size[town_type] - 5)) { + center.y++; + need_redraw = TRUE; + } + if ((PtInRect (&border_rect[3],the_point)) && (center.x < c_town.town.in_town_rect.right) + && (center.x < town_size[town_type] - 5)) { + center.x++; + need_redraw = TRUE; + } + } +// End: Screen shift + + + // Process clicks in PC stats area + if (PtInRect (&pc_area_rect,the_point)) { + point_in_area = the_point; + point_in_area.x -= PC_WIN_UL_X; + point_in_area.y -= PC_WIN_UL_Y; + if (PtInRect (&pc_help_button,point_in_area)) { + OffsetRect(&pc_help_button,PC_WIN_UL_X,PC_WIN_UL_Y); + arrow_button_click(pc_help_button); + OffsetRect(&pc_help_button,-1 * PC_WIN_UL_X,-1 * PC_WIN_UL_Y); + FCD(1082,0); + } + for (i = 0; i < 6; i++) + for (j = 0; j < 5; j++) + if ((pc_area_button_active[i][j] > 0) && (PtInRect (&pc_buttons[i][j],point_in_area))) { + OffsetRect(&pc_buttons[i][j],PC_WIN_UL_X,PC_WIN_UL_Y); + arrow_button_click(pc_buttons[i][j]); + OffsetRect(&pc_buttons[i][j],-1 * PC_WIN_UL_X,-1 * PC_WIN_UL_Y); + switch (j) { + case 0: + if ((prime_time() == FALSE) && (overall_mode != 21)&& (overall_mode != 20)) + add_string_to_buf("Set active: Finish what you're doing first."); + else if (is_combat()) + add_string_to_buf("Set active: Can't set this in combat."); + else if ((adven[i].isAlive() == false) && + ((overall_mode != 21) || (store_shop_type != 3))) + add_string_to_buf("Set active: PC must be here & active."); + else { + current_pc = i; + set_stat_window (i); + if (overall_mode == 21) + sprintf((char *) str,"Now shopping: %s",adven[i].name); + else sprintf((char *) str,"Now active: %s",adven[i].name); + add_string_to_buf((char *)str); + adjust_spell_menus(); + } + break; + case 1: + sprintf((char *) str,"%s has %d health out of %d.",adven[i].name, + adven[i].cur_health,adven[i].max_health); + add_string_to_buf((char *)str); + break; + case 2: + sprintf((char *) str,"%s has %d spell pts. out of %d.",adven[i].name, + adven[i].cur_sp,adven[i].max_sp); + add_string_to_buf((char *)str); + break; + case 3: // pc info + give_pc_info(i); + break; + case 4: // trade places + if (prime_time() == FALSE) + add_string_to_buf("Trade places: Finish what you're doing first."); + else if (is_combat()) + add_string_to_buf("Trade places: Can't do this in combat."); + else { + switch_pc(i); + } + break; + } + } + need_reprint = TRUE; + put_pc_screen(); + put_item_screen(stat_window,0); + if (overall_mode == 21) { + set_up_shop_array(); + draw_shop_graphics(0,pc_buttons[0][0]); + } + } + + // Process clicks in item stats area + if (PtInRect (&item_area_rect,the_point)) { + point_in_area = the_point; + point_in_area.x -= ITEM_WIN_UL_X; + point_in_area.y -= ITEM_WIN_UL_Y; + + for (i = 0; i < 9; i++) + if ((item_bottom_button_active[i] > 0) && (PtInRect (&item_screen_button_rects[i],point_in_area))) { + OffsetRect(&item_screen_button_rects[i],ITEM_WIN_UL_X,ITEM_WIN_UL_Y); + arrow_button_click(item_screen_button_rects[i]); + OffsetRect(&item_screen_button_rects[i],-1 * ITEM_WIN_UL_X,-1 * ITEM_WIN_UL_Y); + switch (i) { + case 0: case 1: case 2: case 3: case 4: case 5: + if ((prime_time() == FALSE) && (overall_mode != 20) && (overall_mode != 21)) + add_string_to_buf("Set active: Finish what you're doing first."); + else { + if (!(is_combat())) { + if ((adven[i].isAlive() == false) && + ((overall_mode != 21) || (store_shop_type != 12))) + add_string_to_buf("Set active: PC must be here & active."); + else { + current_pc = i; + sprintf((char *) str,"Now active: %s",adven[i].name); + add_string_to_buf((char *)str); + adjust_spell_menus(); + } + } + set_stat_window(i); + if (overall_mode == 21) { + set_up_shop_array(); + draw_shop_graphics(0,item_screen_button_rects[i]); // rect is dummy + } + } + break; + case 6: // special screen + give_help(50,0,0); + set_stat_window(6); + break; + case 7: // jobs + give_help(50,0,0); + set_stat_window(7); + break; + case 8: // help + FCD(1090,0); + break; + } + } + if (stat_window < 7) { + for (i = 0; i < 8; i++) + for (j = 0; j < 6; j++) + if ((item_area_button_active[i][j] > 0) && (PtInRect (&item_buttons[i][j],point_in_area))) { + OffsetRect(&item_buttons[i][j],ITEM_WIN_UL_X,ITEM_WIN_UL_Y); + if ((j > 0) || (stat_screen_mode < 2)) + arrow_button_click(item_buttons[i][j]); + OffsetRect(&item_buttons[i][j],-1 * ITEM_WIN_UL_X,-1 * ITEM_WIN_UL_Y); + + item_hit = GetScrollPos(item_sbar,SB_CTL) + i; + if ((prime_time() == FALSE) && (j < 4) + && ((j > 0) || (stat_screen_mode < 2))) + add_string_to_buf("Item action: Finish what you're doing first."); + else switch (j) { + case 0: // equip + if (overall_mode == 4) { + add_string_to_buf("Note: Clicking 'U' button by item"); + add_string_to_buf(" uses the item."); + use_item(stat_window, item_hit); + overall_mode = 1; + take_ap(3); + } + else if (prime_time() == TRUE) { + adven[stat_window].equipItem(item_hit); + take_ap(1); + } + break; + case 1: // use + use_item(stat_window, item_hit); + if ((overall_mode != 3) && (overall_mode != 11)) + did_something = TRUE; + take_ap(3); + break; + case 2: // give + adven[stat_window].giveThing(item_hit); + did_something = TRUE; + need_redraw = TRUE; + take_ap(1); + break; + case 3: // drop + if (stat_window == 6){ + use_spec_item(spec_item_array[item_hit]); + need_redraw = TRUE;//// + } + else if (is_out()) + adven[stat_window].dropItem(item_hit,party.p_loc); + else { + add_string_to_buf("Drop item: Click where to drop item."); + store_drop_item = item_hit; + overall_mode = (is_town()) ? 5 : 15; + } + break; + case 4: // info + if (stat_window == 6) + put_spec_item_info(spec_item_array[item_hit]); + else display_pc_item(stat_window, item_hit,adven[stat_window].items[item_hit],0); + break; + case 5: // sell? That this codes was reached indicates that the item was sellable + switch (stat_screen_mode) { + case 2: // identify item + if (party.takeGold(shop_identify_cost, false) == false) + ASB("Identify: You don't have the gold."); + else { + play_sound(68); + ASB("Your item is identified."); + adven[stat_window].items[item_hit].item_properties = + adven[stat_window].items[item_hit].item_properties | 1; + } + break; + case 3: case 4: case 5: // various selling + play_sound(39); + party.gold += store_selling_values[i]; + ASB("You sell your item."); + adven[stat_window].takeItem(item_hit); + break; + case 6: // enchant item + if (party.takeGold(store_selling_values[i], false) == false) + ASB("Enchant: You don't have the gold."); + else { + play_sound(51); + ASB("Your item is now enchanted."); + adven[stat_window].enchantWeapon(item_hit,shop_identify_cost,store_selling_values[i]); + } + break; + } + + break; + } + } + } + put_pc_screen(); + put_item_screen(stat_window,0); + need_reprint = TRUE; + } + + + // Alchemy + if (the_point.x == 1000) { + need_reprint = TRUE; + need_redraw = TRUE; + if (overall_mode == MODE_TOWN) { + do_alchemy(); + } + else add_string_to_buf("Alchemy: Only in town."); + } + + // Wait 40 spaces (town only) + if (the_point.x == 1001) { + need_reprint = TRUE; + need_redraw = TRUE; + + if (party_sees_a_monst() == TRUE) + add_string_to_buf("Long wait: Monster in sight."); + else { + add_string_to_buf("Long wait... "); + print_buf(); + play_sound(-20); + draw_rest_screen(); + pause(10); + for (i = 0; i < 6; i++){ + store_sp[i] = adven[i].cur_health; + adven[i].status[STATUS_WEBS] = 0; + } + } + i = 0; + + while ((i < 80) && (party_sees_a_monst() == FALSE)){ + increase_age(); + do_monsters(); + do_monster_turn(); + j = get_ran(1,1,160 - c_town.difficulty); + if (j == 10) + create_wand_monst(); + for (j = 0; j < 6; j++) + if (adven[j].cur_health < store_sp[j]) { + i = 200; + j = 6; + add_string_to_buf(" Waiting interrupted."); + } + if (party_sees_a_monst() == TRUE) { + i = 200; + add_string_to_buf(" Monster sighted! "); + } + else i++; + } + put_pc_screen(); + } + + // If in combat and pc delayed, jump forward a step + if (pc_delayed == TRUE) + { + initiate_redraw(); + current_pc++; + combat_next_step(); + set_stat_window(current_pc); + put_pc_screen(); + } + + // At this point, see if any specials have been queued up, and deal with them + for (i = 0; i < 20; i++) + if (special_queue[i] >= 0) { + s3 = 0; + switch (i) { + case 0: + run_special(5,2,special_queue[0],c_town.p_loc,&s1,&s2,&s3); + break; + case 1: + run_special(6,2,special_queue[1],party.p_loc,&s1,&s2,&s3); + break; + } + if (s3 > 0) + initiate_redraw(); + } + + // Handle non-PC stuff (like monsters) if the party actually did something + if (did_something == TRUE) { + draw_map(modeless_dialogs[5],5); + + if ((overall_mode >= 10) && (overall_mode < 20)) { + if (no_pcs_left() == TRUE) { + end_combat(); + if (which_combat_type == 0) { + end_town_mode(0,party.p_loc); + add_string_to_buf("Fled the combat. "); + handle_wandering_specials(2); + } + } + else { + + if (need_redraw == TRUE) { + initiate_redraw(); + if ((combat_active_pc == 6) || (pc_moves[combat_active_pc] > 0)) + need_redraw = FALSE; + } + store_cur_pc = current_pc; + if (combat_next_step() == TRUE) + need_redraw = TRUE; + } + } + else { + increase_age(); + if (!(is_out()) || ((is_out()) && (party.age % 10 == 0))) // no monst move is party outdoors and on horse + do_monsters(); + if (overall_mode != 0) do_monster_turn(); + // Wand monsts + if ((overall_mode == 0) && (party_toast() == FALSE) && (party.age % 10 == 0)) + { + if (get_ran(1,1,70 + PSD[306][8] * 200) == 10) + create_wand_monst(); + + for (i = 0; i < 10; i++) + if (party.out_c[i].exists == TRUE) + if (((adjacent(party.p_loc,party.out_c[i].m_loc) == TRUE) || + (party.out_c[i].what_monst.cant_flee >= 10)) + && (party.in_boat < 0) && (party.isFlying() == false)) { + store_wandering_special = party.out_c[i].what_monst; + + if (handle_wandering_specials(0) == TRUE) + initiate_outdoor_combat(i); + party.out_c[i].exists = FALSE; + + // Get rid of excess keyclicks + FlushEvents(2); + + need_reprint = FALSE; + i = 20; + } + } + if (overall_mode == 1) + if (get_ran(1,1,160 - c_town.difficulty + PSD[306][8] * 200) == 2) + create_wand_monst(); + } + + + } + + + if (need_redraw == TRUE) initiate_redraw(); + + if ((need_reprint == TRUE) || (need_redraw == TRUE)) print_buf(); + + if (end_scenario == TRUE) { + reload_startup(); + in_startup_mode = TRUE; + in_scen_debug=FALSE; + draw_startup(0); + menu_activate(1); + if (FCD(901,0) == 2) save_file(1); + } + if (party_toast() == TRUE) { + for (i = 0; i < 6; i++) + if (adven[i].main_status == MAIN_STATUS_FLED) { + adven[i].main_status = MAIN_STATUS_ALIVE; + if (is_combat()) { + end_town_mode(0,c_town.p_loc); + add_string_to_buf("End combat. "); + handle_wandering_specials(2); + } + } + if (party.stuff_done[304][0] > 0) { + end_split(0); + if (is_combat()) overall_mode = 1; + center = c_town.p_loc; + } + menu_activate(1); + initiate_redraw(); + put_pc_screen(); + put_item_screen(stat_window,0); + if (party_toast() == TRUE) + { + play_sound(13); + handle_death(); + if (All_Done == TRUE) return TRUE; + } + } + are_done = All_Done; + return are_done; +} + +Boolean someone_awake() +{ + short i; + + for (i = 0; i < 6; i++) + if ((adven[i].isAlive()) && (adven[i].status[STATUS_ASLEEP] <= 0) && (adven[i].status[STATUS_PARALYZED] <= 0)) + return TRUE; + return FALSE; +} + +void check_cd_event(HWND hwnd,UINT message, WPARAM wparam, LPARAM lparam) +{ + POINT press; + short wind_hit = -1,item_hit = -1; + + switch (message) { + case WM_COMMAND: + // pare out command messages sent from text box + ///GK2 if (wparam == 150) break; + if (LOWORD(wparam) == 150) break; + cd_find_dlog(hwnd,&wind_hit,&item_hit); // item_hit is dummy + item_hit = (short) LOWORD(wparam); + break; + case WM_KEYDOWN: + wind_hit = cd_process_syskeystroke(hwnd, wparam, lparam,&item_hit); + break; + + case WM_CHAR: + wind_hit = cd_process_keystroke(hwnd, wparam, lparam,&item_hit); + break; + + case WM_LBUTTONDOWN: + press = MAKEPOINT(lparam); + wind_hit = cd_process_click(hwnd,press, wparam, lparam,&item_hit); + break; + case WM_RBUTTONDOWN: + press = MAKEPOINT(lparam); + wparam = wparam | MK_CONTROL; + wind_hit = cd_process_click(hwnd,press, wparam, lparam,&item_hit); + break; + + case WM_PAINT: + cd_redraw(hwnd); + break; + } + if (wind_hit < 0) + return; + + switch (wind_hit) { + case -1: break; + case 869: pick_prefab_scen_event_filter(item_hit); break; + case 947: pick_a_scen_event_filter(item_hit); break; + case 958: tip_of_day_event_filter(item_hit); break; + case 960: talk_notes_event_filter(item_hit); break; + case 961: adventure_notes_event_filter(item_hit); break; + case 970: case 971: case 972: case 973: display_strings_event_filter(item_hit); break; + case 987: display_item_event_filter(item_hit); break; + case 988: pick_trapped_monst_event_filter(item_hit); break; + case 989: edit_party_event_filter(item_hit); break; + case 991: display_pc_event_filter(item_hit); break; + case 996: display_alchemy_event_filter(item_hit); break; + case 997: display_help_event_filter(item_hit); break; + case 998: display_pc_item_event_filter(item_hit); break; + case 999: display_monst_event_filter(item_hit); break; + case 1010: spend_xp_event_filter (item_hit); break; + case 1012: get_num_of_items_event_filter (item_hit); break; + case 1013: pick_race_abil_event_filter (item_hit); break; + case 1014: dialog_not_toast = FALSE; break; + case 1017: case 873: get_text_response_event_filter(item_hit); break; + case 1018: select_pc_event_filter (item_hit); break; + case 1019: give_pc_info_event_filter(item_hit); break; + case 1047: alch_choice_event_filter(item_hit); break; + case 1050: pc_graphic_event_filter(item_hit); break; + case 1051: pc_name_event_filter(); break; + case 1096: display_spells_event_filter (item_hit); break; + case 1097: display_skills_event_filter (item_hit); break; + case 1098: pick_spell_event_filter (item_hit); break; + case 1099: prefs_event_filter (item_hit); break; + case 1100: compatibility_event_filter (item_hit); break; + default: fancy_choice_dialog_event_filter (item_hit); break; + } +} + +void handle_menu_spell(short spell_picked,short spell_type) +{ + POINT pass_point; + + spell_forced = TRUE; + pc_casting = current_pc; + pc_last_cast[spell_type][current_pc] = spell_picked; + if (spell_type == 0) + store_mage = spell_picked; + else store_priest = spell_picked; + if ((spell_type == 0) && (mage_need_select[spell_picked] > 0)) { + if ((store_spell_target = char_select_pc(2 - mage_need_select[spell_picked],0,"Cast spell on who?")) == 6) + return; + } + else { + if ((spell_type == 1) && (priest_need_select[spell_picked] > 0)) + if ((store_spell_target = char_select_pc(2 - priest_need_select[spell_picked],0,"Cast spell on who?")) == 6) + return; + } + + pass_point.x = bottom_buttons[spell_type].left + 5; + pass_point.y = bottom_buttons[spell_type].top + 5; + handle_action(pass_point,0,-1); +} + + void initiate_outdoor_combat(short i) +{ + short m,n; + location to_place; + + initiate_redraw(); + + // Is combat too easy? + if ((adven.getTotalLevel() > ((out_enc_lev_tot(i) * 5) / 3) ) && (out_enc_lev_tot(i) < 200) + && (party.out_c[i].what_monst.cant_flee % 10 != 1)) { + add_string_to_buf("Combat: Monsters fled! "); + party.out_c[i].exists = FALSE; + return; + } + +// Delay((long) 100,&dummy); + + start_outdoor_combat(party.out_c[i], out[party.p_loc.x][party.p_loc.y], party.p_loc.countWalls()); + + party.out_c[i].exists = FALSE; + + for (m = 0; m < 6; m++) + if (adven[m].isAlive()) + to_place = pc_pos[m]; + for (m = 0; m < 6; m++) + for (n = 0; n < 24; n++) + if ((adven[m].isAlive() == false) && (adven[m].items[n].variety != 0)) { + place_item(adven[m].items[n],to_place,TRUE); + adven[m].items[n].variety = 0; + } + + overall_mode = 10; + center = pc_pos[current_pc]; + initiate_redraw(); +} + + void initiate_redraw() +// Draw changes in terrain, but only if terrain is onscreen +{ + if ((overall_mode < 20) || (overall_mode >= 30)) draw_terrain(0); +} + +Boolean handle_syskeystroke(WPARAM wParam, LPARAM,short *handled) +{ + UINT kp[10] = {VK_NUMPAD0,VK_NUMPAD1, VK_NUMPAD2, VK_NUMPAD3, VK_NUMPAD4, + VK_NUMPAD5, VK_NUMPAD6, VK_NUMPAD7, VK_NUMPAD8, VK_NUMPAD9}; + POINT terrain_click[10] = {{150,185},{120,215},{150,215},{180,215}, + {120,185},{150,185},{180,185}, + {120,155},{150,155},{180,135}}; + POINT pass_point; + Boolean are_done = FALSE; + short i; + + if (in_startup_mode == TRUE) + return FALSE; + + for (i = 0; i < 10; i++) + if (wParam == kp[i]) { + if (i == 0) { + *handled = 1; + return handle_keystroke((UINT) 'z',-1); + } + else { + //*handled = 1; + pass_point.x = terrain_click[i].x; + pass_point.y = terrain_click[i].y; + wParam = 0; + FlushEvents(0); + are_done = handle_action(pass_point,wParam,-1); + return are_done; + } + } + + if (overall_mode == 20) { + if (wParam == VK_ESCAPE) { + pass_point.x = preset_words[6].word_rect.left + 9; + pass_point.y = preset_words[6].word_rect.top + 9; + are_done = handle_action(pass_point,wParam,-1); + return are_done; + } + } + else if (overall_mode == 21) { // shopping keystrokes + if (wParam == VK_ESCAPE) { + pass_point.x = 222; + pass_point.y = 398; + are_done = handle_action(pass_point,wParam,-1); + return are_done; + } + } + + if ((wParam == VK_LEFT) || (wParam == VK_RIGHT)) { + *handled = 1; + pass_point.x = (wParam == VK_LEFT) ? 120 : 180; + pass_point.y = 185; + are_done = handle_action(pass_point,wParam,-1); + return are_done; + } + if ((wParam == VK_UP) || (wParam == VK_DOWN)) { + *handled = 1; + pass_point.x = 150; + pass_point.y = (wParam == VK_UP) ? 155 : 215; + are_done = handle_action(pass_point,wParam,-1); + return are_done; + } + return are_done; +} + + +Boolean handle_keystroke(WPARAM wParam, LPARAM lParam) +{ + Boolean are_done = FALSE; + POINT pass_point; + short i,j,k; + POINT terrain_click[10] = {{150,185},{120,215},{150,215},{180,215}, + {120,185},{150,185},{180,185}, + {120,155},{150,155},{180,135}}; + char talk_chars[9] = {'l','n','j','b','s','r','d','g','a'}; + char chr; + + short x,y; + location loc; + + if (in_startup_mode == TRUE) + return FALSE; + + chr = (char) wParam; + + if (overall_mode == MODE_TALKING) { + if (chr == ' ') + chr = 'g'; + for (i = 0; i < 9; i++) + if (chr == talk_chars[i]) { + pass_point.x = preset_words[i].word_rect.left + 9; + pass_point.y = preset_words[i].word_rect.top + 9; + are_done = handle_action(pass_point,wParam,-1); + return are_done; + } + } + else if (overall_mode == MODE_SHOPPING) { // shopping keystrokes + for (i = 0; i < 8; i++) + if (chr == 97 + i) { + pass_point.x = shopping_rects[i][1].left + 9; + pass_point.y = shopping_rects[i][1].top + 9; + are_done = handle_action(pass_point,wParam,-1); + return are_done; + } + } + + if ((overall_mode != MODE_TALKING) && (overall_mode != MODE_SHOPPING)) { + + for (k = 0; k < (short) LOWORD(lParam); k++) + switch(chr) + { + case 'D': + if (in_scen_debug) + { + in_scen_debug = FALSE; + ASB("Debug mode OFF."); + } + else + { + in_scen_debug = TRUE; + ASB("Debug mode ON."); + } + print_buf(); + break; + case '?': + if (is_out()) FCD(1079,0); + if (is_town()) FCD(1080,0); + if (is_combat()) FCD(1081,0); + break; + + case '1': case '2': case '3': case '4': case '5': case '6': + pass_point.x = pc_buttons[((short) chr) - 49][0].left + 1 + PC_WIN_UL_X; + pass_point.y = pc_buttons[((short) chr) - 49][0].top + PC_WIN_UL_Y; + are_done = handle_action(pass_point,wParam,-1); + return are_done; + break; + + case '9': + pass_point.x = item_screen_button_rects[6].left + ITEM_WIN_UL_X; + pass_point.y = item_screen_button_rects[6].top + ITEM_WIN_UL_Y; + are_done = handle_action(pass_point,wParam,-1); + return are_done; + break; + + case ' ': + if (overall_mode == 14) { // cast multi-target spell, set # targets to 0 so that + // space clicked doesn't matter + num_targets_left = 0; + pass_point = terrain_click[5]; + are_done = handle_action(pass_point,wParam,-1); + return are_done; + } + if (overall_mode == 11) + spell_cast_hit_return(); + break; + + + case 'z': + if (((overall_mode >= 10) && (overall_mode < 20)) || (overall_mode == 37)) { + set_stat_window(current_pc); + put_item_screen(stat_window,0); + } + else { + set_stat_window(0); + put_item_screen(stat_window,0); + } + break; + + case '=': + if (in_scen_debug) { + party.gold += 100; + party.food += 100; + for (i = 0; i < 6; i++) { + adven[i].main_status = MAIN_STATUS_ALIVE; + adven[i].cur_health = 100; + adven[i].cur_sp = 100; + } + adven.giveXP(25); + refresh_store_items(); + for (i = 0; i < 6; i++) + for (j = 0; j < 62; j++) { + adven[i].mage_spells[j] = TRUE; + adven[i].priest_spells[j] = TRUE; + adven[i].skills[9] = 7; + adven[i].skills[10] = 7; + } + + add_string_to_buf("Debug: Add stuff and heal. "); + print_buf(); + put_pc_screen(); + } + break; + + // case 'A': Alchemy + case 'B': // Leave town + if (in_scen_debug) { + party.stuff_done[304][0] = 0; + if(overall_mode == MODE_OUTDOORS){ + add_string_to_buf("Debug - Leave Town: You're not in town !"); + print_buf(); + break; + } + overall_mode = MODE_OUTDOORS; + position_party(party.outdoor_corner.x,party.outdoor_corner.y,party.p_loc.x,party.p_loc.y); + clear_map(); + add_string_to_buf("Debug: Leaving town..."); + add_string_to_buf("Choose which direction to go."); + print_buf(); + redraw_screen(0); + } + break; + + case 'C': // Clean up + if (in_scen_debug) { + for (i = 0; i < 6; i++) { + adven[i].status[STATUS_POISON] = 0; + if (adven[i].status[STATUS_BLESS] < 0) + adven[i].status[STATUS_BLESS] = 0; + if (adven[i].status[STATUS_HASTE] < 0) + adven[i].status[STATUS_HASTE] = 0; + adven[i].status[STATUS_WEBS] = 0; + adven[i].status[STATUS_DISEASE] = 0; + adven[i].status[STATUS_DUMB] = 0; + adven[i].status[STATUS_ASLEEP] = 0; + adven[i].status[STATUS_PARALYZED] = 0; + adven[i].status[STATUS_ACID] = 0; + } + add_string_to_buf("Debug: You get cleaned up!"); + print_buf(); + put_pc_screen(); + } + break; +// case 'D': toggle Debug mode +//Can be moved out of this function to allow the character to switch debug mode during dialogues or shopping. + case 'E': // Miscellaneous help + if (in_scen_debug) { + party.stuff_done[305][0] = 10; + party.stuff_done[305][2] = 10; + party.stuff_done[305][3] = 10; + add_string_to_buf("Debug: Sanctuary, Detect, Lavawalk!"); + print_buf(); + put_pc_screen(); + } + break; + case 'F': // Flight + if (in_scen_debug) { + if (overall_mode == MODE_TOWN){ + add_string_to_buf("Debug - Flying: Not while in Town !"); + print_buf(); + break; + } + party.stuff_done[305][1] = 10; + add_string_to_buf("Debug: You start flying!"); + print_buf(); + } + break; + case 'H': // Heal PCs and restore their SP + if (in_scen_debug) { + party.gold += 100; + party.food += 100; + for (i = 0; i < 6; i++) { + if ((adven[i].main_status > MAIN_STATUS_ALIVE) && (adven[i].main_status < MAIN_STATUS_FLED)) + adven[i].main_status = MAIN_STATUS_ALIVE; + } + adven.heal(250); + adven.restoreSP(100); + add_string_to_buf("Debug: Heal."); + print_buf(); + put_pc_screen(); + } + break; + case 'K': + if (in_scen_debug) { + for (i = 0; i < T_M; i++) { + if ((is_combat()) && (c_town.monst.dudes[i].active > 0) && (c_town.monst.dudes[i].attitude % 2 == 1)) + c_town.monst.dudes[i].active = 0; + + if ((c_town.monst.dudes[i].active > 0) && (c_town.monst.dudes[i].attitude % 2 == 1) + && (dist(c_town.monst.dudes[i].m_loc,c_town.p_loc) <= 10) ) + damage_monst(i, 7,1000,0, 4); + } + initiate_redraw(); + add_string_to_buf("Debug: Kill things."); + print_buf(); + break; + } +// case 'L': automap +// case 'M': repeat Mage spell + case 'N': // End scenario + if (in_scen_debug) { + reload_startup(); + in_startup_mode = TRUE; + in_scen_debug=FALSE; + draw_startup(0); + menu_activate(1); + if (FCD(901,0) == 2) save_file(1); + } + break; + case 'O': // Location + if (is_town()) { + loc = (overall_mode == MODE_OUTDOORS) ? party.p_loc : c_town.p_loc; + sprintf ((char *) c_line, "Debug: You're at x %d y %d in town %d.", + (short) loc.x, (short) loc.y, c_town.town_num); + } + if (is_out()) { + loc = (overall_mode == MODE_OUTDOORS) ? party.p_loc : c_town.p_loc; + x = loc.x; y = loc.y; + x += 48 * party.outdoor_corner.x; y += 48 * party.outdoor_corner.y; + sprintf ((char *) c_line, "Debug: You're outside at x %d y %d.",x,y); + } + add_string_to_buf((char *) c_line); + print_buf(); + break; +// case 'P': repeat Priest spell + case 'I': //debug info + char buf[256]; //event timer off debug info + sprintf(buf,"Party Age : %d", party.age); + give_error(buf,"",0); + break; + case 'Q': // Magic map + if (in_scen_debug) { + if (overall_mode == MODE_OUTDOORS) { + for (i = 0; i < 96; i++) + for (j = 0; j < 96; j++) + make_explored(i,j); + } + else { + for (i = 0; i < 64; i++) + for (j = 0; j < 64; j++) + make_explored(i,j); + } + clear_map(); + add_string_to_buf("Debug: Magic Map."); + print_buf(); + } + break; + case 'R': // Return to Start + if (in_scen_debug) { + if (party.in_boat >= 0) { + add_string_to_buf(" Not while in boat. "); + break; + } + force_town_enter(scenario.which_town_start,scenario.where_start); + start_town_mode(scenario.which_town_start,9); + position_party(scenario.out_sec_start.x,scenario.out_sec_start.y, + scenario.out_start.x,scenario.out_start.y); + center = c_town.p_loc = scenario.where_start; + redraw_screen(0); + add_string_to_buf("Debug: You are moved... "); + print_buf(); + } + break; + case 'S': // Set a SDF <= can't set the SDF 0 (it's the default return value if the first character of the string is not a number) + if (in_scen_debug) { //and leave alone the 300+ SDF (game options/mechanics) + char response[256]=""; + display_strings("Enter Stuff Done Flag Part A (between 1 and 299)","",0,0,0,0,"Which SDFa ?",-1,130,0); + get_text_response(873,response,0); + i = atoi(response); + if(i>0 && i <300){ + display_strings("Enter Stuff Done Flag Part B (between 0 and 9)","",0,0,0,0,"Which SDFb ?",-1,130,0); + get_text_response(873,response,0); + j = atoi(response); + if(j >= 0 && j < 10){ + display_strings("Enter Stuff Done Flag Part Value (outrageous values are a sure way to crash, or at least broke, the game)","",0,0,0,0,"Which value ?",-1,130,0); + get_text_response(873,response,0); + x = atoi(response); + party.stuff_done[i][j]=x; + } + } + } + break; + case 'T': // Enter a Town + if (in_scen_debug) { + short find_direction_from; + char response[256]=""; + sprintf(response,"Enter Town Number (between 0 and %d)",scenario.num_towns -1 ); + display_strings(response,"",0,0,0,0,"Which Town ?",-1,130,0); + get_text_response(873,response,0); + i = atoi(response); + if(i>=0 && i < scenario.num_towns ){ + if (party.direction == 0) find_direction_from = 2; + else if (party.direction == 4) find_direction_from = 0; + else if (party.direction < 4) find_direction_from = 3; + else find_direction_from = 1; + start_town_mode(i, find_direction_from); + } + } + break; + case 'W': + if(in_scen_debug){ + refresh_store_items(); + add_string_to_buf("Debug: Refreshed jobs/shops. "); + print_buf(); + } + break; + case '<': // Advance clock by one day + if (in_scen_debug) { + ASB("Debug: One day passes..."); + print_buf(); + party.age += 3700; + put_pc_screen(); + } + break; + case '>': + if(in_scen_debug){ + ASB("Debug: Towns have short memory."); + ASB("Your deeds have been forgotten."); + print_buf(); + for (i = 0; i < 4; i++) + party.creature_save[i].which_town = 200; + } + break; + case '/': // Help list + if(in_scen_debug){ + ASB(" Debug hot keys"); + ASB(" B: Leave town"); + ASB(" C: Get cleaned up"); + ASB(" D: Toggle Debug mode"); + ASB(" E: Sanctuary, Detect, Lavawalk"); + ASB(" F: Flight"); + ASB(" H: Heal"); + ASB(" K: Kill things"); + ASB(" N: End Scenario"); + ASB(" O: Location"); + ASB(" Q: Magic map"); + ASB(" R: Return to Start"); + ASB(" S: Set a SDF"); + ASB(" T: Enter Town"); + ASB(" W: Refresh jobs/shops"); + ASB(" =: Heal, increase magic skills"); + ASB(" <: Make one day pass"); + ASB(" >: Towns forgive you"); + ASB(" /: Bring up this list"); + print_buf(); + } + break; + + case 'a': // automap + if (overall_mode < 2) { + pass_point.x = (overall_mode == 0) ? 170 : 221; + pass_point.y = 405; + are_done = handle_action(pass_point,wParam,-1); + return are_done; + } + + break; + + case 'b': case 'u': case 'L': // End combat, shoot and only active character <= why did you remove 'b' ? + if (overall_mode == 1) { + pass_point.x = (chr == 'u') ? 220 : 205; + pass_point.y = (chr == 'L') ? 405 : 388; + are_done = handle_action(pass_point,wParam,-1); + return are_done; + } + break; + + case 's': case 'x': case 'e': + if ((overall_mode == MODE_COMBAT) || + ((overall_mode == 12) && (chr == 's')) || + ((overall_mode == 13) && (chr == 's')) ) { + pass_point.x = (chr == 's') ? 205 : 240; + pass_point.y = (chr == 'e') ? 390 : 406; + are_done = handle_action(pass_point,wParam,-1); + return are_done; + } + break; + + + case 'A': case 'M': case 'P': case 'd': case 'f': case 'g': case 'l': + case 'm': case 'p': case 'r': case 't': case 'w': + j = 50; + if ((chr == 'm') && ((overall_mode == 11) || (overall_mode == 14))) // cancel spell + j = 0; + if ((chr == 'p') && ((overall_mode == 11) || (overall_mode == 14))) // cancel spell + j = 1; + if ((overall_mode == MODE_OUTDOORS) || (overall_mode == MODE_TOWN) || (overall_mode == MODE_COMBAT)) { + switch (chr) { + case 'M': spell_forced = TRUE; j = 0; break; + case 'm': j = 0; break; + case 'P': spell_forced = TRUE; j = 1; break; + case 'p': j = 1; break; + case 'l': j = 2; break; + case 'r': if (overall_mode != 0) return FALSE; + j = 3; + break; + case 't': if (overall_mode == 1) + j = 3; + else return FALSE; + break; + case 'A':if (overall_mode == 1) { + pass_point.x = 1000; + are_done = handle_action(pass_point,wParam,-1); + } + else { + add_string_to_buf("Alchemy: In town only."); + print_buf(); + return FALSE; + } + break; + case 'w':if (overall_mode == MODE_COMBAT) + j = 5; + else if (overall_mode == 1) { + pass_point.x = 1001; + are_done = handle_action(pass_point,wParam,-1); + } + else { + add_string_to_buf("Wait: In town only."); + print_buf(); + return FALSE; + } + break; + case 'd': if (overall_mode != 10) return FALSE; + j = 3; + break; + case 'g': if (overall_mode == MODE_OUTDOORS) return FALSE; + j = 4; + break; + case 'f': if (overall_mode != MODE_TOWN) return FALSE; + j = 6; + break; + } + } + if (j < 50) { + pass_point.x = bottom_buttons[j].left + 5; + pass_point.y = bottom_buttons[j].top + 5; + are_done = handle_action(pass_point,wParam,-1); + return are_done; + } + break; + } + } + + spell_forced = FALSE; + return are_done; +} + + +void menu_activate(short) +// type; // 0 - save off alter off 1 - not all off +{ + HMENU menu; + + menu = GetMenu(mainPtr); + + if (in_startup_mode == TRUE) { + EnableMenuItem(menu,2,MF_GRAYED | MF_BYCOMMAND); + EnableMenuItem(menu,3,MF_GRAYED | MF_BYCOMMAND); + EnableMenuItem(menu,21,MF_GRAYED | MF_BYCOMMAND); + EnableMenuItem(menu,22,MF_GRAYED | MF_BYCOMMAND); + EnableMenuItem(menu,23,MF_GRAYED | MF_BYCOMMAND); + EnableMenuItem(menu,24,MF_GRAYED | MF_BYCOMMAND); + EnableMenuItem(menu,26,MF_GRAYED | MF_BYCOMMAND); + EnableMenuItem(menu,27,MF_GRAYED | MF_BYCOMMAND); + EnableMenuItem(menu,28,MF_GRAYED | MF_BYCOMMAND); + EnableMenuItem(menu,29,MF_GRAYED | MF_BYCOMMAND); + EnableMenuItem(menu,81,MF_GRAYED | MF_BYCOMMAND); + EnableMenuItem(menu,82,MF_GRAYED | MF_BYCOMMAND); + EnableMenuItem(menu,84,MF_GRAYED | MF_BYCOMMAND); + //EnableMenuItem(menu,,MF_GRAYED | MF_BYCOMMAND); + + DrawMenuBar(mainPtr); + return; + } + + EnableMenuItem(menu,3,MF_ENABLED | MF_BYCOMMAND); + EnableMenuItem(menu,2,MF_ENABLED | MF_BYCOMMAND); + EnableMenuItem(menu,21,MF_ENABLED | MF_BYCOMMAND); + EnableMenuItem(menu,22,MF_ENABLED | MF_BYCOMMAND); + EnableMenuItem(menu,23,MF_ENABLED | MF_BYCOMMAND); + EnableMenuItem(menu,24,MF_ENABLED | MF_BYCOMMAND); + EnableMenuItem(menu,26,MF_ENABLED | MF_BYCOMMAND); + EnableMenuItem(menu,27,MF_ENABLED | MF_BYCOMMAND); + EnableMenuItem(menu,28,MF_ENABLED | MF_BYCOMMAND); + EnableMenuItem(menu,29,MF_ENABLED | MF_BYCOMMAND); + EnableMenuItem(menu,81,MF_ENABLED | MF_BYCOMMAND); + EnableMenuItem(menu,82,MF_ENABLED | MF_BYCOMMAND); + EnableMenuItem(menu,84,MF_ENABLED | MF_BYCOMMAND); + DrawMenuBar(mainPtr); +} + +void do_load() +{ + load_file(); + if (in_startup_mode == FALSE) + post_load(); + menu_activate(1); +} + +void post_load() +{ + current_switch = 6; + + reset_item_max(); + + if (overall_mode == 0) + update_explored(party.p_loc); + if (overall_mode == 1) { + make_town_trim(0); + } + make_out_trim(); + + create_clip_region(); + redraw_screen(0); + + stat_window = first_active_pc(); + set_stat_window(0); + + clear_map(); + adjust_spell_menus(); + adjust_monst_menu(); + + cartoon_happening = FALSE; +} + +void do_save(short mode) //mode 0 - normal 1 - save as +{ + if (overall_mode > 1) { + add_string_to_buf("Save: Only while outdoors, or in "); + add_string_to_buf(" town and not looking/casting. "); + print_buf(); + return; + } + save_file(mode); + pause(6); + initiate_redraw(); + put_pc_screen(); + put_item_screen(stat_window,0); + print_buf(); +} + +void increase_age() +{ + short i,j,item,how_many_short = 0,r1,store_day; + Boolean update_stat = FALSE; + + // Increase age, adjust light level & stealth + store_day = calc_day(); + if (is_out()) { + if (party.in_horse < 0) + party.age -= party.age % 10; + else party.age -= party.age % 5; + party.age += 5; + if (party.in_horse < 0) + party.age += 5; + + } + else party.age++; + if (calc_day() != store_day) { // Day changed, so check for interesting stuff. + update_stat = TRUE; + } + + move_to_zero(party.light_level); + + // decrease monster present counter + move_to_zero(party.stuff_done[305][9]); + + // Party spell effects + if (party.stuff_done[305][0] == 1) {reset_text_bar(); + add_string_to_buf("Your footsteps grow louder. "); } + move_to_zero(party.stuff_done[305][0]); + if (party.stuff_done[305][2] == 1) {reset_text_bar(); + add_string_to_buf("You stop detecting monsters. ");} + move_to_zero(party.stuff_done[305][2]); + if (party.stuff_done[305][3] == 1) {reset_text_bar(); + add_string_to_buf("Your feet stop glowing. ");} + move_to_zero(party.stuff_done[305][3]); + + if (party.stuff_done[305][1] == 2) + add_string_to_buf("You are starting to descend."); + if (party.stuff_done[305][1] == 1) { + if (scenario.ter_types[out[party.p_loc.x][party.p_loc.y]].blockage > 2) { + add_string_to_buf(" You plummet to your deaths. "); + adven.kill(2); + print_buf(); + pause(150); + } + else add_string_to_buf(" You land safely. "); + reset_text_bar(); + } + + move_to_zero(party.stuff_done[305][1]); + + if ((overall_mode > 0) && (c_town.town.lighting == 2)) + party.light_level = max (0,party.light_level - 9); + if (c_town.town.lighting == 3) { + if (party.light_level > 0) + ASB("Your light is drained."); + party.light_level = 0; + } + + + // Specials countdowns + if ((party.age % 500 == 0) && (get_ran(1,0,5) == 3) && (adven.hasAbil(52) == true)) { + update_stat = TRUE; + adven.disease(2); + } + + + // Plants and magic shops + if (party.age % 4000 == 0) refresh_store_items(); + + // Protection, etc. + for (i = 0; i < NUM_OF_PCS; i++) { // Process some status things, and check if stats updated + + if ((adven[i].status[STATUS_INVULNERABLE] == 1) || (adven[i].status[5] == 1) || (adven[i].status[8] == 1) + || (adven[i].status[STATUS_ASLEEP] == 1)|| (adven[i].status[STATUS_PARALYZED] == 1)) + update_stat = TRUE; + move_to_zero(adven[i].status[STATUS_INVULNERABLE]); + move_to_zero(adven[i].status[STATUS_MAGIC_RESISTANCE]); + move_to_zero(adven[i].status[STATUS_INVISIBLE]); + move_to_zero(adven[i].status[STATUS_MARTYRS_SHIELD]); + move_to_zero(adven[i].status[STATUS_ASLEEP]); + move_to_zero(adven[i].status[STATUS_PARALYZED]); + if ((party.age % 40 == 0) && (adven[i].status[0] > 0)) { + update_stat = TRUE; + move_to_zero(adven[i].status[0]); + } + + } + + // Food + if ((party.age % 1000 == 0) && (overall_mode < 10)) { + for (i = 0; i < NUM_OF_PCS; i++) + if (adven[i].isAlive()) + how_many_short++; + how_many_short = party.takeFood (how_many_short, false); + if (how_many_short > 0) { + add_string_to_buf("Starving! "); + play_sound(66); + r1 = get_ran(3,1,6); + adven.damage(r1,4); + update_stat = TRUE; + if (overall_mode < 10) + boom_space(party.p_loc,overall_mode,0,r1,0); + } + else { + play_sound(6); + add_string_to_buf("You eat. "); + } + update_stat = TRUE; + } + + // Poison, acid, disease damage + for (i = 0; i < 6; i++) // Poison + if (adven[i].status[STATUS_POISON] > 0) { + i = 6; + if (((overall_mode == 0) && (party.age % 50 == 0)) || ((overall_mode == 1) && (party.age % 20 == 0))) { + update_stat = TRUE; + do_poison(); + } + } + for (i = 0; i < 6; i++) // Disease + if (adven[i].status[STATUS_DISEASE] > 0) { + i = 6; + if (((overall_mode == 0) && (party.age % 100 == 0)) || ((overall_mode == 1) && (party.age % 25 == 0))) { + update_stat = TRUE; + handle_disease(); + } + } + for (i = 0; i < 6; i++) // Acid + if (adven[i].status[STATUS_ACID] > 0) { + i = 6; + update_stat = TRUE; + handle_acid(); + } + + // Healing and restoration of spell pts. + if (is_out()) { + if (party.age % 100 == 0) { + for (i = 0; i < 6; i++) + if ((adven[i].isAlive()) && (adven[i].cur_health < adven[i].max_health)) + update_stat = TRUE; + adven.heal(2); + } + } + else { + if (party.age % 50 == 0) { + for (i = 0; i < 6; i++) + if ((adven[i].isAlive()) && (adven[i].cur_health < adven[i].max_health)) + update_stat = TRUE; + adven.heal(1); + } + } + if (is_out()) { + if (party.age % 80 == 0) { + for (i = 0; i < 6; i++) + if ((adven[i].isAlive()) && (adven[i].cur_sp < adven[i].max_sp)) + update_stat = TRUE; + adven.restoreSP(2); + } + } + else { + if (party.age % 40 == 0) { + for (i = 0; i < 6; i++) + if ((adven[i].isAlive()) && (adven[i].cur_sp < adven[i].max_sp)) + update_stat = TRUE; + adven.restoreSP(1); + } + } + + // Recuperation and chronic disease disads + for (i = 0; i < 6; i++) + if (adven[i].isAlive()) { + if ((adven[i].traits[9] > 0) && (get_ran(1,0,10) == 1) && (adven[i].cur_health < adven[i].max_health)) { + adven[i].heal(2); + update_stat = TRUE; + } + if ((adven[i].traits[13] > 0) && (get_ran(1,0,110) == 1)) { + adven[i].disease(4); + update_stat = TRUE; + } + + } + + // Blessing, slowed,etc. + if (party.age % 4 == 0) + for (i = 0; i < 6; i++) { + if ((adven[i].status[1] != 0) || (adven[i].status[3] != 0)) + update_stat = TRUE; + move_to_zero(adven[i].status[1]); + move_to_zero(adven[i].status[3]); + if (((item = adven[i].hasAbilEquip(50)) < 24) + && (adven[i].cur_health < adven[i].max_health) + && ((overall_mode > 0) || (get_ran(1,0,10) == 5))){ + j = get_ran(1,0,adven[i].items[item].ability_strength / 3); + if (adven[i].items[item].ability_strength / 3 == 0) + j = get_ran(1,0,1); + if (is_out()) j = j * 4; + adven[i].heal(j); + update_stat = TRUE; + } + } + dump_gold(1); + + special_increase_age(); + push_things(); + + if (is_town()) process_fields(); + + // Cancel switching PC order + current_switch = 6; + + // If a change, draw stat screen + if (update_stat == TRUE) put_pc_screen(); + adjust_spell_menus(); +} + +void switch_pc(short which) +{ + pc_record_type store_pc; + + if (current_switch < 6) { + if (current_switch != which) { + add_string_to_buf("Switch: OK."); + store_pc = adven[which]; + adven[which] = adven[current_switch]; + adven[current_switch] = store_pc; + if (current_pc == current_switch) + current_pc = which; + else if (current_pc == which) + current_pc = current_switch; + set_stat_window(current_pc); + update_pc_graphics(); + current_switch = 6; + } + else { + ASB("Switch: Not with self."); + current_switch = 6; + } + } + else { + add_string_to_buf("Switch: Switch with who? "); + current_switch = which; + } +} + +void handle_death() +{ + short choice; + + in_startup_mode = TRUE; + + while (in_startup_mode == TRUE) + { + + // Use death (or leave Exile) dialog + in_startup_mode = FALSE; + + choice = FCD(1069,0); //// FCD hates it when it gets called in startup mode + // and startup graphiocs aren't loaded. + + in_startup_mode = TRUE; + + if (choice == 1) { + in_startup_mode = FALSE; + load_file(); + if (party_toast() == FALSE) { + if (in_startup_mode == FALSE) + post_load(); + else return; + } + else in_startup_mode = TRUE; + } + + if (choice == 2) + start_new_game(); + + if (choice == 3) { + in_startup_mode = FALSE; + All_Done = TRUE; + } + + } +} + +void start_new_game() +{ + short i; + short choice; + + choice = FCD(1065,0); + + if (choice == 2) return; + + init_party(0); + edit_party(); + + // if no PCs left, forget it + for (i = 0 ; i < NUM_OF_PCS; i++) + if (adven[i].isAlive()) + i = 100; + + if (i == NUM_OF_PCS) + return; + + // everyone gets a weapon + for (i = 0; i < NUM_OF_PCS; i++) + if (adven[i].isAlive()) { + adven[i].items[0] = start_items[adven[i].race * 2]; + adven[i].equip[0] = TRUE; + adven[i].items[1] = start_items[adven[i].race * 2 + 1]; + adven[i].equip[1] = TRUE; + } + // PCs get adjustments + for (i = 0; i < 6; i++) + if (adven[i].isAlive()) { + // Do stat adjs for selected race. + if (adven[i].race == RACE_NEPHIL) { + if (adven[i].skills[1] < 18) + adven[i].skills[1] += 2; + } + if (adven[i].race == RACE_SLITH) { + if (adven[i].skills[0] < 18) + adven[i].skills[0] += 2; + if (adven[i].skills[2] < 19) + adven[i].skills[2] += 1; + } + adven[i].max_sp += adven[i].skills[SKILL_MAGE_SPELLS] * 3 + adven[i].skills[SKILL_PRIEST_SPELLS] * 3; + adven[i].cur_sp = adven[i].max_sp; + } + save_file(1); + party_in_memory = TRUE; +} + +location get_cur_direction(POINT the_point) +{ + location store_dir; + int x = the_point.x; + int y = the_point.y; + + // This is a kludgy adjustment to adjust for the screen shifting between Exile I & II + y += 5; + x += 5; + + if ((x < 135) & (y >= ((x * 34) / 10) - 293) & (y <= (-1 * ((x * 34) / 10) + 663))) + store_dir.x--; + if ((x > 163) & (y <= ((x * 34) / 10) - 350) & (y >= (-1 * ((x * 34) / 10) + 721))) + store_dir.x++; + if ((y < 167) & (y <= (x / 2) + 102) & (y <= (-1 * (x / 2) + 249))) + store_dir.y--; + if ((y > 203) & (y >= (x / 2) + 123) & (y >= (-1 * (x / 2) + 268))) + store_dir.y++; + + return store_dir; +} + +Boolean outd_move_party(location destination,Boolean forced) +{ + char create_line[60]; + short boat_num,horse_num,spec_num; + location real_dest, sector_p_in; + Boolean keep_going = TRUE,check_f; + location store_corner,store_iwc; + unsigned char ter; + + keep_going = check_special_terrain(destination,0,0,&spec_num,&check_f); + if (check_f == TRUE) forced = TRUE; + if (debug_on == TRUE) forced = TRUE; + if (spec_num == 50) forced = TRUE; + + // If not blocked and not put in town by a special, process move + if ((keep_going == TRUE) && (overall_mode == 0)) { + + real_dest.x = destination.x - party.p_loc.x; + real_dest.y = destination.y - party.p_loc.y; + + sector_p_in.x = party.outdoor_corner.x + party.i_w_c.x; + sector_p_in.y = party.outdoor_corner.y + party.i_w_c.y; + + store_corner = party.outdoor_corner; + store_iwc = party.i_w_c; + + // Check if party moves into new sector + if ((destination.x < 6) && (party.outdoor_corner.x > 0)) shift_universe_left(); + if ((destination.x > 90) && (party.outdoor_corner.x < scenario.out_width - 1)) shift_universe_right(); + if ((destination.y < 6) && (party.outdoor_corner.y > 0)) shift_universe_up(); + else if ((destination.y > 90) && (party.outdoor_corner.y < scenario.out_height - 1)) + shift_universe_down(); + // Now stop from going off the world's edge + real_dest.x = party.p_loc.x + real_dest.x; + real_dest.y = party.p_loc.y + real_dest.y; + if ((real_dest.x < 4) && (party.outdoor_corner.x <= 0)) { + ASB("You've reached the world's edge."); + return FALSE; + } + if (((real_dest.x > 92) && (party.outdoor_corner.x >= scenario.out_width - 2)) || + ((real_dest.x > 44) && (party.outdoor_corner.x >= scenario.out_width - 1))) { + ASB("You've reached the world's edge."); + return FALSE; + } + if ((real_dest.y < 4) && (party.outdoor_corner.y <= 0)) { + ASB("You've reached the world's edge."); + return FALSE; + } + else if (((real_dest.y > 92) && (party.outdoor_corner.y >= scenario.out_height - 2)) || + ((real_dest.y > 44) && (party.outdoor_corner.y >= scenario.out_height - 1))) { + ASB("You've reached the world's edge."); + return FALSE; + } + + ter = out[real_dest.x][real_dest.y]; + + if (party.in_boat >= 0) { + if ((outd_is_blocked(real_dest) == FALSE) //&& (outd_is_special(real_dest) == FALSE) + // not in towns + && ((scenario.ter_types[ter].boat_over == FALSE) + || ((real_dest.x != party.p_loc.x) && (real_dest.y != party.p_loc.y))) + && (scenario.ter_types[ter].special != 21)) { + add_string_to_buf("You leave the boat."); + party.in_boat = -1; + } + else if (((real_dest.x != party.p_loc.x) && (real_dest.y != party.p_loc.y)) + || ((forced == FALSE) && (out_boat_there(destination) < 30))) + return FALSE; + else if ((outd_is_blocked(real_dest) == FALSE) + && (scenario.ter_types[ter].boat_over == TRUE) + && (scenario.ter_types[ter].special != 21)) { + if ((fancy_choice_dialog(1086,0)) == 1) + forced = TRUE; + else { + add_string_to_buf("You leave the boat. "); + party.in_boat = -1; + } + } + else if (scenario.ter_types[ter].boat_over == TRUE) + forced = TRUE; + } + + if (((boat_num = out_boat_there(real_dest)) < 30) && (party.in_boat < 0) && (party.in_horse < 0)) { + if (party.isFlying()) + { + add_string_to_buf("You land first. "); + party.stuff_done[305][1] = 0; + } + give_help(61,0,0); + add_string_to_buf("Move: You board the boat. "); + party.in_boat = boat_num; + party.direction = set_direction(party.p_loc, destination); + + party.p_loc = real_dest; + party.i_w_c.x = (party.p_loc.x > 48) ? 1 : 0; + party.i_w_c.y = (party.p_loc.y > 48) ? 1 : 0; + party.loc_in_sec = party.p_loc.toLocal(); + + if ((store_corner.x != party.outdoor_corner.x) || (store_corner.y != party.outdoor_corner.y) || + (store_iwc.x != party.i_w_c.x) || (store_iwc.y != party.i_w_c.y)) + clear_map(); + + return TRUE; + } + else if (((horse_num = out_horse_there(real_dest)) < 30) && (party.in_boat < 0) && (party.in_horse < 0)) { + if (party.isFlying()) + { + add_string_to_buf("Land before mounting horses."); + return FALSE; + } + if ((scenario.ter_types[ter].special >= 2) && (scenario.ter_types[ter].special <= 4)) { + ASB("Your horses quite sensibly refuse."); + return FALSE; + } + + give_help(60,0,0); + add_string_to_buf("Move: You mount the horses. "); + play_sound(84); + party.in_horse = horse_num; + party.direction = set_direction(party.p_loc, destination); + + party.p_loc = real_dest; + party.i_w_c.x = (party.p_loc.x > 48) ? 1 : 0; + party.i_w_c.y = (party.p_loc.y > 48) ? 1 : 0; + party.loc_in_sec = party.p_loc.toLocal(); + + if ((store_corner.x != party.outdoor_corner.x) || (store_corner.y != party.outdoor_corner.y) || + (store_iwc.x != party.i_w_c.x) || (store_iwc.y != party.i_w_c.y)) + clear_map(); + + return TRUE; + } + else if ((outd_is_blocked(real_dest) == FALSE) || (forced == TRUE) + // Check if can fly over + || ((party.isFlying()) && (scenario.ter_types[ter].fly_over == TRUE))) + { + party.direction = set_direction(party.p_loc, destination); + + if ((party.isFlying()) && (scenario.ter_types[ter].special == 21)) { + add_string_to_buf("Moved: You have to land first. "); + return FALSE; + } + + + party.p_loc = real_dest; + party.i_w_c.x = (party.p_loc.x > 47) ? 1 : 0; + party.i_w_c.y = (party.p_loc.y > 47) ? 1 : 0; + party.loc_in_sec = party.p_loc.toLocal(); + move_sound(out[real_dest.x][real_dest.y],num_out_moves); + num_out_moves++; + + if (party.in_boat >= 0) { + // Waterfall!!! + while (scenario.ter_types[out[party.p_loc.x][party.p_loc.y + 1]].special == 15) { + add_string_to_buf(" Waterfall! "); + party.p_loc.y += 2; + party.loc_in_sec.y += 2; + update_explored(party.p_loc); + initiate_redraw(); + print_buf(); + if ((cave_lore_present() > 0) && (get_ran(1,0,1) == 0)) + add_string_to_buf(" (No supplies lost.)"); + else if (party.food > 1800) + party.food -= 50; + else party.food = (party.food * 19) / 20; + put_pc_screen(); + play_sound(28); + pause(8); + } + party.boats[party.in_boat].which_town = 200; + party.boats[party.in_boat].boat_loc_in_sec = party.loc_in_sec; + party.boats[party.in_boat].boat_loc = party.p_loc; + party.boats[party.in_boat].boat_sector.x = party.outdoor_corner.x + party.i_w_c.x; + party.boats[party.in_boat].boat_sector.y = party.outdoor_corner.y + party.i_w_c.y; + + } + if (party.in_horse >= 0) { + party.horses[party.in_horse].which_town = 200; + party.horses[party.in_horse].horse_loc_in_sec = party.loc_in_sec; + party.horses[party.in_horse].horse_loc = party.p_loc; + party.horses[party.in_horse].horse_sector.x = party.outdoor_corner.x + party.i_w_c.x; + party.horses[party.in_horse].horse_sector.y = party.outdoor_corner.y + party.i_w_c.y; + + } + + if ((store_corner.x != party.outdoor_corner.x) || (store_corner.y != party.outdoor_corner.y) || + (store_iwc.x != party.i_w_c.x) || (store_iwc.y != party.i_w_c.y)) + clear_map(); + + return TRUE; + } + else { + sprintf ((char *) create_line, "Blocked: %s",dir_string[set_direction(party.p_loc, destination)]); + add_string_to_buf((char *) create_line); + return FALSE; + } + } + return FALSE; +} + + + +Boolean town_move_party(location destination,short forced) +{ + char create_line[60],keep_going = TRUE; + short boat_there,horse_there,spec_num; + unsigned char ter; + Boolean check_f = FALSE; + + if (debug_on == TRUE) forced = TRUE; + + if (monst_there(destination) > T_M) keep_going = check_special_terrain(destination,1,0,&spec_num,&check_f); + if (check_f == TRUE) forced = TRUE; + if (spec_num == 50) forced = TRUE; + ter = t_d.terrain[destination.x][destination.y]; + + if (keep_going == TRUE) { + if (party.in_boat >= 0) { + if ((is_blocked(destination) == FALSE) && (is_special(destination) == FALSE) + // If to bridge, exit if heading diagonal, keep going is head horiz or vert + && ( (scenario.ter_types[ter].boat_over == FALSE) + || ((destination.x != c_town.p_loc.x) && (destination.y != c_town.p_loc.y)))) { + add_string_to_buf("You leave the boat. "); + party.in_boat = -1; + } + else if ((destination.x != c_town.p_loc.x) && (destination.y != c_town.p_loc.y)) + return FALSE; + // Crossing bridge: land or go through + else if ((is_blocked(destination) == FALSE) && (scenario.ter_types[ter].boat_over == TRUE) && ter != 75 && ter!=76) { + if ((fancy_choice_dialog(1086,0)) == 1) + forced = TRUE; + else if (is_blocked(destination) == FALSE) { + add_string_to_buf("You leave the boat. "); + party.in_boat = -1; + } + } + // boat in destination + else if (town_boat_there(destination) < 30) { + add_string_to_buf(" Boat there already. "); + return FALSE; + } + // water or lava + else if (scenario.ter_types[ter].boat_over == TRUE) + forced = TRUE; + + + } + + if (((boat_there = town_boat_there(destination)) < 30) && (party.in_boat < 0)) { + if (party.boats[boat_there].property == TRUE) { + add_string_to_buf(" Not your boat. "); + return FALSE; + } + give_help(61,0,0); + add_string_to_buf("Move: You board the boat. "); + party.in_boat = boat_there; + party.direction = set_direction(c_town.p_loc, destination); + + c_town.p_loc = destination; + center = c_town.p_loc; + + return TRUE; + } + else if (((horse_there = town_horse_there(destination)) < 30) && (party.in_horse < 0)) { + if (party.horses[horse_there].property == TRUE) { + add_string_to_buf(" Not your horses. "); + return FALSE; + } + give_help(60,0,0); + add_string_to_buf("Move: You mount the horses. "); + play_sound(84); + party.in_horse = horse_there; + party.direction = set_direction(c_town.p_loc, destination); + + c_town.p_loc = destination; + center = c_town.p_loc; + + return TRUE; + } + else if ((is_blocked(destination) == FALSE) || (forced == 1)) { + if (party.in_horse >= 0) { + if ((scenario.ter_types[ter].special >= 2) && (scenario.ter_types[ter].special <= 4)) { + ASB("Your horses quite sensibly refuse."); + return FALSE; + } + if (scenario.ter_types[ter].block_horse == TRUE) { + ASB("You can't take horses there!"); + return FALSE; + } + if ((c_town.town.lighting > 0) && (get_ran(1,0,1) == 0)) { + ASB("The darkness spooks your horses."); + return FALSE; + } + + } + party.direction = set_direction(c_town.p_loc, destination); + c_town.p_loc = destination; + + move_sound(t_d.terrain[destination.x][destination.y],(short) party.age); + + if (party.in_boat >= 0) { // Watchout, party.p_loc is party outdoor location !!! Town location is c_town.p_loc ... + + if(party.stuff_done[309][2] > 0){ + + center = c_town.p_loc; //put on top of waterfall + + // Waterfall!!! + while (scenario.ter_types[t_d.terrain[c_town.p_loc.x][c_town.p_loc.y + 1]].special == 15) { + add_string_to_buf(" Waterfall! "); + c_town.p_loc.y += 2; + update_explored(c_town.p_loc); + initiate_redraw(); + print_buf(); + if ((cave_lore_present() > 0) && (get_ran(1,0,1) == 0)) + add_string_to_buf(" (No supplies lost.)"); + else if (party.food > 1800) + party.food -= 50; + else party.food = (party.food * 19) / 20; + put_pc_screen(); + play_sound(28); + pause(8); + } + } + party.boats[party.in_boat].boat_loc = c_town.p_loc; + party.boats[party.in_boat].which_town = c_town.town_num; + + } + if (party.in_horse >= 0) { + party.horses[party.in_horse].horse_loc = c_town.p_loc; + party.horses[party.in_horse].which_town = c_town.town_num; + } + center = c_town.p_loc; + return TRUE; + } + else { + if (destination.isDoor()) + sprintf ((char *) create_line, "Door locked: %s ",dir_string[set_direction(c_town.p_loc, destination)]); + else sprintf ((char *) create_line, "Blocked: %s ",dir_string[set_direction(c_town.p_loc, destination)]); + add_string_to_buf((char *) create_line); + return FALSE; + } + } + + return FALSE; +} + +bool pc_array::isPoisoned() +{ + for (int i = 0; i < NUM_OF_PCS; i++) + if (pc[i].isAlive() && (pc[i].status[STATUS_POISON] > 0)) + return true; + + return false; +} + +short nearest_monster() +{ + short i = 100,j,s; + + for (j = 0; j < 10; j++) + if (party.out_c[j].exists == TRUE) { + s = dist(party.p_loc,party.out_c[j].m_loc); + i = min(i,s); + } + return i; +} + +short get_outdoor_num() +{ + return (scenario.out_width * (party.outdoor_corner.y + party.i_w_c.y) + party.outdoor_corner.x + party.i_w_c.x); +} diff --git a/Win32/Blades of Exile/ACTIONS.H b/Win32/Blades of Exile/ACTIONS.H new file mode 100644 index 00000000..8e8aa3b4 --- /dev/null +++ b/Win32/Blades of Exile/ACTIONS.H @@ -0,0 +1,34 @@ +#ifndef _ACTIONS_H + #define _ACTIONS_H + +void init_screen_locs(); +Boolean prime_time(); +Boolean handle_action(POINT the_point, WPARAM wparam, LPARAM lparam ); +Boolean someone_awake(); +void flash_rect(RECT to_flash); +void flash_round_rect(RECT to_flash,short radius); +void button_flash_rect(RECT to_flash); +void handle_menu_spell(short spell_picked,short spell_type) ; +void initiate_outdoor_combat(short i); +void initiate_redraw(); +Boolean handle_syskeystroke(UINT wParam,LONG lParam,short *handled); +Boolean handle_keystroke(UINT wParam,LONG lParam); +void menu_activate( short type); +void do_load(); +void post_load(); +void do_save(short mode); +void increase_age(); +void switch_pc(short which); +void handle_death(); +void start_new_game(); +location get_cur_direction(POINT the_point); +Boolean outd_move_party(location destination,Boolean forced); +Boolean town_move_party(location destination,short forced); +Boolean someone_poisoned(); +short nearest_monster(); +void setup_outdoors(location where); +short get_outdoor_num(); +Boolean is_sign(unsigned char ter); +void check_cd_event(HWND hwnd,UINT message,WPARAM wparam,LPARAM lparam); + +#endif diff --git a/Win32/Blades of Exile/BLADES.CPP b/Win32/Blades of Exile/BLADES.CPP new file mode 100644 index 00000000..d64296a7 --- /dev/null +++ b/Win32/Blades of Exile/BLADES.CPP @@ -0,0 +1,899 @@ +#include +#include "global.h" +#include "graphics.h" +#include "newgraph.h" +#include "fileio.h" +#include "actions.h" +#include "text.h" +#include "party.h" +#include "exlsound.h" +#include "items.h" +#include "fields.h" +#include "town.h" +#include "dlogtool.h" +#include "dlgutils.h" +#include "infodlgs.h" +#include "graphutl.h" +#include "blades.h" + +#include "globvar.h" + +void startup_load() +{ + load_file(); + if (in_startup_mode == FALSE) + { + end_startup(); + post_load(); + } + else + { + menu_activate(0); + draw_startup(0); + } +} + +Boolean handle_startup_press(POINT the_point) +{ + short i,scen; + long dummy; + + the_point.x -= ulx; + the_point.y -= uly; + + for (i = 0; i < 5; i++) + if (PtInRect(&startup_button[i],the_point) == TRUE) + { + draw_start_button(i,5); + + if (play_sounds == TRUE) play_sound(37); + else Delay(5,&dummy); + + draw_start_button(i,0); + + switch (i) { + case 0: + startup_load(); + break; + + case 1: + draw_startup(0); + start_new_game(); + update_pc_graphics(); + draw_startup(0); + break; + + case 2: + /* how to order button */ + //draw_startup(0); + break; + + case 3: + if (party_in_memory == FALSE) { // check if party is loaded + FCD(867,0); //no party loaded error message + break; + } + + scen = pick_prefab_scen(); // return a short in scen specifying the chosen scenario + if (scen < 0) + break; + + switch (scen) { //put scenario filename in party.scen_name + case 0: sprintf(party.scen_name,"valleydy.exs"); break; + case 1: sprintf(party.scen_name,"stealth.exs"); break; + case 2: sprintf(party.scen_name,"zakhazi.exs"); break; + } + + put_party_in_scen(); //put the party in the scenario and begin the game + break; + + case 4: // intro + if (party_in_memory == FALSE) { // check if party is loaded + FCD(867,0); //no party loaded error message + break; + } + scen = pick_a_scen(); // return a short to scen specifying the chosen scenario + if (scen_headers[scen].prog_make_ver[0] >= 2) { + FCD(912,0); + break; + } + if (scen >= 0) { + sprintf(party.scen_name,"%s",data_store2->scen_names[scen]); //put scenario filename in party.scen_name retrieving it using scen + put_party_in_scen(); //put the party in the scenario and begin the game + } + + break; + + default: + Delay(50,&dummy); + return TRUE; + } + } + return FALSE; +} + +void loadCursors() +{ + for (int i = 0; i < 3; i++) + for (int j = 0; j < 3; j++) + arrow_curs[i][j] = + LoadCursor(store_hInstance,MAKEINTRESOURCE(100 + (i - 1) + 10 * (j - 1))); + + sword_curs = LoadCursor(store_hInstance,MAKEINTRESOURCE(120)); + key_curs = LoadCursor(store_hInstance,MAKEINTRESOURCE(122)); + target_curs = LoadCursor(store_hInstance,MAKEINTRESOURCE(124)); + talk_curs = LoadCursor(store_hInstance,MAKEINTRESOURCE(126)); + look_curs = LoadCursor(store_hInstance,MAKEINTRESOURCE(129)); +} + +void loadFonts() +{ + AddFontResource("maidword.ttf"); // add font to the system font table + font = CreateFont(12,0,0,0,0, 0,0,0, 0,0, 0,0,0,"MS Sans Serif"); + small_bold_font = CreateFont(12,0,0,0,700, 0,0,0, 0,0, 0,0,0,"MS Sans Serif"); + italic_font = CreateFont(12,0,0,0,700, 1,0,0, 0,0, 0,0,0,"MS Sans Serif"); + underline_font = CreateFont(12,0,0,0,0, 0,1,0, 0,0, 0,0,0,"MS Sans Serif"); + bold_font = CreateFont(14,0,0,0,700, 0,0,0, 0,0, 0,0,0,"MS Sans Serif"); + tiny_font = font; + fantasy_font = CreateFont(22,0,0,0,0, 0,0,0, 0,0, 0,0,0,"MaidenWord"); + if (fantasy_font == NULL) + { + fantasy_font = CreateFont(22,0,0,0,0, 0,0,0, 0,0, 0,0,0,"MS Sans Serif"); + } +} + +int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR, int nCmdShow) +{ + MSG msg; + WNDCLASS wndclass, wndclass2; + RECT windRECT; + HINSTANCE boeSoundsDLL; + + wndclass.style = CS_HREDRAW | CS_VREDRAW | CS_BYTEALIGNWINDOW; + wndclass.lpfnWndProc = WndProc; + wndclass.cbClsExtra = 0; + wndclass.cbWndExtra = 0; + wndclass.hInstance = hInstance; + wndclass.hIcon = LoadIcon(hInstance,MAKEINTRESOURCE(10)); + wndclass.hCursor = NULL; + wndclass.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH); + wndclass.lpszMenuName = MAKEINTRESOURCE(1); + wndclass.lpszClassName = szAppName; + + RegisterClass(&wndclass); + + wndclass2.style = CS_HREDRAW | CS_VREDRAW | CS_BYTEALIGNWINDOW; + wndclass2.lpfnWndProc = WndProc; + wndclass2.cbClsExtra = 0; + wndclass2.cbWndExtra = 0; + wndclass2.hInstance = hInstance; + wndclass2.hIcon = LoadIcon(hInstance,MAKEINTRESOURCE(10)); + wndclass2.hCursor = NULL; + wndclass2.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH); + wndclass2.lpszMenuName = NULL; + wndclass2.lpszClassName = szWinName; + + RegisterClass(&wndclass2); + + mainPtr = CreateWindow (szAppName, "Classic Blades of Exile Beta 1", + WS_OVERLAPPEDWINDOW, + 0, + 0, + 588, + 478, + NULL, + NULL, + hInstance, + NULL); + + if (!hPrevInstance) + { // initialize + Get_Path(file_path_name); + + store_hInstance = hInstance; + accel = LoadAccelerators(hInstance, MAKEINTRESOURCE(1)); + + boeSoundsDLL = LoadLibrary("./boesounds.dll"); + + if (!boeSoundsDLL) + { + MessageBox(mainPtr, "BOESOUNDS.DLL not found", "Error", MB_OK | MB_ICONEXCLAMATION); + return (-1); + } + + load_sounds(boeSoundsDLL); + loadFonts(); + loadCursors(); + + SetCursor(sword_curs); + current_cursor = 124; + /* cursors loaded */ + + data_store = new piles_of_stuff_dumping_type; + data_store2 = new piles_of_stuff_dumping_type2; + data_store3 = new piles_of_stuff_dumping_type3; + data_store4 = new piles_of_stuff_dumping_type4; + data_store5 = new piles_of_stuff_dumping_type5; + + srand(GetCurrentTime()); + + get_reg_data(); + + if (display_mode != 5) + max_window(mainPtr); + else { + GetWindowRect(GetDesktopWindow(),&windRECT); + MoveWindow(mainPtr,(windRECT.right - (588 + 10)) / 2, + (windRECT.bottom - (425 + 52)) / 2 , + 588 + 10,425 + 52,TRUE); + } + + shop_sbar = CreateWindow("scrollbar",NULL, + WS_CHILD | WS_TABSTOP | SBS_VERT, shop_sbar_rect.left,shop_sbar_rect.top,shop_sbar_rect.right,shop_sbar_rect.bottom, + mainPtr,(HMENU) 3, store_hInstance,NULL); + SetScrollRange(shop_sbar,SB_CTL,0,16,FALSE); + + ShowWindow(mainPtr, nCmdShow); + + plop_fancy_startup(); + + init_screen_locs(); + + FlushEvents(2); + + SetTimer(mainPtr,1,620,NULL); + SetTimer(mainPtr,2,200,NULL); + + file_initialize(); + + if (GetDeviceCaps(main_dc,BITSPIXEL) * GetDeviceCaps(main_dc,PLANES) < 8) + { + MessageBox(mainPtr,"Blades of Exile is designed for 256 colors. The current graphics device is set for less. Exile 3 is playable with less colors, but will look somewhat odd." , + "Not 256 colors!",MB_OK | MB_ICONEXCLAMATION); + MessageBox(mainPtr,"For tips on how to get 256 colors, hit F1 for help, and then select 'Getting 256 Colors' from the table of contents." , + "Not 256 colors!",MB_OK | MB_ICONEXCLAMATION); + } + + menu_activate(0); + cursor_stay(); + showcursor(TRUE); + reset_text_bar(); + + adjust_window_mode(); + + cd_init_dialogs(); + + if (game_run_before == FALSE) { + FCD(986,0); + WritePrivateProfileString("Blades of Exile", "game_run_before", "1", "./blades.ini"); + } + else if (give_intro_hint == TRUE) tip_of_day(); + + } + event_handled = FALSE; + + while(GetMessage(&msg,NULL,0,0)) + { + if (event_handled == FALSE) + { + if (!TranslateAccelerator(mainPtr, accel, &msg)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + } + + delete data_store5; + delete data_store4; + delete data_store3; + delete data_store2; + delete data_store; + + RemoveFontResource("maidword.ttf"); // remove the font from the system font table + + FreeLibrary((HMODULE) boeSoundsDLL); + + return msg.wParam; +} + +long CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + HDC hdc; + PAINTSTRUCT ps; + POINT press; + HMENU menu; + RECT dlg_rect; + RECT wind_rect; + + short handled = 0; + short store_ulx; + short store_uly; + short sbar_pos; + short which_sbar; + short old_setting; + short smin; + short smax; + +// First, handle window size + GetWindowRect(mainPtr,&wind_rect); + + switch (display_mode) { + case 1: store_ulx = 0; + store_uly = 0; + break; + case 2: store_ulx = wind_rect.right - 550 - 21; + store_uly = 0; + break; + case 3: store_ulx = 0; + store_uly = wind_rect.bottom - 422 - 24 - 21; + break; + case 4: store_ulx = wind_rect.right - 550 - 21; + store_uly = wind_rect.bottom - 422 - 24 - 21; + break; + case 5: store_ulx = 0; + store_uly = 0; + break; + default: + store_ulx = ((wind_rect.right - wind_rect.left) - 536) / 2 - 30; + store_uly = ((wind_rect.bottom - wind_rect.top) - 478) / 2 + 8; + break; + } + + store_ulx -= store_ulx % 8; + store_uly -= store_uly % 8; + + if ((store_ulx != ulx) || (store_uly != uly)) + { + ulx = store_ulx; + uly = store_uly; + adjust_window_mode(); + } + + switch (message) { + case WM_KEYDOWN: + if (hwnd != mainPtr) + check_cd_event(hwnd,message,wParam,lParam); + else { + cursor_go(); + All_Done = handle_syskeystroke(wParam,lParam,&handled); + check_game_done(); + } + if (handled == 1) + FlushEvents(0); + + return 0; + + case WM_CHAR: + if (hwnd != mainPtr) + check_cd_event(hwnd,message,wParam,lParam); + else { + cursor_go(); + All_Done = handle_keystroke(wParam,lParam); + check_game_done(); + } + return 0; + + case WM_LBUTTONDOWN: + cursor_stay(); + if (hwnd != mainPtr) check_cd_event(hwnd,message,wParam,lParam); + else { + SetFocus(hwnd); + press = MAKEPOINT(lParam); + if (in_startup_mode == FALSE) + All_Done = handle_action(press, wParam,lParam); + else All_Done = handle_startup_press(press); + change_cursor(press); + check_game_done(); + } + return 0; + break; + + case WM_RBUTTONDOWN: + cursor_stay(); + if (hwnd != mainPtr) + check_cd_event(hwnd,message,wParam,lParam); + else { + SetFocus(hwnd); + press = MAKEPOINT(lParam); + if (in_startup_mode == FALSE) + All_Done = handle_action(press, wParam,-2); + else All_Done = handle_startup_press(press); + change_cursor(press); + check_game_done(); + } + return 0; + break; + + case WM_ACTIVATE: + if (hwnd == mainPtr) + { + WORD fActive = LOWORD(wParam); + + if ((fActive == WA_ACTIVE) ||(fActive == WA_CLICKACTIVE)) + { + window_in_front = TRUE; + GetClientRect(hwnd,&dlg_rect); + InvalidateRect(hwnd,&dlg_rect,FALSE); + } + + if (fActive == WA_INACTIVE) + { + cursor_stay(); + anim_onscreen = FALSE; + window_in_front = FALSE; + } + } + return 0; + + case WM_ERASEBKGND: + if (hwnd != mainPtr) break; + block_erase = FALSE; + return 1; + + case WM_MOUSEMOVE: + if (store_mouse != lParam) cursor_stay(); + store_mouse = lParam; + press = MAKEPOINT(lParam); + if (hwnd == mainPtr) { + change_cursor(press); + if ((overall_mode > 10) && (overall_mode < 20)) + draw_targeting_line(press); + } + return 0; + + case WM_PAINT: + if ((block_erase == TRUE) && (hwnd == mainPtr)) { + block_erase = FALSE; + } + hdc = BeginPaint(hwnd,&ps); + EndPaint(hwnd,&ps); + + if (hwnd != mainPtr) + check_cd_event(hwnd,message,wParam,lParam); + else { + string_added = TRUE; + reset_text_bar(); + if (in_startup_mode == TRUE) draw_startup(0); + else if (first_update == TRUE) + { + first_update = FALSE; + if (overall_mode == 0) redraw_screen(0); + if ((overall_mode > 0) & (overall_mode < 10)) redraw_screen(1); + // 1st update never combat + } + else refresh_screen(overall_mode); + } + return 0; + + case WM_TIMER: + switch(wParam) { + case 1: + if ((in_startup_mode == FALSE) && (anim_onscreen == TRUE) + && (window_in_front == TRUE) && (give_delays == FALSE)) { + anim_ticks++; + initiate_redraw(); + } + break; + case 2: + if ((overall_mode > 10) && (overall_mode < 20)) { + GetCursorPos(&press); + press.x -= wind_rect.left + 3; + press.y -= wind_rect.top + 41; + draw_targeting_line(press); + } + if ((in_startup_mode == TRUE) && (window_in_front == TRUE)) + draw_startup_anim(); + break; + } + return 0; + + case WM_COMMAND: // 1006 is dummy event + // creation events 2000 spend xp 2001 pick graphic 2002 finish up + if (hwnd == mainPtr) { + menu = GetMenu(mainPtr); + All_Done = handle_menu((short) LOWORD(wParam), menu); + check_game_done(); + } + else check_cd_event(hwnd,message,wParam,lParam); + + return 0; + + case WM_VSCROLL: + which_sbar = GetWindowLong((HWND) lParam, GWL_ID); + switch (which_sbar) {// 1 text 2 items 3 shop + case 1: + sbar_pos = GetScrollPos(text_sbar,SB_CTL); + switch (wParam ) { + case SB_PAGEDOWN: sbar_pos += 11; break; + case SB_LINEDOWN: sbar_pos++; break; + case SB_PAGEUP: sbar_pos -= 11; break; + case SB_LINEUP: sbar_pos--; break; + case SB_TOP: sbar_pos = 0; break; + case SB_BOTTOM: sbar_pos = 57; break; + case SB_THUMBPOSITION: + case SB_THUMBTRACK: + sbar_pos = LOWORD(lParam); + break; + } + if (sbar_pos < 0) sbar_pos = 0; + if (sbar_pos > 58) sbar_pos = 58; + SetScrollPos(text_sbar,SB_CTL,sbar_pos,TRUE); + string_added = TRUE; + print_buf(); + break; + case 2: + old_setting = sbar_pos = GetScrollPos(item_sbar,SB_CTL); + GetScrollRange(item_sbar,SB_CTL,(int *) &smin,(int *) &smax); + switch (wParam ) { + case SB_PAGEDOWN: sbar_pos += (stat_window == 7) ? 2 : 8; break; + case SB_LINEDOWN: sbar_pos++; break; + case SB_PAGEUP: sbar_pos -= (stat_window == 7) ? 2 : 8; break; + case SB_LINEUP: sbar_pos--; break; + case SB_TOP: sbar_pos = 0; break; + case SB_BOTTOM: sbar_pos = smax; break; + case SB_THUMBPOSITION: + case SB_THUMBTRACK: + sbar_pos = LOWORD(lParam); + break; + } + if (sbar_pos < 0) sbar_pos = 0; + if (sbar_pos > smax) sbar_pos = smax; + SetScrollPos(item_sbar,SB_CTL,sbar_pos,TRUE); + if (sbar_pos != old_setting) + put_item_screen(stat_window,1); + break; + case 3: + old_setting = sbar_pos = GetScrollPos(shop_sbar,SB_CTL); + GetScrollRange(shop_sbar,SB_CTL,(int *) &smin,(int *) &smax); + switch (wParam ) { + case SB_PAGEDOWN: sbar_pos += 8; break; + case SB_LINEDOWN: sbar_pos++; break; + case SB_PAGEUP: sbar_pos -= 8; break; + case SB_LINEUP: sbar_pos--; break; + case SB_TOP: sbar_pos = 0; break; + case SB_BOTTOM: sbar_pos = smax; break; + case SB_THUMBPOSITION: + case SB_THUMBTRACK: + sbar_pos = LOWORD(lParam); + break; + } + if (sbar_pos < 0) sbar_pos = 0; + if (sbar_pos > smax) sbar_pos = smax; + SetScrollPos(shop_sbar,SB_CTL,sbar_pos,TRUE); + if (sbar_pos != old_setting) + draw_shop_graphics(0,shop_sbar_rect); + break; + } + + SetFocus(mainPtr); + return 0; + + case WM_DESTROY: + case WM_CLOSE: + if (hwnd == mainPtr) + { + lose_graphics(); + PostQuitMessage(0); + } + return 0; + case WM_QUIT: + if (hwnd == mainPtr) + lose_graphics(); + break; + } + +return DefWindowProc(hwnd,message,wParam,lParam); +} + +void check_game_done() +{ + through_sending(); + + if (All_Done == TRUE) + { + lose_graphics(); + showcursor(TRUE); + PostQuitMessage(0); + } +} + +Boolean handle_menu (short item, HMENU) +{ + short choice,i; + POINT x = {1001,0},pass_point; + Boolean to_return = FALSE; + + switch (item) { + case 1: // File Menu + if (in_startup_mode == TRUE) startup_load(); + else do_load(); + break; + case 2: + do_save(0); + break; + case 3: + if (in_startup_mode == TRUE) save_file(1); + else do_save(1); + break; + case 4: + if (in_startup_mode == FALSE) + { + choice = FCD(1091,0); + if (choice == 1) return FALSE; + for (i = 0; i < 6; i++) + adven[i].main_status = MAIN_STATUS_ABSENT; + party_in_memory = FALSE; + reload_startup(); + in_startup_mode = TRUE; + draw_startup(0); + } + start_new_game(); + update_pc_graphics(); + draw_startup(0); + break; + case 6: + pick_preferences(); + break; + case 7: + pick_compatibility(); + break; + case 8: // Quit + if (in_startup_mode == TRUE) { + to_return = All_Done = TRUE; + break; + } + if (overall_mode > 1) { + choice = FCD(1067,0); + if (choice == 1) return All_Done; + } + else { + choice = FCD(1066,0); + if (choice == 3) + break; + if (choice == 1) + save_file(0); + } + to_return = All_Done = TRUE; + break; + + // Options menu + case 21: + choice = char_select_pc(0,0,"New graphic for who?"); + if (choice < 6) + pick_pc_graphic(choice,1,0); + update_pc_graphics(); + initiate_redraw(); + break; + + case 22: + choice = select_pc(0,0); + if (choice < 6) + pick_pc_name(choice,0); + put_pc_screen(); + put_item_screen(stat_window,0); + break; + + + case 23: + if (!(is_town())) { + add_string_to_buf("Add PC: Town mode only."); + print_buf(); + break; + } + for (i = 0; i < NUM_OF_PCS; i++) + if (adven[i].main_status == MAIN_STATUS_ABSENT) + i = 20; + if (i == INVALID_PC) { + ASB("Add PC: You already have 6 PCs."); + print_buf(); + } + if (c_town.town_num == scenario.which_town_start) { + give_help(56,0,0); + create_pc(6,0); + } + else { + add_string_to_buf("Add PC: You can only make new"); + add_string_to_buf(" characters in the town you "); + add_string_to_buf(" started in."); + } + print_buf(); + put_pc_screen(); + put_item_screen(stat_window,0); + break; + + case 24: + if (prime_time() == FALSE) { + ASB("Finish what you're doing first."); + print_buf(); + } + else { + choice = char_select_pc(0,0,"Delete who?"); + if (choice < 6) { + if ((i = FCD(1053,0)) == 2) + adven[choice].kill(0); + } + update_pc_graphics(); + initiate_redraw(); + } + break; + + case 27: + if (overall_mode == MODE_TALKING) { + ASB("Talking notes: Can't read while talking."); + print_buf(); + return to_return; + } + talk_notes(); + break; + case 28: + adventure_notes(); + break; + case 29: + if (in_startup_mode == FALSE) print_party_stats(); + break; + + // Help menu + case 41: FCD(1079,0); + break; + case 42: FCD(1080,0); break; + case 43: FCD(1081,0); break; + case 44: FCD(1072,0); break; // magic barriers + case 46: FCD(1084,0); break; + case 47: FCD(1088,0); break; + + // Library + case 61: display_spells(0,100,0); break; + case 62: display_spells(1,100,0); break; + case 63: display_skills(100,0); break; + case 64: display_help(0,0); break; + case 65: tip_of_day(); break; + case 67: FCD(986,0); break; + + // Actions + case 81: + if (overall_mode != 1) { + ASB("Alchemy: In town mode only."); + print_buf(); + break; + } + pass_point.x = 1000; + pass_point.y = 405; + to_return = handle_action(pass_point,(WPARAM) 0,(LPARAM)-1); + break; + case 82: + to_return = handle_action(x,(WPARAM) 0,(LPARAM)-1); + break; + case 84: + if (prime_time() == FALSE) { + ASB("Finish what you're doing first."); + print_buf(); + } + else { + give_help(62,0,0); + display_map(); + } + SetCursor(sword_curs); + break; + + // Mage is 399 + case 399: give_help(209,0,0); + party.help_received[9] = FALSE; break; + + // Priest is 499 + case 499: give_help(209,0,0); + party.help_received[9] = FALSE; break; + + // Monsters is 599 + case 599: give_help(212,0,0); break; + + case 100: // Index + WinHelp(mainPtr,"Blades of Exile.hlp",HELP_CONTENTS,0L); + break; + + case 200: // About + FCD(1062,0); + break; + + default: + if ((item >= 400) && (item < 500)) { // mage spell + if (prime_time() == FALSE) { + ASB("Finish what you're doing first."); + print_buf(); + } + else handle_menu_spell(item - 400,0); + break; + } + if ((item >= 500) && (item < 600)) { // priest spell + if (prime_time() == FALSE) { + ASB("Finish what you're doing first."); + print_buf(); + } + else handle_menu_spell(item - 500,1); + break; + } + if ((item >= 600) && (item < 700)) { // monster spell + display_monst(item - 600,(creature_data_type *) NULL,1); + break; + } + break; + } + if (in_startup_mode == TRUE) + menu_activate(0); + else menu_activate(1); + return to_return; +} + +void change_cursor(POINT where_curs) +{ + short curs_types[50] = {0,0,126,124,122,122,0,0,0,0, + 0,124,124,124,124,122,0,0,0,0, + 120,120,0,0,0,0,0,0,0,0, + 0,0,0,0,0,129,129,129,0,0, + 0,0,0,0,0,120,0,0,0,0},cursor_needed; + location cursor_direction; + RECT world_screen = {23, 23, 274, 346}; + + where_curs.x -= ulx; + where_curs.y -= uly; + + if (PtInRect(&world_screen,where_curs) == FALSE) + cursor_needed = 120; + else cursor_needed = curs_types[overall_mode]; + + if (in_startup_mode == TRUE) + cursor_needed = 120; + else if (cursor_needed == 0) { + if ((PtInRect(&world_screen,where_curs) == FALSE) || (in_startup_mode == TRUE)) + cursor_needed = 120; + else { + cursor_direction = get_cur_direction(where_curs); + cursor_needed = 100 + (cursor_direction.x) + 10 * ( cursor_direction.y); + if (cursor_needed == 100) + cursor_needed = 120; + } + } + current_cursor = cursor_needed; + + switch (cursor_needed) { + case 120: + SetCursor(sword_curs); + break; + case 121: + case 122: + SetCursor(key_curs); + break; + case 124: + SetCursor(target_curs); + break; + case 126: + SetCursor(talk_curs); + break; + case 129: + SetCursor(look_curs); + break; + default: // an arrow + SetCursor(arrow_curs[cursor_direction.x + 1][cursor_direction.y + 1]); + break; + } +} + +void cursor_go() +{ + if (in_startup_mode == TRUE) return; + + if (cursor_shown == TRUE) + { + cursor_shown = FALSE; + showcursor(FALSE); + } +} + +void cursor_stay() +{ + if ((cursor_shown == FALSE) || (in_startup_mode == TRUE)) + { + cursor_shown = TRUE; + showcursor(TRUE); + } +} diff --git a/Win32/Blades of Exile/BLADES.H b/Win32/Blades of Exile/BLADES.H new file mode 100644 index 00000000..73184db5 --- /dev/null +++ b/Win32/Blades of Exile/BLADES.H @@ -0,0 +1,15 @@ +#ifndef _BLADES_H + #define _BLADES_H + +#include "pc.h" // party_record_type +#include "global.h" // structs + +void check_game_done(); +Boolean handle_menu (short item, HMENU menu); +void load_cursors(); +void change_cursor(POINT where_curs); +void cursor_go(); +void cursor_stay(); +long CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM); + +#endif diff --git a/Win32/Blades of Exile/BLADES.RC b/Win32/Blades of Exile/BLADES.RC new file mode 100644 index 00000000..4e86f6e6 --- /dev/null +++ b/Win32/Blades of Exile/BLADES.RC @@ -0,0 +1,132 @@ +/**************************************************************************** + + +EXILE.RC + +produced by Borland Resource Workshop + + +*****************************************************************************/ + +#define CURSOR_1 1 +#define DIALOG_2 2 +#define DIALOG_1 1 +#define ACCELERATORS_1 1 +#define MENU_2 2 +#define MENU_1 1 +#define Exile 1 + +Exile MENU +{ + POPUP "&File" + { + MENUITEM "&Open Game\tCtrl+O", 1 + MENUITEM "&Save Game\tCtrl+S", 2 + MENUITEM "Save As...", 3 + MENUITEM "&New Game\tCtrl+N", 4 + MENUITEM SEPARATOR + MENUITEM "Preferences", 6 + MENUITEM "Compatibility Options", 7 + MENUITEM SEPARATOR + MENUITEM "&Quit\tCtrl+Q", 8 + } + + POPUP "&Options" + { + MENUITEM "Pick New PC Graphic", 21 + MENUITEM "Pick New PC Name", 22 + MENUITEM "Create New PC", 23 + MENUITEM "Delete PC", 24 + MENUITEM SEPARATOR + MENUITEM "See Talking Notes", 27 + MENUITEM "See Encounter Notes", 28 + MENUITEM "See Overall Party Stats", 29 + } + + POPUP "Help" + { + MENUITEM "Outdoor Commands", 41 + MENUITEM "Town Commands", 42 + MENUITEM "Combat Commands", 43 + MENUITEM "Magic Barrier Help", 44 + MENUITEM SEPARATOR + MENUITEM "Hints, Bugs, and Comments", 46 + MENUITEM "Spell Casting Help", 47 + } + + POPUP "&Library" + { + MENUITEM "Mage Spells", 61 + MENUITEM "Priest Spells", 62 + MENUITEM "Skill Info", 63 + MENUITEM "Alchemy/Poison", 64 + MENUITEM "Tip of the Day", 65 + MENUITEM SEPARATOR + MENUITEM "Show Introductory Dialog", 67 + } + + POPUP "&Actions" + { + MENUITEM "Do Alchemy\tCtrl+A", 81 + MENUITEM "Wait 80 Moves\tCtrl+W", 82 + MENUITEM "Display AutoMap\tCtrl+M", 84 + } + + POPUP "&Monsters" + { + MENUITEM "About this menu", 599 + } + + POPUP "&Cast Mage" + { + MENUITEM "About this menu", 399 + } + + POPUP "&Cast Priest" + { + MENUITEM "About this menu", 499 + } + + POPUP "&Help" + { + MENUITEM "Index\tF1", 100 + MENUITEM SEPARATOR + MENUITEM "About Blades of Exile", 200 + } + +} + +ACCELERATORS_1 ACCELERATORS +{ + "^W", 82, ASCII + "^O", 1, ASCII + "^S", 2, ASCII + "^Q", 8, ASCII + "^M", 84, ASCII + "^A", 81, ASCII +} + +89 CURSOR "resources/ul.cur" +90 CURSOR "resources/u.cur" +110 CURSOR "resources/d.cur" +91 CURSOR "resources/ur.cur" +99 CURSOR "resources/l.cur" +100 CURSOR "resources/c.cur" +101 CURSOR "resources/r.cur" +109 CURSOR "resources/dl.cur" +111 CURSOR "resources/dr.cur" + +120 CURSOR "resources/sword.cur" + + +126 CURSOR "resources/talk.cur" + + +124 CURSOR "resources/target.cur" + + +122 CURSOR "resources/key.cur" + +129 CURSOR "resources/look.cur" + +10 ICON "resources/bladexil.ico" diff --git a/Win32/Blades of Exile/Blades of Exile.dev b/Win32/Blades of Exile/Blades of Exile.dev new file mode 100644 index 00000000..9cbaf97b --- /dev/null +++ b/Win32/Blades of Exile/Blades of Exile.dev @@ -0,0 +1,691 @@ +[Project] +FileName=Blades of Exile.dev +Name=Blades of Exile Win32 +UnitCount=56 +Type=0 +Ver=1 +IsCpp=1 +Folders= +CommandLine= +CompilerSettings=0000000000001000000000 +PchHead=-1 +PchSource=-1 +ProfilesCount=1 +ProfileIndex=0 +ObjFiles= +Includes= +Libs= +PrivateResource=Blades_of_Exile_private.rc +ResourceIncludes= +MakeIncludes= +Compiler= +CppCompiler=-Wall_@@_ +Linker=-lwinmm_@@_ +Icon= +ExeOutput= +ObjectOutput= +OverrideOutput=0 +OverrideOutputName=Blades of Exile.exe +HostApplication= +UseCustomMakefile=0 +CustomMakefile= +IncludeVersionInfo=0 +SupportXPThemes=0 +CompilerSet=0 + +[Unit1] +FileName=ACTIONS.CPP +CompileCpp=1 +Folder=Blades of Exile +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit2] +FileName=BLADES.CPP +CompileCpp=1 +Folder=Blades of Exile +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit3] +FileName=COMBAT.CPP +CompileCpp=1 +Folder=Blades of Exile +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit4] +FileName=DLGUTILS.CPP +CompileCpp=1 +Folder=Blades of Exile +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit5] +FileName=DLOGTOOL.CPP +CompileCpp=1 +Folder=Blades of Exile +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit6] +FileName=EXLSOUND.CPP +CompileCpp=1 +Folder=Blades of Exile +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit7] +FileName=FIELDS.CPP +CompileCpp=1 +Folder=Blades of Exile +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit8] +FileName=FILEIO.CPP +CompileCpp=1 +Folder=Blades of Exile +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit9] +FileName=GLOBAL.CPP +CompileCpp=1 +Folder=Blades of Exile +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit10] +FileName=GRAPHICS.CPP +CompileCpp=1 +Folder=Blades of Exile +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit11] +FileName=GRAPHUTL.CPP +CompileCpp=1 +Folder=Blades of Exile +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit12] +FileName=GUTILS.CPP +CompileCpp=1 +Folder=Blades of Exile +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit13] +FileName=INFODLGS.CPP +CompileCpp=1 +Folder=Blades of Exile +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit14] +FileName=ITEMDATA.CPP +CompileCpp=1 +Folder=Blades of Exile +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit15] +FileName=ITEMS.CPP +CompileCpp=1 +Folder=Blades of Exile +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit16] +FileName=LOCUTILS.CPP +CompileCpp=1 +Folder=Blades of Exile +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit17] +FileName=MONSTER.CPP +CompileCpp=1 +Folder=Blades of Exile +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit18] +FileName=NEWGRAPH.CPP +CompileCpp=1 +Folder=Blades of Exile +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit19] +FileName=PARTY.CPP +CompileCpp=1 +Folder=Blades of Exile +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit20] +FileName=SPECIALS.CPP +CompileCpp=1 +Folder=Blades of Exile +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit22] +FileName=TOWN.CPP +CompileCpp=1 +Folder=Blades of Exile +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit24] +FileName=GAMEDLOG.RC +CompileCpp=1 +Folder=Blades of Exile +Compile=1 +Link=0 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[VersionInfo] +Major=0 +Minor=1 +Release=1 +Build=1 +LanguageID=1033 +CharsetID=1252 +CompanyName= +FileVersion= +FileDescription=Developed using the Dev-C++ IDE +InternalName= +LegalCopyright= +LegalTrademarks= +OriginalFilename= +ProductName= +ProductVersion= +AutoIncBuildNrOnRebuild=0 +AutoIncBuildNrOnCompile=0 +AutoIncBuildNr=0 + +[Unit26] +FileName=ACTIONS.H +Folder=Blades of Exile +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= +CompileCpp=1 + +[Unit25] +FileName=GAMESTR.RC +Folder=Blades of Exile +Compile=1 +Link=0 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit27] +FileName=COMBAT.H +Folder=Blades of Exile +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= +CompileCpp=1 + +[Unit28] +FileName=DLGUTILS.H +CompileCpp=1 +Folder=Blades of Exile +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit29] +FileName=DLOGTOOL.H +CompileCpp=1 +Folder=Blades of Exile +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit30] +FileName=EXLSOUND.H +CompileCpp=1 +Folder=Blades of Exile +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit31] +FileName=FIELDS.H +CompileCpp=1 +Folder=Blades of Exile +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit32] +FileName=FILEIO.H +CompileCpp=1 +Folder=Blades of Exile +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit33] +FileName=GLOBAL.H +CompileCpp=1 +Folder=Blades of Exile +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit34] +FileName=GRAPHICS.H +CompileCpp=1 +Folder=Blades of Exile +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit35] +FileName=GRAPHUTL.H +CompileCpp=1 +Folder=Blades of Exile +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit36] +FileName=GUTILS.H +CompileCpp=1 +Folder=Blades of Exile +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit37] +FileName=INFODLGS.H +CompileCpp=1 +Folder=Blades of Exile +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit38] +FileName=ITEMDATA.H +CompileCpp=1 +Folder=Blades of Exile +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit39] +FileName=ITEMS.H +CompileCpp=1 +Folder=Blades of Exile +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit40] +FileName=LOCUTILS.H +CompileCpp=1 +Folder=Blades of Exile +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit41] +FileName=MONSTER.H +CompileCpp=1 +Folder=Blades of Exile +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit42] +FileName=NEWGRAPH.H +CompileCpp=1 +Folder=Blades of Exile +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit45] +FileName=TEXT.H +CompileCpp=1 +Folder=Blades of Exile +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit46] +FileName=TOWN.H +CompileCpp=1 +Folder=Blades of Exile +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit50] +FileName=ITEM.H +CompileCpp=1 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit51] +FileName=LOCATION.H +CompileCpp=1 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit52] +FileName=ITEM.CPP +CompileCpp=1 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit55] +FileName=GLOBVAR.H +CompileCpp=1 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit56] +FileName=CONSTS.H +CompileCpp=1 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit43] +FileName=PARTY.H +CompileCpp=1 +Folder=Blades of Exile +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit44] +FileName=SPECIALS.H +CompileCpp=1 +Folder=Blades of Exile +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit49] +FileName=PC.CPP +CompileCpp=1 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Profile1] +ProfileName=Default Profile +Type=0 +ObjFiles= +Includes= +Libs= +PrivateResource=D:\Blades of Exile Source Release 1\Windows Code Release 2\Default Profile\Blades_of_Exile_private.rc +ResourceIncludes= +MakeIncludes= +Compiler= +CppCompiler=_@@_ +Linker=C:/Dev-Cpp/lib/libwinmm.a_@@_C:/Dev-Cpp/lib/libgdi32.a_@@_C:/Dev-Cpp/lib/libcomdlg32.a_@@_ +PreprocDefines= +CompilerSettings=0000000000000000000000 +Icon= +ExeOutput=Default Profile +ObjectOutput=Default Profile +OverrideOutput=0 +OverrideOutputName=Blades of Exile.exe +HostApplication= +CommandLine= +UseCustomMakefile=0 +CustomMakefile= +IncludeVersionInfo=0 +SupportXPThemes=0 +CompilerSet=0 +compilerType=0 + +[Unit53] +FileName=LOCATION.CPP +CompileCpp=1 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit54] +FileName=GLOBVAR.CPP +CompileCpp=1 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit57] +FileName=CONSTS.H +CompileCpp=1 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit58] +FileName=GLOBVAR.H +CompileCpp=1 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit59] +FileName=CONSTS.H +CompileCpp=1 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit60] +FileName=GLOBVAR.H +CompileCpp=1 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit61] +FileName=CONSTS.H +CompileCpp=1 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit21] +FileName=TEXT.CPP +CompileCpp=1 +Folder=Blades of Exile +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit47] +FileName=BLADES.H +CompileCpp=1 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit23] +FileName=BLADES.RC +Folder=Blades of Exile +Compile=1 +Link=0 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit48] +FileName=PC.H +CompileCpp=1 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + diff --git a/Win32/Blades of Exile/Blades_of_Exile_private.h b/Win32/Blades of Exile/Blades_of_Exile_private.h new file mode 100644 index 00000000..34f06438 --- /dev/null +++ b/Win32/Blades of Exile/Blades_of_Exile_private.h @@ -0,0 +1,23 @@ +/* THIS FILE WILL BE OVERWRITTEN BY DEV-C++ */ +/* DO NOT EDIT ! */ + +#ifndef BLADES_OF_EXILE_PRIVATE_H +#define BLADES_OF_EXILE_PRIVATE_H + +/* VERSION DEFINITIONS */ +#define VER_STRING "0.1.1.1" +#define VER_MAJOR 0 +#define VER_MINOR 1 +#define VER_RELEASE 1 +#define VER_BUILD 1 +#define COMPANY_NAME "" +#define FILE_VERSION "" +#define FILE_DESCRIPTION "Developed using the Dev-C++ IDE" +#define INTERNAL_NAME "" +#define LEGAL_COPYRIGHT "" +#define LEGAL_TRADEMARKS "" +#define ORIGINAL_FILENAME "" +#define PRODUCT_NAME "" +#define PRODUCT_VERSION "" + +#endif /*BLADES_OF_EXILE_PRIVATE_H*/ diff --git a/Win32/Blades of Exile/COMBAT.CPP b/Win32/Blades of Exile/COMBAT.CPP new file mode 100644 index 00000000..450341dc --- /dev/null +++ b/Win32/Blades of Exile/COMBAT.CPP @@ -0,0 +1,4406 @@ +#include +#include "stdio.h" +#include "global.h" +#include "monster.h" +#include "graphics.h" +#include "locutils.h" +#include "newgraph.h" +#include "infodlgs.h" +#include "fields.h" +#include "text.h" +#include "items.h" +#include "party.h" +#include "combat.h" +#include "exlsound.h" +#include "town.h" +#include "specials.h" +#include "gutils.h" + +#include "globvar.h" + +void start_outdoor_combat(outdoor_creature_type encounter,unsigned char in_which_terrain,short num_walls) +{ + short i,j,how_many,num_tries = 0; + short low[10] = {15,7,4,3,2,1,1,7,2,1}; + short high[10] = {30,10,6,5,3,2,1,10,4,1}; + RECT town_rect = {0,0,47,47}; + short nums[10]; + + for (i = 0; i < 7; i++) + nums[i] = get_ran(1,low[i],high[i]); + for (i = 0; i < 3; i++) + nums[i + 7] = get_ran(1,low[i + 7],high[i + 7]); + notify_out_combat_began(encounter.what_monst,nums); + print_buf(); + play_sound(23); + + which_combat_type = 0; + town_type = 1; + overall_mode = 10; + + // Basically, in outdoor combat, we create kind of a 48x48 town for + // the combat to take place in + for (i = 0; i < 48; i++) + for (j = 0; j < 48; j++) { + c_town.explored[i][j] = 0; + misc_i[i][j] = 0; + sfx[i][j] = 0; + } + c_town.town.in_town_rect = town_rect; + + create_out_combat_terrain((short) in_which_terrain,num_walls);//// + + for (i = 0; i < T_M; i++) { + c_town.monst.dudes[i].number = 0; + c_town.monst.dudes[i].active = 0; + } + for (i = 0; i < 7; i++) { + how_many = nums[i]; + if (encounter.what_monst.monst[i] != 0) + for (j = 0; j < how_many; j++) + set_up_monst(0,encounter.what_monst.monst[i]); + } + for (i = 0; i < 3; i++) { + how_many = nums[i + 7]; + if (encounter.what_monst.friendly[i] != 0) + for (j = 0; j < how_many; j++) + set_up_monst(1,encounter.what_monst.friendly[i]); + } + + // place PCs + pc_pos[0] = out_start_loc; + update_explored(pc_pos[0]); + if (get_blockage(combat_terrain[pc_pos[0].x][pc_pos[0].y]) > 0) + combat_terrain[pc_pos[0].x][pc_pos[0].y] = combat_terrain[0][0]; + for (i = 1; i < 6; i++) { + pc_pos[i] = pc_pos[0]; + pc_pos[i].x = pc_pos[i].x + hor_vert_place[i].x; + pc_pos[i].y = pc_pos[i].y + hor_vert_place[i].y; + if (get_blockage(combat_terrain[pc_pos[i].x][pc_pos[i].y]) > 0) + combat_terrain[pc_pos[i].x][pc_pos[i].y] = combat_terrain[0][0]; + update_explored(pc_pos[i]); + + for (j = 0; j < 6; j++) + if (j != 2) + adven[i].status[j] = 0; + } + + // place monsters, w. friendly monsts landing near PCs + for (i = 0; i < T_M; i++) + if (c_town.monst.dudes[i].active > 0) { + monst_target[i] = 6; + + c_town.monst.dudes[i].m_loc.x = get_ran(1,15,25); + c_town.monst.dudes[i].m_loc.y = get_ran(1,14,18); + if (c_town.monst.dudes[i].attitude == 2) + c_town.monst.dudes[i].m_loc.y += 9; + else if ((c_town.monst.dudes[i].m_d.mu > 0) || (c_town.monst.dudes[i].m_d.cl > 0)) + c_town.monst.dudes[i].m_loc.y = c_town.monst.dudes[i].m_loc.y - 4;//max(12,c_town.monst.dudes[i].m_loc.y - 4); + num_tries = 0; + while (((monst_can_be_there(c_town.monst.dudes[i].m_loc,i) == FALSE) || + (combat_terrain[c_town.monst.dudes[i].m_loc.x][c_town.monst.dudes[i].m_loc.y] == 180) || + (pc_there(c_town.monst.dudes[i].m_loc) < 6)) && + (num_tries++ < 50)) { + c_town.monst.dudes[i].m_loc.x = get_ran(1,15,25); + c_town.monst.dudes[i].m_loc.y = get_ran(1,14,18); + if (c_town.monst.dudes[i].attitude == 2) + c_town.monst.dudes[i].m_loc.y += 9; + else if ((c_town.monst.dudes[i].m_d.mu > 0) || (c_town.monst.dudes[i].m_d.cl > 0)) + c_town.monst.dudes[i].m_loc.y = c_town.monst.dudes[i].m_loc.y - 4;//max(12,c_town.monst.dudes[i].m_loc.y - 4); + } + if (get_blockage(combat_terrain[c_town.monst.dudes[i].m_loc.x][c_town.monst.dudes[i].m_loc.y]) > 0) + combat_terrain[c_town.monst.dudes[i].m_loc.x][c_town.monst.dudes[i].m_loc.y] = combat_terrain[0][0]; + } + + + combat_active_pc = 6; + spell_caster = 6; missile_firer = 6; + for (i = 0; i < T_M; i++) + monst_target[i] = 6; + + for (i = 0; i < 6; i++) { + pc_parry[i] = 0; + last_attacked[i] = T_M + 10; + } + + for (i = 0; i < NUM_TOWN_ITEMS; i++) + t_i.items[i].variety = 0; + store_current_pc = current_pc; + current_pc = 0; + set_pc_moves(); + pick_next_pc(); + center = pc_pos[current_pc]; + load_area_graphics(); + draw_buttons(0); + put_pc_screen(); + set_stat_window(current_pc); + + adjust_spell_menus(); + + give_help(48,49,0); +} + +Boolean pc_combat_move(location destination) +{ + short dir,monst_hit,s1,s2,i,monst_exist,switch_pc; + Boolean keep_going = TRUE,forced = FALSE,check_f; + location monst_loc,store_loc; + short spec_num; + + if (monst_there(destination) > T_M) + keep_going = check_special_terrain(destination,2,current_pc,&spec_num,&check_f); + if (check_f == TRUE) + forced = TRUE; + + if (spec_num == 50) + forced = TRUE; + + if (keep_going == TRUE) { + + dir = set_direction(pc_pos[current_pc], destination); + + if ((loc_off_act_area(destination) == TRUE) && (which_combat_type == 1)) { + add_string_to_buf("Move: Can't leave town during combat."); + print_buf(); + return TRUE; + } + else if ((combat_terrain[destination.x][destination.y] == 90) && (which_combat_type == 0)) { + if (get_ran(1,1,10) < 3) { + adven[current_pc].main_status = MAIN_STATUS_FLED; + if (combat_active_pc == current_pc) + combat_active_pc = 6; + sprintf ((char *) create_line, "Moved: Fled. "); + pc_moves[current_pc] = 0; + } + else { + take_ap(1); + sprintf ((char *) create_line, "Moved: Couldn't flee. "); + } + add_string_to_buf((char *) create_line); + return TRUE; + } + else if ((monst_hit = monst_there(destination)) <= T_M) { + s1 = c_town.monst.dudes[monst_hit].attitude; + s2 = (s1 % 2 == 1) ? 2 : fancy_choice_dialog(1045,0); + if ((s2 == 2) && (s1 % 2 != 1)) + make_town_hostile(); + if (s2 == 2) { + last_attacked[current_pc] = monst_hit; + pc_attack(current_pc,monst_hit); + return TRUE; + } + } + else if ((switch_pc = pc_there(destination)) < 6) { + if (pc_moves[switch_pc] == 0) { + add_string_to_buf("Move: Can't switch places."); + add_string_to_buf(" (other PC has no APs) "); + return FALSE; + } + else pc_moves[switch_pc]--; + add_string_to_buf("Move: Switch places."); + store_loc = pc_pos[current_pc]; + pc_pos[current_pc] = destination; + pc_pos[switch_pc] = store_loc; + adven[current_pc].direction = dir; + take_ap(1); + check_special_terrain(store_loc,2,switch_pc,&spec_num,&check_f); + move_sound(combat_terrain[destination.x][destination.y],pc_moves[current_pc]); + return TRUE; + } + else if ((forced == TRUE) + || ((impassable(combat_terrain[destination.x][destination.y]) == FALSE) && (pc_there(destination) == 6))) { + + // monsters get back-shots + for (i = 0; i < T_M; i++) { + monst_loc = c_town.monst.dudes[i].m_loc; + monst_exist = c_town.monst.dudes[i].active; + + s1 = current_pc; + if ((monst_exist > 0) && (monst_adjacent(pc_pos[current_pc],i) == TRUE) + && (monst_adjacent(destination,i) == FALSE) && + (c_town.monst.dudes[i].attitude % 2 == 1) && + (c_town.monst.dudes[i].m_d.status[11] <= 0) && + (c_town.monst.dudes[i].m_d.status[12] <= 0)) { + combat_posing_monster = current_working_monster = 100 + i; + monster_attack_pc(i,current_pc); + combat_posing_monster = current_working_monster = -1; + draw_terrain(0); + } + if (s1 != current_pc) + return FALSE; + } + + // move if still alive + if (adven[current_pc].isAlive()) { + pc_dir[current_pc] = set_direction(pc_pos[current_pc],destination); + pc_pos[current_pc] = destination; + adven[current_pc].direction = dir; + take_ap(1); + //sprintf ((char *) create_line, "Moved: %s ",d_string[dir]); + //add_string_to_buf((char *) create_line); + move_sound(combat_terrain[destination.x][destination.y],pc_moves[current_pc]); + + } + else return FALSE; + return TRUE; + } + else { + sprintf ((char *) create_line, "Blocked: %s ",d_string[dir]); + add_string_to_buf((char *) create_line); + return FALSE; + } + } + return FALSE; +} + +void char_parry() +{ + pc_parry[current_pc] = (pc_moves[current_pc] / 4) * + (2 + adven[current_pc].statAdj(1) + adven[current_pc].skills[8]); + pc_moves[current_pc] = 0; +} + +void char_stand_ready() +{ + pc_parry[current_pc] = 100; + pc_moves[current_pc] = 0; +} + +void pc_attack(short who_att,short target) +{ + short r1,r2,what_skill1 = 1, what_skill2 = 1, weap1 = 24, weap2 = 24,i,store_hp,skill_item; + creature_data_type *which_m; + short hit_adj, dam_adj, spec_dam = 0,poison_amt; + + // slice out bad attacks + if (adven[who_att].isAlive() == false) + return; + if ((adven[who_att].status[11] > 0) || (adven[who_att].status[12] > 0)) + return; + + last_attacked[who_att] = target; + which_m = &c_town.monst.dudes[target]; + + for (i = 0; i < 24; i++) + if (((adven[who_att].items[i].variety == 1) || (adven[who_att].items[i].variety == 2)) && + (adven[who_att].equip[i] == TRUE)) + if (weap1 == 24) + weap1 = i; + else weap2 = i; + + hit_adj = (-5 * minmax(-8,8,(int)adven[who_att].status[1])) + 5 * minmax(-8,8,(int)which_m->m_d.status[1]) + - adven[who_att].statAdj(1) * 5 + (get_encumberance(who_att)) * 5; + + dam_adj = minmax(-8,8,(int)adven[who_att].status[1]) - minmax(-8,8,(int)which_m->m_d.status[1]) + + adven[who_att].statAdj(0); + + if ((which_m->m_d.status[11] > 0) || (which_m->m_d.status[12] > 0)) { + hit_adj -= 80; + dam_adj += 10; + } + + + if ((skill_item = text_pc_has_abil_equip(who_att,37)) < 24) { + hit_adj += 5 * (adven[who_att].items[skill_item].item_level / 2 + 1); + dam_adj += adven[who_att].items[skill_item].item_level / 2; + } + if ((skill_item = text_pc_has_abil_equip(who_att,43)) < 24) { + dam_adj += adven[who_att].items[skill_item].item_level; + hit_adj += adven[who_att].items[skill_item].item_level * 2; + } + + void_sanctuary(who_att); + + store_hp = c_town.monst.dudes[target].m_d.health; + + combat_posing_monster = current_working_monster = who_att; + + if (weap1 == 24) { + + sprintf ((char *) create_line, "%s punches. ",(char *) adven[who_att].name);//,hit_adj, dam_adj); + add_string_to_buf((char *) create_line); + + r1 = get_ran(1,0,100) + hit_adj - 20; + r1 += 5 * (adven[current_pc].status[6] / 3); + r2 = get_ran(1,1,4) + dam_adj; + + if (r1 <= hit_chance[adven[who_att].skills[what_skill1]]) { + damage_monst(target, who_att, r2, 0,400); + } + else { + draw_terrain(2); + sprintf ((char *) create_line, "%s misses. ",(char *) adven[who_att].name); + add_string_to_buf((char *) create_line); + play_sound(2); + } + } + + // Don't forget awkward and stat adj. + if (weap1 < 24) { + what_skill1 = 2 + adven[who_att].items[weap1].type; + + // safety valve + if (what_skill1 == 2) + what_skill1 = 3; + + sprintf ((char *) create_line, "%s swings. ",(char *) adven[who_att].name);//,hit_adj, dam_adj); + add_string_to_buf((char *) create_line); + + r1 = get_ran(1,0,100) - 5 + hit_adj + - 5 * adven[who_att].items[weap1].bonus; + r1 += 5 * (adven[current_pc].status[6] / 3); + + if ((weap2 < 24) && (adven[who_att].traits[TRAIT_AMBIDEXTROUS] == FALSE)) + r1 += 25; + + // race adj. + if ((adven[who_att].race == RACE_SLITH) && (adven[who_att].items[weap1].type == 3)) + r1 -= 10; + + r2 = get_ran(1,1,adven[who_att].items[weap1].item_level) + dam_adj + 2 + adven[who_att].items[weap1].bonus; + if (adven[who_att].items[weap1].ability == 12) + r2 = (r2 * (10 - adven[who_att].items[weap1].ability_strength)) / 10; + + if (r1 <= hit_chance[adven[who_att].skills[what_skill1]]) { + spec_dam = calc_spec_dam(adven[who_att].items[weap1].ability, + adven[who_att].items[weap1].ability_strength,which_m); + + // assassinate + r1 = get_ran(1,0,100); + if ((adven[who_att].level >= which_m->m_d.level - 1) + && (adven[who_att].skills[16] >= which_m->m_d.level / 2) + && (which_m->m_d.spec_skill != 12)) // Can't assassinate splitters + if (r1 < hit_chance[max(adven[who_att].skills[16] - which_m->m_d.level,0)]) { + add_string_to_buf(" You assassinate. "); + spec_dam += r2; + } + + switch (what_skill1) { + case 3: + if (adven[who_att].items[weap1].item_level < 8) + damage_monst(target, who_att, r2, spec_dam, 100); + else damage_monst(target, who_att, r2, spec_dam, 200); + break; + case 4: + damage_monst(target, who_att, r2, spec_dam, 400); + break; + case 5: + damage_monst(target, who_att, r2, spec_dam, 300); + break; + } + // poison + if ((adven[who_att].status[0] > 0) && (adven[who_att].weap_poisoned == weap1)) { + poison_amt = adven[who_att].status[0]; + if (adven[who_att].hasAbilEquip(51) < 24) + poison_amt += 2; + which_m->poison(poison_amt); + move_to_zero(adven[who_att].status[0]); + } + if ((adven[who_att].items[weap1].ability == 14) && (get_ran(1,0,1) == 1)) { + add_string_to_buf(" Blade drips venom. "); + which_m->poison(adven[who_att].items[weap1].ability_strength / 2); + } + if ((adven[who_att].items[weap1].ability == 9) && (get_ran(1,0,1) == 1)) { + add_string_to_buf(" Blade drips acid. "); + which_m->acid(adven[who_att].items[weap1].ability_strength / 2); + } + if ((adven[who_att].items[weap1].ability == 10) && (get_ran(1,0,1) == 1)) { + add_string_to_buf(" Blade drains life. "); + adven[who_att].heal(adven[who_att].items[weap1].ability_strength / 2); + } + } + else { + draw_terrain(2); + sprintf ((char *) create_line, " %s misses. ",(char *) adven[who_att].name); + add_string_to_buf((char *) create_line); + if (what_skill1 == 5) + play_sound(19); + else play_sound(2); + } + } + if ((weap2 < 24) && (which_m->active > 0)) { + what_skill2 = 2 + adven[who_att].items[weap2].type; + + // safety valve + if (what_skill2 == 2) + what_skill2 = 3; + + + sprintf ((char *) create_line, "%s swings. ",(char *) adven[who_att].name);//,hit_adj, dam_adj); + add_string_to_buf((char *) create_line); + r1 = get_ran(1,0,100) + hit_adj - 5 * adven[who_att].items[weap2].bonus; + + // Ambidextrous? + if (adven[who_att].traits[TRAIT_AMBIDEXTROUS] == FALSE) + r1 += 25; + + r1 += 5 * (adven[current_pc].status[6] / 3); + r2 = get_ran(1,1,adven[who_att].items[weap2].item_level) + dam_adj - 1 + adven[who_att].items[weap2].bonus; + if (adven[who_att].items[weap2].ability == 12) + r2 = (r2 * (10 - adven[who_att].items[weap2].ability_strength)) / 10; + + if (r1 <= hit_chance[adven[who_att].skills[what_skill2]]) { + spec_dam = calc_spec_dam(adven[who_att].items[weap2].ability, + adven[who_att].items[weap2].ability_strength,which_m); + switch (what_skill2) { + case 3: + if (adven[who_att].items[weap1].item_level < 8) + damage_monst(target, who_att, r2, spec_dam, 100); + else damage_monst(target, who_att, r2, spec_dam, 200); + break; + case 4: + damage_monst(target, who_att, r2, spec_dam, 400); + break; + case 5: + damage_monst(target, who_att, r2, spec_dam, 300); + break; + } + + if ((adven[who_att].items[weap2].ability == 14) && (get_ran(1,0,1) == 1)) { + add_string_to_buf(" Blade drips venom. "); + which_m->poison(adven[who_att].items[weap2].ability_strength / 2); + } + if ((adven[who_att].items[weap2].ability == 9) && (get_ran(1,0,1) == 1)) { + add_string_to_buf(" Blade drips acid. "); + which_m->acid(adven[who_att].items[weap2].ability_strength / 2); + } + if ((adven[who_att].items[weap2].ability == 10) && (get_ran(1,0,1) == 1)) { + add_string_to_buf(" Blade drains life. "); + adven[who_att].heal(adven[who_att].items[weap2].ability_strength / 2); + } + + } + else { + draw_terrain(2); + sprintf ((char *) create_line, "%s misses. ",(char *) adven[who_att].name); + add_string_to_buf((char *) create_line); + if (what_skill2 == 5) + play_sound(19); + else play_sound(2); + } + } + move_to_zero(adven[who_att].status[0]); + take_ap(4); + + if (((c_town.monst.dudes[target].m_d.status[10] > 0) || (c_town.monst.dudes[target].m_d.spec_skill == 22)) + && (store_hp - c_town.monst.dudes[target].m_d.health > 0)) { + add_string_to_buf(" Shares damage! "); + adven[who_att].damage(store_hp - c_town.monst.dudes[target].m_d.health, 3,-1); + } + combat_posing_monster = current_working_monster = -1; + } + + +short calc_spec_dam(short abil,short abil_str,creature_data_type *monst) //// +{ + short store = 0; + + switch (abil) { + case 1: case 171: + store += get_ran(abil_str,1,6); + break; + case 2: + if (monst->m_d.m_type == 7) + store += 8 * abil_str; + break; + case 3: + if (monst->m_d.m_type == 8) + store += 6 * abil_str; + break; + case 4: + if (monst->m_d.m_type == 1) + store += 5 * abil_str; + break; + case 5: + if (monst->m_d.m_type == 9) + store += 8 * abil_str; + break; + case 6: + if (monst->m_d.m_type == 4) + store += 4 * abil_str; + break; + case 7: + if (monst->m_d.m_type == 5) + store += 4 * abil_str; + break; + case 8: + if (monst->m_d.m_type == 12) + store += 7 * abil_str; + break; + case 13: + monst->scare(abil_str * 10); + break; + case 173: + monst->acid(abil_str); + break; + case 174: + if (monst->m_d.m_type == 8) + store += 20 + 6 * abil_str; + break; + case 175: + if (monst->m_d.m_type == 7) + store += 25 + 8 * abil_str; + break; + } + return store; +} + +void place_target(location target) +{ + short i; + + if (num_targets_left > 0) { + if (loc_off_act_area(target) == TRUE) { + add_string_to_buf(" Space not in town. "); + return; + } + if (can_see(pc_pos[current_pc],target,0) > 4) { + add_string_to_buf(" Can't see target. "); + return; + } + if (dist(pc_pos[current_pc],target) > ((spell_being_cast >= 100) ? priest_range[spell_being_cast - 100] : mage_range[spell_being_cast])) { + add_string_to_buf(" Target out of range."); + return; + } + if ((get_obscurity(target.x,target.y) == 5) && (spell_being_cast != 41)) { + add_string_to_buf(" Target space obstructed. "); + return; + } + if (is_antimagic(target.x,target.y)) { + add_string_to_buf(" Target in antimagic field."); + return; + } + for (i = 0; i < 8; i++) { + if (same_point(spell_targets[i],target) == TRUE) { + add_string_to_buf(" Target removed."); + num_targets_left++; + spell_targets[i].x = 120; + play_sound(-1); + return; + } + } + for (i = 0; i < 8; i++) + if (spell_targets[i].x == 120) { + add_string_to_buf(" Target added."); + spell_targets[i] = target; + num_targets_left--; + play_sound(0); + i = 8; + } + } + + if (num_targets_left == 0) { + do_combat_cast(spell_targets[0]); + overall_mode = 10; + } +} + +// Special spells: +// 62 - Carrunos +// 63 - Summon Rat +// 64 - Ice Wall Balls +// 65 - Goo Bomb +// 66 - Foul vapors +// 67 - SLeep cloud +// 68 - Acid spray +// 69 - Paralyze beam +// 70 - mass sleep +void do_combat_cast(location target) +{ + short adjust,r1,r2,targ_num,s_num,level,bonus = 1,i,item,store_sound = 0; + creature_data_type *cur_monst; + Boolean freebie = FALSE,ap_taken = FALSE,cost_taken = FALSE; + short num_targets = 1,store_m_type = 2; + short spray_type_array[15] = {1,1,1,4,4,5,5,5,6,6,7,7,8,8,9}; + unsigned short summon; + + location ashes_loc; + + // to wedge in animations, have to kludge like crazy + short boom_dam[8] = {0,0,0,0,0,0,0,0}; + short boom_type[8] = {0,0,0,0,0,0,0,0}; + location boom_targ[8]; + + if (spell_being_cast >= 1000) { + spell_being_cast -= 1000; + freebie = TRUE; + level = minmax(2,20, (int) store_item_spell_level); + } + else { + level = 1 + adven[current_pc].level / 2; + bonus = adven[current_pc].statAdj(2); + } + force_wall_position = 10; + s_num = spell_being_cast % 100; + + void_sanctuary(current_pc); + if (overall_mode == 11) spell_targets[0] = target; + else num_targets = 8; + + spell_caster = current_pc; + + // assign monster summoned, if summoning + if (spell_being_cast == 16) summon = get_summon_monster(1); + if (spell_being_cast == 26) summon = get_summon_monster(1); + if (spell_being_cast == 43) summon = get_summon_monster(2); + if (spell_being_cast == 58) summon = get_summon_monster(3); + + combat_posing_monster = current_working_monster = current_pc; + + for (i = 0; i < num_targets; i++) + if (spell_targets[i].x != 120) { + target = spell_targets[i]; + spell_targets[i].x = 120; // nullify target as it is used + + if ((cost_taken == FALSE) && (freebie == FALSE) && (s_num != 52) && (s_num != 35)) { + adven[current_pc].cur_sp -= s_cost[spell_being_cast / 100][s_num]; + cost_taken = TRUE; + } + if ((cost_taken == FALSE) && (freebie == FALSE) && (s_num == 35)) { + adven[current_pc].cur_sp -= store_sum_monst_cost; + cost_taken = TRUE; + } + + if ((adjust = can_see(pc_pos[current_pc],target,0)) > 4) { + add_string_to_buf(" Can't see target. "); + } + else if (loc_off_act_area(target) == TRUE) { + add_string_to_buf(" Space not in town. "); + } + else if (dist(pc_pos[current_pc],target) > ((spell_being_cast >= 100) ? priest_range[spell_being_cast - 100] : mage_range[spell_being_cast])) + add_string_to_buf(" Target out of range."); + else if ((get_obscurity(target.x,target.y) == 5) && (spell_being_cast != 41)) + add_string_to_buf(" Target space obstructed. "); + else if (is_antimagic(target.x,target.y)) + add_string_to_buf(" Target in antimagic field."); + else { + if (ap_taken == FALSE) { + if (freebie == FALSE) + take_ap(5); + ap_taken = TRUE; + draw_terrain(2); + } + boom_targ[i] = target; + switch (spell_being_cast) { + + case 8: case 28: case 65: // web spells + place_spell_pattern(current_pat,target,1,FALSE,current_pc); + break; + case 5: case 17: // fire wall spells + place_spell_pattern(current_pat,target,5,FALSE,current_pc); + break; + case 15: case 66: // stink cloud + place_spell_pattern(current_pat,target,7,FALSE,current_pc); + break; + case 25: case 44: case 126: // force walls + place_spell_pattern(current_pat,target,4,FALSE,current_pc); + break; + case 37: case 64: // ice walls + place_spell_pattern(current_pat,target,8,FALSE,current_pc); + break; + case 51: // antimagic + place_spell_pattern(current_pat,target,6,FALSE,current_pc); + break; + case 19: case 67: // sleep clouds + place_spell_pattern(current_pat,target,12,FALSE,current_pc); + break; + case 60: + make_quickfire(target.x,target.y); + break; + case 45: // spray fields + r1 = get_ran(1,0,14); + place_spell_pattern(current_pat,target,spray_type_array[r1],FALSE,current_pc); + break; + case 159: // wall of blades + place_spell_pattern(current_pat,target,9,FALSE,current_pc); + break; + case 145: case 119: case 18: // wall dispelling + place_spell_pattern(current_pat,target,11,FALSE,current_pc); + break; + case 42: // Fire barrier + play_sound(68); + r1 = get_ran(3,2,7); + hit_space(target,r1,1,TRUE,TRUE); + make_fire_barrier(target.x,target.y); + if (is_fire_barrier(target.x,target.y)) + add_string_to_buf(" You create the barrier. "); + else add_string_to_buf(" Failed."); + break; + case 59: // Force barrier + play_sound(68); + r1 = get_ran(7,2,7); + hit_space(target,r1,1,TRUE,TRUE); + make_force_barrier(target.x,target.y); + if (is_force_barrier(target.x,target.y)) + add_string_to_buf(" You create the barrier. "); + else add_string_to_buf(" Failed."); + break; + + default: // spells which involve animations + start_missile_anim(); + switch (spell_being_cast) { + + case 157: + add_missile(target,9,1,0,0); + store_sound = 11; + r1 = min(18,(level * 7) / 10 + 2 * bonus); + place_spell_pattern(radius2,target,130 + r1,TRUE,current_pc); + ashes_loc = target; + break; + + case 1: case 31: + r1 = (spell_being_cast == 1) ? get_ran(2,1,4) : get_ran(min(20,level + bonus),1,4); + add_missile(target,6,1,0,0); + do_missile_anim(100,pc_pos[current_pc],11); + hit_space(target,r1,(spell_being_cast == 1) ? 3 : 5,1,0); + break; + case 27: // flame arrows + add_missile(target,4,1,0,0); + r1 = get_ran(2,1,4); + boom_type[i] = 1; + boom_dam[i] = r1; + //hit_space(target,r1,1,1,0); + break; + case 129: // smite + add_missile(target,6,1,0,0); + r1 = get_ran(2,1,5); + boom_type[i] = 5; + boom_dam[i] = r1; + //hit_space(target,r1,5,1,0); + break; + case 114: + r1 = get_ran(min(7,2 + bonus + level / 2),1,4); + add_missile(target,14,1,0,0); + do_missile_anim(100,pc_pos[current_pc],24); + hit_space(target,r1,4,1,0); + break; + case 11: + r1 = get_ran(min(10,1 + level / 3 + bonus),1,6); + add_missile(target,2,1,0,0); + do_missile_anim(100,pc_pos[current_pc],11); + hit_space(target,r1,1,1,0); + break; + case 22: case 141: + r1 = min(9,1 + (level * 2) / 3 + bonus) + 1; + add_missile(target,2,1,0,0); + store_sound = 11; + //do_missile_anim(100,pc_pos[current_pc],11); + if (spell_being_cast == 141) + r1 = (r1 * 14) / 10; + else if (r1 > 10) r1 = (r1 * 8) / 10; + if (r1 <= 0) r1 = 1; + place_spell_pattern(square,target,50 + r1,TRUE,current_pc); + ashes_loc = target; + break; + case 40: + add_missile(target,2,1,0,0); + store_sound = 11; + //do_missile_anim(100,pc_pos[current_pc],11); + r1 = min(12,1 + (level * 2) / 3 + bonus) + 2; + if (r1 > 20) + r1 = (r1 * 8) / 10; + place_spell_pattern(radius2,target,50 + r1,TRUE,current_pc); + ashes_loc = target; + break; + case 48: // kill + add_missile(target,9,1,0,0); + do_missile_anim(100,pc_pos[current_pc],11); + r1 = get_ran(3,0,10) + adven[current_pc].level * 2; + hit_space(target,40 + r1,3,1,0); + break; + case 61: // death arrows + add_missile(target,9,1,0,0); + store_sound = 11; + r1 = get_ran(3,0,10) + adven[current_pc].level + 3 * bonus; + boom_type[i] = 3; + boom_dam[i] = r1; + //hit_space(target,40 + r1,3,1,0); + break; + // summoning spells + case 35: case 16: case 26: case 43: case 58: case 50: + case 63: case 115: case 134: case 143: case 150: + add_missile(target,8,1,0,0); + do_missile_anim(50,pc_pos[current_pc],61); + switch (spell_being_cast) { + case 35: // Simulacrum + r2 = get_ran(3,1,4) + adven[current_pc].statAdj(2); + if (summon_monster(store_sum_monst,target,r2,2) == FALSE) + add_string_to_buf(" Summon failed."); + break; + case 16: // summon beast + r2 = get_ran(3,1,4) + adven[current_pc].statAdj(2); + if ((summon == 0) || + (summon_monster(summon,target,r2,2) == FALSE)) + add_string_to_buf(" Summon failed."); + break; + case 26: // summon 1 + r2 = get_ran(4,1,4) + adven[current_pc].statAdj(2); + if ((summon == 0) || (summon_monster(summon,target,r2,2) == FALSE)) + add_string_to_buf(" Summon failed."); + break; + case 43: // summon 2 + r2 = get_ran(5,1,4) + adven[current_pc].statAdj(2); + if ((summon == 0) || (summon_monster(summon,target,r2,2) == FALSE)) + add_string_to_buf(" Summon failed."); + break; + case 58: // summon 3 + r2 = get_ran(7,1,4) + adven[current_pc].statAdj(2); + if ((summon == 0) || (summon_monster(summon,target,r2,2) == FALSE)) + add_string_to_buf(" Summon failed."); + break; + case 50: // Daemon + r2 = get_ran(5,1,4) + adven[current_pc].statAdj(2); + if (summon_monster(85,target,r2,2) == FALSE) + add_string_to_buf(" Summon failed."); + break; + case 63: // Rat! + r1 = get_ran(3,1,4); + if (summon_monster(80,target,r1,2) == FALSE) + add_string_to_buf(" Summon failed."); + break; + + case 115: // summon spirit + r2 = get_ran(2,1,5) + adven[current_pc].statAdj(2); + if (summon_monster(125,target,r2,2) == FALSE) + add_string_to_buf(" Summon failed."); + break; + case 134: // s to s + r1 = get_ran(1,0,7); + r2 = get_ran(2,1,5) + adven[current_pc].statAdj(2); + if (summon_monster((r1 == 1) ? 100 : 99,target,r2,2) == FALSE) + add_string_to_buf(" Summon failed."); + break; + case 143: // host + r2 = get_ran(2,1,4) + adven[current_pc].statAdj(2); + if (summon_monster((i == 0) ? 126 : 125,target,r2,2) == FALSE) + add_string_to_buf(" Summon failed."); + break; + case 150: // guardian + r2 = get_ran(6,1,4) + adven[current_pc].statAdj(2); + if (summon_monster(122,target,r2,2) == FALSE) + add_string_to_buf(" Summon failed."); + break; + } + break; + + + default: + targ_num = monst_there(target); + if (targ_num > T_M) + add_string_to_buf(" Nobody there "); + else { + cur_monst = &c_town.monst.dudes[targ_num]; + if ((cur_monst->attitude % 2 != 1) && (spell_being_cast != 7) + && (spell_being_cast != 34)) + make_town_hostile(); + store_sound = (spell_being_cast >= 50) ? 24 : 25; + switch (spell_being_cast) { + case 68: // spray acid + store_m_type = 0; + cur_monst->acid(level); + break; + case 69: // paralyze + store_m_type = 9; + cur_monst->charm(0,12,500); + break; + + case 7: // monster info + store_m_type = -1; + play_sound(52); + party.m_seen[cur_monst->number] = TRUE; + adjust_monst_menu(); + display_monst(0,cur_monst,0); + break; + case 34: // Capture soul + store_m_type = 15; + cur_monst->record(); + break; + + case 52: // Mindduel! + store_m_type = -1; + if ((cur_monst->m_d.mu == 0) && (cur_monst->m_d.cl == 0)) + add_string_to_buf(" Can't duel: no magic."); + else { + item = adven[current_pc].hasAbil(159); + if (item >= 24) + add_string_to_buf(" You need a smoky crystal. "); + else { + adven[current_pc].removeCharge(item); + do_mindduel(current_pc,cur_monst); + } + } + break; + + case 117: // charm + store_m_type = 14; + cur_monst->charm(-1 * (bonus + adven[current_pc].level / 8),0,0); + break; + + case 118: // disease + store_m_type = 0; + r1 = get_ran(1,0,1); + cur_monst->disease(2 + r1 + bonus); + break; + + case 62: + store_m_type = 14; + cur_monst->m_d.health += 20; + store_sound = 55; + break; + + case 13: + store_m_type = 14; + cur_monst->dumbfound(1 + bonus / 3); + store_sound = 53; + break; + + case 4: + store_m_type = 11; + cur_monst->scare(get_ran(2 + bonus,1,6)); + store_sound = 54; + break; + case 24: + store_m_type = 11; + cur_monst->scare(get_ran(min(20,adven[current_pc].level / 2 + bonus),1, + ((spell_being_cast == 24) ? 8 : 6))); + store_sound = 54; + break; + + case 12: + store_m_type = 11; + r1 = get_ran(1,0,1); + cur_monst->slow(2 + r1 + bonus); + break; + + case 10: case 36: + store_m_type = (spell_being_cast == 36) ? 4 : 11; + cur_monst->poison(2 + bonus / 2); + store_sound = 55; + break; + case 49: // Paralysis + store_m_type = 9; + cur_monst->charm(-10,12,1000); + break; + case 30: + store_m_type = 11; + cur_monst->poison(4 + bonus / 2); + store_sound = 55; + break; + case 46: + store_m_type = 11; + cur_monst->poison(8 + bonus / 2); + store_sound = 55; + break; + + case 109: // stumble + store_m_type = 8; + cur_monst->curse(4 + bonus); + break; + + case 112: + store_m_type = 8; + cur_monst->curse(2 + bonus); + break; + + case 122: + store_m_type = 8; + cur_monst->curse(2 + adven[current_pc].level / 2); + break; + + case 103: case 132: + if (cur_monst->m_d.m_type != 8) { + add_string_to_buf(" Not undead. "); + store_m_type = -1; + break; + } + store_m_type = 8; + r1 = get_ran(1,0,90); + if (r1 > hit_chance[minmax(0,19,bonus * 2 + level * 4 - (cur_monst->m_d.level / 2) + 3)]) + add_string_to_buf(" Monster resisted. "); + else { + r1 = get_ran((spell_being_cast == 103) ? 2 : 6, 1, 14); + + hit_space(cur_monst->m_loc,r1,4,0,current_pc); + } + break; + + case 155: + if (cur_monst->m_d.m_type != 7) { + add_string_to_buf(" Not a demon. "); + store_m_type = -1; + break; + } + r1 = get_ran(1,0,100); + if (r1 > hit_chance[minmax(0,19,level * 4 - cur_monst->m_d.level + 10)]) + add_string_to_buf(" Demon resisted. "); + else { + r1 = get_ran(8 + bonus * 2, 1, 11); + hit_space(cur_monst->m_loc,r1,4,0,current_pc); + } + break; + } + if (store_m_type >= 0) + add_missile(target,store_m_type,1, + 14 * (cur_monst->m_d.x_width - 1),18 * (cur_monst->m_d.y_width - 1)); + + } + break; + } + } + } + } + + do_missile_anim((num_targets > 1) ? 35 : 60,pc_pos[current_pc],store_sound); + + // process mass damage + for (i = 0; i < 8; i++) + if (boom_dam[i] > 0) + hit_space(boom_targ[i],boom_dam[i],boom_type[i],1,0); + + if (ashes_loc.x > 0) + make_sfx(ashes_loc.x,ashes_loc.y,6); + + do_explosion_anim(5,0); + + end_missile_anim(); + + handle_marked_damage(); + combat_posing_monster = current_working_monster = -1; + + print_buf(); +} + +void handle_marked_damage() +{ + int i; + + for (i = 0; i < NUM_OF_PCS; i++) + if (pc_marked_damage[i] > 0) + { + adven[i].damage(pc_marked_damage[i],10,-1); + pc_marked_damage[i] = 0; + } + + for (i = 0; i < T_M; i++) + if (monst_marked_damage[i] > 0) + { + damage_monst(i, current_pc, monst_marked_damage[i], 0, 9 ); + + monst_marked_damage[i] = 0; + } +} + +void load_missile() +{ + short i,bow = 24,arrow = 24,thrown = 24,crossbow = 24,bolts = 24,no_ammo = 24; + + for (i = 0; i < 24; i++) { + if ((adven[current_pc].equip[i] == TRUE) && + (adven[current_pc].items[i].variety == 6)) + thrown = i; + if ((adven[current_pc].equip[i] == TRUE) && + (adven[current_pc].items[i].variety == 4)) + bow = i; + if ((adven[current_pc].equip[i] == TRUE) && + (adven[current_pc].items[i].variety == 5)) + arrow = i; + if ((adven[current_pc].equip[i] == TRUE) && + (adven[current_pc].items[i].variety == 23)) + crossbow = i; + if ((adven[current_pc].equip[i] == TRUE) && + (adven[current_pc].items[i].variety == 24)) + bolts = i; + if ((adven[current_pc].equip[i] == TRUE) && + (adven[current_pc].items[i].variety == 25)) + no_ammo = i; + } + + if (thrown < 24) { + ammo_inv_slot = thrown; + add_string_to_buf("Throw: Select a target. "); + add_string_to_buf(" (Hit 's' to cancel.)"); + overall_mode = MODE_THROWING; + current_spell_range = 8; + current_pat = single; + } + else if (((bolts < 24) && (bow < 24)) || ((arrow < 24) && (crossbow < 24))) { + add_string_to_buf("Fire: Wrong ammunition. "); + } + else if ((arrow == 24) && (bow < 24)) { + add_string_to_buf("Fire: Equip some arrows. "); + } + else if ((arrow < 24) && (bow < 24)) { + missile_inv_slot = bow; + ammo_inv_slot = arrow; + overall_mode = MODE_FIRING; + add_string_to_buf("Fire: Select a target. "); + add_string_to_buf(" (Hit 's' to cancel.)"); + current_spell_range = 12; + if(adven[current_pc].items[arrow].ability == 172 && adven[current_pc].items[arrow].isIdent() == TRUE) + current_pat = radius2; + else + current_pat = single; + } + else if ((bolts < 24) && (crossbow < 24)) { + missile_inv_slot = crossbow; + ammo_inv_slot = bolts; + overall_mode = MODE_FIRING; + add_string_to_buf("Fire: Select a target. "); + add_string_to_buf(" (Hit 's' to cancel.)"); + current_spell_range = 12; + current_pat = single; + } + else if (no_ammo < 24) { + missile_inv_slot = no_ammo; + ammo_inv_slot = no_ammo; + overall_mode = MODE_FIRING; + add_string_to_buf("Fire: Select a target. "); + add_string_to_buf(" (Hit 's' to cancel.)"); + current_spell_range = 12; + current_pat = single; + } + else add_string_to_buf("Fire: Equip a missile. "); +} + +void fire_missile(location target) +{ + short r1, r2, skill, dam, dam_bonus, hit_bonus, range, targ_monst, spec_dam = 0,poison_amt = 0; + short skill_item,m_type = 0; + creature_data_type *cur_monst; + Boolean exploding = FALSE; + + skill = (overall_mode == MODE_FIRING) ? adven[current_pc].skills[SKILL_ARCHERY] : adven[current_pc].skills[SKILL_THROWN_MISSILES]; + range = (overall_mode == MODE_FIRING) ? 12 : 8; + dam = adven[current_pc].items[ammo_inv_slot].item_level; + dam_bonus = adven[current_pc].items[ammo_inv_slot].bonus + minmax(-8,8,(int)adven[current_pc].status[1]); + hit_bonus = (overall_mode == MODE_FIRING) ? adven[current_pc].items[missile_inv_slot].bonus : 0; + hit_bonus += adven[current_pc].statAdj(1) - can_see(pc_pos[current_pc],target,0) + + minmax(-8,8,(int) adven[current_pc].status[1]); + if ((skill_item = adven[current_pc].hasAbilEquip(41)) < 24) { + hit_bonus += adven[current_pc].items[skill_item].ability_strength / 2; + dam_bonus += adven[current_pc].items[skill_item].ability_strength / 2; + } + + // race adj. + if (adven[current_pc].race == RACE_NEPHIL) + hit_bonus += 2; + + if (adven[current_pc].items[ammo_inv_slot].ability == 172) + exploding = TRUE; + + if (dist(pc_pos[current_pc],target) > range) + add_string_to_buf(" Out of range."); + else if (can_see(pc_pos[current_pc],target,0) > 4) + add_string_to_buf(" Can't see target. "); + else { + // First, some missiles do special things + if (exploding == TRUE) { + take_ap((overall_mode == 12) ? 3 : 2); + void_sanctuary(current_pc); + missile_firer = current_pc; + add_string_to_buf(" The arrow explodes! "); +/* run_a_missile(pc_pos[current_pc],target,2,1,5, + 0,0,100);*/ + run_a_missile(pc_pos[current_pc],target,2,1,5, + 0,0,100); + start_missile_anim(); + add_missile(target,2,1, 0, 0); +// do_missile_anim(100,pc_pos[current_pc], 5); <= redundant missile anim + place_spell_pattern(radius2,target, + 50 + adven[current_pc].items[ammo_inv_slot].ability_strength * 2,TRUE,current_pc); + do_explosion_anim(5,0); + end_missile_anim(); + handle_marked_damage(); + + }//end of exploding arrow + + else{ + + combat_posing_monster = current_working_monster = current_pc; + draw_terrain(2); + void_sanctuary(current_pc); + //play_sound((overall_mode == 12) ? 12 : 14); + take_ap((overall_mode == MODE_FIRING) ? 3 : 2); + missile_firer = current_pc; + r1 = get_ran(1,0,100) - 5 * hit_bonus - 10; + r1 += 5 * (adven[current_pc].status[6] / 3); + r2 = get_ran(1,1,dam) + dam_bonus; + sprintf ((char *) create_line, "%s fires.",(char *) adven[current_pc].name); // debug + add_string_to_buf((char *) create_line); + + switch (overall_mode) { + case MODE_THROWING: + switch (adven[current_pc].items[ammo_inv_slot].item_level) { + case 7:m_type = 10;break; + case 4:m_type = 1;break; + case 8:m_type = 5;break; + case 9:m_type = 7;break; + default:m_type = 10;break; + } + break; + case MODE_FIRING: case MODE_FANCY_TARGET: + m_type = (adven[current_pc].items[ammo_inv_slot].isMagic()) ? 4 : 3; + break; + } + run_a_missile(pc_pos[current_pc],target,m_type,1,(overall_mode == 12) ? 12 : 14, + 0,0,100); + + if (r1 > hit_chance[skill]) + add_string_to_buf(" Missed."); + else if ((targ_monst = monst_there(target)) < T_M) { + cur_monst = &c_town.monst.dudes[targ_monst]; + spec_dam = calc_spec_dam(adven[current_pc].items[ammo_inv_slot].ability, + adven[current_pc].items[ammo_inv_slot].ability_strength,cur_monst); + if (adven[current_pc].items[ammo_inv_slot].ability == 176) { + ASB(" There is a flash of light."); + cur_monst->m_d.health += r2; + } + else damage_monst(targ_monst, current_pc, r2, spec_dam, 1300); + + // poison + if ((adven[current_pc].status[0] > 0) && (adven[current_pc].weap_poisoned == ammo_inv_slot)) { + poison_amt = adven[current_pc].status[0]; + if (adven[current_pc].hasAbilEquip(51) < 24) + poison_amt++; + cur_monst->poison(poison_amt); + } + } +/* else if((targ_monst = pc_there(target)) < 6 && adven[current_pc].items[ammo_inv_slot].ability == 176){ //Heal Target missiles heal PC ? + ASB(" There is a flash of light."); + adven[targ_monst].heal(r2); + }*/ + else hit_space(target,r2,0,1,0); +} + + if (adven[missile_firer].items[ammo_inv_slot].variety != 25) {//in case someone has been killed and current_pc is not the firer anymore + if (adven[missile_firer].items[ammo_inv_slot].ability != 170) + adven[missile_firer].items[ammo_inv_slot].charges--; + else adven[missile_firer].items[ammo_inv_slot].charges = 1; + if ((adven[missile_firer].hasAbilEquip(11) < 24) && (adven[missile_firer].items[ammo_inv_slot].ability != 170)) + adven[missile_firer].items[ammo_inv_slot].charges--; + if (adven[missile_firer].items[ammo_inv_slot].charges <= 0) + adven[missile_firer].takeItem(ammo_inv_slot); + } + + } + + if(exploding == FALSE){ + combat_posing_monster = current_working_monster = -1; + move_to_zero(adven[current_pc].status[0]); + } + print_buf();//// +} + +// Select next active PC and, if necessary, run monsters +// if monsters go or PC switches (i.e. if need redraw above), return TRUE +Boolean combat_next_step() +{ + Boolean to_return = FALSE; + short store_pc; // will print current pc name is active pc changes + + store_pc = current_pc; + while (pick_next_pc() == TRUE) { + combat_run_monst(); + set_pc_moves(); + to_return = TRUE; + // Safety valve + if (party_toast() == TRUE) + return TRUE; + } + pick_next_pc(); + if (current_pc != store_pc) + to_return = TRUE; + center = pc_pos[current_pc]; + + adjust_spell_menus(); + + if ((combat_active_pc == 6) && (current_pc != store_pc)) { + sprintf((char *)create_line, "Active: %s (#%d, %d ap.) ", + adven[current_pc].name,current_pc + 1,pc_moves[current_pc]); + add_string_to_buf((char *)create_line); + print_buf(); + } + if ((current_pc != store_pc) || (to_return == TRUE)) { + put_pc_screen(); + set_stat_window(current_pc); + } + return to_return; +} + +// Find next active PC, return TRUE is monsters need running, and run monsters is slow spells +// active +Boolean pick_next_pc() +{ + Boolean store = FALSE; + + if (current_pc == 6) + current_pc = 0; + + // If current pc isn't active, fry its moves + if ((combat_active_pc < 6) && (combat_active_pc != current_pc)) + pc_moves[current_pc] = 0; + + // Find next PC with moves + while ((pc_moves[current_pc] <= 0) && (current_pc < 6)) { + current_pc++; + if ((combat_active_pc < 6) && (combat_active_pc != current_pc)) + pc_moves[current_pc] = 0; + } + + // If run out of PC's, return to start and try again + if (current_pc == 6) { + current_pc = 0; + while ((pc_moves[current_pc] <= 0) && (current_pc < 6)) { + current_pc++; + if ((combat_active_pc < 6) && (combat_active_pc != current_pc)) + pc_moves[current_pc] = 0; + } + if (current_pc == 6) { + store = TRUE; + current_pc = 0; + } + } + + return store; +} + + +void combat_run_monst() +{ + short i,item,item_level; + Boolean update_stat = FALSE; + + + monsters_going = TRUE; + do_monster_turn(); + monsters_going = FALSE; + + process_fields(); + move_to_zero(party.light_level); + if ((which_combat_type == 1) && (c_town.town.lighting == 2)) + party.light_level = max (0,party.light_level - 9); + if (c_town.town.lighting == 3) + party.light_level = 0; + + move_to_zero(party.stuff_done[305][2]); + move_to_zero(party.stuff_done[305][3]); + + // decrease monster present counter + move_to_zero(party.stuff_done[305][9]); + + dump_gold(1); + + party.age++; + if (party.age % 4 == 0) + for (i = 0; i < 6; i++) { + if ((adven[i].status[1] != 0) || (adven[i].status[3] != 0)) + update_stat = TRUE; + move_to_zero(adven[i].status[1]); + move_to_zero(adven[i].status[3]); + move_to_zero(party.stuff_done[305][0]); + if ((item = adven[i].hasAbilEquip(50)) < 24) { + update_stat = TRUE; + adven[i].heal(get_ran(1,0,adven[i].items[item].item_level + 1)); + } + } + for (i = 0; i < 6; i++) + if (adven[i].main_status == MAIN_STATUS_ALIVE) { + if ((adven[i].status[4] != 0) || (adven[i].status[5] != 0) + || (adven[i].status[8] != 0)|| (adven[i].status[10] != 0) + || (adven[i].status[11] != 0)|| (adven[i].status[12] != 0)) + update_stat = TRUE; + + move_to_zero(adven[i].status[4]); + move_to_zero(adven[i].status[5]); + move_to_zero(adven[i].status[8]); + move_to_zero(adven[i].status[10]); + move_to_zero(adven[i].status[11]); + move_to_zero(adven[i].status[12]); + + // Do special items + if (((item_level = adven[i].getProtLevel(47)) > 0) + && (get_ran(1,0,10) == 5)) { + update_stat = TRUE; + adven[i].status[3] += item_level / 2; + add_string_to_buf("An item hastes you!"); + } + if ((item_level = adven[i].getProtLevel(46)) > 0) { + if (get_ran(1,0,10) == 5) { + update_stat = TRUE; + adven[i].status[1] += item_level / 2; + add_string_to_buf("An item blesses you!"); + } + } + + + } + + special_increase_age(); + push_things(); + + if (party.age % 2 == 0) do_poison(); + if (party.age % 3 == 0) handle_disease(); + handle_acid(); + + if (update_stat == TRUE) + put_pc_screen(); + +} + + +void do_monster_turn() +{ + Boolean acted_yet, had_monst = FALSE,printed_poison = FALSE,printed_disease = FALSE,printed_acid = FALSE; + Boolean redraw_not_yet_done = TRUE; + location targ_space,move_targ,l; + short i,j,k,num_monst,target,r1,move_target; + creature_data_type *cur_monst; + Boolean pc_adj[6]; + short abil_range[40] = {0,6,8,8,10, 10,10,8,6,8, 6,0,0,0,6, 0,0,0,0,4, 10,0,0,6,0, + 0,0,0,0,0, 0,0,8,6,9, 0,0,0,0,0}; + short abil_odds[40] = {0,5,7,6,6, 5,5,6,6,6, 6,0,0,0,4, 0,0,0,0,4, 8,0,0,7,0, + 0,0,0,0,0, 0,0,7,5,6, 0,0,0,0,0}; + + monsters_going = TRUE; // This affects how graphics are drawn. + + num_monst = T_M; + if (overall_mode < 10) + which_combat_type = 1; + + for (i = 0; i < num_monst; i++) { // Give monsters ap's, check activity + + cur_monst = &c_town.monst.dudes[i]; + + // See if hostile monster notices party, during combat + if ((cur_monst->active == 1) && (cur_monst->attitude % 2 == 1) && (overall_mode == MODE_COMBAT)) { + r1 = get_ran(1,1,100); // Check if see PCs first + r1 += (party.stuff_done[305][0] > 0) ? 45 : 0; + r1 += can_see(cur_monst->m_loc,closest_pc_loc(cur_monst->m_loc),0) * 10; + if (r1 < 50) + cur_monst->active = 2; + + for (j = 0; j < T_M; j++) + if (monst_near(j,cur_monst->m_loc,5,1) == TRUE) { + cur_monst->active = 2; + } + } + if ((cur_monst->active == 1) && (cur_monst->attitude % 2 == 1)) { + // Now it looks for PC-friendly monsters + // dist check is for efficiency + for (j = 0; j < T_M; j++) + if ((c_town.monst.dudes[j].active > 0) && + (c_town.monst.dudes[j].attitude % 2 != 1) && + (dist(cur_monst->m_loc,c_town.monst.dudes[j].m_loc) <= 6) && + (can_see(cur_monst->m_loc,c_town.monst.dudes[j].m_loc,0) < 5)) + cur_monst->active = 2; + } + + // See if friendly, fighting monster see hostile monster. If so, make mobile + // dist check is for efficiency + if ((cur_monst->active == 1) && (cur_monst->attitude == 2)) { + for (j = 0; j < T_M; j++) + if ((c_town.monst.dudes[j].active > 0) && (c_town.monst.dudes[j].attitude % 2 == 1) && + (dist(cur_monst->m_loc,c_town.monst.dudes[j].m_loc) <= 6) + && (can_see(cur_monst->m_loc,c_town.monst.dudes[j].m_loc,0) < 5)) { + cur_monst->active = 2; + cur_monst->mobile = TRUE; + } + } + // End of seeing if monsters see others + + cur_monst->m_d.ap = 0; + if (cur_monst->active == 2) { // Begin action loop for angry, active monsters + // First note that hostile monsters are around. + if (cur_monst->attitude % 2 == 1) + party.stuff_done[305][9] = 30; + + // Give monster its action points + cur_monst->m_d.ap = cur_monst->m_d.speed; + if (is_town()) + cur_monst->m_d.ap = max(1,cur_monst->m_d.ap / 3); + if (party.age % 2 == 0) + if (cur_monst->m_d.status[3] < 0) + cur_monst->m_d.ap = 0; + if (cur_monst->m_d.ap > 0) { // adjust for webs + cur_monst->m_d.ap = max(0,cur_monst->m_d.ap - cur_monst->m_d.status[6] / 2); + if (cur_monst->m_d.ap == 0) + cur_monst->m_d.status[6] = max(0,cur_monst->m_d.status[6] - 2); + } + if (cur_monst->m_d.status[3] > 0) + cur_monst->m_d.ap *= 2; + } + if ((cur_monst->m_d.status[11] > 0) || (cur_monst->m_d.status[12] > 0)) + cur_monst->m_d.ap = 0; + if (in_scen_debug == TRUE) + cur_monst->m_d.ap = 0; + center_on_monst = FALSE; + + // Now take care of summoned monsters + if (cur_monst->active > 0) { + if ((cur_monst->summoned % 100) == 1) { + cur_monst->active = 0; + cur_monst->m_d.ap = 0; + monst_spell_note(cur_monst->number,17); + } + move_to_zero(cur_monst->summoned); + } + + } + + for (i = 0; i < num_monst; i++) { // Begin main monster loop, do monster actions + // If party dead, no point + if (party_toast() == TRUE) + return; + + futzing = 0; // assume monster is fresh + + cur_monst = &c_town.monst.dudes[i]; + + + for (j = 0; j < 6; j++) + if ((adven[j].isAlive()) && (monst_adjacent(pc_pos[j],i) == TRUE)) + pc_adj[j] = TRUE; + else pc_adj[j] = FALSE; + + + + while ((cur_monst->m_d.ap > 0) && (cur_monst->active > 0)) { // Spend each action point + + if (is_combat()) { // Pick target. If in town, target already picked + // in do_monsters + target = monst_pick_target(i); + target = switch_target_to_adjacent(i,target); + if (target < 6) + targ_space = pc_pos[target]; + else if (target != 6) + targ_space = c_town.monst.dudes[target - 100].m_loc; + monst_target[i] = target; + } + else { + if (monst_target[i] < 6) + targ_space = c_town.p_loc; + else if (monst_target[i] != 6) + targ_space = c_town.monst.dudes[monst_target[i] - 100].m_loc; + } + + // sprintf((char *)create_line," %d targets %d.",i,target); + // add_string_to_buf((char *) create_line); + + if ((monst_target[i] < 0) || ((monst_target[i] > 5) && (monst_target[i] < 100))) + monst_target[i] = 6; + target = monst_target[i]; + + // Now if in town and monster about to attack, do a redraw, so we see monster + // in right place + if ((target != 6) && (is_town() == TRUE) && (redraw_not_yet_done == TRUE) + && (party_can_see_monst(i) == TRUE)) { + draw_terrain(0); + redraw_not_yet_done = FALSE; + } + + // Draw w. monster in center, if can see + if ((cur_monst->m_d.ap > 0) && (is_combat() == TRUE) + // First make sure it has a target and is close, if not, don't bother + && (cur_monst->attitude > 0) && (cur_monst->m_d.picture_num > 0) + && ((target != 6) || (cur_monst->attitude % 2 == 1)) + && (party_can_see_monst(i) == TRUE) ) { + center_on_monst = TRUE; + center = cur_monst->m_loc; + draw_terrain(0); + pause((PSD[306][6] == 3) ? 9 : PSD[306][6]); + } + + combat_posing_monster = current_working_monster = 100 + i; + + acted_yet = FALSE; + + + // Now the monster, if evil, looks at the situation and maybe picks a tactic. + // This only happens when there is >1 a.p. left, and tends to involve + // running to a nice position. + current_monst_tactic = 0; + if ((target != 6) && (cur_monst->m_d.ap > 1) && (futzing == 0)) { + l = closest_pc_loc(cur_monst->m_loc); + if (((cur_monst->m_d.mu > 0) || (cur_monst->m_d.cl > 0)) && + (dist(cur_monst->m_loc,l) < 5) && (monst_adjacent(l,i) == FALSE)) + current_monst_tactic = 1; // this means flee + + + if ( (((cur_monst->m_d.spec_skill > 0) && (cur_monst->m_d.spec_skill < 4)) + || (cur_monst->m_d.spec_skill == 20)) && // Archer? + (dist(cur_monst->m_loc,targ_space) < 6) && + (monst_adjacent(targ_space,i) == FALSE)) + current_monst_tactic = 1; // this means flee + } + + + // flee + if ((monst_target[i] < 6) && (((cur_monst->m_d.morale <= 0) + && (cur_monst->m_d.spec_skill != 13) && (cur_monst->m_d.m_type != 8)) + || (current_monst_tactic == 1))) { + if (cur_monst->m_d.morale < 0) + cur_monst->m_d.morale++; + if (cur_monst->m_d.health > 50) + cur_monst->m_d.morale++; + r1 = get_ran(1,1,6); + if (r1 == 3) + cur_monst->m_d.morale++; +/*crash*/ if ((adven[monst_target[i]].isAlive()) && (cur_monst->mobile == TRUE)) { + acted_yet = flee_party (i,cur_monst->m_loc,targ_space); + if (acted_yet == TRUE) take_m_ap(1,cur_monst); + } + } + if ((target != 6) && (cur_monst->attitude > 0) + && (monst_can_see(i,targ_space) == TRUE) + && (can_see_monst(targ_space,i) == TRUE)) { // Begin spec. attacks + + + // Breathe (fire) + if ( (cur_monst->m_d.breath > 0) + && (get_ran(1,1,8) < 4) && (acted_yet == FALSE)) { + //print_nums(cur_monst->m_d.breath,cur_monst->m_d.breath_type,dist(cur_monst->m_loc,targ_space) ); + if ((target != 6) + && (dist(cur_monst->m_loc,targ_space) <= 8)) { + acted_yet = monst_breathe(cur_monst,targ_space,cur_monst->m_d.breath_type); + had_monst = TRUE; + acted_yet = TRUE; + take_m_ap(4,cur_monst); + } + } + // Mage spell + if ((cur_monst->m_d.mu > 0) && (get_ran(1,1,10) < ((cur_monst->m_d.cl > 0) ? 6 : 9) ) + && (acted_yet == FALSE)) { + if (((monst_adjacent(targ_space,i) == FALSE) || (get_ran(1,0,2) < 2) || (cur_monst->number >= 160) + || (cur_monst->m_d.level > 9)) + && (dist(cur_monst->m_loc,targ_space) <= 10)) { + acted_yet = monst_cast_mage(cur_monst,target); + had_monst = TRUE; + acted_yet = TRUE; + take_m_ap(5,cur_monst); + } + } + // Priest spell + if ((cur_monst->m_d.cl > 0) && (get_ran(1,1,8) < 7) && (acted_yet == FALSE)) { + if (((monst_adjacent(targ_space,i) == FALSE) || (get_ran(1,0,2) < 2) || (cur_monst->m_d.level > 9)) + && (dist(cur_monst->m_loc,targ_space) <= 10)) { + acted_yet = monst_cast_priest(cur_monst,target); + had_monst = TRUE; + acted_yet = TRUE; + take_m_ap(4,cur_monst); + } + } + + // Missile + if ((abil_range[cur_monst->m_d.spec_skill] > 0) // breathing gas short range + && (get_ran(1,1,8) < abil_odds[cur_monst->m_d.spec_skill]) && (acted_yet == FALSE)) { + // Don't fire when adjacent, unless non-gaze magical attack + if (((monst_adjacent(targ_space,i) == FALSE) || + ((cur_monst->m_d.spec_skill > 7) && (cur_monst->m_d.spec_skill != 20) + && (cur_monst->m_d.spec_skill != 33))) + // missile range + && (dist(cur_monst->m_loc,targ_space) <= abil_range[cur_monst->m_d.spec_skill])) { + print_monst_name(cur_monst->number); + monst_fire_missile(i,cur_monst->m_d.status[1], + cur_monst->m_d.spec_skill,cur_monst->m_loc,target); + + // Vapors don't count as action + if ((cur_monst->m_d.spec_skill == 11) || (cur_monst->m_d.spec_skill == 7) || + (cur_monst->m_d.spec_skill == 20)) + take_m_ap(2,cur_monst); + else if (cur_monst->m_d.spec_skill == 10) + take_m_ap(1,cur_monst); + else take_m_ap(3,cur_monst); + had_monst = TRUE; + acted_yet = TRUE; + } + } + } // Special attacks + + // Attack pc + if ((monst_target[i] < 6) && (adven[monst_target[i]].isAlive()) + && (monst_adjacent(targ_space,i) == TRUE) && (cur_monst->attitude % 2 == 1) + && (acted_yet == FALSE)) { + monster_attack_pc(i,monst_target[i]); + take_m_ap(4,cur_monst); + acted_yet = TRUE; + had_monst = TRUE; + } + // Attack monst + if ((monst_target[i] >= 100) && (c_town.monst.dudes[monst_target[i] - 100].active > 0) + && (monst_adjacent(targ_space,i) == TRUE) && (cur_monst->attitude > 0) + && (acted_yet == FALSE)) { + monster_attack_monster(i,monst_target[i] - 100); + take_m_ap(4,cur_monst); + acted_yet = TRUE; + had_monst = TRUE; + } + + if (acted_yet == TRUE) { + print_buf(); + if (j == 0) + pause(8); + FlushEvents(2); + } + + if (overall_mode == MODE_COMBAT) { + if ((acted_yet == FALSE) && (cur_monst->mobile == TRUE)) { // move monst + move_target = (monst_target[i] != 6) ? monst_target[i] : closest_pc(cur_monst->m_loc); + if (monst_hate_spot(i,&move_targ) == TRUE) // First, maybe move out of dangerous space + seek_party (i,cur_monst->m_loc,move_targ); + else { // spot is OK, so go nuts + if ((cur_monst->attitude % 2 == 1) && (move_target < 6)) // Monsters seeking party do so + if (adven[move_target].isAlive()) { + seek_party (i,cur_monst->m_loc,pc_pos[move_target]); + for (k = 0; k < 6; k++) + if ((pc_parry[k] > 99) && (monst_adjacent(pc_pos[k],i) == TRUE) + && (cur_monst->active > 0)) { + pc_parry[k] = 0; + pc_attack(k,i); + } + } + + if (move_target >= 100) // Monsters seeking monsters do so + if (c_town.monst.dudes[move_target - 100].active > 0) { + seek_party (i,cur_monst->m_loc,c_town.monst.dudes[move_target - 100].m_loc); + for (k = 0; k < 6; k++) + if ((pc_parry[k] > 99) && (monst_adjacent(pc_pos[k],i) == TRUE) + && (cur_monst->active > 0) && (cur_monst->attitude % 2 == 1)) { + pc_parry[k] = 0; + pc_attack(k,i); + } + } + + if (cur_monst->attitude == 0) { + acted_yet = rand_move (i); + futzing++; + } + } + take_m_ap(1,cur_monst); + } + if ((acted_yet == FALSE) && (cur_monst->mobile == FALSE)) { // drain action points + take_m_ap(1,cur_monst); + futzing++; + } + } + else if (acted_yet == FALSE) { + take_m_ap(1,cur_monst); + futzing++; + } + + // pcs attack any fleeing monsters + if ((overall_mode >= 10) && (overall_mode < 20)) + for (k = 0; k < 6; k++) + if ((adven[k].isAlive()) && (monst_adjacent(pc_pos[k],i) == FALSE) + && (pc_adj[k] == TRUE) && (cur_monst->attitude % 2 == 1) && (cur_monst->active > 0) && + (adven[k].status[8] == 0)) { + combat_posing_monster = current_working_monster = k; + pc_attack(k,i); + combat_posing_monster = current_working_monster = 100 + i; + pc_adj[k] = FALSE; + } + + // Place fields for monsters that create them. Only done when monst sees foe + if ((target != 6) && (can_see(cur_monst->m_loc,targ_space,0) < 5)) { //// + if ((cur_monst->m_d.radiate_1 == 1) && (get_ran(1,1,100) <= cur_monst->m_d.radiate_2)) + place_spell_pattern(square,cur_monst->m_loc,5,FALSE,7); + if ((cur_monst->m_d.radiate_1 == 2) && (get_ran(1,1,100) <= cur_monst->m_d.radiate_2)) + place_spell_pattern(square,cur_monst->m_loc,8,FALSE,7); + if ((cur_monst->m_d.radiate_1 == 3) && (get_ran(1,1,100) <= cur_monst->m_d.radiate_2)) + place_spell_pattern(square,cur_monst->m_loc,4,FALSE,7); + if ((cur_monst->m_d.radiate_1 == 4) && (get_ran(1,1,100) <= cur_monst->m_d.radiate_2)) + place_spell_pattern(square,cur_monst->m_loc,6,FALSE,7); + if ((cur_monst->m_d.radiate_1 == 5) && (get_ran(1,1,100) <= cur_monst->m_d.radiate_2)) + place_spell_pattern(square,cur_monst->m_loc,12,FALSE,7); + if ((cur_monst->m_d.radiate_1 == 6) && (get_ran(1,1,100) <= cur_monst->m_d.radiate_2)) + place_spell_pattern(square,cur_monst->m_loc,7,FALSE,7); + if ((cur_monst->m_d.radiate_1 == 10) && (get_ran(1,0,99) < 5)){ + if (summon_monster(cur_monst->m_d.radiate_2, + cur_monst->m_loc,130,cur_monst->attitude) == TRUE) + {monst_spell_note(cur_monst->number,33); play_sound(61);} + } + if ((cur_monst->m_d.radiate_1 == 11) && (get_ran(1,0,99) < 20)){ + if (summon_monster(cur_monst->m_d.radiate_2, + cur_monst->m_loc,130,cur_monst->attitude) == TRUE) + {monst_spell_note(cur_monst->number,33); play_sound(61);} + } + if ((cur_monst->m_d.radiate_1 == 12) && (get_ran(1,0,99) < 50)){ + if (summon_monster(cur_monst->m_d.radiate_2, + cur_monst->m_loc,130,cur_monst->attitude) == TRUE) + {monst_spell_note(cur_monst->number,33); play_sound(61);} + } + } + + combat_posing_monster = current_working_monster = -1; + // Redraw monster after it goes + if ((cur_monst->attitude > 0) && (cur_monst->active > 0) && (cur_monst->m_d.ap == 0) + && (is_combat()) && (cur_monst->m_d.picture_num > 0) && (party_can_see_monst(i) == TRUE)) { + center = cur_monst->m_loc; + draw_terrain(0); + + } + + // If monster dead, take away actions + if (cur_monst->active == 0) + cur_monst->m_d.ap = 0; + + //if ((futzing == 1) && (get_ran(1,0,1) == 0)) // If monster's just pissing around, give up + // cur_monst->m_d.ap = 0; + if (futzing > 1) // If monster's just pissing around, give up + cur_monst->m_d.ap = 0; + } // End of monster action loop + + + } + + for (i = 0; i < num_monst; i++) { // Begin monster time stuff loop + // If party dead, no point + if (party_toast() == TRUE) + return; + + cur_monst = &c_town.monst.dudes[i]; + + if ((cur_monst->active < 0) || (cur_monst->active > 2)) + cur_monst->active = 0; // clean up + if (cur_monst->active != 0) { // Take care of monster effects + if (cur_monst->m_d.status[13] > 0) { // Acid + if (printed_acid == FALSE) { + add_string_to_buf("Acid: "); + printed_acid = TRUE; + } + r1 = get_ran(cur_monst->m_d.status[13],1,6); + damage_monst(i, 6,r1, 0, 3); + cur_monst->m_d.status[13]--; + } + + if (cur_monst->m_d.status[11] == 1) + monst_spell_note(cur_monst->number,29); + move_to_zero(cur_monst->m_d.status[11]); + move_to_zero(cur_monst->m_d.status[12]); + + if (party.age % 2 == 0) { + move_to_zero(cur_monst->m_d.status[1]); + move_to_zero(cur_monst->m_d.status[3]); + move_to_zero(cur_monst->m_d.status[6]); + + if (cur_monst->m_d.status[2] > 0) { // Poison + if (printed_poison == FALSE) { + add_string_to_buf("Poisoned monsters: "); + printed_poison = TRUE; + } + r1 = get_ran(cur_monst->m_d.status[2],1,6); + damage_monst(i, 6, r1, 0, 2); + cur_monst->m_d.status[2]--; + } + if (cur_monst->m_d.status[7] > 0) { // Disease + if (printed_disease == FALSE) { + add_string_to_buf("Diseased monsters: "); + printed_disease = TRUE; + } + k = get_ran(1,1,5); + switch (k) { + case 1: + case 2: cur_monst->poison(2);break; + case 3: cur_monst->slow(2); break; + case 4: cur_monst->curse(2); break; + case 5: cur_monst->scare(10); break; + } + if (get_ran(1,1,6) < 4) + cur_monst->m_d.status[7]--; + } + + } + + if (party.age % 4 == 0) { + if (cur_monst->m_d.mp < cur_monst->m_d.max_mp) + cur_monst->m_d.mp += 2; + move_to_zero(cur_monst->m_d.status[9]); + } + } // end take care of monsters + } + + // If in town, need to restore center + if (overall_mode < 10) + center = c_town.p_loc; + if (had_monst == TRUE) + put_pc_screen(); + for (i = 0; i < 6; i++) + pc_parry[i] = 0; + + monsters_going = FALSE; +} + +void monster_attack_pc(short who_att,short target) +{ + creature_data_type *attacker; + short r1,r2,i,dam_type = 0,store_hp,sound_type = 0; + + + attacker = &c_town.monst.dudes[who_att]; + + // A peaceful monster won't attack + if (attacker->attitude % 2 != 1) + return; + + // Draw attacker frames + if ((is_combat()) + && ((center_on_monst == TRUE) || (monsters_going == FALSE))) { + if (attacker->m_d.spec_skill != 11) + frame_space(attacker->m_loc,0,attacker->m_d.x_width,attacker->m_d.y_width); + frame_space(pc_pos[target],1,1,1); + } + + + + if ((attacker->m_d.a[0] != 0) || (attacker->m_d.a[2] != 0)) + print_monst_attacks(attacker->number,target); + + // Check sanctuary + if (adven[target].status[8] > 0) { + r1 = get_ran(1,0,100); + if (r1 > hit_chance[attacker->m_d.level / 2]) { + add_string_to_buf(" Can't find target! "); + } + return; + } + + for (i = 0; i < 3; i++) { + if ((attacker->m_d.a[i] > 0) && (adven[target].isAlive())) { + + // Attack roll + r1 = get_ran(1,0,100) - 5 * min(8,attacker->m_d.status[1]) + 5 * adven[target].status[1] + + 5 * adven[target].statAdj(1) - 15; + r1 += 5 * (attacker->m_d.status[6] / 3); + if (pc_parry[target] < 100) + r1 += 5 * pc_parry[target]; + + // Damage roll + r2 = get_ran(attacker->m_d.a[i] / 100 + 1,1,attacker->m_d.a[i] % 100) + + min(8,attacker->m_d.status[1]) - adven[target].status[1] + 1; + if (difficulty_adjust() > 2) + r2 = r2 * 2; + if (difficulty_adjust() == 2) + r2 = (r2 * 3) / 2; + + if ((adven[target].status[11] > 0) || (adven[target].status[12] > 0)) { + r1 -= 80; + r2 = r2 * 2; + } + + draw_terrain(2); + // Check if hit, and do effects + if (r1 <= hit_chance[(attacker->m_d.skill + 4) / 2]) { + if (attacker->m_d.m_type == MONSTER_TYPE_DEMON) + dam_type = DAMAGE_DEMON; + if (attacker->m_d.m_type == MONSTER_TYPE_UNDEAD) + dam_type = DAMAGE_UNDEAD; + + store_hp = adven[target].cur_health; + sound_type = get_monst_sound(attacker,i); + + if ((adven[target].damage(r2,sound_type * 100 + 30 + dam_type, + attacker->m_d.m_type) == true) && + (store_hp - adven[target].cur_health > 0)) { + damaged_message(store_hp - adven[target].cur_health, + (i > 0) ? attacker->m_d.a23_type : attacker->m_d.a1_type); + + if (adven[target].status[10] > 0) { + add_string_to_buf(" Shares damage! "); + damage_monst(who_att, 6, store_hp - adven[target].cur_health, 0, 3); + } + + if ((attacker->m_d.poison > 0) && (i == 0)) { + adven[target].poison(attacker->m_d.poison); + } + + // Gremlin + if ((attacker->m_d.spec_skill == 21) && (get_ran(1,0,2) < 2)) { + add_string_to_buf(" Steals food! "); + print_buf(); + play_sound(26); + party.food = (long) max(0, (short) (party.food) - get_ran(1,0,10) - 10); + put_pc_screen(); + } + + // Disease + if ((attacker->m_d.spec_skill == 25) && (get_ran(1,0,2) < 2)) { + add_string_to_buf(" Causes disease! "); + print_buf(); + adven[target].disease((attacker->m_d.spec_skill == 25) ? 6 : 2); + } + + // Undead xp drain + if (((attacker->m_d.spec_skill == 16) || (attacker->m_d.spec_skill == 17)) + && (adven[target].hasAbilEquip(48) == 24)) { + add_string_to_buf(" Drains life! "); + adven[target].drainXP((attacker->m_d.level * 3) / 2); + put_pc_screen(); + } + + // Undead slow + if ((attacker->m_d.spec_skill == 18) && (get_ran(1,0,8) < 6) + && (adven[target].hasAbilEquip(48) == 24)) { + add_string_to_buf(" Stuns! "); + adven[target].slow(2); + put_pc_screen(); + } + // Dumbfound target + if (attacker->m_d.spec_skill == 24) { + add_string_to_buf(" Dumbfounds! "); + adven[target].dumbfound(2); + put_pc_screen(); + } + + // Web target + if (attacker->m_d.spec_skill == 27) { + add_string_to_buf(" Webs! "); + adven[target].web(5); + put_pc_screen(); + } + // Sleep target + if (attacker->m_d.spec_skill == 28) { + add_string_to_buf(" Sleeps! "); + adven[target].sleep(6,11,-15); + put_pc_screen(); + } + // Paralyze target + if (attacker->m_d.spec_skill == 29) { + add_string_to_buf(" Paralysis touch! "); + adven[target].sleep(500,12,-5); + put_pc_screen(); + } + // Acid touch + if (attacker->m_d.spec_skill == 31) { + add_string_to_buf(" Acid touch! "); + adven[target].acid((attacker->m_d.level > 20) ? 4 : 2); + } + + // Freezing touch + if (((attacker->m_d.spec_skill == 15) || (attacker->m_d.spec_skill == 17)) + && (get_ran(1,0,8) < 6) && (adven[target].hasAbilEquip(48) == 24)) { + add_string_to_buf(" Freezing touch!"); + r1 = get_ran(3,1,10); + adven[target].damage(r1, DAMAGE_COLD, -1); + } + // Killing touch + if (attacker->m_d.spec_skill == 35) + { + add_string_to_buf(" Killing touch!"); + r1 = get_ran(20,1,10); + adven[target].damage(r1,DAMAGE_UNBLOCKABLE,-1); + } + // Petrification touch + if (attacker->m_d.spec_skill == 30 && (get_ran(1,0,8) < 3)) + { + add_string_to_buf(" Petrifying touch!"); + print_buf(); + adven[target].kill(4); + } + } + } + else { + sprintf ((char *) create_line, " Misses."); + add_string_to_buf((char *) create_line); + play_sound(2); + } + combat_posing_monster = -1; + draw_terrain(2); + combat_posing_monster = 100 + who_att; + + + } + if (adven[target].isAlive() == false) + i = 3; + } + +} + +void monster_attack_monster(short who_att,short attackee) +{ + creature_data_type *attacker,*target; + short r1,r2,i,dam_type = 0,store_hp,sound_type = 0; + + attacker = &c_town.monst.dudes[who_att]; + target = &c_town.monst.dudes[attackee]; + + // Draw attacker frames + if ((is_combat()) + && ((center_on_monst == TRUE) || (monsters_going == FALSE))) { + if (attacker->m_d.spec_skill != 11) + frame_space(attacker->m_loc,0,attacker->m_d.x_width,attacker->m_d.y_width); + frame_space(target->m_loc,1,1,1); + } + + + if ((attacker->m_d.a[1] != 0) || (attacker->m_d.a[0] != 0)) + print_monst_attacks(attacker->number,100 + attackee); + for (i = 0; i < 3; i++) { + if ((attacker->m_d.a[i] > 0) && (target->active != 0)) { +// sprintf ((char *) create_line, " Attacks %s.",(char *) adven[target].name); +// add_string_to_buf((char *) create_line); + + // if friendly to party, make able to attack + if (target->attitude == 0) + target->attitude = 2; + + // Attack roll + r1 = get_ran(1,0,100) - 5 * min(10,attacker->m_d.status[1]) + + 5 * target->m_d.status[1] - 15; + r1 += 5 * (attacker->m_d.status[6] / 3); + + // Damage roll + r2 = get_ran(attacker->m_d.a[i] / 100 + 1,1,attacker->m_d.a[i] % 100) + + min(10,attacker->m_d.status[1]) - target->m_d.status[1] + 2; + + if ((target->m_d.status[11] > 0) || (target->m_d.status[12] > 0)) { + r1 -= 80; + r2 = r2 * 2; + } + + draw_terrain(2); + // Check if hit, and do effects + if (r1 <= hit_chance[(attacker->m_d.skill + 4) / 2]) { + if (attacker->m_d.m_type == MONSTER_TYPE_DEMON) + dam_type = DAMAGE_DEMON; + if (attacker->m_d.m_type == MONSTER_TYPE_UNDEAD) + dam_type = DAMAGE_UNDEAD; + store_hp = target->m_d.health; + + sound_type = get_monst_sound(attacker,i); + + if (damage_monst(attackee,7,r2,0,sound_type * 100 + 10 + dam_type) == TRUE) { + damaged_message(store_hp - target->m_d.health, + (i > 0) ? attacker->m_d.a23_type : attacker->m_d.a1_type); + + if ((attacker->m_d.poison > 0) && (i == 0)) { + target->poison(attacker->m_d.poison); + } + + // Undead slow + if ((attacker->m_d.spec_skill == 18) && (get_ran(1,0,8) < 6)) { + add_string_to_buf(" Stuns! "); + target->slow(2); + } + + // Web target + if (attacker->m_d.spec_skill == 27) { + add_string_to_buf(" Webs! "); + target->web(4); + } + // Sleep target + if (attacker->m_d.spec_skill == 28) { + add_string_to_buf(" Sleeps! "); + target->charm(-15,11,6); + } + // Dumbfound target + if (attacker->m_d.spec_skill == 24) { + add_string_to_buf(" Dumbfounds! "); + target->dumbfound(2); + } + // Paralyze target + if (attacker->m_d.spec_skill == 29) { + add_string_to_buf(" Paralysis touch! "); + target->charm(-5,12,500); + } + // Acid touch + if (attacker->m_d.spec_skill == 31) { + add_string_to_buf(" Acid touch! "); + target->acid(3); + } + + // Freezing touch + if (((attacker->m_d.spec_skill == 15) || (attacker->m_d.spec_skill == 17)) + && (get_ran(1,0,8) < 6)) { + add_string_to_buf(" Freezing touch!"); + r1 = get_ran(3,1,10); + damage_monst(attackee,7,r1,0,5); + } + + // Death touch + if ((attacker->m_d.spec_skill == 35) + && (get_ran(1,0,8) < 6)) { + add_string_to_buf(" Killing touch!"); + r1 = get_ran(20,1,10); + damage_monst(attackee,7,r1,0,4); + } + } + } + else { + sprintf ((char *) create_line, " Misses."); + add_string_to_buf((char *) create_line); + play_sound(2); + } + combat_posing_monster = -1; + draw_terrain(2); + combat_posing_monster = 100 + who_att; + } + if (target->active == 0) + i = 3; + } + +} + + +void monst_fire_missile(short m_num,short bless,short level,location source,short target) +//short target; // 100 + - monster is target +{ + creature_data_type *m_target; + short r1,r2,dam[40] = {0,1,2,3,4, 6,8,7,0,0, 0,0,0,0,0, 0,0,0,0,0, + 8,0,0,0,0, 0,0,0,0,0, 0,0,0,0,6, 0,0,0,0,0},i,j; + location targ_space; + + if (target == INVALID_PC) + return; + if (target >= 100) { + targ_space = c_town.monst.dudes[target - 100].m_loc; + if (c_town.monst.dudes[target - 100].active == 0) + return; + } + else { + targ_space = (is_combat()) ? pc_pos[target] : c_town.p_loc; + if (adven[target].isAlive() == false) + return; + } + + if (target >= 100) + m_target = &c_town.monst.dudes[target - 100]; + if (((overall_mode >= 10) && (overall_mode <= 20)) && (center_on_monst == TRUE)) { + frame_space(source,0,c_town.monst.dudes[m_num].m_d.x_width,c_town.monst.dudes[m_num].m_d.y_width); + if (target >= 100) + frame_space(targ_space,1,m_target->m_d.x_width,m_target->m_d.y_width); + else frame_space(targ_space,1,1,1); + } + + draw_terrain(2); + if (level == 32) { // sleep cloud + ASB("Creature breathes."); + run_a_missile(source,targ_space,0,0,44, + 0,0,100); + place_spell_pattern(radius2,targ_space,12,FALSE,7); + } + else if (level == 14) { // vapors + if (target < 100) { // on PC + sprintf ((char *) create_line, " Breathes on %s. ",(char *) adven[target].name); + add_string_to_buf((char *) create_line); + } + else { // on monst + add_string_to_buf(" Breathes vapors."); + } + run_a_missile(source,targ_space,12,0,44, + 0,0,100); + scloud_space(targ_space.x,targ_space.y); + } + else if (level == 19) { // webs + if (target < 100) { // on PC + sprintf ((char *) create_line, " Throws web at %s. ",(char *) adven[target].name); + add_string_to_buf((char *) create_line); + } + else { // on monst + add_string_to_buf(" Throws web."); + } + run_a_missile(source,targ_space,8,0,14, + 0,0,100); + web_space(targ_space.x,targ_space.y); + } + else if (level == 23) { // paral + play_sound(51); + if (target < 100) { // on PC + sprintf ((char *) create_line, " Fires ray at %s. ",(char *) adven[target].name); + add_string_to_buf((char *) create_line); + adven[target].sleep(100,12,0); + } + else { // on monst + add_string_to_buf(" Shoots a ray."); + m_target->charm(0,12,100); + } + } + else if (level == 8) { // petrify + run_a_missile(source,targ_space,14,0,43,0,0,100); + if (target < 100) { // on PC + sprintf ((char *) create_line, " Gazes at %s. ",(char *) adven[target].name); + add_string_to_buf((char *) create_line); + r1 = get_ran(1,0,20) + adven[target].level / 4 + adven[target].status[1]; + if (r1 > 14) { + sprintf ((char *) create_line, " %s resists. ",(char *) adven[target].name); + add_string_to_buf((char *) create_line); + } + else { + adven[target].kill(4); + } + } + else { + monst_spell_note(m_target->number,9); + r1 = get_ran(1,0,20) + m_target->m_d.level / 4 + m_target->m_d.status[1]; + if ((r1 > 14) || (m_target->m_d.immunities & 2)) + monst_spell_note(m_target->number,10); + else { + monst_spell_note(m_target->number,8); + kill_monst(m_target,7); + } + } + } + else if (level == 9) { /// Drain sp + if (target < 100) { // pc + // modify target is target has no sp + if (adven[target].cur_sp < 4) { + for (i = 0; i < 8; i++) { + j = get_ran(1,0,5); + if ((adven[j].isAlive()) && (adven[j].cur_sp > 4) && + (can_see(source,pc_pos[j],0) < 5) && (dist(source,pc_pos[j]) <= 8)) { + target = j; + i = 8; + targ_space = pc_pos[target]; + } + } + + } + run_a_missile(source,targ_space,8,0,43,0,0,100); + sprintf ((char *) create_line, " Drains %s. ",(char *) adven[target].name); + add_string_to_buf((char *) create_line); + adven[target].cur_sp = adven[target].cur_sp / 2; + } + else { // on monst + run_a_missile(source,targ_space,8,0,43,0,0,100); + monst_spell_note(m_target->number,11); + if (m_target->m_d.mp >= 4) + m_target->m_d.mp = m_target->m_d.mp / 2; + else m_target->m_d.skill = 1; + } + } + else if (level == 10) { // heat ray + run_a_missile(source,targ_space,13,0,51,0,0,100); + r1 = get_ran(7,1,6); + start_missile_anim(); + if (target < 100) { // pc + sprintf ((char *) create_line, " Hits %s with heat ray.",(char *) adven[target].name); + add_string_to_buf((char *) create_line); + adven[target].damage(r1,DAMAGE_FIRE,-1); + } + else { // on monst + add_string_to_buf(" Fires heat ray."); + damage_monst(target - 100,7,r1,0,1); + } + do_explosion_anim(5,0); + end_missile_anim(); + handle_marked_damage(); + } + else if (level == 33) { // acid spit + run_a_missile(source,targ_space,0,1,64,0,0,100); + if (target < 100) { // pc + sprintf ((char *) create_line, " Spits acid on %s.",(char *) adven[target].name); + add_string_to_buf((char *) create_line); + adven[target].acid(6); + } + else { // on monst + add_string_to_buf(" Spits acid."); + m_target->acid(6); + } + } + else if (target < 100) { // missile on PC + + switch (level) { + case 1: case 2: case 20: + run_a_missile(source,targ_space,3,1,12,0,0,100); + sprintf ((char *) create_line, " Shoots at %s.",(char *) adven[target].name); + break; + case 3: + run_a_missile(source,targ_space,5,1,14,0,0,100); + sprintf ((char *) create_line, " Throws spear at %s.",(char *) adven[target].name); + break; + case 7: + run_a_missile(source,targ_space,7,1,14,0,0,100); + sprintf ((char *) create_line, " Throws razordisk at %s.",(char *) adven[target].name); + break; + case 34: + run_a_missile(source,targ_space,5,1,14,0,0,100); + sprintf ((char *) create_line, " Fires spines at %s.",(char *) adven[target].name); + break; + default: + run_a_missile(source,targ_space,12,1,14,0,0,100); + sprintf ((char *) create_line, " Throws rock at %s.",(char *) adven[target].name); + break; + } + + add_string_to_buf((char *) create_line); + + // Check sanctuary + if (adven[target].status[8] > 0) { + r1 = get_ran(1,0,100); + if (r1 > hit_chance[level]) { + add_string_to_buf(" Can't find target! "); + } + return; + } + + r1 = get_ran(1,0,100) - 5 * min(10,bless) + 5 * adven[target].status[1] + - 5 * (can_see(source, pc_pos[target],0)); + if (pc_parry[target] < 100) + r1 += 5 * pc_parry[target]; + r2 = get_ran(dam[level],1,7) + min(10,bless); + + if (r1 <= hit_chance[dam[level] * 2]) { + if (adven[target].damage(r2,1300,-1) == true) { } + } + else { + sprintf ((char *) create_line, " Misses %s.",(char *) adven[target].name); + add_string_to_buf((char *) create_line); + } + + } + else { // missile on monst + switch (level) { + case 1: case 2: case 20: + run_a_missile(source,targ_space,3,1,12,0,0,100); + monst_spell_note(m_target->number,12); + break; + case 3: + run_a_missile(source,targ_space,5,1,14,0,0,100); + monst_spell_note(m_target->number,13); + break; + case 7: + run_a_missile(source,targ_space,7,1,14,0,0,100); + monst_spell_note(m_target->number,15); + break; + case 34: + run_a_missile(source,targ_space,5,1,14,0,0,100); + monst_spell_note(m_target->number,32); + break; + default: + run_a_missile(source,targ_space,12,1,14,0,0,100); + monst_spell_note(m_target->number,14); + break; + } + r1 = get_ran(1,0,100) - 5 * min(10,bless) + 5 * m_target->m_d.status[1] + - 5 * (can_see(source, m_target->m_loc,0)); + r2 = get_ran(dam[level],1,7) + min(10,bless); + + if (r1 <= hit_chance[dam[level] * 2]) { +// monst_spell_note(m_target->number,16); + + damage_monst(target - 100,7,r2,0,1300); + } + else { + monst_spell_note(m_target->number,18); + } + } +} + + +Boolean monst_breathe(creature_data_type *caster,location targ_space,short dam_type) +//dam_type; // 0 - fire 1 - cold 2 - magic +{ + short level,type[4] = {1,5,3,4},missile_t[4] = {13,6,8,8}; + location l; + + draw_terrain(2); + if ((is_combat()) && (center_on_monst == TRUE)) { + frame_space(caster->m_loc,0,caster->m_d.x_width,caster->m_d.y_width); + } + + l = caster->m_loc; + if ((caster->m_d.direction < 4) && + (caster->m_d.x_width > 1)) + l.x++; + + dam_type = caster->m_d.breath_type; + run_a_missile(l,targ_space,missile_t[dam_type],0,44,0,0,100); + level = caster->m_d.breath; + + monst_breathe_note(caster->number); + level = get_ran(caster->m_d.breath,1,8); + if (overall_mode < 10) + level = level / 3; + start_missile_anim(); + hit_space(targ_space,level,type[dam_type],1,1); + do_explosion_anim(5,0); + end_missile_anim(); + handle_marked_damage(); + + return TRUE; +} + +Boolean monst_cast_mage(creature_data_type *caster,short targ) +{ + short j,spell,i,level,target_levels,friend_levels_near,x; + unsigned short r1; + Boolean acted = FALSE; + location target,vict_loc,ashes_loc,l; + creature_data_type *affected; + long dummy; + short caster_array[7][18] = {{1,1,1,2,2, 2,1,3,4,4, 1,1,1,2,2, 2,3,4}, + {5,5,5,6,7, 8,9,10,11,11, 2,2,2,5,7, 10,10,5}, + {5,5,2,9,11, 12,12,12,14,13, 13,12,12,2,2, 2,2,2}, + {15,15,16,17,17, 5,12,12,13,13, 17,17,16,17,16, 2,2,2}, + {15,18,19,19,20, 20,21,21,16,17, 18,18,18,18,19, 19,19,20}, + {23,23,22,22,21, 21,20,24,19,18, 18,18,18,18,18, 23,23,19}, + {23,23,24,25,26, 27,19,22,19,18, 18,18,18,18,26, 24,24,23}}; + short emer_spells[7][4] = {{2,0,0,5}, + {2,10,11,7}, + {2,13,12,13}, + {2,13,12,13}, + {18,20,19,18}, + {18,24,19,24}, + {18,26,19,27}}; + + + if (is_antimagic(caster->m_loc.x,caster->m_loc.y)) { + return FALSE; + } + // is target dead? + if ((targ < 6) && (adven[targ].isAlive() == false)) + return FALSE; + if ((targ >= 100) && (c_town.monst.dudes[targ - 100].active == 0)) + return FALSE; + + level = max(1,caster->m_d.mu - caster->m_d.status[9]) - 1; + + target = find_fireball_loc(caster->m_loc,1,(caster->attitude % 2 == 1) ? 0 : 1,&target_levels); + friend_levels_near = (caster->attitude % 2 != 1) ? count_levels(caster->m_loc,3) : -1 * count_levels(caster->m_loc,3); + + if ((caster->m_d.health * 4 < caster->m_d.m_health) && (get_ran(1,0,10) < 9)) + spell = emer_spells[level][3]; + else if ((((caster->m_d.status[3] < 0) && (get_ran(1,0,10) < 7)) || + ((caster->m_d.status[3] == 0) && (get_ran(1,0,10) < 5))) && (emer_spells[level][0] != 0)) + spell = emer_spells[level][0]; + else if ((friend_levels_near <= -10) && (get_ran(1,0,10) < 7) && (emer_spells[level][1] != 0)) + spell = emer_spells[level][1]; + else if ((target_levels > 50) && (get_ran(1,0,10) < 7) && (emer_spells[level][2] != 0)) + spell = emer_spells[level][2]; + else { + r1 = get_ran(1,0,17); + spell = caster_array[level][r1]; + } + + // Hastes happen often now, but don't cast them redundantly + if ((caster->m_d.status[3] > 0) && ((spell == 2) || (spell == 18))) + spell = emer_spells[level][3]; + + + // Anything prventing spell? + if ((target.x > 64) && (monst_mage_area_effect[spell - 1] > 0)) { + r1 = get_ran(1,0,9); + spell = caster_array[level][r1]; + if ((target.x > 64) && (monst_mage_area_effect[spell - 1] > 0)) + return FALSE; + } + if (monst_mage_area_effect[spell - 1] > 0) { + targ = 6; + } + + if (targ < 6) { + vict_loc = (is_combat()) ? pc_pos[targ] : c_town.p_loc; + if (is_town()) + vict_loc = target = c_town.p_loc; + } + if (targ >= 100) + vict_loc = c_town.monst.dudes[targ - 100].m_loc; + if ((targ == 6) && (is_antimagic(target.x,target.y))) + return FALSE; + + // check antimagic + if (is_combat()) + if ((targ < 6) && (is_antimagic(pc_pos[targ].x,pc_pos[targ].y))) + return FALSE; + if (is_town()) + if ((targ < 6) && (is_antimagic(c_town.p_loc.x,c_town.p_loc.y))) + return FALSE; + if ((targ >= 100) && (is_antimagic(c_town.monst.dudes[targ - 100].m_loc.x, + c_town.monst.dudes[targ - 100].m_loc.y))) + return FALSE; + + + // How about shockwave? Good idea? + if ((spell == 27) && (caster->attitude % 2 != 1)) + spell = 26; + if ((spell == 27) && (caster->attitude % 2 == 1) && (count_levels(caster->m_loc,10) < 45)) + spell = 26; + + l = caster->m_loc; + if ((caster->m_d.direction < 4) && (caster->m_d.x_width > 1)) + l.x++; + + if (caster->m_d.mp >= monst_mage_cost[spell - 1]) { + monst_cast_spell_note(caster->number,spell,0); + acted = TRUE; + caster->m_d.mp -= monst_mage_cost[spell - 1]; + + draw_terrain(2); + switch (spell) { + case 1: // spark + run_a_missile(l,vict_loc,6,1,11,0,0,80); + r1 = get_ran(2,1,4); + damage_target(targ,r1,1); + break; + case 2: // minor haste + play_sound(25); + caster->m_d.status[3] += 2; + break; + case 3: // strength + play_sound(25); + caster->m_d.status[1] += 3; + break; + case 4: // flame cloud + run_a_missile(l,vict_loc,2,1,11,0,0,80); + place_spell_pattern(single,vict_loc,5,FALSE,7); + break; + case 5: // flame + run_a_missile(l,vict_loc,2,1,11,0,0,80); + start_missile_anim(); + r1 = get_ran(caster->m_d.level,1,4); + damage_target(targ,r1,1); + break; + case 6: // minor poison + run_a_missile(l,vict_loc,11,0,25,0,0,80); + if (targ < 6) + adven[targ].poison(2 + get_ran(1,0,1)); + else c_town.monst.dudes[targ - 100].poison(2 + get_ran(1,0,1)); + break; + case 7: // slow + run_a_missile(l,vict_loc,15,0,25,0,0,80); + if (targ < 6) + adven[targ].slow(2 + caster->m_d.level / 2); + else c_town.monst.dudes[targ - 100].slow(2 + caster->m_d.level / 2); + break; + case 8: // dumbfound + run_a_missile(l,vict_loc,14,0,25,0,0,80); + if (targ < 6) + adven[targ].dumbfound(2); + else c_town.monst.dudes[targ - 100].dumbfound(2); + break; + case 9: // scloud + run_a_missile(l,target,0,0,25,0,0,80); + place_spell_pattern(square,target,7,FALSE,7); + break; + case 10: // summon beast + r1 = get_summon_monster(1); + if (r1 == 0) + break; + x = get_ran(3,1,4); + //Delay(12,&dummy); // gives sound time to end + play_sound(25); + play_sound(-61); + summon_monster(r1,caster->m_loc, + ((caster->attitude % 2 != 1) ? 0 : 100) + x,caster->attitude); + break; + case 11: // conflagration + run_a_missile(l,target,13,1,25,0,0,80); + place_spell_pattern(radius2,target,5,FALSE,7); + break; + case 12: // fireball + r1 = 1 + (caster->m_d.level * 3) / 4; + if (r1 > 29) r1 = 29; + run_a_missile(l,target,2,1,11,0,0,80); + start_missile_anim(); + place_spell_pattern(square,target,50 + r1,TRUE,7); + ashes_loc = target; + break; + case 13: case 20: case 26:// summon + play_sound(25); + if (spell == 13) { + r1 = get_summon_monster(1); + if (r1 == 0) + break; + j = get_ran(2,1,3) + 1; + } + if (spell == 20) { + r1 = get_summon_monster(2); + if (r1 == 0) + break; + j = get_ran(2,1,2) + 1; + } + if (spell == 26) { + r1 = get_summon_monster(3); + if (r1 == 0) + break; + j = get_ran(1,2,3); + } + Delay(12,&dummy); // gives sound time to end + x = get_ran(4,1,4); + for (i = 0; i < j; i++){ + play_sound(-61); + if (summon_monster(r1,caster->m_loc, + ((caster->attitude % 2 != 1) ? 0 : 100) + x,caster->attitude) == FALSE) { + add_string_to_buf(" Summon failed."); i = j;} + } + break; + case 14: // web + play_sound(25); + place_spell_pattern(radius2,target,1,FALSE,7); + break; + case 15: // poison + run_a_missile(l,vict_loc,11,0,25,0,0,80); + x = get_ran(1,0,3); + if (targ < 6) + adven[targ].poison(4 + x); + else c_town.monst.dudes[targ - 100].poison(4 + x); + break; + case 16: // ice bolt + run_a_missile(l,vict_loc,6,1,11,0,0,80); + r1 = get_ran(5 + (caster->m_d.level / 5),1,8); + start_missile_anim(); + damage_target(targ,r1,5); + break; + case 17: // slow gp + play_sound(25); + if (caster->attitude % 2 == 1) + for (i = 0; i < 6; i++) + if (pc_near(i,caster->m_loc,8)) + adven[i].slow(2 + caster->m_d.level / 4); + for (i = 0; i < T_M; i++) { + if ((c_town.monst.dudes[i].active != 0) && + (((c_town.monst.dudes[i].attitude % 2 == 1) && (caster->attitude % 2 != 1)) || + ((c_town.monst.dudes[i].attitude % 2 != 1) && (caster->attitude % 2 == 1)) || + ((c_town.monst.dudes[i].attitude % 2 == 1) && (caster->attitude != c_town.monst.dudes[i].attitude))) + && (dist(caster->m_loc,c_town.monst.dudes[i].m_loc) <= 7)) + c_town.monst.dudes[i].slow(2 + caster->m_d.level / 4); + } + break; + case 18: // major haste + play_sound(25); + for (i = 0; i < T_M; i++) + if ((monst_near(i,caster->m_loc,8,0)) && + (caster->attitude == c_town.monst.dudes[i].attitude)) { + affected = &c_town.monst.dudes[i]; + affected->m_d.status[3] += 3; + } + play_sound(4); + break; + case 19: // firestorm + run_a_missile(l,target,2,1,11,0,0,80); + r1 = 1 + (caster->m_d.level * 3) / 4 + 3; + if (r1 > 29) r1 = 29; + start_missile_anim(); + place_spell_pattern(radius2,target,50 + r1,TRUE,7); + ashes_loc = target; + break; + case 21: // shockstorm + run_a_missile(l,target,6,1,11,0,0,80); + place_spell_pattern(radius2,target,4,FALSE,7); + break; + case 22: // m. poison + run_a_missile(l,vict_loc,11,1,11,0,0,80); + x = get_ran(1,1,2); + if (targ < 6) + adven[targ].poison(6 + x); + else c_town.monst.dudes[targ - 100].poison(6 + x); + break; + case 23: // kill!!! + run_a_missile(l,vict_loc,9,1,11,0,0,80); + r1 = 35 + get_ran(3,1,10); + start_missile_anim(); + damage_target(targ,r1,3); + break; + case 24: // daemon + x = get_ran(3,1,4); + play_sound(25); + play_sound(-61); + Delay(12,&dummy); // gives sound time to end + summon_monster(85,caster->m_loc, + ((caster->attitude % 2 != 1) ? 0 : 100) + x,caster->attitude); + break; + case 25: // major bless + play_sound(25); + for (i = 0; i < T_M; i++) + if ((monst_near(i,caster->m_loc,8,0)) && + (caster->attitude == c_town.monst.dudes[i].attitude)) { + affected = &c_town.monst.dudes[i]; + affected->m_d.health += get_ran(2,1,10); + r1 = get_ran(3,1,4); + affected->m_d.status[1] = min(8,affected->m_d.status[1] + r1); + affected->m_d.status[6] = 0; + if (affected->m_d.status[3] < 0) + affected->m_d.status[3] = 0; + affected->m_d.morale += get_ran(3,1,10); + } + play_sound(4); + break; + case 27: // shockwave + do_shockwave(caster->m_loc); + break; + } + } + else caster->m_d.mp++; + + if (ashes_loc.x > 0) + make_sfx(ashes_loc.x,ashes_loc.y,6); + do_explosion_anim(5,0); + end_missile_anim(); + handle_marked_damage(); + + return acted; +} + +Boolean monst_cast_priest(creature_data_type *caster,short targ) +{ + short r1,r2,spell,i,x,level,target_levels,friend_levels_near; + Boolean acted = FALSE; + location target,vict_loc,l; + creature_data_type *affected; + short caster_array[7][10] = {{1,1,1,1,3,3,3,4,4,4}, + {5,5,6,6,7,7,8,8,8,9}, + {9,6,6,8,11,12,12,5,5,12}, + {12,12,13,13,14,9,9,14,14,15}, + {19,18,13,19,15,18,18,19,16,18}, + {22,18,16,19,18,18,21,22,23,23}, + {26,26,25,24,26,22,24,22,26,25}}; + short emer_spells[7][4] = {{0,1,0,2}, + {0,8,0,2}, + {0,8,0,10}, + {0,14,0,10}, + {0,19,18,17}, + {0,19,18,20}, + {25,25,26,24}}; + location ashes_loc; + + + if ((targ < 6) && (adven[targ].isAlive() == false)) + return FALSE; + if ((targ >= 100) && (c_town.monst.dudes[targ - 100].active == 0)) + return FALSE; + if (is_antimagic(caster->m_loc.x,caster->m_loc.y)) { + return FALSE; + } + level = max(1,caster->m_d.cl - caster->m_d.status[9]) - 1; + + target = find_fireball_loc(caster->m_loc,1,(caster->attitude % 2 == 1) ? 0 : 1,&target_levels); + friend_levels_near = (caster->attitude % 2 != 1) ? count_levels(caster->m_loc,3) : -1 * count_levels(caster->m_loc,3); + + if ((caster->m_d.health * 4 < caster->m_d.m_health) && (get_ran(1,0,10) < 9)) + spell = emer_spells[level][3]; + else if ((caster->m_d.status[3] < 0) && (get_ran(1,0,10) < 7) && (emer_spells[level][0] != 0)) + spell = emer_spells[level][0]; + else if ((friend_levels_near <= -10) && (get_ran(1,0,10) < 7) && (emer_spells[level][1] != 0)) + spell = emer_spells[level][1]; + else if ((target_levels > 50 < 0) && (get_ran(1,0,10) < 7) && (emer_spells[level][2] != 0)) + spell = emer_spells[level][2]; + else { + r1 = get_ran(1,0,9); + spell = caster_array[level][r1]; + } + + + + // Anything preventing spell? + if ((target.x > 64) && (monst_priest_area_effect[spell - 1] > 0)) { + r1 = get_ran(1,0,9); + spell = caster_array[level][r1]; + if ((target.x > 64) && (monst_priest_area_effect[spell - 1] > 0)) + return FALSE; + } + if (monst_priest_area_effect[spell - 1] > 0) + targ = 6; + if (targ < 6) + vict_loc = (is_town()) ? c_town.p_loc : pc_pos[targ]; + if (targ >= 100) + vict_loc = c_town.monst.dudes[targ - 100].m_loc; + if ((targ == 6) && (is_antimagic(target.x,target.y))) + return FALSE; + if ((targ < 6) && (is_antimagic(pc_pos[targ].x,pc_pos[targ].y))) + return FALSE; + if ((targ >= 100) && (is_antimagic(c_town.monst.dudes[targ - 100].m_loc.x, + c_town.monst.dudes[targ - 100].m_loc.y))) + return FALSE; + + // snuff heals if unwounded + if ((caster->m_d.health == caster->m_d.m_health) && + ((spell == 17) || (spell == 20))) + spell--; + + l = caster->m_loc; + if ((caster->m_d.direction < 4) && (caster->m_d.x_width > 1)) + l.x++; + + if (caster->m_d.mp >= monst_priest_cost[spell - 1]) { + monst_cast_spell_note(caster->number,spell,1); + acted = TRUE; + caster->m_d.mp -= monst_priest_cost[spell - 1]; + draw_terrain(2); + switch (spell) { + case 3: // wrack + run_a_missile(l,vict_loc,8,0,24,0,0,80); + r1 = get_ran(2,1,4); + start_missile_anim(); + damage_target(targ,r1,4); + break; + case 4: // stumble + play_sound(24); + place_spell_pattern(single,vict_loc,1,FALSE,7); + break; + case 1: case 5: // Blesses + play_sound(24); + caster->m_d.status[1] = min(8,caster->m_d.status[1] + (spell == 1) ? 3 : 5); + play_sound(4); + break; + case 6: // curse + run_a_missile(l,vict_loc,8,0,24,0,0,80); + x = get_ran(1,0,1); + if (targ < 6) + adven[targ].curse(2 + x); + else c_town.monst.dudes[targ - 100].curse(2 + x); + break; + case 7: // wound + run_a_missile(l,vict_loc,8,0,24,0,0,80); + r1 = get_ran(2,1,6) + 2; + start_missile_anim(); + damage_target(targ,r1,3); + break; + case 8: case 22: // summon spirit,summon guardian + play_sound(24); + play_sound(-61); + + x = get_ran(3,1,4); + summon_monster(((spell == 8) ? 125 : 122),caster->m_loc, + ((caster->attitude % 2 != 1) ? 0 : 100) + x,caster->attitude); + break; + case 9: // disease + run_a_missile(l,vict_loc,11,0,24,0,0,80); + x = get_ran(1,0,2); + if (targ < 6) + adven[targ].disease(2 + x); + else c_town.monst.dudes[targ - 100].disease(2 + x); + break; + case 11: // holy scourge + run_a_missile(l,vict_loc,15,0,24,0,0,80); + if (targ < 6) { + r1 = get_ran(1,0,2); + adven[targ].slow(2 + r1); + r1 = get_ran(1,0,2); + adven[targ].curse(3 + r1); + } + else { + r1 = get_ran(1,0,2); + c_town.monst.dudes[targ - 100].slow(r1); + r1 = get_ran(1,0,2); + c_town.monst.dudes[targ - 100].curse(r1); + } + break; + case 12: // smite + run_a_missile(l,vict_loc,6,0,24,0,0,80); + r1 = get_ran(4,1,6) + 2; + start_missile_anim(); + damage_target(targ,r1,5); + break; + case 14: // sticks to snakes + play_sound(24); + r1 = get_ran(1,1,4) + 2; + for (i = 0; i < r1; i++) { + play_sound(-61); + r2 = get_ran(1,0,7); + x = get_ran(3,1,4); + summon_monster((r2 == 1) ? 100 : 99,caster->m_loc, + ((caster->attitude % 2 != 1) ? 0 : 100) + x,caster->attitude); + } + break; + case 15: // martyr's shield + play_sound(24); + caster->m_d.status[10] = min(10,caster->m_d.status[10] + 5); + break; + case 19: // summon host + play_sound(24); + x = get_ran(3,1,4) + 1; + play_sound(-61); + summon_monster(126,caster->m_loc, + ((caster->attitude % 2 != 1) ? 0 : 100) + x,caster->attitude); + for (i = 0; i < 4; i++) { + play_sound(-61); + if (summon_monster(125,caster->m_loc, + ((caster->attitude % 2 != 1) ? 0 : 100) + x,caster->attitude) == FALSE) + i = 4; + } + break; + + case 13: case 23: // holy scourge,curse all,pestilence + play_sound(24); + r1 = get_ran(2,0,2); + r2 = get_ran(1,0,2); + if (caster->attitude % 2 == 1) + for (i = 0; i < 6; i++) + if (pc_near(i,caster->m_loc,8)) { + if (spell == 13) + adven[i].curse(2 + r1); + if (spell == 23) + adven[i].disease(2 + r2); + } + for (i = 0; i < T_M; i++) { + if ((c_town.monst.dudes[i].active != 0) && + (((c_town.monst.dudes[i].attitude % 2 == 1) && (caster->attitude % 2 != 1)) || + ((c_town.monst.dudes[i].attitude % 2 != 1) && (caster->attitude % 2 == 1)) || + ((c_town.monst.dudes[i].attitude % 2 == 1) && (caster->attitude != c_town.monst.dudes[i].attitude))) + && (dist(caster->m_loc,c_town.monst.dudes[i].m_loc) <= 7)) { + if (spell == 13) + c_town.monst.dudes[i].curse(2 + r1); + if (spell == 23) + c_town.monst.dudes[i].disease(2 + r2); + } + } + break; + + case 2: case 10: case 17: case 20: // heals + play_sound(24); + switch(spell) { + case 2: r1 = get_ran(2,1,4) + 2; break; + case 10: r1 = get_ran(3,1,6); break; + case 17: r1 = get_ran(5,1,6) + 3; break; + case 20: r1 = 50; break; + } + caster->m_d.health = min(caster->m_d.health + r1, caster->m_d.m_health); + break; + case 16: case 24:// bless all,revive all + play_sound(24); + r1 = get_ran(2,1,4); r2 = get_ran(3,1,6); + for (i = 0; i < T_M; i++) + if ((monst_near(i,caster->m_loc,8,0)) && + (caster->attitude == c_town.monst.dudes[i].attitude)) { + affected = &c_town.monst.dudes[i]; + if (spell == 16) + affected->m_d.status[1] = min(8,affected->m_d.status[1] + r1); + if (spell == 24) + affected->m_d.health += r1; + } + play_sound(4); + break; + case 18: // Flamestrike + run_a_missile(l,target,2,0,11,0,0,80); + r1 = 2 + caster->m_d.level / 2 + 2; + start_missile_anim(); + place_spell_pattern(square,target,50 + r1,TRUE,7); + ashes_loc = target; + break; + + + case 21: // holy ravaging + run_a_missile(l,vict_loc,14,0,53,0,0,80); + r1 = get_ran(4,1,8); + r2 = get_ran(1,0,2); + damage_target(targ,r1,3); + if (targ < 6) { + adven[targ].slow(6); + adven[targ].poison(5 + r2); + } + else { + c_town.monst.dudes[targ - 100].slow(6); + c_town.monst.dudes[targ - 100].poison(5 + r2); + } + break; + case 25: // avatar + play_sound(24); + monst_spell_note(caster->number,26); + caster->m_d.health = caster->m_d.m_health; + caster->m_d.status[1] = 8; + caster->m_d.status[2] = 0; + caster->m_d.status[3] = 8; + caster->m_d.status[6] = 0; + caster->m_d.status[7] = 0; + caster->m_d.status[9] = 0; + caster->m_d.status[10] = 8; + break; + case 26: // divine thud + run_a_missile(l,target,9,0,11,0,0,80); + r1 = (caster->m_d.level * 3) / 4 + 5; + if (r1 > 29) r1 = 29; + start_missile_anim(); + place_spell_pattern(radius2,target,130 + r1,TRUE,7 ); + ashes_loc = target; + break; + } + + + } + else caster->m_d.mp++; + if (ashes_loc.x > 0) + make_sfx(ashes_loc.x,ashes_loc.y,6); + do_explosion_anim(5,0); + end_missile_anim(); + handle_marked_damage(); + + return acted; +} + +void damage_target(short target,short dam,short type) +{ + if (target == INVALID_PC) return; + if (target < NUM_OF_PCS) + adven[target].damage(dam,type,-1); + else damage_monst(target - 100, 7, dam, 0, type); +} + + +// target = find_fireball_loc(caster->m_loc,1,(caster->attitude == 1) ? 0 : 1,&target_levels); + +location find_fireball_loc(location where,short radius,short mode,short *m) +//short mode; // 0 - hostile casting 1 - friendly casting +{ + location check_loc,cast_loc = location(120,0); + short cur_lev,level_max = 10; + + for (check_loc.x = 1; check_loc.x < town_size[town_type] - 1; check_loc.x ++) + for (check_loc.y = 1; check_loc.y < town_size[town_type] - 1; check_loc.y ++) + if ((dist(where,check_loc) <= 8) && (can_see(where,check_loc,2) < 5) && (get_obscurity(check_loc.x,check_loc.y) < 5)) { + { + cur_lev = count_levels(check_loc,radius); + if (mode == 1) + cur_lev = cur_lev * -1; + if ( ((cur_lev > level_max) || ((cur_lev == level_max) && (get_ran(1,0,1) == 0))) + && (dist(where,check_loc) > radius)) { + level_max = cur_lev; + cast_loc = check_loc; + } + } + } + *m = level_max; + + return cast_loc; +} + +location closest_pc_loc(location where) +{ + short i; + location pc_where = location(120,120); + + for (i = 0; i < 6; i++) + if (adven[i].isAlive()) + if ((dist(where,pc_pos[i])) < (dist(where,pc_where))) + pc_where = pc_pos[i]; + return pc_where; +} + +short count_levels(location where,short radius) +{ + short i,store = 0; + + for (i = 0; i < T_M; i++) + if (monst_near(i,where,radius,0) == TRUE) { + if (c_town.monst.dudes[i].attitude % 2 == 1) + store = store - c_town.monst.dudes[i].m_d.level; + else store = store + c_town.monst.dudes[i].m_d.level; + } + if (is_combat()) { + for (i = 0; i < 6; i++) + if (pc_near(i,where,radius) == TRUE) + store = store + 10; + } + if (is_town()) + if ((vdist(where,c_town.p_loc) <= radius) && (can_see(where,c_town.p_loc,2) < 5)) + store += 20; + + return store; +} + +Boolean pc_near(short pc_num,location where,short radius) +{ + // Assuming not looking + if (overall_mode >= 10) { + if ((adven[pc_num].isAlive()) && (vdist(pc_pos[pc_num],where) <= radius)) + return TRUE; + else return FALSE; + } + if ((adven[pc_num].isAlive()) && (vdist(c_town.p_loc,where) <= radius)) + return TRUE; + else return FALSE; +} + +Boolean monst_near(short m_num,location where,short radius,short active) +//short active; // 0 - any monst 1 - monster need be active +{ + if ((c_town.monst.dudes[m_num].active != 0) && (vdist(c_town.monst.dudes[m_num].m_loc,where) <= radius) + && ((active == 0) || (c_town.monst.dudes[m_num].active == 2)) ) + return TRUE; + else return FALSE; +} + +void place_spell_pattern(effect_pat_type pat,location center,short type,Boolean,short who_hit) +//type; // 0 - take codes in pattern, OW make all nonzero this type +// Types 0 - Null 1 - web 2 - fire barrier 3 - force barrier 4 - force wall 5 - fire wall +// 6 - anti-magic field 7 - stink cloud 8 - ice wall 9 - blade wall 10 - quickfire +// 11 - dispel 12 - sleep field +// 50 + i - 80 : id6 fire damage 90 + i - 120 : id6 cold damage 130 + i - 160 : id6 magic dam. +// if prep for anim is TRUE, suppress look checks and go fast +{ + short i,j,r1,k,store = 0; + unsigned char effect; + location spot_hit; + location s_loc; + RECT active; + creature_data_type *which_m; + Boolean monster_hit = FALSE; + +if (type > 0) + modify_pattern(&pat,type); + + active = c_town.town.in_town_rect.rect32();; + // eliminate barriers that can't be seen + for (i = minmax(active.left + 1,active.right - 1,(long)center.x - 4); + i <= minmax(active.left + 1,active.right - 1,(long)center.x + 4); i++) + for (j = minmax(active.top + 1,active.bottom - 1,(long)center.y - 4); + j <= minmax(active.top + 1,active.bottom - 1,(long)center.y + 4); j++) { + s_loc.x = i; s_loc.y = j; + if (can_see(center,s_loc,0) > 4) + pat.pattern[i - center.x + 4][j - center.y + 4] = 0; + } + + + // First actually make barriers, then draw them, then inflict damaging effects. + for (i = minmax(0,town_size[town_type] - 1,center.x - 4); i <= minmax(0,town_size[town_type] - 1,center.x + 4); i++) + for (j = minmax(0,town_size[town_type] - 1,center.y - 4); j <= minmax(0,town_size[town_type] - 1,center.y + 4); j++) + if (get_obscurity(i,j) < 5) { + effect = pat.pattern[i - center.x + 4][j - center.y + 4]; + switch (effect) { + case 1: web_space(i,j); break; + case 2: make_fire_barrier(i,j); break; + case 3: make_force_barrier(i,j); break; + case 4: + make_force_wall(i,j); break; + case 5: make_fire_wall(i,j); break; + case 6: make_antimagic(i,j); break; + case 7: scloud_space(i,j); break; + case 8: make_ice_wall(i,j); break; + case 9: make_blade_wall(i,j); break; + case 10: + make_quickfire(i,j); + break; + case 11: + dispel_fields(i,j,0); + break; + case 12: sleep_cloud_space(i,j); break; + } + } + draw_terrain(0); + if (is_town()) // now make things move faster if in town + fast_bang = 2; + + // Damage to pcs + for (k = 0; k < 6; k++) + for (i = minmax(0,town_size[town_type] - 1,center.x - 4); i <= minmax(0,town_size[town_type] - 1,center.x + 4); i++) + for (j = minmax(0,town_size[town_type] - 1,center.y - 4); j <= minmax(0,town_size[town_type] - 1,center.y + 4); j++) { + spot_hit.x = i; + spot_hit.y = j; + if ((get_obscurity(i,j) < 5) && (adven[k].isAlive()) + && (((is_combat()) &&(same_point(pc_pos[k],spot_hit) == TRUE)) || + ((is_town()) && (same_point(c_town.p_loc,spot_hit) == TRUE)))) { + effect = pat.pattern[i - center.x + 4][j - center.y + 4]; + switch (effect) { + case 4: + r1 = get_ran(2,1,6); + adven[k].damage(r1,3,-1); + break; + case 5: + r1 = get_ran(1,1,6) + 1; + adven[k].damage(r1,1,-1); + break; + case 8: + r1 = get_ran(2,1,6); + adven[k].damage(r1,5,-1); + break; + case 9: + r1 = get_ran(4,1,8); + adven[k].damage(r1,0,-1); + break; + default: + if ((effect >= 50) && (effect < 80)) { + r1 = get_ran(effect - 50,1,6); + adven[k].damage(r1,1,-1); + } + if ((effect >= 90) && (effect < 120)) { + r1 = get_ran(effect - 90,1,6); + adven[k].damage(r1,5,-1); + } + if ((effect >= 130) && (effect < 160)) { + r1 = get_ran(effect - 130,1,6); + adven[k].damage(r1,3,-1); + } + break; + } + } + } + + fast_bang = 0; + + // Damage to monsters + for (k = 0; k < T_M; k++) + if ((c_town.monst.dudes[k].active > 0) && (dist(center,c_town.monst.dudes[k].m_loc) <= 5)) { + monster_hit = FALSE; + // First actually make barriers, then draw them, then inflict damaging effects. + for (i = minmax(0,town_size[town_type] - 1,center.x - 4); i <= minmax(0,town_size[town_type] - 1,center.x + 4); i++) + for (j = minmax(0,town_size[town_type] - 1,center.y - 4); j <= minmax(0,town_size[town_type] - 1,center.y + 4); j++) { + spot_hit.x = i; + spot_hit.y = j; + + if ((monster_hit == FALSE) && (get_obscurity(i,j) < 5) && (monst_on_space(spot_hit,k) > 0)) { + + if (pat.pattern[i - center.x + 4][j - center.y + 4] > 0) + monster_hit = TRUE; + effect = pat.pattern[i - center.x + 4][j - center.y + 4]; + switch (effect) { + case 1: + which_m = &c_town.monst.dudes[k]; + which_m->web(3); + break; + case 4: + r1 = get_ran(3,1,6); + damage_monst(k, who_hit, r1,0, 3); + break; + case 5: + r1 = get_ran(2,1,6); + which_m = &c_town.monst.dudes[k]; + if (which_m->m_d.spec_skill == 22) + break; + damage_monst(k, who_hit, r1,0, 1); + break; + case 7: + which_m = &c_town.monst.dudes[k]; + which_m->curse(get_ran(1,1,2)); + break; + case 8: + which_m = &c_town.monst.dudes[k]; + r1 = get_ran(3,1,6); + if (which_m->m_d.spec_skill == 23) + break; + damage_monst(k, who_hit, r1,0, 5); + break; + case 9: + r1 = get_ran(6,1,8); + damage_monst(k, who_hit, r1,0, 0); + break; + case 12: + which_m = &c_town.monst.dudes[k]; + which_m->charm(0,11,3); + break; + default: + if ((effect >= 50) && (effect < 80)) { + r1 = get_ran(effect - 50,1,6); + damage_monst(k,who_hit, r1,0,1); + } + if ((effect >= 90) && (effect < 120)) { + r1 = get_ran(effect - 90,1,6); + damage_monst(k,who_hit, r1,0, 5); + } + if ((effect >= 130) && (effect < 160)) { + r1 = get_ran(effect - 130,1,6); + damage_monst(k,who_hit, r1,0, 3 ); + } + } + } + } + } +} + + +void modify_pattern(effect_pat_type *pat,short type) +{ + short i,j; + + for (i = 0; i < 9; i++) + for (j = 0; j < 9; j++) + if (pat->pattern[i][j] > 0) + pat->pattern[i][j] = type; +} + +void do_shockwave(location target) +{ + short i; + + start_missile_anim(); + for (i = 0; i < 6; i++) + if ((dist(target,pc_pos[i]) > 0) && (dist(target,pc_pos[i]) < 11) + && (adven[i].isAlive())) + adven[i].damage(get_ran(2 + dist(target,pc_pos[i]) / 2, 1, 6), 4,-1); + for (i = 0; i < T_M; i++) + if ((c_town.monst.dudes[i].active != 0) && (dist(target,c_town.monst.dudes[i].m_loc) > 0) + && (dist(target,c_town.monst.dudes[i].m_loc) < 11) + && (can_see(target,c_town.monst.dudes[i].m_loc,0) < 5)) + damage_monst(i, current_pc, get_ran(2 + dist(target,c_town.monst.dudes[i].m_loc) / 2 , 1, 6), 0, 4); + do_explosion_anim(5,0); + end_missile_anim(); + handle_marked_damage(); +} + +void radius_damage(location target,short radius, short dam, short type)//// +{ + short i; + + if (is_town()) { + for (i = 0; i < 6; i++) + if ((dist(target,c_town.p_loc) > 0) && (dist(target,c_town.p_loc) <= radius) + && (adven[i].isAlive())) + adven[i].damage(dam, type,-1); + for (i = 0; i < T_M; i++) + if ((c_town.monst.dudes[i].active != 0) && (dist(target,c_town.monst.dudes[i].m_loc) > 0) + && (dist(target,c_town.monst.dudes[i].m_loc) <= radius) + && (can_see(target,c_town.monst.dudes[i].m_loc,0) < 5)) + damage_monst(i, current_pc, dam, 0, type); + return; + } + + start_missile_anim(); + for (i = 0; i < 6; i++) + if ((dist(target,pc_pos[i]) > 0) && (dist(target,pc_pos[i]) <= radius) + && (adven[i].isAlive())) + adven[i].damage(dam, type,-1); + for (i = 0; i < T_M; i++) + if ((c_town.monst.dudes[i].active != 0) && (dist(target,c_town.monst.dudes[i].m_loc) > 0) + && (dist(target,c_town.monst.dudes[i].m_loc) <= radius) + && (can_see(target,c_town.monst.dudes[i].m_loc,0) < 5)) + damage_monst(i, current_pc, dam, 0, type); + do_explosion_anim(5,0); + end_missile_anim(); + handle_marked_damage(); +} + +// Slightly kludgy way to only damage PCs in space) +void hit_pcs_in_space(location target,short dam,short type,short report,short hit_all) +{ + hit_space(target, dam,type, report, 10 + hit_all); +} + +void hit_space(location target,short dam,short type,short report,short hit_all) +//type; // 0 - weapon 1 - fire 2 - poison 3 - general magic 4 - unblockable 5 - cold + // 6 - demon 7 - undead +//short report; // 0 - no 1 - print result +//hit_all; // 0 - nail top thing 1 - hit all in space + 10 ... no monsters +{ + short i; + Boolean stop_hitting = FALSE,hit_monsters = TRUE; + + if ((target.x < 0) || (target.x > 63) || (target.y < 0) || (target.y > 63)) + return; + + if (hit_all >= 10) { + hit_monsters = FALSE; + hit_all -= 10; + } + + if ((is_antimagic(target.x,target.y)) && ((type == 1) || (type == 3) || (type == 5))) { + return; + } + + if (dam <= 0) { + add_string_to_buf(" No damage."); + return; + } + + for (i = 0; i < T_M; i++) + if ((hit_monsters == TRUE) && (c_town.monst.dudes[i].active != 0) && (stop_hitting == FALSE)) + if (monst_on_space(target,i)) { + if (processing_fields == TRUE) + damage_monst(i, 6, dam, 0, type); + else damage_monst(i, (monsters_going == TRUE) ? 7 : current_pc, dam, 0, type); + stop_hitting = (hit_all == 1) ? FALSE : TRUE; + } + + if (overall_mode >= 10) + for (i = 0; i < NUM_OF_PCS; i++) + if ((adven[i].isAlive()) && (stop_hitting == FALSE)) + if (same_point(pc_pos[i],target) == TRUE) { + adven[i].damage(dam,type,-1); + stop_hitting = (hit_all == 1) ? FALSE : TRUE; + } + if (overall_mode < 10) + if (same_point(target,c_town.p_loc) == TRUE) { + fast_bang = 1; + adven.damage(dam,type); + fast_bang = 0; + stop_hitting = (hit_all == 1) ? FALSE : TRUE; + } + + if ((report == 1) && (hit_all == 0) && (stop_hitting == FALSE)) + add_string_to_buf(" Missed."); + +} + + + +void do_poison() +{ + short i,r1 = 0; + Boolean some_poison = FALSE; + + for (i = 0; i < 6; i++) + if (adven[i].isAlive()) + if (adven[i].status[2] > 0) + some_poison = TRUE; + if (some_poison == TRUE) { + add_string_to_buf("Poison: "); + for (i = 0; i < 6; i++) + if (adven[i].isAlive()) + if (adven[i].status[2] > 0) { + r1 = get_ran(adven[i].status[2],1,6); + adven[i].damage(r1,2,-1); + if (get_ran(1,0,8) < 6) + move_to_zero(adven[i].status[2]); + if (get_ran(1,0,8) < 6) + if (adven[i].traits[6] == TRUE) + move_to_zero(adven[i].status[2]); + } + put_pc_screen(); + } +} + + +void handle_disease() +{ + short i,r1 = 0; + Boolean disease = FALSE; + + for (i = 0; i < 6; i++) + if (adven[i].isAlive()) + if (adven[i].status[7] > 0) + disease = TRUE; + + if (disease == TRUE) { + add_string_to_buf("Disease: "); + for (i = 0; i < NUM_OF_PCS; i++) + if (adven[i].isAlive()) + if (adven[i].status[7] > 0) { + r1 = get_ran(1,1,10); + switch (r1) { + case 1: case 2: + adven[i].poison(2); + break; + case 3: case 4: + adven[i].slow(2); + break; + case 5: + adven[i].drainXP(5); + break; + case 6: case 7: + adven[i].curse(3); + break; + case 8: + adven[i].dumbfound(3); + break; + case 9: case 10: + sprintf ((char *) create_line, " %s unaffected. ", + (char *) adven[i].name); + add_string_to_buf((char *) create_line); + break; + } + r1 = get_ran(1,0,7); + if (adven[i].traits[6] == TRUE) + r1 -= 2; + if ((get_ran(1,0,7) <= 0) || (adven[i].hasAbilEquip(67) < 24)) + move_to_zero(adven[i].status[7]); + } + put_pc_screen(); + } +} + +void handle_acid() +{ + short i,r1 = 0; + Boolean some_acid = FALSE; + + for (i = 0; i < NUM_OF_PCS; i++) + if (adven[i].isAlive()) + if (adven[i].status[13] > 0) + some_acid = TRUE; + + if (some_acid == TRUE) { + add_string_to_buf("Acid: "); + for (i = 0; i < NUM_OF_PCS; i++) + if (adven[i].isAlive()) + if (adven[i].status[13] > 0) { + r1 = get_ran(adven[i].status[13],1,6); + adven[i].damage(r1,3,-1); + move_to_zero(adven[i].status[13]); + } + if (overall_mode < 10) + boom_space(party.p_loc,overall_mode,3,r1,8); + } +} + +Boolean no_pcs_left() +{ + short i = 0; + + while (i < 6) { + if (adven[i].isAlive()) + return FALSE; + i++; + } + return TRUE; + +} + +Boolean hit_end_c_button() +{ + Boolean end_ok = TRUE; + + if (which_combat_type == 0) { + end_ok = out_monst_all_dead(); + } + if (end_ok == TRUE) + end_combat(); + return end_ok; +} + +Boolean out_monst_all_dead() +{ + short i; + + for (i = 0; i < T_M; i++) + if ((c_town.monst.dudes[i].active > 0) && (c_town.monst.dudes[i].attitude % 2 == 1)) + return FALSE; + return TRUE; +} + +void end_combat() +{ + short i; + + for (i = 0; i < 6; i++) { + if (adven[i].main_status == MAIN_STATUS_FLED) + adven[i].main_status = MAIN_STATUS_ALIVE; + adven[i].status[0] = 0; + adven[i].status[1] = 0; + adven[i].status[3] = 0; + } + if (which_combat_type == 0) { + overall_mode = 0; + load_area_graphics(); + } + combat_active_pc = 6; + current_pc = store_current_pc; + if (adven[current_pc].isAlive() == false) + current_pc = first_active_pc(); + put_item_screen(stat_window,0); + draw_buttons(0); +} + + +Boolean combat_cast_mage_spell() +{ + short spell_num,target,i,store_sp,bonus = 1,r1,store_sound = 0,store_m_type = 0,num_opp = 0; + char c_line[60]; + creature_data_type *which_m; + monster_record_type get_monst; + // 0 - refer 1 - do in combat immed. 2 - need targeting 3 - need fancy targeting + short refer_mage[62] = {0,2,1,1,2,2,0,2,2,0, 2,2,2,2,1,2,2,2,2,2, 0,1,2,0,2,2,3,3,2,1, + 2,2,1,0,2,2,3,2, 0,1,2,0,2,3,2,3, 2,1,2,3,2,2,2,0, 1,1,1,0,3,2,2,3}; + + if (is_antimagic(pc_pos[current_pc].x,pc_pos[current_pc].y)) { + add_string_to_buf(" Not in antimagic field."); + return FALSE; + } + store_sp = adven[current_pc].cur_sp; + if (adven[current_pc].cur_sp == 0) + add_string_to_buf("Cast: No spell points. "); + else if (adven[current_pc].skills[SKILL_MAGE_SPELLS] == 0) + add_string_to_buf("Cast: No mage skill. "); + else if (get_encumberance(current_pc) > 1) { + add_string_to_buf("Cast: Too encumbered. "); + take_ap(6); + give_help(40,0,0); + return TRUE; + } + else { + + + if (spell_forced == FALSE) + spell_num = pick_spell(current_pc,0,2); + else { + if (repeat_cast_ok(0) == FALSE) + return FALSE; + spell_num = pc_last_cast[0][current_pc]; + } + + if (spell_num == 35) { + store_sum_monst = pick_trapped_monst(); + if (store_sum_monst == 0) + return FALSE; + get_monst = return_monster_template(store_sum_monst); + if (store_sp < get_monst.level) { + add_string_to_buf("Cast: Not enough spell points. "); + return FALSE; + } + store_sum_monst_cost = get_monst.level; + } + + bonus = adven[current_pc].statAdj(2); + combat_posing_monster = current_working_monster = current_pc; + if (spell_num >= 70) + return FALSE; + if (spell_num < 70) { + print_spell_cast(spell_num,0); + if (refer_mage[spell_num] == 0) { + take_ap(6); + draw_terrain(2); + do_mage_spell(current_pc,spell_num); + combat_posing_monster = current_working_monster = -1; + } + else if (refer_mage[spell_num] == 2) { + start_spell_targeting(spell_num); + } + else if (refer_mage[spell_num] == 3) { + start_fancy_spell_targeting(spell_num); + } + else { + start_missile_anim(); + take_ap(6); + draw_terrain(2); + switch (spell_num) { + case 54: + adven[current_pc].cur_sp -= s_cost[0][spell_num]; + add_string_to_buf(" The ground shakes. "); + do_shockwave(pc_pos[current_pc]); + break; + + case 2: case 21: case 3: case 14: case 29: + target = store_spell_target; + if (target < 6) { + adven[current_pc].cur_sp -= s_cost[0][spell_num]; + play_sound(4); + switch (spell_num) { + case 14: + sprintf ((char *) c_line, " %s receives venom. ", + (char *) adven[target].name); + poison_weapon(target,3 + bonus,1); + store_m_type = 11; + break; + + case 3: + sprintf ((char *) c_line, " %s stronger. ", + (char *) adven[target].name); + adven[target].status[1] = adven[target].status[1] + 3; + store_m_type = 8; + break; + case 29: + sprintf ((char *) c_line, " %s resistant. ", + (char *) adven[target].name); + adven[target].status[5] = adven[target].status[5] + 5 + bonus; + store_m_type = 15; + break; + + default: + i = (spell_num == 2) ? 2 : max(2,adven[current_pc].level / 2 + bonus); + adven[target].status[3] = min(8,adven[target].status[3] + i); + sprintf ((char *) c_line, " %s hasted. ", + (char *) adven[target].name); + store_m_type = 8; + break; + } + add_string_to_buf((char *) c_line); + add_missile(pc_pos[target],store_m_type,0,0,0); + } + break; + + case 39: case 55: + store_sound = 25; + adven[current_pc].cur_sp -= s_cost[0][spell_num]; + + + for (i = 0; i < 6; i++) + if (adven[i].isAlive()) { + adven[i].status[3] = min(8, + adven[i].status[3] + ((spell_num == 39) ? 1 + adven[current_pc].level / 8 + bonus : 3 + bonus)); + if (spell_num == 55) { + poison_weapon(i,2,1); + adven[i].status[1] += 4; + add_missile(pc_pos[i],14,0,0,0); + } + else add_missile(pc_pos[i],8,0,0,0); + } + //play_sound(4); + if (spell_num == 39) + sprintf ((char *) c_line, " Party hasted. "); + else + sprintf ((char *) c_line, " Party blessed! "); + add_string_to_buf((char *) c_line); + + break; + + + + case 32: case 47: case 56: // affect monsters in area spells + adven[current_pc].cur_sp -= s_cost[0][spell_num]; + store_sound = 25; + if (spell_num == 47) + store_sound = 54; + switch (spell_num) { + case 32: sprintf ((char *) c_line, " Enemy slowed: "); break; + case 49: sprintf ((char *) c_line, " Enemy ravaged: ");break; + case 47: sprintf ((char *) c_line, " Enemy scared: ");break; + case 56: sprintf ((char *) c_line, " Enemy paralyzed: ");break; + } + add_string_to_buf((char *) c_line); + for (i = 0; i < T_M; i++) { + if ((c_town.monst.dudes[i].active != 0) && (c_town.monst.dudes[i].attitude % 2 == 1) + && (dist(pc_pos[current_pc],c_town.monst.dudes[i].m_loc) <= mage_range[spell_num]) + && (can_see(pc_pos[current_pc],c_town.monst.dudes[i].m_loc,0) < 5)) { + which_m = &c_town.monst.dudes[i]; + switch (spell_num) { + case 47: + r1 = get_ran(adven[current_pc].level / 3,1,8); + which_m->scare(r1); + store_m_type = 10; + break; + case 32: case 49: + which_m->slow(5 + bonus); + if (spell_num == 49) + which_m->curse(3 + bonus); + store_m_type = 8; + break; + case 56: + which_m->charm(5,12,1000); + store_m_type = 15; + break; + } + num_opp++; + add_missile(c_town.monst.dudes[i].m_loc,store_m_type,0, + 14 * (which_m->m_d.x_width - 1),18 * (which_m->m_d.y_width - 1)); + } + + } + break; + + } + + } + if (num_opp < 10) + do_missile_anim((num_opp < 5) ? 50 : 25,pc_pos[current_pc],store_sound); + else play_sound(store_sound); + end_missile_anim(); + put_pc_screen(); + + } + } + combat_posing_monster = current_working_monster = -1; + // Did anything actually get cast? + if (store_sp == adven[current_pc].cur_sp) + return FALSE; + else return TRUE; +} + + +Boolean combat_cast_priest_spell() +{ + short spell_num,target,i,store_sp,bonus,store_sound = 0,store_m_type = 0,num_opp = 0; + char c_line[60]; + creature_data_type *which_m; + // 0 - refer 1 - do in combat immed. 2 - need targeting 3 - need fancy targeting + short refer_priest[62] = {1,0,0,2,0,0,0,0,0,2, 1,0,2,0,2,2,0,2,3,0, 0,0,2,0,0,0,2,0,0,3, + 0,1,2,0,3,0,0,0, 1,0,0,2,0,3,0,2, 0,0,0,0,2,1,1,1, 0,2,0,2,1,2,0,0}; + effect_pat_type protect_pat = {{{0,4,4,4,4,4,4,4,0}, + {4,8,8,8,8,8,8,8,4}, + {4,8,9,9,9,9,9,8,4}, + {4,8,9,6,6,6,9,8,4}, + {4,8,9,6,6,6,9,8,4}, + {4,8,9,6,6,6,9,8,4}, + {4,8,9,9,9,9,9,8,4}, + {4,8,8,8,8,8,8,8,4}, + {0,4,4,4,4,4,4,4,0}}}; + + if (is_antimagic(pc_pos[current_pc].x,pc_pos[current_pc].y)) { + add_string_to_buf(" Not in antimagic field."); + return FALSE; + } + if (spell_forced == FALSE) + spell_num = pick_spell(current_pc,1,2); + else { + if (repeat_cast_ok(1) == FALSE) + return FALSE; + spell_num = pc_last_cast[1][current_pc]; + } + + store_sp = adven[current_pc].cur_sp; + + if (spell_num >= 70) + return FALSE; + + bonus = adven[current_pc].statAdj(2); + + combat_posing_monster = current_working_monster = current_pc; + + if (adven[current_pc].cur_sp == 0) + add_string_to_buf("Cast: No spell points. "); + else if (spell_num < 70) { + print_spell_cast(spell_num,1); + if (refer_priest[spell_num] == 0) { + take_ap(5); + draw_terrain(2); + do_priest_spell(current_pc,spell_num); + } + else if (refer_priest[spell_num] == 2) { + start_spell_targeting(100 + spell_num); + } + else if (refer_priest[spell_num] == 3) { + start_fancy_spell_targeting(100 + spell_num); + } + else { + start_missile_anim(); + take_ap(5); + draw_terrain(2); + switch (spell_num) { + case 0: case 10: +// target = select_pc(11,0); + target = store_spell_target; + if (target < 6) { + store_sound = 4; + adven[current_pc].cur_sp -= s_cost[1][spell_num]; + adven[target].status[1] += (spell_num == 0) ? 2 : + max(2,(adven[current_pc].level * 3) / 4 + 1 + bonus); + sprintf ((char *) c_line, " %s blessed. ", + (char *) adven[target].name); + add_string_to_buf((char *) c_line); + add_missile(pc_pos[target],8,0,0,0); + } + break; + + case 38: + adven[current_pc].cur_sp -= s_cost[1][spell_num]; + for (i = 0; i < 6; i++) + if (adven[i].isAlive()) { + adven[i].status[1] += adven[current_pc].level / 3; + add_missile(pc_pos[i],8,0,0,0); + } + sprintf ((char *) c_line, " Party blessed. "); + add_string_to_buf((char *) c_line); + store_sound = 4; + break; + + case 58: + adven[current_pc].cur_sp -= s_cost[1][spell_num]; + sprintf ((char *) c_line, " %s is an avatar! ", + (char *) adven[current_pc].name); + add_string_to_buf((char *) c_line); + adven[current_pc].heal(200); + adven[current_pc].cure(8); + adven[current_pc].status[1] = 8; + adven[current_pc].status[3] = 8; + adven[current_pc].status[4] = 3; + adven[current_pc].status[5] = 8; + adven[current_pc].status[6] = 0; + adven[current_pc].status[7] = 0; + adven[current_pc].status[9] = 0; + adven[current_pc].status[10] = 8; + break; + + case 31: case 51: case 53: + adven[current_pc].cur_sp -= s_cost[1][spell_num]; + store_sound = 24; + for (i = 0; i < T_M; i++) { + if ((c_town.monst.dudes[i].active != 0) &&(c_town.monst.dudes[i].attitude % 2 == 1) && + (dist(pc_pos[current_pc],c_town.monst.dudes[i].m_loc) <= priest_range[spell_num])) { + which_m = &c_town.monst.dudes[i]; + switch (spell_num) { + case 31: + which_m->curse(3 + bonus); + store_m_type = 8; + break; + case 51: + which_m->charm(28 - bonus,0,0); + store_m_type = 14; + break; + case 53: + which_m->disease(3 + bonus); + store_m_type = 0; + break; + } + num_opp++; + add_missile(c_town.monst.dudes[i].m_loc,store_m_type,0, + 14 * (which_m->m_d.x_width - 1),18 * (which_m->m_d.y_width - 1)); + } + } + + break; + + case 52: + adven[current_pc].cur_sp -= s_cost[1][spell_num]; + play_sound(24); + add_string_to_buf(" Protective field created."); + place_spell_pattern(protect_pat,pc_pos[current_pc],0,FALSE,6); + break; + } + } + if (num_opp < 10) + do_missile_anim((num_opp < 5) ? 50 : 25,pc_pos[current_pc],store_sound); + else play_sound(store_sound); + end_missile_anim(); + put_pc_screen(); + } + + combat_posing_monster = current_working_monster = -1; + // Did anything actually get cast? + if (store_sp == adven[current_pc].cur_sp) + return FALSE; + else return TRUE; +} + +void start_spell_targeting(short num) +{ + // First, remember what spell was cast. + spell_being_cast = num; + + // Then, is num >= 1000, it's a freebie, so remove the 1000 + if (num >= 1000) + num -= 1000; + sprintf ((char *) create_line, " Target spell. "); + add_string_to_buf((char *) create_line); + if (num < 100) + add_string_to_buf(" (Hit 'm' to cancel.)"); + else add_string_to_buf(" (Hit 'p' to cancel.)"); + overall_mode = 11; + current_spell_range = (num >= 100) ? priest_range[num - 100] : mage_range[num]; + current_pat = single; + + switch (num) { // Different spells have different messages and diff. target shapes + case 19: + current_pat = small_square; + break; + case 18: case 22: case 141: case 126: case 15: case 119: + current_pat = square; + break; + case 17: case 40: case 44: case 28: case 51: case 157: case 145: case 64: case 67: + current_pat = radius2; + break; + case 153: case 65: case 66: + current_pat = radius3; + break; + case 25: case 37: case 159: + add_string_to_buf(" (Hit space to rotate.)"); + force_wall_position = 0; + current_pat = field[0]; + break; + } +} + +void start_fancy_spell_targeting(short num) +{ + short i; + location null_loc = location(120,0); + + // First, remember what spell was cast. + spell_being_cast = num; + // Then, is num >= 1000, it's a freebie, so remove the 1000 + if (num >= 1000) + num -= 1000; + + for (i = 0; i < 8; i++) + spell_targets[i] = null_loc; + sprintf ((char *) create_line, " Target spell. "); + if (num < 100) + add_string_to_buf(" (Hit 'm' to cancel.)"); + else add_string_to_buf(" (Hit 'p' to cancel.)"); + add_string_to_buf(" (Hit space to cast.)"); + add_string_to_buf((char *) create_line); + overall_mode = 14; + current_pat = single; + current_spell_range = (num >= 100) ? priest_range[num - 100] : mage_range[num]; + + switch (num) { // Assign special targeting shapes and number of targets + case 129: // smite + num_targets_left = minmax(1,8,adven[current_pc].level / 4 + adven[current_pc].statAdj(2) / 2); + break; + case 134: // sticks to snakes + num_targets_left = adven[current_pc].level / 5 + adven[current_pc].statAdj(2) / 2; + break; + case 143: // summon host + num_targets_left = 5; + break; + case 27: // flame arrows + num_targets_left = adven[current_pc].level / 4 + adven[current_pc].statAdj(2) / 2; + break; + case 36: // venom arrows + num_targets_left = adven[current_pc].level / 5 + adven[current_pc].statAdj(2) / 2; + break; + case 61: case 49: // paralysis, death arrows + num_targets_left = adven[current_pc].level / 8 + adven[current_pc].statAdj(2) / 3; + break; + case 45: // spray fields + num_targets_left = adven[current_pc].level / 5 + adven[current_pc].statAdj(2) / 2; + current_pat = t; + break; + case 26: // summon 1 + num_targets_left = minmax(1,7,adven[current_pc].level / 4 + adven[current_pc].statAdj(2) / 2); + break; + case 43: // summon 2 + num_targets_left = minmax(1,6,adven[current_pc].level / 6 + adven[current_pc].statAdj(2) / 2); + break; + case 58: // summon 3 + num_targets_left = minmax(1,5,adven[current_pc].level / 8 + adven[current_pc].statAdj(2) / 2); + break; + } + + num_targets_left = minmax(1,8,num_targets_left); +} + +void spell_cast_hit_return() +{ + if (force_wall_position < 10) { + force_wall_position = (force_wall_position + 1) % 8; + current_pat = field[force_wall_position]; + } +} + +void process_fields() +{ + short i,j,k,r1; + location loc; + char qf[64][64]; + RECT r; + + if (is_out()) + return; + + if (quickfire) + { + r = c_town.town.in_town_rect.rect32(); + for (i = 0; i < town_size[town_type]; i++) + for (j = 0; j < town_size[town_type]; j++) + qf[i][j] = (is_quickfire(i,j)) ? 2 : 0; + for (k = 0; k < ((is_combat()) ? 4 : 1); k++) { + for (i = r.left + 1; i < r.right ; i++) + for (j = r.top + 1; j < r.bottom ; j++) + if (is_quickfire(i,j) > 0) { + r1 = get_ran(1,1,8); + if (r1 != 1) { + qf[i - 1][j] = 1; + qf[i + 1][j] = 1; + qf[i][j + 1] = 1; + qf[i][j - 1] = 1; + } + } + for (i = r.left + 1; i < r.right ; i++) + for (j = r.top + 1; j < r.bottom ; j++) + if (qf[i][j] > 0) { + make_quickfire(i,j); + } + } + } + + for (i = 0; i < T_M; i++) + if (c_town.monst.dudes[i].active > 0) + monst_inflict_fields(i); + + // First fry PCs, then call to handle damage to monsters + processing_fields = TRUE; // this, in hit_space, makes damage considered to come from whole party + if (force_wall) { + force_wall = FALSE; + for (i = 0; i < town_size[town_type]; i++) + for (j = 0; j < town_size[town_type]; j++) + if (is_force_wall(i,j)) { + r1 = get_ran(3,1,6); + loc.x = i; loc.y = j; + hit_pcs_in_space(loc,r1,3,1,1); + r1 = get_ran(1,1,6); + if (r1 == 2) + take_force_wall(i,j); + else { + force_wall = TRUE; + } + } + } + if (fire_wall) { + fire_wall = FALSE; + for (i = 0; i < town_size[town_type]; i++) + for (j = 0; j < town_size[town_type]; j++) + if (is_fire_wall(i,j)) { + loc.x = i; loc.y = j; + r1 = get_ran(2,1,6) + 1; + hit_pcs_in_space(loc,r1,1,1,1); + r1 = get_ran(1,1,4); + if (r1 == 2) + take_fire_wall(i,j); + else { + fire_wall = TRUE; + } + } + } + if (antimagic) { + antimagic = FALSE; + for (i = 0; i < town_size[town_type]; i++) + for (j = 0; j < town_size[town_type]; j++) + if (is_antimagic(i,j)) { + r1 = get_ran(1,1,8); + if (r1 == 2) + take_antimagic(i,j); + else antimagic = TRUE; + } + } + if (scloud) { + scloud = FALSE; + for (i = 0; i < town_size[town_type]; i++) + for (j = 0; j < town_size[town_type]; j++) + if (is_scloud(i,j)) { + r1 = get_ran(1,1,4); + if (r1 == 2) + take_scloud(i,j); + else { + scloud_space(i,j); + scloud = TRUE; + } + } + } + if (sleep_field) { + sleep_field = FALSE; + for (i = 0; i < town_size[town_type]; i++) + for (j = 0; j < town_size[town_type]; j++) + if (is_sleep_cloud(i,j)) { + r1 = get_ran(1,1,4); + if (r1 == 2) + take_sleep_cloud(i,j); + else { + sleep_cloud_space(i,j); + sleep_field = TRUE; + } + } + } + if (ice_wall) { + ice_wall = FALSE; + for (i = 0; i < town_size[town_type]; i++) + for (j = 0; j < town_size[town_type]; j++) + if (is_ice_wall(i,j)) { + loc.x = i; loc.y = j; + r1 = get_ran(3,1,6); + hit_pcs_in_space(loc,r1,5,1,1); + r1 = get_ran(1,1,6); + if (r1 == 1) + take_ice_wall(i,j); + else { + ice_wall = TRUE; + } + } + } + if (blade_wall) { + blade_wall = FALSE; + for (i = 0; i < town_size[town_type]; i++) + for (j = 0; j < town_size[town_type]; j++) + if (is_blade_wall(i,j)) { + loc.x = i; loc.y = j; + r1 = get_ran(6,1,8); + hit_pcs_in_space(loc,r1,0,1,1); + r1 = get_ran(1,1,5); + if (r1 == 1) + take_blade_wall(i,j); + else { + blade_wall = TRUE; + } + } + } + + processing_fields = FALSE; + monsters_going = TRUE; // this changes who the damage is considered to come from + // in hit_space + + if (quickfire) { + for (i = 0; i < town_size[town_type]; i++) + for (j = 0; j < town_size[town_type]; j++) + if (is_quickfire(i,j)) { + loc.x = i; loc.y = j; + r1 = get_ran(2,1,8); + hit_pcs_in_space(loc,r1,1,1,1); + } + } + + monsters_going = FALSE; +} + +void scloud_space(short m,short n) +{ + location target; + short i; + + target.x = (char) m; + target.y = (char) n; + + make_scloud(m,n); + + if (overall_mode >= 10) + for (i = 0; i < 6; i++) + if (adven[i].isAlive()) + if (same_point(pc_pos[i],target) == TRUE) { + adven[i].curse(get_ran(1,1,2)); + } + if (overall_mode < 10) + if (same_point(target,c_town.p_loc) == TRUE) { + for (i = 0; i < 6; i++) + adven[i].curse(get_ran(1,1,2)); + } +} + +void web_space(short m,short n) +{ + location target; + short i; + + target.x = (char) m; + target.y = (char) n; + + make_web(m,n); + + if (overall_mode >= 10) + for (i = 0; i < 6; i++) + if (adven[i].isAlive()) + if (same_point(pc_pos[i],target) == TRUE) { + adven[i].web(3); + } + if (overall_mode < 10) + if (same_point(target,c_town.p_loc) == TRUE) { + for (i = 0; i < 6; i++) + adven[i].web(3); + } +} +void sleep_cloud_space(short m,short n) +{ + location target; + short i; + + target.x = (char) m; + target.y = (char) n; + + make_sleep_cloud(m,n); + + if (overall_mode >= 10) + for (i = 0; i < 6; i++) + if (adven[i].isAlive()) + if (same_point(pc_pos[i],target) == TRUE) { + adven[i].sleep(3,11,0); + } + if (overall_mode < 10) + if (same_point(target,c_town.p_loc) == TRUE) { + for (i = 0; i < 6; i++) + adven[i].sleep(3,11,0); + } +} + +void take_m_ap(short num,creature_data_type *monst) +{ + monst->m_d.ap = max(0,monst->m_d.ap - num); +} + +short get_monst_sound(creature_data_type *attacker,short which_att) { + short type,strength; + + type = (which_att == 0) ? attacker->m_d.a1_type : attacker->m_d.a23_type; + strength = attacker->m_d.a[which_att]; + + switch (type) { + case 3: + return 11; + break; + case 4: + return 4; + break; + case 1: + return 9; + break; + case 2: + return 10; + break; + + default: + if (attacker->m_d.m_type == 0) { + if (strength > 9) + return 3; + else return 2; + } + if ((attacker->m_d.m_type == 0) ||(attacker->m_d.m_type == 6) ||(attacker->m_d.m_type == 9) ){ + return 2; + } + if (attacker->m_d.m_type == 4) + return 1; + if (attacker->m_d.m_type == 5) + return 4; + return 0; + break; + } + return 0; + } diff --git a/Win32/Blades of Exile/COMBAT.H b/Win32/Blades of Exile/COMBAT.H new file mode 100644 index 00000000..1963352a --- /dev/null +++ b/Win32/Blades of Exile/COMBAT.H @@ -0,0 +1,60 @@ +#ifndef _COMBAT_H + #define _COMBAT_H + +#include "location.h" +#include "global.h" + +void start_outdoor_combat(outdoor_creature_type encounter,unsigned char in_which_terrain,short num_walls); +Boolean pc_combat_move(location destination); +void char_parry(); +void char_stand_ready(); +void pc_attack(short who_att,short target); +short calc_spec_dam(short abil,short abil_str,creature_data_type *monst); +void place_target(location target); +void do_combat_cast(location target); +void handle_marked_damage(); +void load_missile(); +void fire_missile(location target); +Boolean combat_next_step(); +Boolean pick_next_pc(); +void combat_run_monst(); +void do_monster_turn(); +void monster_attack_pc(short who_att,short target); +void monster_attack_monster(short who_att,short attackee); +void monst_fire_missile(short m_num,short bless,short level,location source,short target); +Boolean monst_breathe(creature_data_type *caster,location targ_space,short dam_type); +Boolean monst_cast_mage(creature_data_type *caster,short targ); +Boolean monst_cast_priest(creature_data_type *caster,short targ); +void damage_target(short target,short dam,short type); +location find_fireball_loc(location where,short radius,short mode,short *m); +location closest_pc_loc(location where); +short count_levels(location where,short radius); +Boolean pc_near(short pc_num,location where,short radius); +Boolean monst_near(short m_num,location where,short radius,short active); +void place_spell_pattern(effect_pat_type pat,location center,short type,Boolean prep_for_anim,short who_hit); +void handle_item_spell(location loc,short num); +void modify_pattern(effect_pat_type *pat,short type); +void do_shockwave(location target); +void radius_damage(location target,short radius, short dam, short type); +void hit_pcs_in_space(location target,short dam,short type,short report,short hit_all); +void hit_space(location target,short dam,short type,short report,short hit_all); +void do_poison(); +void handle_disease(); +void handle_acid(); +Boolean no_pcs_left(); +Boolean hit_end_c_button(); +Boolean out_monst_all_dead(); +void end_combat(); +Boolean combat_cast_mage_spell(); +Boolean combat_cast_priest_spell(); +void start_spell_targeting(short num); +void start_fancy_spell_targeting(short num); +void spell_cast_hit_return(); +void process_fields(); +void scloud_space(short m,short n); +void web_space(short m,short n); +void sleep_cloud_space(short m,short n); +void take_m_ap(short num,creature_data_type *monst); +short get_monst_sound(creature_data_type *attacker,short which_att); + +#endif diff --git a/Win32/Blades of Exile/CONSTS.H b/Win32/Blades of Exile/CONSTS.H new file mode 100644 index 00000000..50d9664a --- /dev/null +++ b/Win32/Blades of Exile/CONSTS.H @@ -0,0 +1,541 @@ +#ifndef _CONSTS_H + #define _CONSTS_H + +/* + This file contain numerous constans in form of #defines. + Almost all of this constants cannot be changed because + that would make the game work improperly. +*/ + +#define NUM_OF_PCS 6 +#define INVALID_PC NUM_OF_PCS + +#define INVALID_TOWN 200 + +#define NUM_OF_BOATS 30 +#define NUM_OF_HORSES 30 + +#define SFX_SMALL_BLOOD 1 +#define SFX_MEDIUM_BLOOD 2 +#define SFX_LARGE_BLOOD 4 +#define SFX_SMALL_SLIME 8 +#define SFX_BIG_SLIME 16 +#define SFX_ASH 32 +#define SFX_BONES 64 +#define SFX_RUBBLE 128 + +/* stuff done flags */ +#define SDF_IS_PARTY_SPLIT 304][0 +#define SDF_PARTY_SPLIT_X 304][1 +#define SDF_PARTY_SPLIT_Y 304][2 +#define SDF_NO_INSTANT_HELP 306][4 // boolean + +/* overall mode; some seem to be missing */ + #define MODE_OUTDOORS 0 + #define MODE_TOWN 1 + #define MODE_TALK_TOWN 2 // looking for someone to talk + #define MODE_TOWN_TARGET 3 // spell target, that is + #define MODE_USE 4 + #define MODE_COMBAT 10 + #define MODE_SPELL_TARGET 11 + #define MODE_FIRING 12 // firing from bow or crossbow + #define MODE_THROWING 13 // throwing missile + #define MODE_FANCY_TARGET 14 // spell target, that is + #define MODE_DROPPING 15 + #define MODE_TALKING 20 + #define MODE_SHOPPING 21 + #define MODE_LOOK_OUTDOORS 35 // looking at something + #define MODE_LOOK_TOWN 36 + #define MODE_LOOK_COMBAT 37 + #define MODE_STARTUP 45 + #define MODE_REDRAW 50 + +/* adven[i].main_status */ //complete +#define MAIN_STATUS_ABSENT 0 // absent, empty slot +#define MAIN_STATUS_ALIVE 1 +#define MAIN_STATUS_DEAD 2 +#define MAIN_STATUS_DUST 3 +#define MAIN_STATUS_STONE 4 +#define MAIN_STATUS_FLED 5 +#define MAIN_STATUS_SURFACE 6 // fled to surface? +#define MAIN_STATUS_WON 7 +/* main status modifiers */ +#define MAIN_STATUS_SPLIT 10 // split from party, added to previous status (e.g 11 is splited alive : waiting for the active pc to return). + + +/* adven[i].skills */ //complete +#define SKILL_STRENGTH 0 +#define SKILL_DEXTERITY 1 +#define SKILL_INTELLIGENCE 2 +#define SKILL_EDGED_WEAPONS 3 +#define SKILL_BASHING_WEAPONS 4 +#define SKILL_POLE_WEAPONS 5 +#define SKILL_THROWN_MISSILES 6 +#define SKILL_ARCHERY 7 +#define SKILL_DEFENSE 8 +#define SKILL_MAGE_SPELLS 9 +#define SKILL_PRIEST_SPELLS 10 +#define SKILL_MAGE_LORE 11 +#define SKILL_ALCHEMY 12 +#define SKILL_ITEM_LORE 13 +#define SKILL_DISARM_TRAPS 14 +#define SKILL_LOCKPICKING 15 +#define SKILL_ASSASSINATION 16 +#define SKILL_POISON 17 +#define SKILL_LUCK 18 + + +/* adven[i].traits */ //complete +#define TRAIT_TOUGHNESS 0 +#define TRAIT_MAGICALLY_APT 1 +#define TRAIT_AMBIDEXTROUS 2 +#define TRAIT_NIMBLE 3 +#define TRAIT_CAVE_LORE 4 +#define TRAIT_WOODSMAN 5 +#define TRAIT_GOOD_CONST 6 +#define TRAIT_HIGHLY_ALERT 7 +#define TRAIT_EXCEPTIONAL_STRENGTH 8 +#define TRAIT_RECUPERATION 9 +#define TRAIT_SLUGGISH 10 +#define TRAIT_MAGICALLY_INEPT 11 +#define TRAIT_FRAIL 12 +#define TRAIT_CHRONIC_DISEASE 13 +#define TRAIT_BAD_BACK 14 + +/* adven[i].race */ //complete +#define RACE_HUMAN 0 +#define RACE_NEPHIL 1 +#define RACE_SLITH 2 + +/* adven[i].status*/ //complete - assign a positive value for a help pc effect, a negative for harm pc +#define STATUS_POISONED_WEAPON 0 +#define STATUS_BLESS 1 +#define STATUS_POISON 2 +#define STATUS_HASTE 3 +#define STATUS_INVULNERABLE 4 +#define STATUS_MAGIC_RESISTANCE 5 +#define STATUS_WEBS 6 +#define STATUS_DISEASE 7 +#define STATUS_INVISIBLE 8 //sanctuary +#define STATUS_DUMB 9 +#define STATUS_MARTYRS_SHIELD 10 +#define STATUS_ASLEEP 11 +#define STATUS_PARALYZED 12 +#define STATUS_ACID 13 + +/* damage type*/ +/* used as parameter to some functions */ +#define DAMAGE_WEAPON 0 +#define DAMAGE_FIRE 1 +#define DAMAGE_POISON 2 +#define DAMAGE_MAGIC 3 +#define DAMAGE_UNBLOCKABLE 4 //from the source files - the display is the same as the magic one (damage_monst in SPECIALS.cpp or pc_record_type::runTrap in PARTY.cpp) +#define DAMAGE_COLD 5 +#define DAMAGE_UNDEAD 6 //from the source files - the display is the same as the weapon one +#define DAMAGE_DEMON 7 //from the source files - the display is the same as the weapon one +// 8 and 9 aren't defined : doesn't print any damage. According to the source files the 9 is DAMAGE_MARKED though. Wrong ? +#define DAMAGE_MARKED 10 // usage: DAMAGE_MARKED + damage_type +#define DAMAGE_NO_PRINT 30 // usage: DAMAGE_NO_PRINT + damage_type + +/* trap type */ +/* used in pc_record_type::runTrap(...) */ +#define TRAP_RANDOM 0 +#define TRAP_BLADE 1 +#define TRAP_DART 2 +#define TRAP_GAS 3 // poisons all +#define TRAP_EXPLOSION 4 // damages all => uses c_town.difficulty rather than trap_level to calculates damages (and even c_town.difficulty /13). +#define TRAP_SLEEP_RAY 5 +#define TRAP_FALSE_ALARM 6 +#define TRAP_DRAIN_XP 7 +#define TRAP_ALERT 8 // makes town hostile +#define TRAP_FLAMES 9 // damages all => uses trap_level (*5) to calculates damages. +#define TRAP_DUMBFOUND 10 //dumbfound all +#define TRAP_DISEASE 11 +#define TRAP_DISEASE_ALL 12 + +/* items[i].type a.k.a type of weapon */ +#define ITEM_EDGED 1 +#define ITEM_BASHING 2 +#define ITEM_POLE 3 + +/* items[i].variety a.k.a item type (in editor) */ +#define ITEM_TYPE_NO_ITEM 0 //a guess, i can't test it ; but should be accurate => confirmed by the code +#define ITEM_TYPE_ONE_HANDED 1 +#define ITEM_TYPE_TWO_HANDED 2 +#define ITEM_TYPE_GOLD 3 //a guess, i can't test it ; but should be accurate => confirmed by the code +#define ITEM_TYPE_BOW 4 +#define ITEM_TYPE_ARROW 5 +#define ITEM_TYPE_THROWN_MISSILE 6 +#define ITEM_TYPE_POTION 7 // potion/magic item +#define ITEM_TYPE_SCROLL 8 // scroll/magic item +#define ITEM_TYPE_WAND 9 +#define ITEM_TYPE_TOOL 10 +#define ITEM_TYPE_FOOD 11 //a guess, i can't test it ; but should be accurate => confirmed by the code +#define ITEM_TYPE_SHIELD 12 +#define ITEM_TYPE_ARMOR 13 +#define ITEM_TYPE_HELM 14 +#define ITEM_TYPE_GLOVES 15 +#define ITEM_TYPE_SHIELD_2 16 //don't know why a second type of shield is used ; it is actually checked in the armor code (item >= 12 and <= 17) +#define ITEM_TYPE_BOOTS 17 //(continued) and you can't equip another (12) shield while wearing it ... I didn't find a single item with this property in the bladbase.exs ... +#define ITEM_TYPE_RING 18 +#define ITEM_TYPE_NECKLACE 19 +#define ITEM_TYPE_WEAPON_POISON 20 +#define ITEM_TYPE_NON_USE_OBJECT 21 +#define ITEM_TYPE_PANTS 22 +#define ITEM_TYPE_CROSSBOW 23 +#define ITEM_TYPE_BOLTS 24 +#define ITEM_TYPE_MISSILE_NO_AMMO 25 //e.g slings + +/* items[i].ability */ + +/* Weapons Ability */ +#define ITEM_NO_ABILITY 0 +#define ITEM_FLAMING_WEAPON 1 +#define ITEM_DEMON_SLAYER 2 +#define ITEM_UNDEAD_SLAYER 3 +#define ITEM_LIZARD_SLAYER 4 +#define ITEM_GIANT_SLAYER 5 +#define ITEM_MAGE_SLAYER 6 +#define ITEM_PRIEST_SLAYER 7 +#define ITEM_BUG_SLAYER 8 +#define ITEM_ACIDIC_WEAPON 9 +#define ITEM_SOULSUCKER 10 +#define ITEM_DRAIN_MISSILES 11 +#define ITEM_WEAK_WEAPON 12 +#define ITEM_CAUSES_FEAR 13 +#define ITEM_POISONED_WEAPON 14 + +/* General Ability */ +#define ITEM_PROTECTION 30 +#define ITEM_FULL_PROTECTION 31 +#define ITEM_FIRE_PROTECTION 32 +#define ITEM_COLD_PROTECTION 33 +#define ITEM_POISON_PROTECTION 34 +#define ITEM_MAGIC_PROTECTION 35 +#define ITEM_ACID_PROTECTION 36 +#define ITEM_SKILL 37 +#define ITEM_STRENGTH 38 +#define ITEM_DEXTERITY 39 +#define ITEM_INTELLIGENCE 40 +#define ITEM_ACCURACY 41 +#define ITEM_THIEVING 42 +#define ITEM_GIANT_STRENGTH 43 +#define ITEM_LIGHTER_OBJECT 44 +#define ITEM_HEAVIER_OBJECT 45 +#define ITEM_OCCASIONAL_BLESS 46 +#define ITEM_OCCASIONAL_HASTE 47 +#define ITEM_LIFE_SAVING 48 +#define ITEM_PROTECT_FROM_PETRIFY 49 +#define ITEM_REGENERATE 50 +#define ITEM_POISON_AUGMENT 51 +#define ITEM_DISEASE_PARTY 52 +#define ITEM_WILL 53 +#define ITEM_FREE_ACTION 54 +#define ITEM_SPEED 55 +#define ITEM_SLOW_WEARER 56 +#define ITEM_PROTECT_FROM_UNDEAD 57 +#define ITEM_PROTECT_FROM_DEMONS 58 +#define ITEM_PROTECT_FROM_HUMANOIDS 59 +#define ITEM_PROTECT_FROM_REPTILES 60 +#define ITEM_PROTECT_FROM_GIANTS 61 +#define ITEM_PROTECT_FROM_DISEASE 62 + +/* NonSpell Use ; the constant refers to both the positive and negative effect (don't mind the name). */ +/*#define ITEM_POISON_WEAPON 70 //put poison on weapon +#define ITEM_BLESS_USER 71 +#define ITEM_CURE_POISON 72 +#define ITEM_HASTE_USER 73 +#define ITEM_ADD_INVULNERABILITY 74 +#define ITEM_ADD_MAGIC_RESISTANCE 75 +#define ITEM_ADD_WEB 76 +#define ITEM_CAUSE_DISEASE 77 +#define ITEM_ADD_SANCTUARY 78 +#define ITEM_CAUSE_DUMBFOUND 79 +#define ITEM_ADD_MARTYRS_SHIELD 80 +#define ITEM_CURE_SLEEP 81 +#define ITEM_CURE_PARALYSIS 82 +#define ITEM_CURE_ACID 83 +#define ITEM_BLISS 84 +#define ITEM_ADD_EXPERIENCE 85 +#define ITEM_ADD_SKILL_POINTS 86 +#define ITEM_ADD_HEALTH 87 +#define ITEM_ADD_SPELL_POINTS 88 +#define ITEM_DOOM 89 +#define ITEM_LIGHT 90 +#define ITEM_STEALTH 91 +#define ITEM_FIREWALK 92 +#define ITEM_FLYING 93 +#define ITEM_MAJOR_HEALING 94*/ + +#define ITEM_POISON_WEAPON 70 //put poison on weapon +#define ITEM_BLESS_CURSE 71 +#define ITEM_AFFECT_POISON 72 +#define ITEM_HASTE_SLOW 73 +#define ITEM_AFFECT_INVULN 74 +#define ITEM_AFFECT_MAGIC_RES 75 +#define ITEM_AFFECT_WEB 76 +#define ITEM_AFFECT_DISEASE 77 +#define ITEM_AFFECT_SANCTUARY 78 +#define ITEM_AFFECT_DUMBFOUND 79 +#define ITEM_AFFECT_MARTYRS_SHIELD 80 +#define ITEM_AFFECT_SLEEP 81 +#define ITEM_AFFECT_PARALYSIS 82 +#define ITEM_AFFECT_ACID 83 +#define ITEM_BLISS 84 +#define ITEM_AFFECT_EXPERIENCE 85 +#define ITEM_AFFECT_SKILL_POINTS 86 +#define ITEM_AFFECT_HEALTH 87 +#define ITEM_AFFECT_SPELL_POINTS 88 +#define ITEM_DOOM 89 +#define ITEM_LIGHT 90 +#define ITEM_STEALTH 91 +#define ITEM_FIREWALK 92 +#define ITEM_FLYING 93 +#define ITEM_MAJOR_HEALING 94 + + +/* Spell Usable */ + +#define ITEM_SPELL_FLAME 110 +#define ITEM_SPELL_FIREBALL 111 +#define ITEM_SPELL_FIRESTORM 112 +#define ITEM_SPELL_KILL 113 +#define ITEM_SPELL_ICE_BOLT 114 +#define ITEM_SPELL_SLOW 115 +#define ITEM_SPELL_SHOCKWAVE 116 +#define ITEM_SPELL_DISPEL_UNDEAD 117 +#define ITEM_SPELL_DISPEL_SPIRIT 118 +#define ITEM_SPELL_SUMMONING 119 +#define ITEM_SPELL_MASS_SUMMONING 120 +#define ITEM_SPELL_ACID_SPRAY 121 +#define ITEM_SPELL_STINKING_CLOUD 122 +#define ITEM_SPELL_SLEEP_FIELD 123 +#define ITEM_SPELL_VENOM 124 +#define ITEM_SPELL_SHOCKSTORM 125 +#define ITEM_SPELL_PARALYSIS 126 +#define ITEM_SPELL_WEB_SPELL 127 +#define ITEM_SPELL_STRENGTHEN_TARGET 128 //wand of carrunos effect +#define ITEM_SPELL_QUICKFIRE 129 +#define ITEM_SPELL_MASS_CHARM 130 +#define ITEM_SPELL_MAGIC_MAP 131 +#define ITEM_SPELL_DISPEL_BARRIER 132 +#define ITEM_SPELL_MAKE_ICE_WALL 133 +#define ITEM_SPELL_CHARM_SPELL 134 +#define ITEM_SPELL_ANTIMAGIC_CLOUD 135 + +/* Reagents */ +#define ITEM_HOLLY 150 // Holly/Toadstool +#define ITEM_COMFREY_ROOT 151 +#define ITEM_GLOWING_NETTLE 152 +#define ITEM_CRYPT_SHROOM 153 // Crypt Shroom/Wormgr. +#define ITEM_ASPTONGUE_MOLD 154 +#define ITEM_EMBER_FLOWERS 155 +#define ITEM_GRAYMOLD 156 +#define ITEM_MANDRAKE 157 +#define ITEM_SAPPHIRE 158 +#define ITEM_SMOKY_CRYSTAL 159 +#define ITEM_RESSURECTION_BALM 160 +#define ITEM_LOCKPICKS 161 + +/* Missiles */ + +#define ITEM_MISSILE_RETURNING 170 +#define ITEM_MISSILE_LIGHTNING 171 +#define ITEM_MISSILE_EXPLODING 172 +#define ITEM_MISSILE_ACID 173 +#define ITEM_MISSILE_SLAY_UNDEAD 174 +#define ITEM_MISSILE_SLAY_DEMON 175 +#define ITEM_MISSILE_HEAL_TARGET 176 + +/* Monsters Stuff */ + +/* Skills Same as PC */ + +/* Monster Type */ + +#define MONSTER_TYPE_HUMAN 0 +#define MONSTER_TYPE_REPTILE 1 +#define MONSTER_TYPE_BEAST 2 +#define MONSTER_TYPE_IMPORTANT 3 +#define MONSTER_TYPE_MAGE 4 +#define MONSTER_TYPE_PRIEST 5 +#define MONSTER_TYPE_HUMANOID 6 +#define MONSTER_TYPE_DEMON 7 +#define MONSTER_TYPE_UNDEAD 8 +#define MONSTER_TYPE_GIANT 9 +#define MONSTER_TYPE_SLIME 10 +#define MONSTER_TYPE_STONE 11 +#define MONSTER_TYPE_BUG 12 +#define MONSTER_TYPE_DRAGON 13 +#define MONSTER_TYPE_MAGICAL_CREATURE 14 + +/* Attack Types */ + +#define MONSTER_ATTACK_SWINGS 0 +#define MONSTER_ATTACK_CLAWS 1 +#define MONSTER_ATTACK_BITES 2 +#define MONSTER_ATTACK_SLIMES 3 +#define MONSTER_ATTACK_PUNCHES 4 +#define MONSTER_ATTACK_STINGS 5 +#define MONSTER_ATTACK_CLUBS 6 +#define MONSTER_ATTACK_BURNS 7 +#define MONSTER_ATTACK_HARMS 8 +#define MONSTER_ATTACK_STABS 9 + +/* Special Ability a.k.a spec_skill */ + +#define MONSTER_NO_SPECIAL_ABILITY 0 +#define MONSTER_THROWS_DARTS 1 +#define MONSTER_SHOOTS_ARROWS 2 +#define MONSTER_THROWS_SPEARS 3 +#define MONSTER_THROWS_ROCKS1 4 //4-24 damages +#define MONSTER_THROWS_ROCKS2 5 //5-30 damages +#define MONSTER_THROWS_ROCKS3 6 //6-36 damages +#define MONSTER_THROWS_RAZORDISKS 7 +#define MONSTER_PETRIFICATION_RAY 8 +#define MONSTER_SP_DRAIN_RAY 9 //spell points drain ray +#define MONSTER_HEAT_RAY 10 +#define MONSTER_INVISIBLE 11 +#define MONSTER_SPLITS 12 +#define MONSTER_MINDLESS 13 +#define MONSTER_BREATHES_STINKING_CLOUDS 14 +#define MONSTER_ICY_TOUCH 15 +#define MONSTER_XP_DRAINING_TOUCH 16 +#define MONSTER_ICY_AND_DRAINING_TOUCH 17 +#define MONSTER_SLOWING_TOUCH 18 +#define MONSTER_SHOOTS_WEB 19 +#define MONSTER_GOOD_ARCHER 20 +#define MONSTER_STEALS_FOOD 21 +#define MONSTER_PERMANENT_MARTYRS_SHIELD 22 +#define MONSTER_PARALYSIS_RAY 23 +#define MONSTER_DUMBFOUNDING_TOUCH 24 +#define MONSTER_DISEASE_TOUCH 25 +#define MONSTER_ABSORB_SPELLS 26 +#define MONSTER_WEB_TOUCH 27 +#define MONSTER_SLEEP_TOUCH 28 +#define MONSTER_PARALYSIS_TOUCH 29 +#define MONSTER_PETRIFICATION_TOUCH 30 +#define MONSTER_ACID_TOUCH 31 +#define MONSTER_BREATHES_SLEEP_CLOUDS 32 +#define MONSTER_ACID_SPIT 33 +#define MONSTER_SHOOTS_SPINES 34 +#define MONSTER_DEATH_TOUCH 35 +#define MONSTER_INVULNERABILITY 36 +#define MONSTER_GUARD 37 + +/* Create Monsters/Fields */ + +#define MONSTER_NO_RADIATE 0 +#define MONSTER_RADIATE_FIRE_FIELDS 1 +#define MONSTER_RADIATE_ICE_FIELDS 2 +#define MONSTER_RADIATE_SHOCK_FIELDS 3 +#define MONSTER_RADIATE_ANTIMAGIC_FIELDS 4 +#define MONSTER_RADIATE_SLEEP_FIELDS 5 +#define MONSTER_RADIATE_STINKING_CLOUDS 6 +//as said 7,8 and 9 are unused +#define MONSTER_SUMMON1 10 //5 percent chance +#define MONSTER_SUMMON2 11 //20 percent chance +#define MONSTER_SUMMON3 12 //50 percent chance +//as said 13 and 14 are unused +#define MONSTER_DEATH_TRIGGERS 15 //death triggers global special + +/* Terrains Specials Properties : scenario.ter_types[i].special */ //complete + +#define TER_SPEC_NONE 0 +#define TER_SPEC_CHANGE_WHEN_STEP_ON 1 +#define TER_SPEC_DOES_FIRE_DAMAGE 2 +#define TER_SPEC_DOES_COLD_DAMAGE 3 +#define TER_SPEC_DOES_MAGIC_DAMAGE 4 +#define TER_SPEC_POISON_LAND 5 +#define TER_SPEC_DISEASED_LAND 6 +#define TER_SPEC_CRUMBLING_TERRAIN 7 +#define TER_SPEC_LOCKABLE_TERRAIN 8 +#define TER_SPEC_UNLOCKABLE_TERRAIN 9 +#define TER_SPEC_UNLOCKABLE_BASHABLE 10 +#define TER_SPEC_IS_A_SIGN 11 +#define TER_SPEC_CALL_LOCAL_SPECIAL 12 +#define TER_SPEC_CALL_SCENARIO_SPECIAL 13 +#define TER_SPEC_IS_A_CONTAINER 14 +#define TER_SPEC_WATERFALL 15 +#define TER_SPEC_CONVEYOR_NORTH 16 +#define TER_SPEC_CONVEYOR_EAST 17 +#define TER_SPEC_CONVEYOR_SOUTH 18 +#define TER_SPEC_CONVEYOR_WEST 19 +#define TER_SPEC_BLOCKED_TO_MONSTERS 20 +#define TER_SPEC_TOWN_ENTRANCE 21 +#define TER_SPEC_CAN_BE_USED 22 +#define TER_SPEC_CALL_SPECIAL_WHEN_USED 23 + +/*//stuff used in actions.cpp + +//Startup button rects (also used in blades.cpp) +#define STARTBTN_LOAD 0 +#define STARTBTN_NEW 1 +#define STARTBTN_ORDER 2 +#define STARTBTN_JOIN 3 +#define STARTBTN_CUSTOM 4 + +//Shop rects +#define SHOPRECT_WHOLE_AREA 0 +#define SHOPRECT_ACTIVE_AREA 1 +#define SHOPRECT_GRAPHIC 2 +#define SHOPRECT_ITEM_NAME 3 +#define SHOPRECT_ITEM_COST 4 +#define SHOPRECT_ITEM_EXTRA 5 +#define SHOPRECT_ITEM_HELP 6 + +// Item button rects +#define ITEMBTN_NAME 0 +#define ITEMBTN_USE 1 +#define ITEMBTN_GIVE 2 +#define ITEMBTN_DROP 3 +#define ITEMBTN_INFO 4 +#define ITEMBTN_SPEC 5 // Sell, Identify, or Enchant + +// PC button rects +#define PCBTN_NAME 0 +#define PCBTN_HP 1 +#define PCBTN_SP 2 +#define PCBTN_INFO 3 +#define PCBTN_TRADE 4 + +//Spell select +#define SPELL_SELECT_NONE 0 +#define SPELL_SELECT_ACTIVE 1 +#define SPELL_SELECT_ANY 2 + +//Spell refer +#define SPELL_REFER 0 +#define SPELL_IMMED 1 +#define SPELL_TARGET 2 +#define SPELL_FANCY_TARGET 3 + +#define SDF_IS_PARTY_SLIPT 304][0 +#define SDF_PARTY_SPLIT_WHERE_PARTY_X 304][1 +#define SDF_PARTY_SPLIT_WHERE_PARTY_Y 304][2 +#define SDF_PARTY_SPLIT_PC 304][3 +#define SDF_PARTY_SPLIT_TOWN 304][4 // for future use, hopefully +#define SDF_SKIP_STARTUP 305][4 +#define SDF_LESS_SOUND 305][5 +#define SDF_NO_TARGET_LINE 305][6 +#define SFD_NO_MAPS 306][0 +#define SDF_NO_SOUNDS 306][1 +#define SDF_NO_FRILLS 306][2 +#define SDF_ROOM_DESCS_AGAIN 306][3 +#define SDF_NO_INSTANT_HELP 306][4 // boolean +#define SDF_NO_SHORE_FRILLS 306][5 +#define SDF_GAME_SPEED 306][6 +#define SDF_EASY_MODE 306][7 +#define SDF_LESS_WANDER_ENC 306][8 +#define SDF_NO_TER_ANIM 306][9 +#define SDF_HIDDEN_MAP 308][0 +#define SDF_LEGACY_SCENARIO 305][8*/ //0 is new scenario, 1 is legacy + +/* Monsters Attitudes : + 0 - Friendly, Docile + 1 - Hostile, Type A + 2 - Friendly, Will fight + 3 - Hostile, Type B +*/ + +#endif diff --git a/Win32/Blades of Exile/Changes.txt b/Win32/Blades of Exile/Changes.txt new file mode 100644 index 00000000..173d785c --- /dev/null +++ b/Win32/Blades of Exile/Changes.txt @@ -0,0 +1,182 @@ +Bug Fixes : + +- Custom Scenario Loading now works. +- Conceal Ability Flag now works. +- Game now uses the font that comes with it. +- Strengh potions can now be made (Ishad Nha) +- Add/Lose Sanctuary and Add/Lose Martyr's Shield abilities fixed. (Ishad Nha) +- Acidic weapons works as living saving charm fixed. (Ishad Nha) +- Fixed the raise_dead node so that it actually raise dead. (Ishad Nha) +- Fixed the second part of a special node dialog called from a conversation wasn't properly recorded (actually read). +- Fixed custom items weren't properly masked (transparent background) in the inventory . +- The Defense skill was used rather than the Thrown Missiles skill when firing missiles weapons . +- Fixed the Paralysing Ray trap wasn't working. +- Fixed the petrification touch was causing disease. You now have the same chance of being petrified that when a basilisk gazes at you each time your are hit (subject to changes) (!). +- Make the automap updates after terrain change/swap/transform. +- Cleaned and expanded the Debug Mode. Type 'D' to begin debug mode and '/' to see commands. (Ishad Nha) +- Corrected doubling 152 index in m_pic_index (little alien beast graphic can now be used). (Ishad Nha) +- Corrected the "Town Special Encounter" node so that it makes full use of the ten groups. +- Fixed the ring of Will was not checked during mind duel. (Lots of people) +- Fixed Destroy Items and Move Items nodes so that they work for rectangles as well as a single space. +- Hide Town now works. +- Appears/Disappears on Day X now works. So does Appears/Disappears on Events. +- Fixed the day_reached function so that it correctly checks if the major event between 1 and 10 has occured (0 always happens) +- Nimble trait actually gave lower chance to disarm a trap, picklock and to put poison correctly. Fixed, the game now gives bonus to nimble ones rather than penalizing characters without the trait. +- Changing non-conveyer belt terrain into conveyer belt terrain will not work unless the town where the change occurs begins with a least one square of conveyer belt terrain as default. Fixed +- Step on sound code implemented. +- Corrected the Affect Statistic Node random calculation method, so that 100 happens all the time (and 0 never). +- Conveyor freezes upon loading fixed. +- Chances of dropping fixed, so that 100 happens all the time (and 0 never) +- Monster radiates field and rect_spec were plagued with the same random calculation as affect statistic node. Monster special ability : summons is now accurate. +- Last missile weapon in a group that possess special abilities will fail when fired and last stack of an ordinary thrown item that is placed immediately prior to a stack of another missile weapon with a special ability in that PC’s inventory will gain the special ability of the adjacent missile weapon fixed. +- Fixed the bug where you could fire an exploding arrow everywhere on the map, even if the target was out of range or not in sight. +- The 16 different area descriptions can now be used. +- The Spells “Resurrection” and "Raise Dead" did not require a Resurrection Balm, despite advertisements to the contrary. This is fixed in new scenarios (major version more or equal to 2) and left alone in legacy scenarios for compatibility reasons. +- If two friendly NPCs occupy the same space, and they both have dialogued personalities, talking to either of them will talk count as if talking to the first placed mosnter. This prevent the game from freezing. +- According to the BOE Manual, the Affect Party — Do Damage special node allows the scenario designer to vary the Pict. box. Doing so will supposedly only cause damage to the PC who triggers the special, if the party is in combat node. Fortunately, this has been fixed. +- Ice and Magic damaging terrains now displays the right effect/plays the right sound when damaging the party while not in combat. +- “Map Not Available” Option implemented. => (temporary ?) assigned to SDF[308][0] +- Fixed oddities appearing in the map with animated terrains (torches, firecamp, water, ...). +- Strength, Intelligence and Dexterity enhancing items will now works. (Windows specific) +- Fixed demons were doing undead damage and vice-versa. +- Loading a different party that is not in a scenario while playing a scenario won't result on mixed pc graphics in startup screen anymore. +- Call Local Special terrain ability now correctly calls outdoor specials if outdoors (was calling last town specials) (Celtic Minstrel) +- Fixed the town wandering function so that only the supposed monsters would appear in pair. +- Fixed the outdoor wandering function so that the number of monster appearing follows the specified values in the Scenario Editor. +- The generic portal/stairway node now don't call the next node if "Leave" is choose. +- Damaging terrains (cold/fire/magic) will not damage party when in boat. + +Changes : +- Created a compatibility menu +- Debug mode : Set a SDF added. +- Debug mode : Enter Town added (the party outdoor location is not changed). +- Add a preference option that displays or not the start-up picture and music. +- Changed the "Wait 40 moves" dialog to "Wait 80 moves" to better reflect the time actually waited. +- Added a "Fast Boom Space Effects" option that speeds up any boom sfx in the game. +- The party status text (Flying, Firewalk, Detect Life, Stealth) is not longer black on black. It should be readable now. +- Once identified, the exploding arrows now shows the radius of the explosion. +- Added a "Use Darker Graphics (Mac version)" option in the Preferences menu. To prevent mixing graphics, the game must be restarted after selecting this option (which can be set directly through the ini file to avoid this). +- Frills won't appears on pits while in outdoor combat anymore (pits here = darkness which you can flee to) +- Deleted a reference to PSD[181][6] which could prevent targeting lines from being drawn. +- Cleans up from Exile 3 : + - Anama references removed (was able to gain Anama's bonus against demons when the right SDF was set and suffers the Anama's wrath for learning Mage Spells is the same SDF was set) + - Monsters can now breaks barriers in town which number is 20 or less. + - You can't destroy non-existant slimes pools in town number 23 and 46, effectively locking the game because of missing dialogs, anymore. +- Variables changed to unsigned : + - Summoning variables + - Gold + - Food + - Party statistics (amount killed, ...) +- When the party is split, the following affect nodes now only affect the lone pc (Affect Health, Affect SP, Affect Skill Points, Affect Statistic, Give Mage Spell, Give Priest Spell) +- Trims (frills) now displays in grass terrain (compatibility option). +- Creatures in "one time place town encounters" now checks their life flag. +- Mac legacy saves compatibility added. + +Cleans : + +- Removed build_scen_file_name function that actullay did just strcpy "scenarios/%s",party.scen_name to a string (FILEIO.cpp) +- Various code cleaning (Ishad Nha) + +Changes : + +- the global variable file_path_name now points to the executable path. +- Checked/Completed the abilities, traits, status, main_status, items, monsters, terrain specials properties and race constants in CONST.h . +- Began to use the MODE_ constants in CONST.h to clean up the ACTIONS.cpp file. +- Fixed class pc_record_type::kill, so that it checks if the character has a protection from petrification item equipped before stoning him. (PC.cpp) +=> so removed the doubling check in monst_fire_missile with stoning gaze. (COMBAT.cpp) +- Moved the " %s turns to stone." message in the pc_record_type::kill class. +- Changes the debug mode switch : now each time you returns to start screen, debug mode is desactivated. Loading games with debug mode on, leave it on. +- Changed the way the ini file was handled so that it actually works +- Created a compatibility menu +- Debug mode : Set a SDF added. +- Debug mode : Enter Town added (the party outdoor location is not changed). +- Add a preference option that displays or not the start-up picture and music. +- Fixed the day_reached function so that it checks if the major event between 1 and 10 has occured (0 always happens) +- Changed "Turn off frills on shore" index to put it on a protected one ([306][5]). +- PSD [4][0] was appartenance to Anama :) All references to Anama have been commented. +- Changed the "Wait 40 moves" dialog to "Wait 80 moves" to better reflect the time actually waited. +- Added a "Fast Boom Space Effects" option that speeds up any boom sfx in the game. +- The party status text (Flying, Firewalk, Detect Life, Stealth) is not longer black on black. It should be readable now. +- Once identified, the exploding arrows now shows the radius of the explosion. +- Variables changed to unsigned : + - Summoning variables + - Gold + - Food + - Party statistics (amount killed, ...) +- When the party is split, the following affect nodes now only affect the lone pc (Affect Health, Affect SP, Affect Skill Points, Affect Statistic, Give Mage Spell, Give Priest Spell) +- Added legacy Exile graphics to the default terrains sheets. +- Mac legacy saves compatibility added. + +Compatibility Switches : + +- Switch between legacy Resurrection Node or fixed one (so that only present pc are resurrected, not the full party). +- Switch between Waterfalls working in Town or not (so that the user/scenario designer decided if the waterfall works in Town) +- (Temporary ?) Switch between fixed and funky day_reached function (to test backwards compatibility) + +ToDo : + +- elim_monst() function is now unused. +- Complete MIXED_D.BMP (ppats ...) +- Make the variables for day, level, etc unsigned so that a roll-over does not leave you in the negative ? +Note: Anywhere an unsigned char variable is used to store a terrain type or a monster type it must be changed to unsigned short! Otherwise we won't be able to extend the limit on the numbers of monsters and terrains. Local variables in particular should be looked out for. +- When an item is placed and the Amount/Charges field is filled in with a number other than -1, it has no effect (unless the item is food or gold). +*- Apparently event timers are broken. +- Stairway nodes can only be called as a result of moving. You can’t look to change levels, you can’t change levels in the middle of combat, you can’t change levels at the end of a timer. For normal stairways, this doesn’t matter. For forced stairways, you NEED to put in looking blocks and combat blocks. +- Outdoor terrain changes are forgotten after loading saved games. If you call a special to change a piece of outdoor terrain, that change will be forgotten if the player loads a saved game. This can be a VERY problematic node — the only way around is to surround the terrain with special nodes that call if upon a certain SDF. Problem is, Outdoor sections have very limited special nodes, limiting the ability to do this in relatively open areas. It is the same with Towns. +- Merging items wipes special classes if some of the merged items do not have a special class. For example, if you have arrows in your scenario that you give a special class, and the party brings in arrows from another scenario, and merges the two, NONE of the arrows will contain the new special class. For any combinable items that have a special class, make sure to give them a unique type class, so items from other scenarios won’t wipe them clean. You’ll still be vulnerable to the party taking items from your scenario, leaving the scenario, and then coming back in, but unfortunately there’s no way around this. +*- Empties! Occasionally, for no known reason, the BOE editor will stick in little “EMPTY” monsters, who appear with the Dwarf with the two-handed axe graphic, are hostile type “A”, and have no stats whatsoever. No one has quite yet figured out why this happens, but the effect has surfaced in several different scenarios. +- If you put a special class item in a crate and a party moves the crate in the game and then the special node checks where is the item (If-thens, Item with special class on a space), the node reacts as if the item was on the original space of the crate. This bug is especially bad because it makes a workaround for the lack of the node checking if the crate is on the space. (Thanks to Tigrene for pointing this out.) +*- Changing the visibility (i.e., opaque, transparent, etc.) of terrain types often does not work. I’m not sure if it always fails, but it definitely does sometimes. Make sure, through beta-testing, that the terrain type works properly. The work-around is this: if you want an opaque custom terrain type, don’t replace a terrain that is transparent. Instead, replace one that was already opaque. I’m not sure if this bug is also present with blocked vs. passable, but once again, during beta testing check all changed terrains by looking at them, looking through them (if possible), and trying to walk into them. +- Conveyors can push through solid objects (legacy compatibility warning !!!) +*- 100% in Blades doesn’t equal 100%. It’s closer to 95% as near as I can figure. Places where this becomes problematic are many, the two most notable are affect Statistics nodes, and creatures dropping items when killed. NEVER make a single creature drop something that is vital to continuation of the scenario, even set at 100% it will still fail to do so fairly often. <= this is normally fixed + +Suggestions : + +- Oh! One thing that could be done with the Extra values is allowing custom messages when being pushed or prevented by a conveyor belt. Right now, when you step on a conveyor belt and it pushes you, you get a small message in the text area that says "You get pushed." and if you attempt to move in the opposite direction of the conveyor belt, it says "The moving floor prevents you." Perhaps one Extra value could correspond to a scenario message that defines the two messages, separated by a | (the same character that creates line breaks in signs). +For instance, let's say you select scenario message 10 to be the conveyor belt's messages. Message 10 says "You float down the river.|The water's too fast to move upstream!" Now, when the party moves along the "belt", it says "You float down the river." and when they try to move against the direction of the "belt", it says "The water's too fast to move upstream!" +- Outdoor conveyor belts ? +- Also, perhaps instead of including only one version of the graphics, perhaps a switch could be put in the preferences for darker or lighter graphics + +Not a bug ?/Fixed ? + +- If a “place monster” special node is called within a town that would force the town to hold more than its maximum number of monsters, (30 for small towns, 40 for medium towns, 60 for large towns), the game will freeze. <= seems to have been fixed (placement forced or not) +- (don't use PSD[0][0] for a monster's life flag ?) <= seems ok ... such a monster (with life flag at PSD[0][0]) can be erased by forcing another monster to be placed. +- You know what would be a good use for this? An option to specifically turn off damage sounds -- or better still, force them to play asynchronously. At the moment, walking on damage floors or damaging fields takes forever because you have to wait for the *zap* *zap* *zap* *zap* *zap* *zap* as all your characters get hit every single step. +- 100 town bug lurking ? <= should be done +- Trap type #0 is listed as “Random Trap Selected”. This is incorrect, any traps set to #0 will always produce trap type #1 — Damage Single Character (Knives fly out). <= random trap actually choose between traps 1 to 4 +- In shops, the item graphic 5 rows above the correct graphic is displayed. +- When dumbfounded, characters disarms trap with more ease ? (Doesn't seems so after all) +- Fix the bug that prevents the use of the small Alien Beast graphic. <= done ? +- Select A PC, Certain Affect PCs nodes. In theory, if you call a select a PC, any further affect PC nodes in that chain should affect that PC and only that PC. But, for at least the nodes Affect Health and Affect Spell Points, no change occurs. This prohibits you from designing nebulous cauldrons with positive effects — e.g., the party comes across a cauldron, and is asked does anyone want to drink. If yes is pressed, they are asked to select a PC — that PC will not receive either the benefits or detriments from Affect Health or Affect Spell Points. +- Switch between legacy Town Place Encounter Node or fixed one (so that you can make full use of the 10 special groups in scenario editor) <= function worked correctly, the information text was to blame. +- The Affect PC-Webbing Node’s values are reversed. Specials that add webs will in fact remove them, and specials that remove webs will add them. (Thanks to GazeDoom for pointing this out.) <= corrected in the scen_editor +- When the party is split up, Affect PC special nodes should only affect the active PC ? <= can be done with Select PC ... So, no fix ? + + +PNG handling : + +void Paint(HWND hWnd, HDC hDC) +{ + Graphics graphics(hDC); + Rect rect(50, 50, 300, 600); + RECT cRect; + Rect CRect; + Image * pImage = Image::FromFile( L"C:\\download\\Visine4.png"); + + graphics.SetSmoothingMode(SmoothingModeAntiAlias); + graphics.SetTextRenderingHint(TextRenderingHintAntiAlias); + graphics.SetCompositingMode(CompositingModeSourceOver); + graphics.SetCompositingQuality(CompositingQualityGammaCorrected); + graphics.SetInterpolationMode(InterpolationModeHighQualityBicubic); +// mGraphics->SetPageUnit(mMeasurementType); + + GetClientRect(hWnd, &cRect); + + CRect.Width = cRect.right; + CRect.Height = cRect.bottom; + + graphics.FillRectangle(&SolidBrush(Color(252, 217, 211)), CRect); + graphics.DrawImage(pImage, rect); + + delete pImage; +} \ No newline at end of file diff --git a/Win32/Blades of Exile/DLGUTILS.CPP b/Win32/Blades of Exile/DLGUTILS.CPP new file mode 100644 index 00000000..7ff75901 --- /dev/null +++ b/Win32/Blades of Exile/DLGUTILS.CPP @@ -0,0 +1,1463 @@ +#include +#include "string.h" +#include "global.h" +#include "dlgutils.h" +#include "text.h" +#include "town.h" +#include "itemdata.h" +#include "locutils.h" +#include "fields.h" +#include "party.h" +#include "specials.h" +#include "fileio.h" +#include "graphics.h" +#include "items.h" +#include "exlsound.h" +#include "stdio.h" +#include "dlogtool.h" +#include "newgraph.h" +#include "infodlgs.h" +#include "graphutl.h" + +#include "globvar.h" + +#define NUM_HINTS 30 + +extern BOOL fry_startup; + +/* +shop_type: +0 - weapon shop +1 - armor shop +2 - misc shop +3 - healer +4 - food +5-9 - magic shop +10 - mage spells +11 - priest spells +12 alchemy +*/ +void start_shop_mode(short shop_type,short shop_min,short shop_max,short cost_adj,char *store_name) +{ + RECT area_rect; + + if (shop_max < shop_min) + shop_max = shop_min; //// + store_cost_mult = cost_adj; + if (store_cost_mult > 6) + store_cost_mult = 6; + store_shop_type = shop_type; + store_shop_min = shop_min; + store_shop_max = shop_max; + + area_rect = talk_area_rect; + strcpy((char *) store_store_name,store_name); + + OffsetRect(&area_rect, -1 * area_rect.left,-1 * area_rect.top); + if (talk_gworld == NULL) + talk_gworld = CreateCompatibleBitmap(main_dc,area_rect.right,area_rect.bottom); + + store_pre_shop_mode = overall_mode; + overall_mode = 21; + stat_screen_mode = 1; + create_clip_region(); + + set_up_shop_array(); + put_background(); + + draw_shop_graphics(0,area_rect); + + put_item_screen(stat_window,0); + give_help(26,27,0); +} + +void end_shop_mode() +{ + RECT dummy_rect = {0,0,0,0}; + + ShowScrollBar(shop_sbar,SB_CTL,FALSE); + if (store_pre_shop_mode == 20) { + sprintf((char *)old_str1,"You conclude your business."); + sprintf((char *)old_str2,""); + sprintf((char *)one_back1,"You conclude your business."); + sprintf((char *)one_back2,""); + + strnum1 = strnum2 = oldstrnum1 = oldstrnum2 = 0; + place_talk_str((char *)old_str1,"",0,dummy_rect); + } + else { + DeleteObject(talk_gworld); + talk_gworld = NULL; + } + + overall_mode = store_pre_shop_mode; + create_clip_region(); + if (overall_mode == MODE_TALK_TOWN) + overall_mode = MODE_TOWN; + if (overall_mode == MODE_TOWN) { + center = c_town.p_loc; + update_explored(center); + } + stat_screen_mode = 0; + put_item_screen(stat_window,0); + put_pc_screen(); + refresh_screen(0); +} + +void handle_shop_event(POINT p) +{ + short i,store_what_picked; + + p.x -= 5; + p.y -= 5; + + if (PtInRect(&talk_help_rect,p)) { + click_shop_rect(talk_help_rect); + party.help_received[26] = 0; + give_help(26,27,0); + return; + } + if (PtInRect(&shop_done_rect, p)) { + click_shop_rect(shop_done_rect); + end_shop_mode(); + return; + } + + for (i = 0; i < 8; i++) { + store_what_picked = i + GetScrollPos(shop_sbar,SB_CTL); + if ((PtInRect(&shopping_rects[i][1],p)) && (store_shop_items[store_what_picked] >= 0)) { + click_shop_rect(shopping_rects[i][1]); + handle_sale(store_shop_items[store_what_picked],store_shop_costs[store_what_picked]); + } + if ((PtInRect(&shopping_rects[i][6],p)) && (store_shop_items[store_what_picked] >= 0) + && (store_shop_type != 3) && (store_shop_type != 4)){ + click_shop_rect(shopping_rects[i][6]); + handle_info_request(store_shop_items[store_what_picked]); + } + } +} + +void handle_sale(short what_chosen,short cost) +{ + item_record_type base_item; + short what_magic_shop,what_magic_shop_item,i; + RECT dummy_rect = {0,0,0,0}; + + switch (what_chosen / 100) { + case 0: case 1: case 2: case 3: case 4: + base_item = get_stored_item(what_chosen); + base_item.item_properties = base_item.item_properties | 1; + //cost = (base_item.charges == 0) ? base_item.value : base_item.value * base_item.charges; + switch (adven[current_pc].okToBuy(cost,base_item)) { + case 1: play_sound(-38); adven[current_pc].giveToPC(base_item,true); break; + case 2: ASB("Can't carry any more items."); break; + case 3: ASB("Not enough cash."); break; + case 4: ASB("Item is too heavy."); break; + case 5: ASB("You own too many of this."); break; + } + break; + case 5: + base_item = store_alchemy(what_chosen - 500); + if (party.alchemy[base_item.item_level] == TRUE) + ASB("You already know that recipe."); + else if (party.takeGold(cost, false) == false) + ASB("Not enough gold."); + else { + play_sound(62); + ASB("You buy an alchemical recipe."); + party.alchemy[base_item.item_level] = TRUE; + } + break; + case 7: + what_chosen -= 700; + if (party.takeGold(cost, false) == false) + ASB("Not enough gold."); + else { + ASB("You pay the healer."); + play_sound(68); + switch (what_chosen) { + case 0: + adven[current_pc].cur_health = adven[current_pc].max_health; + break; + case 1: + adven[current_pc].status[2] = 0; + break; + case 2: + adven[current_pc].status[7] = 0; break; + case 3: + adven[current_pc].status[12] = 0; break; + case 4: + for (i = 0; i < 24; i++) + if ((adven[current_pc].equip[i] == TRUE) && + (adven[current_pc].items[i].isCursed())) + adven[current_pc].items[i].item_properties = + adven[current_pc].items[i].item_properties & 239; + break; + case 5: case 6: case 7: + adven[current_pc].main_status = MAIN_STATUS_ALIVE; break; + case 8: + adven[current_pc].status[9] = 0; break; + } + } + break; + case 8: + base_item = store_mage_spells(what_chosen - 800 - 30); + if ((base_item.item_level < 0) || (base_item.item_level > 61)) { + MessageBeep(MB_OK); ASB("Error 102: Report this!"); break;} + if (adven[current_pc].mage_spells[base_item.item_level] == TRUE) + ASB("You already have this spell."); + else if (party.takeGold(cost, false) == false) + ASB("Not enough gold."); + else { + play_sound(62); + ASB("You buy a spell."); + adven[current_pc].mage_spells[base_item.item_level] = TRUE; + give_help(41,0,0); + } + break; + case 9: + base_item = store_priest_spells(what_chosen - 900 - 30); + if ((base_item.item_level < 0) || (base_item.item_level > 61)) { + MessageBeep(MB_OK); ASB("Error 101: Report this!"); break;} + if (adven[current_pc].priest_spells[base_item.item_level] == TRUE) + ASB("You already have this spell."); + else if (party.takeGold(cost, false) == false) + ASB("Not enough gold."); + else { + play_sound(62); + ASB("You buy a spell."); + adven[current_pc].priest_spells[base_item.item_level] = TRUE; + give_help(41,0,0); + } + break; + default: + what_magic_shop = (what_chosen / 1000) - 1; + what_magic_shop_item = what_chosen % 1000; + base_item = party.magic_store_items[what_magic_shop][what_magic_shop_item]; + base_item.item_properties = base_item.item_properties | 1; + switch (adven[current_pc].okToBuy(cost,base_item)) { + case 1: play_sound(-38); adven[current_pc].giveToPC(base_item,true); + party.magic_store_items[what_magic_shop][what_magic_shop_item].variety = 0; + break; + case 2: ASB("Can't carry any more items."); break; + case 3: ASB("Not enough cash."); break; + case 4: ASB("Item is too heavy."); break; + } + break; + } + set_up_shop_array(); + + if (overall_mode != 21) { + MessageBeep(MB_OK); + ASB("Shop error 1. Report This!"); + } + draw_shop_graphics(0,dummy_rect); + print_buf(); + put_pc_screen(); + put_item_screen(stat_window,0); +} + + +void handle_info_request(short what_chosen) +{ + item_record_type base_item; + short what_magic_shop,what_magic_shop_item; + + switch (what_chosen / 100) { + case 0: case 1: case 2: case 3: case 4: + base_item = get_stored_item(what_chosen); + base_item.item_properties = base_item.item_properties | 1; + display_pc_item(6,0, base_item,0); + break; + case 5: + display_help(0,0); + break; + case 8: + base_item = store_mage_spells(what_chosen - 800 - 30); + display_spells(0,base_item.item_level,0); + break; + case 9: + base_item = store_priest_spells(what_chosen - 900 - 30); + display_spells(1,base_item.item_level,0); + break; + default: + what_magic_shop = (what_chosen / 1000) - 1; + what_magic_shop_item = what_chosen % 1000; + base_item = party.magic_store_items[what_magic_shop][what_magic_shop_item]; + base_item.item_properties = base_item.item_properties | 1; + display_pc_item(6,0, base_item,0); + break; + } +} + +void set_up_shop_array() +{ + short i,shop_pos = 0; + Boolean cursed_item = FALSE; + item_record_type store_i; + long store_l; + + for (i = 0; i < 30; i++) + store_shop_items[i] = -1; + switch (store_shop_type) { + case 0: case 1: case 2: + for (i = store_shop_min; i < store_shop_max + 1; i++) { + store_shop_items[shop_pos] = i; + store_i = get_stored_item(store_shop_items[shop_pos]); + store_shop_costs[shop_pos] = (store_i.charges == 0) ? + store_i.value : store_i.value * store_i.charges; + shop_pos++; + } + break; + case 3: + if (adven[current_pc].cur_health < adven[current_pc].max_health) { + store_shop_items[shop_pos] = 700; + store_shop_costs[shop_pos] = heal_costs[0]; + shop_pos++; + } + if (adven[current_pc].status[2] > 0) { + store_shop_items[shop_pos] = 701; + store_shop_costs[shop_pos] = heal_costs[1]; + shop_pos++; + } + if (adven[current_pc].status[7] > 0) { + store_shop_items[shop_pos] = 702; + store_shop_costs[shop_pos] = heal_costs[2]; + shop_pos++; + } + if (adven[current_pc].status[12] > 0) { + store_shop_items[shop_pos] = 703; + store_shop_costs[shop_pos] = heal_costs[3]; + shop_pos++; + } + if (adven[current_pc].status[9] > 0) { + store_shop_items[shop_pos] = 708; + store_shop_costs[shop_pos] = heal_costs[8]; + shop_pos++; + } + for (i = 0; i < 24; i++) + if ((adven[current_pc].equip[i] == TRUE) && (adven[current_pc].items[i].isCursed())) + cursed_item = TRUE; + if (cursed_item) { + store_shop_items[shop_pos] = 704; + store_shop_costs[shop_pos] = heal_costs[4]; + shop_pos++; + } + if (adven[current_pc].main_status == MAIN_STATUS_STONE) { + store_shop_items[shop_pos] = 705; + store_shop_costs[shop_pos] = heal_costs[5]; + shop_pos++; + } + if (adven[current_pc].main_status == MAIN_STATUS_DEAD){ + store_shop_items[shop_pos] = 706; + store_shop_costs[shop_pos] = heal_costs[6]; + shop_pos++; + } + if (adven[current_pc].main_status == MAIN_STATUS_DUST){ + store_shop_items[shop_pos] = 707; + store_shop_costs[shop_pos] = heal_costs[7]; + shop_pos++; + } + break; + case 4: + break; + case 5: case 6: case 7: case 8: case 9: + for (i = 0; i < 10; i++) + if (party.magic_store_items[store_shop_type - 5][i].variety != 0) { + store_shop_items[shop_pos] = (store_shop_type - 4) * 1000 + i; + store_i = party.magic_store_items[store_shop_type - 5][i]; + store_shop_costs[shop_pos] = (store_i.charges == 0) ? + store_i.value : store_i.value * store_i.charges; + shop_pos++; + } + break; + case 10: + for (i = store_shop_min; i < store_shop_max + 1; i++) + if (i == minmax(0,31,(int)i)) { + store_i = store_mage_spells(i); + store_shop_costs[shop_pos] = store_i.value; + store_shop_items[shop_pos] = 800 + i + 30; + shop_pos++; + } + break; + case 11: + for (i = store_shop_min; i < store_shop_max + 1; i++) + if (i == minmax(0,31,(int)i)) { + store_i = store_priest_spells(i); + store_shop_costs[shop_pos] = store_i.value; + store_shop_items[shop_pos] = 900 + i + 30; + shop_pos++; + } + break; + case 12: + for (i = store_shop_min; i < store_shop_max + 1; i++) + if (i == minmax(0,19,(int)i)) { + store_i = store_alchemy(i); + store_shop_costs[shop_pos] = store_i.value; + store_shop_items[shop_pos] = 500 + i; + shop_pos++; + } + break; + } + for (i = 0; i < 30; i++) + if (store_shop_items[i] >= 0) { + store_l = store_shop_costs[i]; + store_l = (store_l * cost_mult[store_cost_mult]) / 10; + store_shop_costs[i] = (short) store_l; + } + i = max(0,shop_pos - 8); + SetScrollRange(shop_sbar,SB_CTL,0,i,TRUE); + +} + +void start_talk_mode(short m_num,short personality,unsigned char monst_type,short store_face_pic)//// +{ + RECT area_rect; + char place_string1[256] = ""; + char place_string2[256] = ""; + + store_personality = personality; + + store_monst_type = monst_type; + store_m_num = m_num; + store_talk_face_pic = store_face_pic; //// + area_rect = talk_area_rect; + OffsetRect(&area_rect, -1 * area_rect.left,-1 * area_rect.top); + talk_gworld = CreateCompatibleBitmap(main_dc,area_rect.right,area_rect.bottom); + + // first make sure relevant talk strs are loaded in + if (personality / 10 != cur_town_talk_loaded) + load_town(personality / 10,1,0,NULL); + + // Dredge up critter's name + sprintf((char *) title_string,"%s:",data_store3->talk_strs[personality % 10]); + + store_pre_talk_mode = overall_mode; + overall_mode = 20; + create_clip_region(); + talk_end_forced = FALSE; + stat_screen_mode = 1; + + // Bring up and place first strings. + sprintf((char *) place_string1,"%s",data_store3->talk_strs[personality % 10 + 10]); + strnum1 = personality % 10 + 10; + strnum2 = 0; + strcpy((char *) old_str1,(char *) place_string1); + strcpy((char *) old_str2,(char *) place_string2); + strcpy((char *) one_back1,(char *) place_string1); + strcpy((char *) one_back2,(char *) place_string2); + place_talk_str((char *) place_string1,(char *) place_string2,0,dummy_rect); + + put_item_screen(stat_window,0); + give_help(5,6,0); + +} + +void end_talk_mode() +{ + DeleteObject(talk_gworld); + talk_gworld = NULL; + + overall_mode = store_pre_talk_mode; + create_clip_region(); + if (overall_mode == 2) + overall_mode = 1; + if (overall_mode == 1) { + center = c_town.p_loc; + update_explored(center); + } + stat_screen_mode = 0; + put_item_screen(stat_window,0); + put_pc_screen(); + redraw_screen(0); +} + +void handle_talk_event(POINT p) +{ + short i,j,force_special = 0,get_pc,s1 = -1,s2 = -1,s3 = -1; + char asked[4]; + char place_string1[256] = ""; + char place_string2[256] = ""; + + short a,b,c,d,ttype,which_talk_entry = -1; + + p.x -= 5; + p.y -= 5; + + if (PtInRect(&talk_help_rect,p)) { + party.help_received[5] = 0; + give_help(5,6,0); + return; + } + + for (i = 0; i < 9; i++) + if ((PtInRect(&preset_words[i].word_rect,p)) && ((talk_end_forced == FALSE) || (i == 6) || (i == 5))) { + click_talk_rect((char *) old_str1,(char *) old_str2,preset_words[i].word_rect); + switch (i) { + case 0: case 1: case 2: case 7: case 8: + force_special = i + 1; + break; + case 3: case 4: + force_special = i + 1; + break; + case 5: // save + if (strnum1 <= 0) { + MessageBeep(MB_OK); + return; + } + for (j = 0; j < 120; j++) + if ((party.talk_save[j].personality == store_personality) && + (party.talk_save[j].str1 == strnum1) && + (party.talk_save[j].str2 == strnum2)) { + ASB("This is already saved."); + print_buf(); + return; + } + for (j = 0; j < 120; j++) + if (party.talk_save[j].personality <= 0) { + give_help(57,0,0); + play_sound(0); + party.talk_save[j].personality = store_personality; + party.talk_save[j].town_num = (unsigned char) c_town.town_num; + party.talk_save[j].str1 = strnum1; + party.talk_save[j].str2 = strnum2; + ASB("Noted in journal."); + j = 200; + } + if (j < 200) { + MessageBeep(MB_OK); + ASB("No more room in talking journal."); + } + print_buf(); + return; + break; + case 6: // quit + end_talk_mode(); + return; + break; + default: + for (j = 0; j < 4; j++) + asked[j] = preset_words[i].word[j]; + break; + } + i = 100; + } + if (i < 100) { + for (i = 0; i < 50; i++) + if ((PtInRect(&store_words[i].word_rect,p)) && (talk_end_forced == FALSE)) { + click_talk_rect((char *) old_str1,(char *) old_str2,store_words[i].word_rect); + for (j = 0; j < 4; j++) + asked[j] = store_words[i].word[j]; + + i = 100; + } + } + if (i == 50) // no event + return; + if (force_special == 9) { + get_text_response(1017,place_string1,0); + asked[0] = place_string1[0]; + asked[1] = place_string1[1]; + asked[2] = place_string1[2]; + asked[3] = place_string1[3]; + } + + if ((asked[0] == 'n') && (asked[1] == 'a') &&(asked[2] == 'm') &&(asked[3] == 'a')) { + force_special = 2; + } + if ((asked[0] == 'l') && (asked[1] == 'o') &&(asked[2] == 'o') &&(asked[3] == 'k')) { + force_special = 1; + } + if (((asked[0] == 'j') && (asked[1] == 'o') &&(asked[2] == 'b')) || + ((asked[0] == 'w') && (asked[1] == 'o') &&(asked[2] == 'r')&&(asked[3] == 'k')) ) { + force_special = 3; + } + + if (force_special > 0) { + switch (force_special) { + case 1: case 2: case 3: + GetIndString(place_string1,120 + ((store_personality - 1) / 10), + ((store_personality - 1) % 10) * 3 + 10 + force_special); + sprintf((char *) place_string1,"%s",data_store3->talk_strs[store_personality % 10 + 10 * force_special]); + + oldstrnum1 = strnum1; oldstrnum2 = strnum2; + strnum1 = store_personality % 10 + 10 * force_special; + strnum2 = 0; + strcpy((char *) one_back1,(char *) old_str1); + strcpy((char *) one_back2,(char *) old_str2); + strcpy((char *) old_str1,(char *) place_string1); + strcpy((char *) old_str2,(char *) place_string2); + place_talk_str((char *) place_string1,(char *) place_string2,0,dummy_rect); + return; + break; + case 4: // buy button + asked[0] = 'p';asked[1] = 'u';asked[2] = 'r';asked[3] = 'c'; + if (scan_for_response(asked) >= 0) + break; + asked[0] = 's';asked[1] = 'a';asked[2] = 'l';asked[3] = 'e'; + if (scan_for_response(asked) >= 0) + break; + asked[0] = 'h';asked[1] = 'e';asked[2] = 'a';asked[3] = 'l'; + if (scan_for_response(asked) >= 0) + break; + asked[0] = 'i';asked[1] = 'd';asked[2] = 'e';asked[3] = 'n'; + if (scan_for_response(asked) >= 0) + break; + asked[0] = 't';asked[1] = 'r';asked[2] = 'a';asked[3] = 'i'; + if (scan_for_response(asked) >= 0) + break; + break; + case 5: // sell button + asked[0] = 's';asked[1] = 'e';asked[2] = 'l';asked[3] = 'l'; + if (scan_for_response(asked) >= 0) + break; + break; + case 8: // back 1 + strnum1 = oldstrnum1; strnum2 = oldstrnum2; + strcpy((char *) place_string1,(char *) one_back1); + strcpy((char *) place_string2,(char *) one_back2); + strcpy((char *) one_back1,(char *) old_str1); + strcpy((char *) one_back2,(char *) old_str2); + strcpy((char *) old_str1,(char *) place_string1); + strcpy((char *) old_str2,(char *) place_string2); + place_talk_str((char *) place_string1,(char *) place_string2,0,dummy_rect); + return; + break; + } + } + + which_talk_entry = scan_for_response(asked); + if ((which_talk_entry < 0) || (which_talk_entry > 59)) { + strcpy((char *) one_back1,(char *) old_str1); + strcpy((char *) one_back2,(char *) old_str2); + sprintf((char *) old_str2,""); + sprintf((char *) old_str1,"%s",data_store3->talk_strs[store_personality % 10 + 160]); + if (strlen((char *) old_str1) < 2) + sprintf((char *) old_str1,"You get no response."); + place_talk_str((char *) old_str1,(char *) old_str2,0,dummy_rect); + strnum1 = -1; + return; + } + + ttype = talking.talk_nodes[which_talk_entry].type; + a = talking.talk_nodes[which_talk_entry].extras[0]; + b = talking.talk_nodes[which_talk_entry].extras[1]; + c = talking.talk_nodes[which_talk_entry].extras[2]; + d = talking.talk_nodes[which_talk_entry].extras[3]; + + sprintf((char *) place_string1,"%s",data_store3->talk_strs[40 + which_talk_entry * 2]); + sprintf((char *) place_string2,"%s",data_store3->talk_strs[40 + which_talk_entry * 2 + 1]); + + oldstrnum1 = strnum1; oldstrnum2 = strnum2; + strnum1 = 40 + which_talk_entry * 2; strnum2 = 40 + which_talk_entry * 2 + 1; + + switch(ttype) { + case 0: + break; + case 1: + if (PSD[a][b] > c) { + strnum1 = strnum2; + strcpy((char *) place_string1,(char *) place_string2); + } + sprintf((char *) place_string2,""); + strnum2 = 0; + break; + case 2: + PSD[a][b] = 1; + break; + case 3: + if (party.gold < a) { + strnum1 = strnum2; + strcpy((char *) place_string1,(char *) place_string2); + } + else { + talk_end_forced = TRUE; + party.gold -= a; + put_pc_screen(); + adven.heal(30 * b); + adven.restoreSP(25 * b); + party.age += 700; + c_town.p_loc.x = c; + c_town.p_loc.y = d; + center = c_town.p_loc; + } + strnum2 = 0; + sprintf((char *) place_string2,""); + break; + case 4: + if (day_reached((unsigned char) a,0) == TRUE) { + strnum1 = strnum2; + strcpy((char *) place_string1,(char *) place_string2); + } + sprintf((char *) place_string2,""); + strnum2 = 0; + break; + case 5: + if (day_reached((unsigned char) a,(unsigned char) b) == TRUE) { + strnum1 = strnum2; + strcpy((char *) place_string1,(char *) place_string2); + } + sprintf((char *) place_string2,""); + strnum2 = 0; + break; + case 6: + if (c_town.town_num != a) { + strnum1 = strnum2; + strcpy((char *) place_string1,(char *) place_string2); + } + sprintf((char *) place_string2,""); + strnum2 = 0; + break; + case 7: + c = minmax(1,30,(int)c); + start_shop_mode(2,b, + b + c - 1,a,(char *)place_string1); + strnum1 = -1; + return; + case 8: + if ((get_pc = char_select_pc(1,0,"Train who?")) < 6) { + strnum1 = -1; + spend_xp(get_pc,1, 0); + } + sprintf((char *) place_string1, "You conclude your training."); + return; + + case 9: case 10: case 11: + c = minmax(1,30,(int)c); + start_shop_mode(ttype + 1,b, + b + c - 1,a,(char *)place_string1); + strnum1 = -1; + return; + case 12: //healer + start_shop_mode(3,c_town.monst.dudes[store_m_num].monst_start.extra1, + c_town.monst.dudes[store_m_num].monst_start.extra2,a,(char *)place_string1); + strnum1 = -1; + return; + break; + case 13: // sell weap + strnum1 = -1; + stat_screen_mode = 3; + put_item_screen(stat_window,1); + give_help(42,43,0); + break; + case 14: // sell armor + strnum1 = -1; + stat_screen_mode = 4; + put_item_screen(stat_window,1); + give_help(42,43,0); + break; + case 15: // sell misc + strnum1 = -1; + stat_screen_mode = 5; + put_item_screen(stat_window,1); + give_help(42,43,0); + break; + case 16: case 17: // ident enchant + strnum1 = -1; + stat_screen_mode = (ttype == 16) ? 2 : 6; + shop_identify_cost = a; + put_item_screen(stat_window,1); + give_help(ttype - 16 + 44,0,0); + break; + case 18: + if (party.gold < a) { + strnum1 = strnum2; + strcpy((char *) place_string1,(char *) place_string2); + } + else { + party.gold -= a; + put_pc_screen(); + + } + sprintf((char *) place_string2,""); + strnum2 = 0; + break; + case 19: + if ((sd_legit(b,c) == TRUE) && (PSD[b][c] == d)) { + sprintf((char *) place_string1, "You've already learned that."); + strnum1 = -1; + } + else if (party.gold < a) { + strnum1 = strnum2; + strcpy((char *) place_string1,(char *) place_string2); + } + else { + party.gold -= a; + put_pc_screen(); + if (sd_legit(b,c) == TRUE) + PSD[b][c] = d; + else give_error("Invalid Stuff Done flag called in conversation.","",0); + } + strnum2 = 0; + sprintf((char *) place_string2,""); + break; + case 20: + if (party.gold < a) { + strnum1 = strnum2; + strnum2 = 0; + strcpy((char *) place_string1,(char *) place_string2); + sprintf((char *) place_string2,""); + break; + } + else { + for (i = b; i <= b + c; i++) + if ((i >= 0) && (i < 30) && (party.boats[i].property == TRUE)) { + party.gold -= a; + put_pc_screen(); + party.boats[i].property = FALSE; + sprintf((char *) place_string2,""); + strnum2 = 0; + i = 1000; + } + if (i >= 1000) + break; + } + sprintf((char *) place_string1, "There are no boats left."); + sprintf((char *) place_string2,""); + strnum1 = -1; + strnum2 = -1; + break; + case 21: + if (party.gold < a) { + strnum1 = strnum2; + strnum2 = 0; + strcpy((char *) place_string1,(char *) place_string2); + sprintf((char *) place_string2,""); + break; + } + else { + for (i = b; i <= b + c; i++) + if ((i >= 0) && (i < 30) && (party.horses[i].property == TRUE)) { + party.gold -= a; + put_pc_screen(); + party.horses[i].property = FALSE; + sprintf((char *) place_string2,""); + strnum2 = 0; + i = 1000; + } + if (i >= 1000) + break; + } + sprintf((char *) place_string1, "There are no horses left."); + sprintf((char *) place_string2,""); + strnum1 = -1; + strnum2 = -1; + break; + case 22: + if (party.spec_items[a] > 0) { + sprintf((char *) place_string1, "You already have it."); + strnum1 = -1; + } + else if (party.gold < b) { + strcpy((char *) place_string1,(char *) place_string2); + strnum1 = strnum2; + } + else { + party.gold -= b; + put_pc_screen(); + party.spec_items[a] = 1; + } + strnum2 = 0; + sprintf((char *) place_string2,""); + break; + case 23: + start_shop_mode(5 + b,0, + 9,a,(char *)place_string1); + strnum1 = -1; + return; + case 24: + if (party.can_find_town[b] > 0) { + } + else if (party.gold < a) { + strnum1 = strnum2; + strcpy((char *) place_string1,(char *) place_string2); + } + else { + party.gold -= a; + put_pc_screen(); + party.can_find_town[b] = 1; + } + strnum2 = 0; + sprintf((char *) place_string2,""); + break; + case 25: + talk_end_forced = TRUE; + break; + case 26: + c_town.monst.dudes[store_m_num].attitude = 1; + c_town.monst.dudes[store_m_num].mobile = 1; + talk_end_forced = TRUE; + break; + case 27: + make_town_hostile(); + talk_end_forced = TRUE; + break; + case 28: + c_town.monst.dudes[store_m_num].active = 0; + // Special killing effects + if (sd_legit(c_town.monst.dudes[store_m_num].monst_start.spec1,c_town.monst.dudes[store_m_num].monst_start.spec2) == TRUE) + party.stuff_done[c_town.monst.dudes[store_m_num].monst_start.spec1][c_town.monst.dudes[store_m_num].monst_start.spec2] = 1; + talk_end_forced = TRUE; + break; + case 29: // town special + run_special(7,2,a,c_town.p_loc,&s1,&s2,&s3); + // check s1 & s2 to see if we got diff str, and, if so, munch old strs + if ((s1 >= 0) || (s2 >= 0)) { + strnum1 = -1; + strnum2 = -1; + sprintf((char *) place_string1,""); + sprintf((char *) place_string2,""); + } + get_strs((char *) place_string1,(char *) place_string2,2,s1,s2); + if (s1 >= 0) strnum1 = 2000 + s1; + if (s2 >= 0) strnum2 = 2000 + s2; + put_pc_screen(); + put_item_screen(stat_window,0); + break; + case 30: // scen special + run_special(7,0,a,c_town.p_loc,&s1,&s2,&s3); + // check s1 & s2 to see if we got diff str, and, if so, munch old strs + if ((s1 >= 0) || (s2 >= 0)) { + strnum1 = -1; + strnum2 = -1; + sprintf((char *) place_string1,""); + sprintf((char *) place_string2,""); + } + get_strs((char *) place_string1,(char *) place_string2,0,s1,s2); + if (s1 >= 0) strnum1 = 3000 + s1; + if (s2 >= 0) strnum2 = 3000 + s2; + put_pc_screen(); + put_item_screen(stat_window,0); + break; + } + + strcpy((char *) one_back1,(char *) old_str1); + strcpy((char *) one_back2,(char *) old_str2); + strcpy((char *) old_str1,(char *) place_string1); + strcpy((char *) old_str2,(char *) place_string2); + place_talk_str((char *) old_str1,(char *) old_str2,0,dummy_rect); + +} + +void do_sign(short town_num, short which_sign, short sign_type) +//town_num; // Will be 0 - 200 for town, 200 - 290 for outdoors +//short sign_type; // terrain type +{ + char sign_text[256]; + location view_loc; + + view_loc = (is_out()) ? party.p_loc : c_town.p_loc; + SetCursor(sword_curs); + + cd_create_dialog(1014,mainPtr); + + store_sign_mode = sign_type; + if (terrain_pic[sign_type] < 1000) + csp(1014,3,terrain_pic[sign_type]); + else csp(1014,3,94); + + if (town_num >= 200) { + town_num -= 200; + load_outdoors(town_num % scenario.out_width, town_num / scenario.out_width,party.i_w_c.x,party.i_w_c.y, + 1,which_sign + 100,(char *) sign_text); + } + else { + sprintf((char *) sign_text,"%s",data_store->town_strs[120 + which_sign]); + } + csit(1014,2,(char *) sign_text); + + while (dialog_not_toast) + ModalDialog(); + cd_kill_dialog(1014,0); +} + + + + +Boolean prefs_event_filter (short item_hit) +{ + Boolean done_yet = FALSE,did_cancel = FALSE; + short i; + RECT windRECT; + + switch (item_hit) { + case 1: + done_yet = TRUE; + dialog_not_toast = FALSE; + break; + + case 2: + done_yet = TRUE; + dialog_not_toast = FALSE; + did_cancel = TRUE; + break; + + case 50: case 52: case 54: case 56: case 18: case 20: case 22: case 24: case 27: case 38: case 40: case 43: case 45: + cd_set_led(1099,item_hit,1 - cd_get_led(1099,item_hit)); + break; + + case 29: + cd_set_led(1099,29,1); + break; + + case 32: case 34: case 36: case 47: + cd_set_led(1099,32,(item_hit == 32) ? 1 : 0); + cd_set_led(1099,34,(item_hit == 34) ? 1 : 0); + cd_set_led(1099,36,(item_hit == 36) ? 1 : 0); + cd_set_led(1099,47,(item_hit == 47) ? 1 : 0); + break; + + case 58: + cd_set_led(1099,58,1 - cd_get_led(1099,58)); + break; + + default: + cd_set_led(1099,4 + cur_display_mode,0); + cur_display_mode = item_hit - 4; + cd_set_led(1099,4 + cur_display_mode,1); + break; + } + if (done_yet== TRUE) { + if (did_cancel == FALSE) { + display_mode = cur_display_mode; + party.stuff_done[306][0] = cd_get_led(1099,18); + party.stuff_done[306][1] = cd_get_led(1099,20); + play_sounds = 1 - party.stuff_done[306][1]; + party.stuff_done[306][2] = cd_get_led(1099,22); + party.stuff_done[306][3] = cd_get_led(1099,24); + party.stuff_done[306][4] = cd_get_led(1099,27); + party.stuff_done[306][7] = cd_get_led(1099,38); + party.stuff_done[306][8] = cd_get_led(1099,40); + party.stuff_done[306][9] = cd_get_led(1099,43); + party.stuff_done[306][5] = cd_get_led(1099,45); + party.stuff_done[305][6] = cd_get_led(1099,50); + party.stuff_done[305][5] = cd_get_led(1099,52); + fry_startup = cd_get_led(1099,54); + party.stuff_done[305][7] = cd_get_led(1099,56); + party.stuff_done[307][0] = cd_get_led(1099,58); + if (cd_get_led(1099,32) == 1) + PSD[306][6] = 0; + if (cd_get_led(1099,34) == 1) + PSD[306][6] = 1; + if (cd_get_led(1099,36) == 1) + PSD[306][6] = 2; + if (cd_get_led(1099,47) == 1) + PSD[306][6] = 3; + if (cd_get_led(1099,29) == 1) + for (i = 0; i < 120; i++) + party.help_received[i] = 0; + if (display_mode < 5) + max_window(mainPtr); + else { + GetWindowRect(GetDesktopWindow(),&windRECT); + MoveWindow(mainPtr,(windRECT.right - (588 + 10)) / 2, + (windRECT.bottom - (425 + 52)) / 2 , + 588 + 10,425 + 52,TRUE); + } + } + save_maps = 1 - party.stuff_done[306][0]; + give_delays = party.stuff_done[306][2]; + build_data_file(2); + } + + return FALSE; +} + +void pick_preferences() +{ + get_reg_data(); + cur_display_mode = display_mode; + + SetCursor(sword_curs); + + cd_create_dialog(1099,mainPtr); + + cd_set_led(1099,4 + cur_display_mode,1); + + cd_set_led(1099,18,(party.stuff_done[306][0] != 0) ? 1 : 0); + cd_set_led(1099,20,(play_sounds == FALSE) ? 1 : 0); + cd_set_led(1099,22,(party.stuff_done[306][2] != 0) ? 1 : 0); + cd_set_led(1099,24,(party.stuff_done[306][3] != 0) ? 1 : 0); + cd_set_led(1099,27,(party.stuff_done[306][4] != 0) ? 1 : 0); + cd_set_led(1099,38,(party.stuff_done[306][7] != 0) ? 1 : 0); + cd_set_led(1099,40,(party.stuff_done[306][8] != 0) ? 1 : 0); + cd_set_led(1099,43,(party.stuff_done[306][9] != 0) ? 1 : 0); + cd_set_led(1099,45,(party.stuff_done[306][5] != 0) ? 1 : 0); + cd_set_led(1099,50,(party.stuff_done[305][6] != 0) ? 1 : 0); + cd_set_led(1099,52,(party.stuff_done[305][5] != 0) ? 1 : 0); + cd_set_led(1099,54,(fry_startup != FALSE) ? 1 : 0); + cd_set_led(1099,56,(party.stuff_done[305][7] != 0) ? 1 : 0); + cd_set_led(1099,58,(party.stuff_done[307][0] != 0) ? 1 : 0); + cd_set_flag(1099,3,1); + if (PSD[306][6] == 3) + cd_set_led(1099,47,1); + else cd_set_led(1099,32 + PSD[306][6] * 2,1); + + if (party.help_received[55] == 0) { + cd_initial_draw(1099); + give_help(55,0,1099); + } + + while (dialog_not_toast) + ModalDialog(); + cd_kill_dialog(1099,0); + adjust_window_mode(); +} + +Boolean compatibility_event_filter (short item_hit) +{ + Boolean done_yet = FALSE,did_cancel = FALSE; + + switch (item_hit) { + case 1: + done_yet = TRUE; + dialog_not_toast = FALSE; + break; + + case 2: + done_yet = TRUE; + dialog_not_toast = FALSE; + did_cancel = TRUE; + break; + + + case 7: case 9: case 11: case 13: + cd_set_led(1100,item_hit,1 - cd_get_led(1100,item_hit)); + break; + } + + if (done_yet== TRUE) { + if (did_cancel == FALSE) { + party.stuff_done[309][0]=cd_get_led(1100,7); + party.stuff_done[309][1]=1-cd_get_led(1100,9); + party.stuff_done[309][2]=1-cd_get_led(1100,11); + party.stuff_done[309][3]=cd_get_led(1100,13); + } + build_data_file(1); + } + + return FALSE; +} + +void pick_compatibility() +{ + get_reg_data(); + SetCursor(sword_curs); + + cd_create_dialog(1100,mainPtr); + + cd_set_led(1100,7,(party.stuff_done[309][0]!= 0) ? 1: 0);// party.stuff_done[309][0] legacy_day_reached + cd_set_led(1100,9,(party.stuff_done[309][1] != 0) ? 0 : 1);// party.stuff_done[309][1] legacy_kill_node + cd_set_led(1100,11,(party.stuff_done[309][2] != 0) ? 0 : 1);// party.stuff_done[309][2] town_waterfalls + cd_set_led(1100,13,(party.stuff_done[309][3] != 0) ? 1 : 0);// party.stuff_done[309][3] display_grass_trims + + if (party.help_received[110] == 0) { + cd_initial_draw(1100); + give_help(110,111,1100); + } + + while (dialog_not_toast) + ModalDialog(); + cd_kill_dialog(1100,0); + adjust_window_mode(); +} + +void put_party_stats() +{ + short i; + + for (i = 0; i < 6; i++) { + if (adven[i].main_status > MAIN_STATUS_ABSENT) { + cd_set_item_text(989,5 + 5 * i,adven[i].name); + cd_activate_item(989,7 + 5 * i,1); + cd_activate_item(989,8 + 5 * i,1); + cd_set_flag(989,6 + 5 * i,96); + cd_activate_item(989,35 + i,1); + cd_activate_item(989,42 + i,1); + csp(989,42 + i,800 + adven[i].which_graphic); + } + else { + cd_set_item_text(989,5 + 5 * i,"Empty."); + cd_activate_item(989,7 + 5 * i,0); + cd_activate_item(989,8 + 5 * i,0); + cd_set_flag(989,6 + 5 * i,98); + cd_activate_item(989,35 + i,0); + cd_activate_item(989,42 + i,0); + } + + } +} + +void edit_party_event_filter (short item_hit) +{ + short which_pc; + + switch (item_hit) { + case 1: + dialog_not_toast = FALSE; + break; + + case 41: + party.help_received[22] = 0; + give_help(222,23,989); + return; + + case 5: case 10: case 15: case 20: case 25: case 30: + which_pc = (item_hit - 5) / 5; + if (adven[which_pc].main_status != MAIN_STATUS_ABSENT) + pick_pc_name(which_pc,989); + put_party_stats(); + break; + case 7: case 12: case 17: case 22: case 27: case 32: + which_pc = (item_hit - 7) / 5; + pick_race_abil(&adven[which_pc],0,989); + put_party_stats(); + break; + case 8: case 13: case 18: case 23: case 28: case 33: + which_pc = (item_hit - 8) / 5; + spend_xp(which_pc,0,989); + put_party_stats(); + break; + case 35: case 36: case 37: case 38: case 39: case 40: + which_pc = item_hit - 35; + + if (adven[which_pc].main_status <= MAIN_STATUS_ABSENT) + break; + if (adven[which_pc].main_status != MAIN_STATUS_ABSENT) + pick_pc_graphic(which_pc,1,989); + put_party_stats(); + break; + case 6: case 11: case 16: case 21: case 26: case 31: + which_pc = (item_hit - 6) / 5; + if (adven[which_pc].main_status != MAIN_STATUS_ABSENT) { + if (FCD(1053,989) == 2) + adven[which_pc].main_status = MAIN_STATUS_ABSENT; + put_party_stats(); + } + else { + give_help(56,0,989); + create_pc(which_pc,989); + put_party_stats(); + cd_initial_draw(989); // extra redraw, just in case + } + break; +// case 7: case 12: case 17: case 22: case 27: case 32: + + } + +} + +void edit_party() +{ + Boolean munch_pc_graphic = FALSE; + + SetCursor(sword_curs); + + if (pcs_gworld == NULL) { + munch_pc_graphic = TRUE; + pcs_gworld = load_pict(902,main_dc); + } + + cd_create_dialog(989,mainPtr); + + put_party_stats(); + if (party.help_received[22] == 0) { + cd_initial_draw(989); + give_help(22,23,989); + } + while (dialog_not_toast) + ModalDialog(); + cd_kill_dialog(989,0); + + if (munch_pc_graphic == TRUE) { + DeleteObject(pcs_gworld); + pcs_gworld = NULL; + } + + if (adven[current_pc].isAlive() == false) + current_pc = first_active_pc(); + + +} + +void tip_of_day_event_filter (short item_hit) +{ + char place_str[256]; + + switch (item_hit) { + case 1: + dialog_not_toast = FALSE; + break; + + case 5: + store_tip_page_on++; + if (store_tip_page_on == NUM_HINTS) + store_tip_page_on = 0; + GetIndString(place_str,12,50 + store_tip_page_on); + csit(958,3,(char *) place_str); + break; + + case 7: + give_intro_hint = 1 - give_intro_hint; + cd_set_led(958,7,give_intro_hint); + break; + } + +} + +void tip_of_day() +{ + char place_str[256]; + + store_tip_page_on = get_ran(1,0,NUM_HINTS - 1); + + SetCursor(sword_curs); + + cd_create_dialog_parent_num(958,0); + + GetIndString(place_str,12,50 + store_tip_page_on); + csit(958,3,(char *) place_str); + + cd_set_led(958,7,give_intro_hint); + + while (dialog_not_toast) ModalDialog(); + + cd_kill_dialog(958,0); + build_data_file(2); +} + +void max_window(HWND window) +{ + RECT main_rect,wind_rect; + short width,height; + + cursor_shown = TRUE; + showcursor(TRUE); + + GetWindowRect(GetDesktopWindow(),&main_rect); + GetWindowRect(window,&wind_rect); + width = main_rect.right - main_rect.left; + height = main_rect.bottom - main_rect.top; + MoveWindow(window,0,0,width,height,TRUE); +} + +void put_scen_info() +{ + short i; + char place_str[256]; + char *ratings[] = {"G","PG","R","NC-17"}; + char *difficulty[] = {"Low","Medium","High","Very High"}; + + for (i = 0; i < 3; i++) + if (scen_headers[store_scen_page_on * 3 + i].flag1 != 0) { + cd_set_pict(947, 6 + i * 3,1600 + scen_headers[store_scen_page_on * 3 + i].intro_pic); + sprintf((char *) place_str, + "%s v%d.%d.%d - | Difficulty: %s, Rating: %s |%s |%s", + data_store2->scen_header_strs[store_scen_page_on * 3 + i][0], + (short) scen_headers[store_scen_page_on * 3 + i].ver[0], + (short) scen_headers[store_scen_page_on * 3 + i].ver[1], + (short) scen_headers[store_scen_page_on * 3 + i].ver[2], + difficulty[scen_headers[store_scen_page_on * 3 + i].difficulty], + ratings[scen_headers[store_scen_page_on * 3 + i].default_ground], + data_store2->scen_header_strs[store_scen_page_on * 3 + i][1], + data_store2->scen_header_strs[store_scen_page_on * 3 + i][2]); + csit(947,7 + i * 3,(char *) place_str); + cd_activate_item(947,8 + i * 3,1); + } + else { + cd_set_pict(947, 6 + i * 3,950); + csit(947,7 + i * 3,""); + cd_activate_item(947,8 + i * 3,0); + } +} + +void pick_a_scen_event_filter (short item_hit) +{ + switch (item_hit) { + case 1: + dialog_answer = -1; + dialog_not_toast = FALSE; + break; + + case 3: case 4: + if (item_hit == 3) { + if (store_scen_page_on == 0) + store_scen_page_on = (store_num_scen - 1) / 3; + else store_scen_page_on--; + } + else { + if (store_scen_page_on == (store_num_scen - 1) / 3) + store_scen_page_on = 0; + else store_scen_page_on++; + } + put_scen_info(); + break; + + case 8: case 11: case 14: + dialog_answer = ((item_hit - 8) / 3) + store_scen_page_on * 3; + dialog_not_toast = FALSE; + break; + } + +} + +short pick_a_scen() +{ + short i; + + build_scen_headers(); + + store_num_scen = 0; + for (i = 0; i < 100; i++) + if (scen_headers[i].flag1 != 0) + store_num_scen++; + store_scen_page_on = 0; + + if (store_num_scen == 0) { + FCD(868,0); + return -1; + } + SetCursor(sword_curs); + + cd_create_dialog_parent_num(947,0); + + put_scen_info(); + + if (store_num_scen <= 3) { + cd_activate_item(947,3,0); + cd_activate_item(947,4,0); + } + while (dialog_not_toast) + ModalDialog(); + cd_kill_dialog(947,0); + return dialog_answer; +} + + +void pick_prefab_scen_event_filter (short item_hit) +{ + switch (item_hit) { + case 1: + dialog_answer = -1; + dialog_not_toast = FALSE; + break; + + case 6: case 9: case 12: + dialog_answer = ((item_hit - 6) / 3); + dialog_not_toast = FALSE; + break; + } +} + +short pick_prefab_scen() +{ + SetCursor(sword_curs); + + cd_create_dialog_parent_num(869,0); + cd_activate_item(869,2,0); + + while (dialog_not_toast) + ModalDialog(); + cd_kill_dialog(869,0); + return dialog_answer; +} diff --git a/Win32/Blades of Exile/DLGUTILS.H b/Win32/Blades of Exile/DLGUTILS.H new file mode 100644 index 00000000..47d8e00b --- /dev/null +++ b/Win32/Blades of Exile/DLGUTILS.H @@ -0,0 +1,36 @@ +#ifndef _DLGUTILS_H + #define _DLGUTILS_H + +void start_shop_mode(short shop_type,short shop_min,short shop_max,short cost_adj,char *store_name); +void end_shop_mode(); +void handle_shop_event(POINT p); +void handle_sale(short what_chosen,short cost); +void handle_info_request(short what_chosen); +void set_up_shop_array(); +void start_talk_mode(short m_num,short personality,unsigned char monst_type,short store_face_pic); +void end_talk_mode(); +void handle_talk_event(POINT p); +void handle_talk_spec(short ttype,char *place_string1,char *place_string2); +void put_num_in_text(short num_to_put,HWND the_dialog,short item_num); +long get_text_item_num(short item_num,HWND the_dialog); +void do_sign(short town_num, short which_sign, short sign_type); +void do_talk(short personality, unsigned char m_num); +void edit_party_event_filter (short item_hit); +void put_party_stats(); +void edit_party(); +Boolean prefs_event_filter (short item_hit); +Boolean compatibility_event_filter (short item_hit); +void pick_preferences() ; +void pick_compatibility(); + +void tip_of_day_event_filter (short item_hit); +void tip_of_day(); +void max_window(HWND window); + +void put_scen_info(); +void pick_a_scen_event_filter (short item_hit); +short pick_a_scen(); +short pick_prefab_scen(); +void pick_prefab_scen_event_filter (short item_hit); + +#endif diff --git a/Win32/Blades of Exile/DLOGTOOL.CPP b/Win32/Blades of Exile/DLOGTOOL.CPP new file mode 100644 index 00000000..f5e4531a --- /dev/null +++ b/Win32/Blades of Exile/DLOGTOOL.CPP @@ -0,0 +1,1850 @@ +#include +#include "string.h" +#include "global.h" +#include "graphutl.h" +#include "stdio.h" +#include "exlsound.h" +#include "dlogtool.h" +#include "text.h" +#include "locutils.h" + +#include "globvar.h" + +/* +struct Dialog +{ + short key; + short type; + HWND handle; + HWND parent; + short highest_item; + Boolean draw_ready; + + Dialog() : key(-1), type(0), handle(NULL), highest_item(0) { } +} dialogs[ND]; +*/ + +short current_key = 0; +short dlg_keys[ND]; +short dlg_types[ND]; +HWND dlgs[ND]; +HWND dlg_parent[ND]; +short dlg_highest_item[ND]; +Boolean dlg_draw_ready[ND]; + +short item_dlg[NI]; +short item_number[NI]; +char item_type[NI]; +RECT item_rect[NI]; +short item_flag[NI]; +char item_active[NI]; +char item_key[NI]; +short item_label[NI]; +short item_label_loc[NI]; + +inline void cd_kill_dc(short which_slot,HDC hdc) { fry_dc(dlgs[which_slot],hdc); } + +BOOL CALLBACK dummy_dialog_proc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam); +LRESULT CALLBACK fresh_edit_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); + +long CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM); + +void cd_init_dialogs() +{ + short i; + + for (i = 0; i < ND; i++) + { + dlg_keys[i] = -1; + dlg_types[i] = 0; + dlgs[i] = NULL; + dlg_highest_item[i] = 0; + } + for (i = 0; i < NI; i++) item_dlg[i] = -1; + for (i = 0; i < NL; i++) label_taken[i] = FALSE; + + d_proc = dummy_dialog_proc; + edit_proc = fresh_edit_proc; +} + +long CALLBACK fresh_edit_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + switch (message) { + case WM_KEYDOWN: + if (wParam == VK_RETURN) + SendMessage( + store_edit_parent, + WM_COMMAND, + 9, + 0 + ); + if (wParam == VK_ESCAPE) + SendMessage(store_edit_parent, + WM_COMMAND, + 8, + 0); + break; + } + + //return CallWindowProc((WNDPROC) old_edit_proc,hwnd,message,wParam,lParam); + return CallWindowProc((WNDPROC) old_edit_proc,hwnd,message,wParam,lParam); +} + +short cd_create_dialog_parent_num(short dlog_num,short parent) +{ + short i; + + if ((parent == 0) || (parent == 1)) + return cd_create_dialog(dlog_num,mainPtr); + i = cd_get_dlg_index(parent); + if (i < 0) + return -1; + return cd_create_dialog(dlog_num,dlgs[i]); + +} + +short cd_create_custom_dialog(HWND parent, + char *str_block,short pic_num,short buttons[3]) +{ + + short i,j,free_slot = -1,free_item = -1,str_width,cur_but_right = 0; + short total_len = 0; + + char strs[6][256]; + + short cur_item = 1; + short but_items[3] = {-1,-1,-1}; + RECT measure_rect,pic_rect = {8,8,44,44},cur_text_rect = {50,2,0,0}; + short win_width = 100, win_height = 100; + + for (i = 0; i < 256; i++) { + strs[0][i] = str_block[i]; + strs[1][i] = str_block[i + 256]; + strs[2][i] = str_block[i + 512]; + strs[3][i] = str_block[i + 768]; + strs[4][i] = str_block[i + 1024]; + strs[5][i] = str_block[i + 1280]; + } + + if (parent != NULL) { + if (IsWindowEnabled(parent) == 0) + return -1; + } + store_dlog_num = 900; + + for (i = 0; i < ND; i++) { + if ((dlg_keys[i] >= 0) && (dlg_types[i] == 900)) + return -1; + } + for (i = 0; i < ND; i++) { + if (dlg_keys[i] < 0) { + free_slot = i; + i = 500; + } + } + if (free_slot < 0) + return -2; + + // quick check, to make sure there's at least 1 button + if ((buttons[0] < 0) && (buttons[1] < 0) && (buttons[2] < 0)) + buttons[0] = 1; + current_key++; + dlg_keys[free_slot] = current_key; + dlg_types[free_slot] = 900; + dlg_highest_item[free_slot] = 1; + dlg_draw_ready[free_slot] = FALSE; + dlgs[free_slot] = NULL; + + // first, create dummy dlog + store_free_slot = free_slot; + + dlgs[free_slot] = CreateWindow (szWinName, + "Blades of Exile", + 0,// was visible + 0, + 0, + 100, + 100, + NULL, + NULL, + store_hInstance, + NULL); + if (dlgs[free_slot] == NULL) { + play_sound(3); + return -3; + } + + dlg_parent[free_slot] = parent; + + //process_new_window (dlgs[free_slot]); + // instead of this, custom make items + free_item = -1; + + // first, do 1-3 buttons + for (i = 0; i < 3; i++) + if (buttons[i] >= 0) {// buttons + for (j = 150; j < NI; j++) + if (item_dlg[j] < 0) { + free_item = j; + j = NI + 1; + } + item_dlg[free_item] = store_dlog_num; + item_type[free_item] = (i == 0) ? 1 : 0; + item_number[free_item] = cur_item; + + item_flag[free_item] = available_dlog_buttons[buttons[i]]; + item_active[free_item] = 1; + item_label[free_item] = 0; + item_label_loc[free_item] = -1; + item_key[free_item] = button_def_key[available_dlog_buttons[buttons[i]]]; + if (i == 0) + item_key[free_item] = 31; + but_items[i] = free_item; // remember this to set item rect later + cur_item++; + } + // next, the upper left picture (always there) + for (j = 150; j < NI; j++) + if (item_dlg[j] < 0) { + free_item = j; + j = NI + 1; + } + item_dlg[free_item] = store_dlog_num; + item_type[free_item] = 5; + item_number[free_item] = cur_item; + item_rect[free_item] = pic_rect; + + if (pic_num < 0) { + item_flag[free_item] = pic_num * -1; + } + else //if (pic_num < 1000) + item_flag[free_item] = pic_num; + item_active[free_item] = 1; + item_label[free_item] = 0; + item_label_loc[free_item] = -1; + item_key[free_item] = 0; + cur_item++; + + // finally, 0-6 text, first do preprocessing to find out how much room we need + for (i = 0; i < 6; i++) + total_len += string_length((char *) strs[i],main_dc); + total_len = total_len * 12; + str_width = 100 + 20; + if (str_width < 340) + str_width = 340; + cur_text_rect.right = cur_text_rect.left + str_width; + // finally, 0-6 text, then create the items + for (i = 0; i < 6; i++) + if (strlen((char *) strs[i]) > 0) {// text + for (j = 0; j < 10; j++) + if (item_dlg[j] < 0) { + free_item = j; + j = NI + 1; + } + item_dlg[free_item] = store_dlog_num; + item_type[free_item] = 9; + item_number[free_item] = cur_item; + item_rect[free_item] = cur_text_rect; + measure_rect.top = 0; measure_rect.bottom = 0; + measure_rect.left = 0; measure_rect.right = 340; + DrawText(main_dc, (char *) strs[i],strlen((char *) strs[i]), + &measure_rect,DT_CALCRECT | DT_WORDBREAK); + item_rect[free_item].bottom = item_rect[free_item].top + + (measure_rect.bottom - measure_rect.top) + 16; + + cur_text_rect.top = item_rect[free_item].bottom + 8; + item_flag[free_item] = 0; + item_active[free_item] = 1; + item_label[free_item] = 0; + item_label_loc[free_item] = -1; + item_key[free_item] = 0; + sprintf(text_long_str[free_item],"%s", + (char *) strs[i]); + cur_item++; + } + + dlg_highest_item[free_slot] = cur_item - 1; + + // finally, do button rects + cur_but_right = cur_text_rect.right + 30; + //cur_text_rect.top += 8; + for (i = 0; i < 3; i++) + if (buttons[i] >= 0) { + item_rect[but_items[i]].right = cur_but_right; + item_rect[but_items[i]].top = cur_text_rect.top; + item_rect[but_items[i]].bottom = item_rect[but_items[i]].top + 23; + if (button_type[available_dlog_buttons[buttons[i]]] == 1) + item_rect[but_items[i]].left = item_rect[but_items[i]].right - 63; + else item_rect[but_items[i]].left = item_rect[but_items[i]].right - 110; + cur_but_right = item_rect[but_items[i]].left - 4; + if (i == 0) { + win_width = item_rect[but_items[i]].right + 6; + win_height = item_rect[but_items[i]].bottom + 6; + } + } + + win_height += 18; + + MoveWindow(dlgs[free_slot],0,0,win_width,win_height,FALSE); + center_window(dlgs[free_slot]); + ShowWindow(dlgs[free_slot],SW_SHOW); + + if (dlg_parent[free_slot] != NULL) { + EnableWindow(dlg_parent[free_slot],FALSE); + if (dlg_parent[free_slot] == mainPtr) + for (i = 0; i < 18; i++) + if (modeless_exists[i] == TRUE) + EnableWindow(modeless_dialogs[i],FALSE); + } + dialog_not_toast = TRUE; + return 0; +} + +short cd_create_dialog(short dlog_num, HWND parent) +{ + short i, free_slot = -1; + HWND dlg; + + if (parent != NULL) { + if (IsWindowEnabled(parent) == 0) return -1; + } + + store_dlog_num = dlog_num; + store_parent = parent; + + for (i = 0; i < ND; i++) + if ((dlg_keys[i] >= 0) && (dlg_types[i] == dlog_num)) return -1; + + for (i = 0; i < ND; i++) { + if (dlg_keys[i] < 0) { + free_slot = i; + break; + } + } + if (free_slot < 0) return -2; + + current_key++; + + dlg_keys[free_slot] = current_key; + dlg_types[free_slot] = dlog_num; + dlg_highest_item[free_slot] = 1; + dlg_draw_ready[free_slot] = FALSE; + dlgs[free_slot] = NULL; + + // first, create dummy dlog + store_free_slot = free_slot; + + dlg = CreateDialog( + (HINSTANCE) store_hInstance, + MAKEINTRESOURCE(dlog_num), + 0, + (DLGPROC) d_proc + ); + + if (dlgs[free_slot] == NULL) + { + play_sound(3); + DebugQuit("Couldn't create Dialog Box"); + return -3; + } + + center_window(dlgs[free_slot]); + + dlg_parent[free_slot] = parent; + + switch (dlog_num) { + case 958: SetWindowText(dlgs[free_slot],"Tip of the Day"); break; + case 960: SetWindowText(dlgs[free_slot],"Talking Notes"); break; + case 961: SetWindowText(dlgs[free_slot],"Adventure Notes"); break; + case 962: SetWindowText(dlgs[free_slot],"Adventure Journal"); break; + case 970: case 971: case 972: case 973: SetWindowText(dlgs[free_slot],"Blades of Exile"); break; + case 987: SetWindowText(dlgs[free_slot],"Getting Items"); break; + case 988: SetWindowText(dlgs[free_slot],"Casting Simulacrum"); break; + case 989: SetWindowText(dlgs[free_slot],"Create a Party"); break; + case 991: SetWindowText(dlgs[free_slot],"Character Statistics"); break; + case 996: SetWindowText(dlgs[free_slot],"Known Alchemy"); break; + case 997: SetWindowText(dlgs[free_slot],"Getting Help"); break; + case 998: SetWindowText(dlgs[free_slot],"Item Information"); break; + case 999: SetWindowText(dlgs[free_slot],"Monster Stats"); break; + case 1012: SetWindowText(dlgs[free_slot],"How many?"); break; + case 1013: SetWindowText(dlgs[free_slot],"Race/Advantages/Disadvantages"); break; + case 1010: SetWindowText(dlgs[free_slot],"Training a PC"); break; + case 1014: SetWindowText(dlgs[free_slot],"Reading a Sign"); break; + case 1017: SetWindowText(dlgs[free_slot],"Blades of Exile"); break; + case 1018: SetWindowText(dlgs[free_slot],"Select a PC"); break; + case 1019: SetWindowText(dlgs[free_slot],"Character Statistics"); break; + case 1020: SetWindowText(dlgs[free_slot],"In a Shop"); break; + case 1021: SetWindowText(dlgs[free_slot],"Buying Food"); break; + case 1047: SetWindowText(dlgs[free_slot],"Select Alchemy"); break; + case 1048: SetWindowText(dlgs[free_slot],"Visiting the Healer"); break; + case 1050: SetWindowText(dlgs[free_slot],"Pick PC Graphic"); break; + case 1051: SetWindowText(dlgs[free_slot],"Pick PC Name"); break; + case 1096: SetWindowText(dlgs[free_slot],"Spells Help"); break; + case 1097: SetWindowText(dlgs[free_slot],"Skills Help"); break; + case 1098: SetWindowText(dlgs[free_slot],"Cast a Spell"); break; + case 1099: SetWindowText(dlgs[free_slot],"Preferences"); break; + case 1100: SetWindowText(dlgs[free_slot],"Compatibility Options"); break; + default: SetWindowText(dlgs[free_slot],"Blades of Exile"); break; + } + + ShowWindow(dlgs[free_slot],SW_SHOW); + DestroyWindow(dlg); //Necesary? Dunno. + + if (dlg_parent[free_slot] != NULL) + { + EnableWindow(dlg_parent[free_slot], FALSE); + + if (dlg_parent[free_slot] == mainPtr) + for (i = 0; i < 18; i++) + if (modeless_exists[i] == TRUE) EnableWindow(modeless_dialogs[i],FALSE); + } + dialog_not_toast = TRUE; + return 0; +} + +BOOL CALLBACK dummy_dialog_proc (HWND hDlg, UINT message, WPARAM, LPARAM) +{ + short i,j,k,free_slot = -1,free_item = -1; + int type, flag; + char item_str[256]; + Boolean str_stored = FALSE; + RECT dlg_rect; + short win_height = 0, win_width = 0; + short str_offset = 1; + + free_slot = store_free_slot; + + switch (message) + { + case WM_INITDIALOG: + // now, make a window, matching dialog + GetWindowRect(hDlg,&dlg_rect); + dlgs[store_free_slot] = CreateWindow( + szWinName, + "Blades of Exile Dialog", + 0,// was visible + 0, + 0, + dlg_rect.right - dlg_rect.left, + dlg_rect.bottom - dlg_rect.top, + NULL, + NULL, + store_hInstance, + NULL); + + // Now, give the window its items + for (i = 0; i < 200; i++) + if (GetDlgItem(hDlg,i) != NULL) + { + GetDlgItemText(hDlg,i,item_str,256); + str_offset = 1; + dlg_highest_item[free_slot] = i; + str_stored = FALSE; + + if (strlen((char *)item_str) == 0) + { + sprintf((char *) item_str, "+"); + type = 3; + flag = 0; + str_stored = TRUE; + } + else if (item_str[0] == '+') { // default is framed text + type = 3; + flag = 1; + str_stored = TRUE; + } + else if (item_str[0] == '*') { + type = 3; + flag = 0; + str_stored = TRUE; + } + else if (item_str[0] == '~') { + type = 7; + flag = 0; + str_stored = TRUE; + } + else if (item_str[0] == '!') { + type = 4; + flag = 0; + str_stored = TRUE; + } + else if (item_str[0] == '=') { + type = 9; + flag = 1; + str_stored = TRUE; + } + else if (((item_str[0] >= 65) && (item_str[0] <= 122)) || (item_str[0] == '"')) { + type = 9; + flag = 0; + str_offset = 0; + str_stored = TRUE; + } + else if ((item_str[0] == '^') || (item_str[0] == '&')) { + type = (item_str[0] == '^') ? 10 : 11; + flag = 1; + str_stored = TRUE; + } + else sscanf(item_str,"%d_%d",&type,&flag); + + free_item = -1; + // find free item + switch (type) { + case 0: case 1: case 2: case 5: case 6: + for (j = 150; j < NI; j++) + if (item_dlg[j] < 0) { + free_item = j; + j = NI + 1; + } + break; + default: + if ((type == 9) || + ((str_stored == TRUE) && (strlen((char *) item_str) > 35))) { + for (j = 0; j < 10; j++) + if (item_dlg[j] < 0) { + free_item = j; + j = NI + 1; + } + } + else { + for (j = 10; j < 140; j++) + if (item_dlg[j] < 0) { + free_item = j; + j = NI + 1; + } + } + break; + } + + if (free_item >= 0) { + item_dlg[free_item] = store_dlog_num; + item_type[free_item] = type; + item_number[free_item] = i; + + item_rect[free_item] = get_item_rect(hDlg,i); + item_rect[free_item].top = item_rect[free_item].top / 2; + item_rect[free_item].left = item_rect[free_item].left / 2; + item_rect[free_item].bottom = item_rect[free_item].bottom / 2; + item_rect[free_item].right = item_rect[free_item].right / 2; + + if ((type != 5) && ((store_dlog_num >= 2000) || (store_dlog_num == 986))) { + item_rect[free_item].top = + (item_rect[free_item].top * 11) / 10; + item_rect[free_item].bottom = + (item_rect[free_item].bottom * 11) / 10; + } + + item_flag[free_item] = flag; + item_active[free_item] = 1; + item_label[free_item] = 0; + item_label_loc[free_item] = -1; + item_key[free_item] = 0; + + switch (type) { + case 0: case 1: + if (item_flag[free_item] != 143) { + item_rect[free_item].right = item_rect[free_item].left + button_width[button_type[flag]]; + item_rect[free_item].bottom = item_rect[free_item].top + button_height[button_type[flag]]; + + item_key[free_item] = button_def_key[flag]; + if (type == 1) + item_key[free_item] = 31; + } + break; + case 2: + item_rect[free_item].right = item_rect[free_item].left + 14; + item_rect[free_item].bottom = item_rect[free_item].top + 10; + item_key[free_item] = 255; + break; + case 3: case 4: case 7: case 8: case 9: case 10: case 11: + sprintf(((free_item < 10) ? text_long_str[free_item] : text_short_str[free_item - 10]),""); + if (str_stored == TRUE) { + if (free_item < 10) { + sprintf(text_long_str[free_item],"%s", + (char *) (item_str + str_offset)); + for (k = 0; k < 256; k++) { + if (text_long_str[free_item][k] == '|') + text_long_str[free_item][k] = 13; + if (text_long_str[free_item][k] == '_') + text_long_str[free_item][k] = '"'; + } + } + else { + sprintf(text_short_str[free_item - 10],"%-34s", + (char *) (item_str + str_offset)); + for (k = 0; k < 35; k++) { + if (text_short_str[free_item][k] == '|') + text_short_str[free_item][k] = 13; + if (text_short_str[free_item][k] == '_') + text_short_str[free_item][k] = '"'; + } + } + } + item_key[free_item] = 255; + break; + case 6: + edit_box = CreateWindow("edit",NULL,WS_CHILD | WS_BORDER | WS_VISIBLE, + item_rect[free_item].left,item_rect[free_item].top, + item_rect[free_item].right - item_rect[free_item].left, + item_rect[free_item].bottom - item_rect[free_item].top, + dlgs[free_slot],(HMENU) 150,(HINSTANCE) store_hInstance,NULL); + store_edit_parent = dlgs[free_slot]; + old_edit_proc = (WNDPROC) (GetWindowLong(edit_box,GWL_WNDPROC)); + SetWindowLong(edit_box,GWL_WNDPROC,(LONG) edit_proc); + break; + } + win_height = max(win_height, item_rect[free_item].bottom + 28); + win_width = max(win_width, item_rect[free_item].right + 11); + } + } + MoveWindow(dlgs[free_slot],0,0,win_width,win_height,FALSE); + EndDialog(hDlg, 0); + return TRUE; + } /* end of switch */ + + return TRUE; +} + +short cd_kill_dialog(short dlog_num,short parent_message) +{ + short i,which_dlg = -1; + + for (i = 0; i < ND; i++) + if ((dlg_keys[i] >= 0) && (dlg_types[i] == dlog_num)) + which_dlg = i; + + if (which_dlg < 0) + return -1; + + for (i = 0; i < NI; i++) + if (item_dlg[i] == dlog_num) { + if (item_type[i] == 6) { + DestroyWindow(edit_box); + edit_box = NULL; + } + if (item_label[i] > 0) + label_taken[item_label_loc[i]] = FALSE; + item_dlg[i] = -1; + } + + if (dlg_parent[which_dlg] != NULL) { + EnableWindow(dlg_parent[which_dlg],TRUE); + if (dlg_parent[which_dlg] == mainPtr) + for (i = 0; i < 18; i++) + if (modeless_exists[i] == TRUE) + EnableWindow(modeless_dialogs[i],TRUE); + SetFocus(dlg_parent[which_dlg]); + SetWindowPos(dlg_parent[which_dlg],HWND_TOP,0,0,100,100, + SWP_NOMOVE | SWP_NOSIZE | SWP_NOREDRAW); + cd_set_edit_focus(); + } + + if (parent_message > 0) + SendMessage(dlg_parent[which_dlg],WM_COMMAND,parent_message,0); + + DestroyWindow(dlgs[which_dlg]); + dlg_keys[which_dlg] = -1; + dialog_not_toast = TRUE; + block_erase = TRUE; + return 0; +} + +short cd_process_click(HWND window, POINT the_point, WPARAM wparam, LPARAM,short *item) +{ + short i,which_dlg,dlg_num,item_id; + short dlog_key; +// char dummy[256]; + + if ((which_dlg = cd_find_dlog(window,&dlg_num,&dlog_key)) < 0) + return -1; + + for (i = 0; i < dlg_highest_item[which_dlg] + 1; i++) + { + if ((item_id = cd_get_item_id(dlg_num,i)) >= 0) + { + if (PtInRect(&item_rect[item_id],the_point) && (item_active[item_id] > 0) + && ((item_type[item_id] < 3) || (item_type[item_id] == 8) + || (item_type[item_id] == 10)|| (item_type[item_id] == 11))) + { + *item = i; + if (MK_CONTROL & wparam) *item += 100; + if (item_type[item_id] != 8) cd_press_button(dlg_num,i); + return dlg_num; + } + } + } + + return -1; +} + +short cd_process_syskeystroke(HWND window, WPARAM wparam, LPARAM,short *item) +{ + short i,which_dlg,dlg_num,dlg_key,item_id; + char char_hit; + + + if ((which_dlg = cd_find_dlog(window,&dlg_num,&dlg_key)) < 0) + return -1; + // specials ... 20 - <- 21 - -> 22 up 23 down 24 esc + // 25-30 ctrl 1-6 + + switch (wparam) { + case VK_ESCAPE: + char_hit = 24; + break; + //case VK_SPACE: + // char_hit = ' '; + // break; + case VK_LEFT: + char_hit = 20; + break; + case VK_UP: + char_hit = 22; + break; + case VK_RIGHT: + char_hit = 21; + break; + case VK_DOWN: + char_hit = 23; + break; + case VK_RETURN: + char_hit = 31; + break; + default: + return -1; + } + + for (i = 0; i < dlg_highest_item[which_dlg] + 1; i++) + if ((item_id = cd_get_item_id(dlg_num,i)) >= 0) { + if ((item_key[item_id] == char_hit) && (item_active[item_id] > 0) + && ((item_type[item_id] < 3) || (item_type[item_id] == 8))) { + *item = i; + if (item_type[item_id] != 8) + cd_press_button(dlg_num,i); + return dlg_num; + } + } + // kludgy. If you get an escape and is isn't processed, make it an enter + if (wparam == VK_ESCAPE) { + char_hit = 31; + for (i = 0; i < dlg_highest_item[which_dlg] + 1; i++) + if ((item_id = cd_get_item_id(dlg_num,i)) >= 0) { + if ((item_key[item_id] == char_hit) && (item_active[item_id] > 0) + && ((item_type[item_id] < 3) || (item_type[item_id] == 8))) { + *item = i; + if (item_type[item_id] != 8) + cd_press_button(dlg_num,i); + return dlg_num; + } + } + } + + return -1; +} + +short cd_process_keystroke(HWND window, WPARAM wparam, LPARAM, short *item) +{ + short i,which_dlg,dlg_num,dlg_key,item_id; + char char_hit; + + if ((which_dlg = cd_find_dlog(window,&dlg_num,&dlg_key)) < 0) + return -1; + // specials ... 20 - <- 21 - -> 22 up 23 down 24 esc + // 25-30 ctrl 1-6 + + char_hit = (char) wparam; + + for (i = 0; i < dlg_highest_item[which_dlg] + 1; i++) + if ((item_id = cd_get_item_id(dlg_num,i)) >= 0) { + if ((item_key[item_id] == char_hit) && (item_active[item_id] > 0) + && ((item_type[item_id] < 3) || (item_type[item_id] == 8))) { + *item = i; + if (item_type[item_id] != 8) + cd_press_button(dlg_num,i); + return dlg_num; + } + } + return -1; +} + +void cd_attach_key(short dlog_num,short item_num,char key) +{ + short dlg_index,item_index; + + if (cd_get_indices(dlog_num,item_num,&dlg_index,&item_index) < 0) + return; + + if ((item_type[item_index] > 2) && (item_type[item_index] != 8)) { + beep(); + return; + } + item_key[item_index] = key; +} + +void cd_set_pict(short dlog_num, short item_num, short pict_num) +{ + short dlg_index,item_index; + if (cd_get_indices(dlog_num,item_num,&dlg_index,&item_index) < 0) + return; + if (item_type[item_index] != 5) { + beep(); + return; + } + item_flag[item_index] = pict_num; + if (pict_num == -1) + cd_erase_item(dlog_num,item_num); + else cd_draw_item(dlog_num,item_num); +} + +void cd_activate_item(short dlog_num, short item_num, short status) +{ + short dlg_index,item_index; + if (cd_get_indices(dlog_num,item_num,&dlg_index,&item_index) < 0) + return; + + item_active[item_index] = status; + cd_draw_item(dlog_num,item_num); +} + +short cd_get_active(short dlog_num, short item_num) +{ + short dlg_index,item_index; + if (cd_get_indices(dlog_num,item_num,&dlg_index,&item_index) < 0) + return -1; + + return item_active[item_index]; +} + +void cd_get_text_edit_str(short, char *str) +{ + if (edit_box != NULL) + GetWindowText(edit_box,str,255); + else str[0] = 0; +} + +void cd_set_item_text(short dlog_num, short item_num, char *str) +{ + short k,dlg_index,item_index; + if (cd_get_indices(dlog_num,item_num,&dlg_index,&item_index) < 0) + return ; + if (item_type[item_index] == 6) { + if (edit_box != NULL) + SetWindowText(edit_box,str); + return; + } + if (item_index >= 150) { + beep(); + return; + } + if (item_index < 10) { + sprintf(text_long_str[item_index],"%s",str); + for (k = 0; k < 256; k++) { + if (text_long_str[item_index][k] == '|') + text_long_str[item_index][k] = 13; + if (text_long_str[item_index][k] == '_') + text_long_str[item_index][k] = '"'; + } + + } + else sprintf(text_short_str[item_index - 10],"%-34s",str); + cd_draw_item( dlog_num,item_num); +} + +void cd_set_item_num(short dlog_num, short item_num, short num) +{ + short dlg_index,item_index; + if (cd_get_indices(dlog_num,item_num,&dlg_index,&item_index) < 0) + return ; + if (item_index >= 150) { + beep(); + return; + } + if (item_index < 10) + sprintf(text_long_str[item_index],"%d",num); + else sprintf(text_short_str[item_index - 10],"%d",num); + cd_draw_item( dlog_num,item_num); +} + +void cd_set_flag(short dlog_num,short item_num,short flag) +{ + short dlg_index,item_index; + + if (cd_get_indices(dlog_num,item_num,&dlg_index,&item_index) < 0) + return; + + item_flag[item_index] = flag; + cd_draw_item(dlog_num,item_num); +} + +void cd_set_led(short dlog_num,short item_num,short state) +{ + short dlg_index,item_index; + + if (cd_get_indices(dlog_num,item_num,&dlg_index,&item_index) < 0) + return; + + if (item_type[item_index] != 2) { + beep(); + return; + } + item_flag[item_index] = state; + cd_draw_item(dlog_num,item_num); +} + +short cd_get_led(short dlog_num,short item_num) +{ + short dlg_index,item_index; + + if (cd_get_indices(dlog_num,item_num,&dlg_index,&item_index) < 0) + return 0; + + if (item_type[item_index] != 2) { + beep(); + return 0; + } + return item_flag[item_index]; +} + + +void cd_text_frame(short dlog_num,short item_num,short frame) +{ + short dlg_index,item_index; + + if (cd_get_indices(dlog_num,item_num,&dlg_index,&item_index) < 0) + return; + + if (item_index >= 150) { + beep(); + return; + } + item_flag[item_index] = frame; + cd_draw_item(dlog_num,item_num); +} + +void cd_add_label(short dlog_num, short item_num, char *label, short label_flag) +{ + short dlg_index,item_index,label_loc = -1; + short i; + + if (cd_get_indices(dlog_num,item_num,&dlg_index,&item_index) < 0) + return; + + if (item_label_loc[item_index] < 0) { + item_label[item_index] = label_flag; + for (i = 0; i < 100; i++) + if (label_taken[i] == FALSE) { + label_loc = i; + label_taken[i] = TRUE; + i = 100; + } + if (label_loc < 0) { + beep(); + return; + } + item_label_loc[item_index] = label_loc; + } + else cd_erase_item(dlog_num,item_num + 100); + label_loc = item_label_loc[item_index]; + sprintf((char *) labels[label_loc],"%-24s",label); + if (item_active[item_index] > 0) + cd_draw_item(dlog_num,item_num); +} + +void cd_key_label(short dlog_num, short item_num,short loc) +{ + short dlg_index,item_index; + char str[10]; + if (cd_get_indices(dlog_num,item_num,&dlg_index,&item_index) < 0) + return; + sprintf((char *) str," "); + str[0] = item_key[item_index]; + cd_add_label(dlog_num,item_num, str, 7 + loc * 100); +} + +void cd_draw_item(short dlog_num,short item_num) +{ + short dlg_index,item_index,store_label; + HDC win_dc; + COLORREF colors[4] = {RGB(0,0,0),RGB(255,0,0),RGB(0,0,102),RGB(255,255,255)}; + RECT from_rect,to_rect; + HFONT old_font; + + if (cd_get_indices(dlog_num,item_num,&dlg_index,&item_index) < 0) + return; + if (dlg_draw_ready[dlg_index] == FALSE) + return; + + win_dc = cd_get_dlog_dc(dlg_index); + old_font = (HFONT) SelectObject(win_dc,small_bold_font); + dlg_force_dc = win_dc; + + if (item_active[item_index] == 0) { + cd_erase_item(dlog_num,item_num); + cd_erase_item(dlog_num,item_num + 100); + } + else { + switch (item_type[item_index]) { + case 0: case 1: case 10: case 11: + if (item_flag[item_index] == 143) + break; + from_rect.top = button_ul_y[button_type[item_flag[item_index]]]; + from_rect.left = button_ul_x[button_type[item_flag[item_index]]]; + from_rect.bottom = from_rect.top + button_height[button_type[item_flag[item_index]]]; + from_rect.right = from_rect.left + button_width[button_type[item_flag[item_index]]]; + rect_draw_some_item(dlg_buttons_gworld,from_rect,(HBITMAP) win_dc,item_rect[item_index],0,2); + + SelectObject(win_dc,bold_font); + SetTextColor(win_dc,colors[2]); + if (item_type[item_index] < 2) + OffsetRect(&item_rect[item_index],-1 * button_left_adj[item_flag[item_index]],0); + if (item_type[item_index] < 2) { + char_win_draw_string(win_dc,item_rect[item_index], + (char *) (button_strs[item_flag[item_index]]),1,8); + } + else { + char_win_draw_string(win_dc,item_rect[item_index], + (char *) ((item_index < 10) ? text_long_str[item_index] : + text_short_str[item_index - 10]),1,8); + } + if (item_type[item_index] < 2) + OffsetRect(&item_rect[item_index],button_left_adj[item_flag[item_index]],0); + SetTextColor(win_dc,colors[0]); + + break; + + case 2: + switch (item_flag[item_index]) { + case 0: from_rect.left = 166; from_rect.top = 36; break; + case 1: from_rect.left = 152; from_rect.top = 36; break; + case 2: from_rect.left = 138; from_rect.top = 36; break; + } + from_rect.right = from_rect.left + 14; + from_rect.bottom = from_rect.top + 10; + rect_draw_some_item( dlg_buttons_gworld,from_rect, (HBITMAP) win_dc,item_rect[item_index],0,2); break; + break; + + case 3: case 4: case 7: case 8: case 9: + cd_erase_item(dlog_num,item_num); + SetTextColor(win_dc,colors[3]); + if ((item_type[item_index] == 3) || (item_type[item_index] == 9)) + SelectObject(win_dc,small_bold_font); + if (item_type[item_index] == 4) + SelectObject(win_dc,tiny_font); + if (item_type[item_index] == 7) + SelectObject(win_dc,bold_font); + if (item_flag[item_index] % 10 == 1) + cd_frame_item(dlog_num,item_num,2); + if (item_flag[item_index] >= 10) { + SetTextColor(win_dc,colors[1]); + } + + if (item_rect[item_index].bottom - item_rect[item_index].top < 20) { + item_rect[item_index].left += 3; + DrawText(win_dc,(char *) ((item_index < 10) ? text_long_str[item_index] : + text_short_str[item_index - 10]), -1, &item_rect[item_index], + DT_LEFT | DT_SINGLELINE | DT_VCENTER | DT_NOCLIP); + item_rect[item_index].left -= 3; + } + else { + InflateRect(&item_rect[item_index],-4,-4); + DrawText(win_dc,(char *) ((item_index < 10) ? text_long_str[item_index] : + text_short_str[item_index - 10]), -1, &item_rect[item_index], + DT_LEFT | DT_WORDBREAK | DT_NOCLIP); + InflateRect(&item_rect[item_index],4,4); + } + SetTextColor(win_dc,colors[0]); + break; + case 5: + if (item_flag[item_index] == -1) + cd_erase_item(dlog_num,item_num); + else draw_dialog_graphic(dlgs[dlg_index], item_rect[item_index], + item_flag[item_index],(item_flag[item_index] >= 2000) ? FALSE : TRUE,0); + break; + } + } + + if (item_label[item_index] != 0) { + store_label = item_label[item_index]; + if (store_label >= 1000) { + store_label -= 1000; + SelectObject(win_dc,bold_font); + } + else SelectObject(win_dc,tiny_font); + to_rect = item_rect[item_index]; + switch (store_label / 100) { + case 0: + to_rect.right = to_rect.left; + to_rect.left -= 2 * (store_label % 100); + break; + case 1: + to_rect.bottom = to_rect.top; + to_rect.top -= 2 * (store_label % 100); + break; + case 2: + to_rect.left = to_rect.right; + to_rect.right += 2 * (store_label % 100); + break; + case 3: + to_rect.top = to_rect.bottom; + to_rect.bottom += 2 * (store_label % 100); + break; + } + + if (to_rect.bottom - to_rect.top < 14) { + to_rect.bottom += (14 - (to_rect.bottom - to_rect.top)) / 2 + 1; + to_rect.top -= (14 - (to_rect.bottom - to_rect.top)) / 2 + 1; + } + + if (item_active[item_index] != 0) { + SetTextColor(win_dc,colors[3]); + + DrawText(win_dc, (char *) labels[item_label_loc[item_index]], + -1, &to_rect, DT_LEFT | DT_SINGLELINE | DT_VCENTER); + SetTextColor(win_dc,colors[0]); + + } + } + + // hook in special stuff. kludgy + if ((dlog_num == 1098) && ((item_num >= 18) && (item_num <= 23))) { + draw_pc_effects(10 + item_num - 18,win_dc); + } + + SelectObject(win_dc,old_font); + cd_kill_dc(dlg_index,win_dc); + dlg_force_dc = NULL; + } + +void cd_initial_draw(short dlog_num) +{ + short i,which_dlg = -1; + + for (i = 0; i < ND; i++) + if ((dlg_keys[i] >= 0) && (dlg_types[i] == dlog_num)) + which_dlg = i; + if (which_dlg < 0) + return; + dlg_draw_ready[which_dlg] = TRUE; + + cd_erase_item(dlog_num, 0); + cd_draw(dlog_num); +} + +void cd_draw(short dlog_num) +{ + short i,which_dlg = -1; + + for (i = 0; i < ND; i++) + if ((dlg_keys[i] >= 0) && (dlg_types[i] == dlog_num)) + which_dlg = i; + if (which_dlg < 0) + return; + + for (i = 0; i < dlg_highest_item[which_dlg] + 1; i++) { + cd_draw_item(dlog_num,i); + } +} + +void cd_redraw(HWND window) +{ + short which_dlg,dlg_num,dlg_key; + + if ((which_dlg = cd_find_dlog(window,&dlg_num,&dlg_key)) < 0) + return; + dlg_draw_ready[which_dlg] = TRUE; + cd_initial_draw(dlg_num); +} + +void cd_frame_item(short dlog_num, short item_num, short width) +{ + short dlg_index,item_index; + + if (cd_get_indices(dlog_num,item_num,&dlg_index,&item_index) < 0) + return; + frame_dlog_rect(dlgs[dlg_index], item_rect[item_index], width); +} + +void cd_erase_item(short dlog_num, short item_num) +// if item_num is 0, nail whole window +// item_num + 100 just erase label +{ + short i,dlg_index,item_index,store_label; + RECT to_fry; + HDC win_dc; + Boolean just_label = FALSE; + + if (item_num >= 100) { + item_num -= 100; + just_label = TRUE; + } + + if (item_num == 0) { + for (i = 0; i < ND; i++) + if ((dlg_keys[i] >= 0) && (dlg_types[i] == dlog_num)) + dlg_index = i; + GetWindowRect(dlgs[dlg_index],&to_fry); + OffsetRect(&to_fry,-1 * to_fry.left,-1 * to_fry.top); + } + else { + if (cd_get_indices(dlog_num,item_num,&dlg_index,&item_index) < 0) + return; + to_fry = item_rect[item_index]; + if (just_label == TRUE) { + if (item_label[item_index] != 0) { + store_label = item_label[item_index]; + if (store_label >= 1000) + store_label -= 1000; + + switch (store_label / 100) { + case 0: + to_fry.right = to_fry.left; + to_fry.left -= 2 * (store_label % 100); + break; + case 1: + to_fry.bottom = to_fry.top; + to_fry.top -= 2 * (store_label % 100); + break; + case 2: + to_fry.left = to_fry.right; + to_fry.right += 2 * (store_label % 100); + break; + case 3: + to_fry.top = to_fry.bottom; + to_fry.bottom += 2 * (store_label % 100); + break; + } + if ((i = 12 - (to_fry.bottom - to_fry.top)) > 0) { + // adjust rect ... but doesn't work for bold letters + to_fry.bottom += i / 2; + to_fry.bottom++; // extra pixel to get dangly letters + to_fry.top -= i / 2; + } + } + } + InflateRect(&to_fry,1,1); + + } + if (dlg_draw_ready[dlg_index] == FALSE) + return; + win_dc = cd_get_dlog_dc(dlg_index); + paint_pattern((HBITMAP) win_dc,2,to_fry,0); + cd_kill_dc(dlg_index,win_dc); +} + +void cd_press_button(short dlog_num, short item_num) +{ + short dlg_index,item_index; + long dummy; + HDC win_dc; + RECT from_rect; + COLORREF colors[3] = {RGB(0,0,0),RGB(0,0,112),RGB(0,255,255)}; + + if (cd_get_indices(dlog_num,item_num,&dlg_index,&item_index) < 0) + return; + // no press action for redio buttons + if ((item_type[item_index] == 2) || (item_flag[item_index] == 143)) { + play_sound(34); + return; + } + + win_dc = cd_get_dlog_dc(dlg_index); + + from_rect.top = button_ul_y[button_type[item_flag[item_index]]]; + from_rect.left = button_ul_x[button_type[item_flag[item_index]]]; + from_rect.bottom = from_rect.top + button_height[button_type[item_flag[item_index]]]; + from_rect.right = from_rect.left + button_width[button_type[item_flag[item_index]]]; + OffsetRect(&from_rect,button_width[button_type[item_flag[item_index]]],0); + + rect_draw_some_item(dlg_buttons_gworld,from_rect,(HBITMAP)win_dc,item_rect[item_index],0,2); + + SelectObject(win_dc,bold_font); + SetTextColor(win_dc,colors[2]); + if (item_type[item_index] < 2) + OffsetRect(&item_rect[item_index],-1 * button_left_adj[item_flag[item_index]],0); + if (item_type[item_index] < 2) { + char_win_draw_string(win_dc,item_rect[item_index], + (char *) (button_strs[item_flag[item_index]]),1,8); + } + else { + char_win_draw_string(win_dc,item_rect[item_index], + (char *) ((item_index < 10) ? text_long_str[item_index] : + text_short_str[item_index - 10]),1,8); + } + if (item_type[item_index] < 2) + OffsetRect(&item_rect[item_index],button_left_adj[item_flag[item_index]],0); + + if (play_sounds == TRUE) { + play_sound(37); + Delay(6,&dummy); + } + else Delay(10,&dummy); + + OffsetRect(&from_rect,-1 * button_width[button_type[item_flag[item_index]]],0); + rect_draw_some_item(dlg_buttons_gworld,from_rect,(HBITMAP)win_dc,item_rect[item_index],0,2); + + SelectObject(win_dc,bold_font); + SetTextColor(win_dc,colors[1]); + if (item_type[item_index] < 2) + OffsetRect(&item_rect[item_index],-1 * button_left_adj[item_flag[item_index]],0); + if (item_type[item_index] < 2) { + char_win_draw_string(win_dc,item_rect[item_index], + (char *) (button_strs[item_flag[item_index]]),1,8); + } + else { + char_win_draw_string(win_dc,item_rect[item_index], + (char *) ((item_index < 10) ? text_long_str[item_index] : + text_short_str[item_index - 10]),1,8); + } + if (item_type[item_index] < 2) + OffsetRect(&item_rect[item_index],button_left_adj[item_flag[item_index]],0); + + SelectObject(win_dc,font); + SetTextColor(win_dc,colors[0]); + + cd_kill_dc(dlg_index,win_dc); + } + +// LOW LEVEL +short cd_get_indices(short dlg_num, short item_num, short *dlg_index, short *item_index) +{ + if ((*dlg_index = cd_get_dlg_index(dlg_num)) < 0) return -1; + if ((*item_index = cd_get_item_id(dlg_num,item_num)) < 0) return -1; + return 0; +} + +short cd_get_dlg_index(short dlog_num) +{ + short i; + + for (i = 0; i < ND; i++) + if ((dlg_keys[i] >= 0) && (dlg_types[i] == dlog_num)) + return i; + return -1; +} + +short cd_find_dlog(HWND window, short *dlg_num, short *dlg_key) +{ + short i; + for (i = 0; i < ND; i++) + if ((dlg_keys[i] >= 0) && (dlgs[i] == window)) { + *dlg_num = dlg_types[i]; + *dlg_key = dlg_keys[i]; + return i; + } + return -1; +} + +short cd_get_item_id(short dlg_num, short item_num) +{ + short i; + + for (i = 0; i < NI; i++) + if ((item_dlg[i] == dlg_num) && (item_number[i] == item_num)) + return i; + return -1; +} + +HDC cd_get_dlog_dc(short which_slot) +{ + HDC win_dc = GetDC(dlgs[which_slot]); + SetBkMode(win_dc,TRANSPARENT); + return win_dc; +} + +void center_window(HWND window) +{ + RECT main_rect,wind_rect; + short width,height; + + cursor_shown = TRUE; + showcursor(TRUE); + + GetWindowRect(GetDesktopWindow(),&main_rect); + GetWindowRect(window,&wind_rect); + width = wind_rect.right - wind_rect.left; + height = wind_rect.bottom - wind_rect.top; + MoveWindow(window,((main_rect.right - main_rect.left) - width) / 2, + ((main_rect.bottom - main_rect.top) - height) / 2,width,height,TRUE); + +} + +RECT get_item_rect(HWND hDlg, short item_num) +{ + HWND item; + RECT big_rect,small_rect; + + item = GetDlgItem(hDlg, item_num); + GetWindowRect(hDlg,&big_rect); + GetWindowRect(item,&small_rect); + OffsetRect(&small_rect, -1 * big_rect.left - 7, -1 * big_rect.top - 7); + small_rect.right += 2; + small_rect.bottom += 2; + return small_rect; +} + + +void frame_dlog_rect(HWND hDlg, RECT rect, short val) +{ + HDC hdc; + HPEN dpen,lpen,old_pen; + COLORREF x = RGB(0,204,255),y = RGB(0,204,255);//y = RGB(119,119,119); + Boolean keep_dc = FALSE; + + InflateRect(&rect,val,val); + + if (hDlg == mainPtr) + { + keep_dc = TRUE; + hdc = main_dc; + } + else if (dlg_force_dc != NULL) + { + hdc = dlg_force_dc; + keep_dc = TRUE; + } + else hdc = GetDC(hDlg); + + if (hdc == NULL) + { + beep(); + return; + } + + lpen = CreatePen(PS_SOLID,1,x); + dpen = CreatePen(PS_SOLID,1,y); + old_pen = (HPEN) SelectObject(hdc,dpen); + MoveToEx(hdc,rect.left,rect.top, NULL); + LineTo(hdc,rect.right,rect.top); + SelectObject(hdc,lpen); + LineTo(hdc,rect.right,rect.bottom); + LineTo(hdc,rect.left,rect.bottom); + SelectObject(hdc,dpen); + LineTo(hdc,rect.left,rect.top); + SelectObject(hdc,old_pen); + if (keep_dc == FALSE) + fry_dc(hDlg,hdc); + DeleteObject(dpen); + DeleteObject(lpen); +} + +void draw_dialog_graphic(HWND hDlg, RECT rect, short which_g, Boolean do_frame,short win_or_gworld) +// win_or_gworld: 0 - window 1 - an HBITMAP +// 1 means hDlg is actually an HBITMAP variable! +// 0 - 300 number of terrain graphic +// 400 + x - monster graphic num +// 600 + x item graphic +// 700 + x dlog graphic +// 800 + x pc graphic +// 900 + x B&W graphic +// 950 null item +// 1000 + x Talking face +// 1100 - item info help +// 1200 - pc screen help +// 1300 - combat ap +// 1400-1402 - button help +// 1500 - stat symbols help +// 1600 + x - B&W maps +// 1700 + x - anim graphic +{ + RECT from2 = {0,0,36,36},tiny_obj_rect = {0,0,18,18}; + RECT from_rect = {0,0,28, 36}; + RECT face_from = {0,0,32,32}; + RECT to_rect = {6,6,42,42}; + RECT bw_from = {0,0,120,120}; + + RECT pc_info_from = {0,127,106,157}; + RECT item_info_from = {174,0,312,112}; + RECT button_help_from = {0,0,320,100}; + RECT combat_ap_from = {0,0,275,100}; + RECT stat_symbols_from = {0,0,386,94}; /**/ + RECT small_monst_rect = {0,0,14,18}; + RECT large_scen_from = {0,0,64,64}; + + HBITMAP from_gworld; + short draw_dest = 2; + HDC hdc; + HBRUSH old_brush; + short m_start_pic = 0,square_size = 32; + + if (win_or_gworld == 1) draw_dest = 0; + if (which_g < 0) return; + if (which_g >= 3000) do_frame = FALSE; + which_g %= 3000; + + if (win_or_gworld == 0) { + if (dlg_force_dc != NULL) + hdc = dlg_force_dc; + else hdc = GetDC(hDlg); + } + if (which_g == 950) { // Empty. Maybe clear space. + if (win_or_gworld == 0) { + paint_pattern((HBITMAP) hdc,2,rect,0); + } + //FillCRect(&rect,bg[5]); // don't forget to nail dc!!! + if (dlg_force_dc == NULL) + fry_dc(hDlg, hdc); + return; + } + + switch (which_g / 100) { + case 0: case 1: case 2: // terrain + from_gworld = load_pict(800 + which_g / 50,main_dc); + which_g = which_g % 50; + from_rect = calc_rect(which_g % 10, which_g / 10); + if (rect.right - rect.left != 28) { + rect.left += 1; + rect.right = rect.left + 28; + } + rect_draw_some_item(from_gworld,from_rect,(HBITMAP) ((win_or_gworld == 1) ? (HBITMAP)(hDlg): (HBITMAP)hdc) + ,rect,0,draw_dest); + DeleteObject(from_gworld); + break; + case 3: // animated terrain + which_g -= 300; + from_gworld = load_pict(820,main_dc); + from_rect = calc_rect(4 * (which_g / 5), which_g % 5); + rect_draw_some_item(from_gworld,from_rect,(HBITMAP) ((win_or_gworld == 1) ? (HBITMAP)hDlg: (HBITMAP)hdc) + ,rect,0,draw_dest); + DeleteObject(from_gworld); + break; + case 4: case 5: // monster + // There are 4 different ways to draw, depending on size of monster + which_g -= 400; + m_start_pic = m_pic_index[which_g]; + if ((m_pic_index_x[which_g] == 1) && (m_pic_index_y[which_g] == 1)) { + from_gworld = load_pict(1100 + m_start_pic / 20,main_dc); + m_start_pic = m_start_pic % 20; + from_rect = calc_rect(2 * (m_start_pic / 10), m_start_pic % 10); + rect.right = rect.left + 28; rect.bottom = rect.top + 36; + if (win_or_gworld == 0) { + old_brush = (HBRUSH) SelectObject(hdc,GetStockObject(BLACK_BRUSH)); + Rectangle(hdc,rect.left,rect.top,rect.right,rect.bottom); + SelectObject(hdc,old_brush); + } + if (win_or_gworld == 1) + rect_draw_some_item(from_gworld,from_rect,(HBITMAP) hDlg,rect,0,0); + else rect_draw_some_item(from_gworld,from_rect,(HBITMAP)hdc,rect,0,draw_dest); + DeleteObject(from_gworld); + } + if ((m_pic_index_x[which_g] == 2) && (m_pic_index_y[which_g] == 1)) { + rect.right = rect.left + 28; rect.bottom = rect.top + 36; + if (win_or_gworld == 0) { + old_brush = (HBRUSH) SelectObject(hdc,GetStockObject(BLACK_BRUSH)); + Rectangle(hdc,rect.left,rect.top,rect.right,rect.bottom); + SelectObject(hdc,old_brush); + } + from_gworld = load_pict(1100 + m_start_pic / 20,main_dc); + m_start_pic = m_start_pic % 20; + from_rect = calc_rect(2 * (m_start_pic / 10), m_start_pic % 10); + OffsetRect(&small_monst_rect,rect.left,rect.top + 7); + + if (win_or_gworld == 1) + rect_draw_some_item(from_gworld,from_rect,(HBITMAP) hDlg,small_monst_rect,0,0); + else rect_draw_some_item(from_gworld,from_rect,(HBITMAP)hdc,small_monst_rect,0,draw_dest); + + m_start_pic = m_pic_index[which_g] + 1; + DeleteObject(from_gworld); + from_gworld = load_pict(1100 + m_start_pic / 20,main_dc); + m_start_pic = m_start_pic % 20; + from_rect = calc_rect(2 * (m_start_pic / 10), m_start_pic % 10); + OffsetRect(&small_monst_rect,14,0); + + if (win_or_gworld == 1) + rect_draw_some_item(from_gworld,from_rect,(HBITMAP) hDlg,small_monst_rect,0,0); + else rect_draw_some_item(from_gworld,from_rect,(HBITMAP)hdc,small_monst_rect,0,draw_dest); + DeleteObject(from_gworld); + } + if ((m_pic_index_x[which_g] == 1) && (m_pic_index_y[which_g] == 2)) { + rect.right = rect.left + 28; rect.bottom = rect.top + 36; + if (win_or_gworld == 0) { + old_brush = (HBRUSH)SelectObject(hdc,GetStockObject(BLACK_BRUSH)); + Rectangle(hdc,rect.left,rect.top,rect.right,rect.bottom); + SelectObject(hdc,old_brush); + } + + from_gworld = load_pict(1100 + m_start_pic / 20,main_dc); + m_start_pic = m_start_pic % 20; + from_rect = calc_rect(2 * (m_start_pic / 10), m_start_pic % 10); + OffsetRect(&small_monst_rect,rect.left + 7,rect.top); + + if (win_or_gworld == 1) + rect_draw_some_item(from_gworld,from_rect,(HBITMAP) hDlg,small_monst_rect,0,0); + else rect_draw_some_item(from_gworld,from_rect,(HBITMAP)hdc,small_monst_rect,0,draw_dest); + m_start_pic = m_pic_index[which_g] + 1; + DeleteObject(from_gworld); + from_gworld = load_pict(1100 + m_start_pic / 20,main_dc); + m_start_pic = m_start_pic % 20; + from_rect = calc_rect(2 * (m_start_pic / 10), m_start_pic % 10); + OffsetRect(&small_monst_rect,0,18); + + if (win_or_gworld == 1) + rect_draw_some_item(from_gworld,from_rect,(HBITMAP) hDlg,small_monst_rect,0,0); + else rect_draw_some_item(from_gworld,from_rect,(HBITMAP)hdc,small_monst_rect,0,draw_dest); + DeleteObject(from_gworld); + } + + if ((m_pic_index_x[which_g] == 2) && (m_pic_index_y[which_g] == 2)) { + rect.right = rect.left + 28; rect.bottom = rect.top + 36; + if (win_or_gworld == 0) { + old_brush = (HBRUSH)SelectObject(hdc,GetStockObject(BLACK_BRUSH)); + Rectangle(hdc,rect.left,rect.top,rect.right,rect.bottom); + SelectObject(hdc,old_brush); + } + from_gworld = load_pict(1100 + m_start_pic / 20,main_dc); + m_start_pic = m_start_pic % 20; + from_rect = calc_rect(2 * (m_start_pic / 10), m_start_pic % 10); + OffsetRect(&small_monst_rect,rect.left,rect.top); + + if (win_or_gworld == 1) + rect_draw_some_item(from_gworld,from_rect,(HBITMAP) hDlg,small_monst_rect,0,0); + else rect_draw_some_item(from_gworld,from_rect,(HBITMAP)hdc,small_monst_rect,0,draw_dest); + + m_start_pic = m_pic_index[which_g] + 1; + DeleteObject(from_gworld); + from_gworld = load_pict(1100 + m_start_pic / 20,main_dc); + m_start_pic = m_start_pic % 20; + from_rect = calc_rect(2 * (m_start_pic / 10), m_start_pic % 10); + OffsetRect(&small_monst_rect,14,0); + + if (win_or_gworld == 1) + rect_draw_some_item(from_gworld,from_rect,(HBITMAP) hDlg,small_monst_rect,0,0); + else rect_draw_some_item(from_gworld,from_rect,(HBITMAP)hdc,small_monst_rect,0,draw_dest); + + m_start_pic = m_pic_index[which_g] + 2; + DeleteObject(from_gworld); + from_gworld = load_pict(1100 + m_start_pic / 20,main_dc); + m_start_pic = m_start_pic % 20; + from_rect = calc_rect(2 * (m_start_pic / 10), m_start_pic % 10); + OffsetRect(&small_monst_rect,-14,18); + + if (win_or_gworld == 1) + rect_draw_some_item(from_gworld,from_rect,(HBITMAP) hDlg,small_monst_rect,0,0); + else rect_draw_some_item(from_gworld,from_rect,(HBITMAP)hdc,small_monst_rect,0,draw_dest); + m_start_pic = m_pic_index[which_g] + 3; + DeleteObject(from_gworld); + from_gworld = load_pict(1100 + m_start_pic / 20,main_dc); + m_start_pic = m_start_pic % 20; + from_rect = calc_rect(2 * (m_start_pic / 10), m_start_pic % 10); + OffsetRect(&small_monst_rect,14,0); + + if (win_or_gworld == 1) + rect_draw_some_item(from_gworld,from_rect,(HBITMAP) hDlg,small_monst_rect,0,0); + else rect_draw_some_item(from_gworld,from_rect,(HBITMAP)hdc,small_monst_rect,0,draw_dest); + } + DeleteObject(from_gworld); + break; + case 18: case 19: // item + which_g -= 1800; + to_rect = rect; + if (which_g < 45) { + from_gworld = items_gworld; + from_rect = calc_rect(which_g % 5, which_g / 5); + } + else { + from_gworld = tiny_obj_gworld; + //rect.top += 4; rect.bottom -= 4; + //InflateRect(&to_rect,-5,-9); + to_rect.top += 9; + to_rect.left += 5; + to_rect.right = to_rect.left + 18; + to_rect.bottom = to_rect.top + 18; + from_rect = tiny_obj_rect; + OffsetRect(&from_rect,18 * (which_g % 10), 18 * (which_g / 10)); + } + rect_draw_some_item(from_gworld,from_rect,(HBITMAP) ((win_or_gworld == 1) ? (HBITMAP)hDlg: (HBITMAP)hdc) + ,to_rect,1,draw_dest); + break; + case 7: // dialog + which_g -= 700; + from_gworld = dlogpics_gworld; + OffsetRect(&from2,36 * (which_g % 4),36 * (which_g / 4)); + rect_draw_some_item(from_gworld,from2,(HBITMAP) ((win_or_gworld == 1) ? (HBITMAP)hDlg: (HBITMAP)hdc) + ,rect,0,draw_dest); + break; + case 8: // PC + if (pcs_gworld != NULL) + from_gworld = pcs_gworld; + else from_gworld = load_pict(902,main_dc); + which_g -= 800; + from_rect = calc_rect(2 * (which_g / 8), which_g % 8); + old_brush = (HBRUSH)SelectObject(hdc,GetStockObject(BLACK_BRUSH)); + Rectangle(hdc,rect.left,rect.top,rect.right,rect.bottom); + SelectObject(hdc,old_brush); + //PaintRect(&rect); + rect_draw_some_item(from_gworld,from_rect,(HBITMAP) ((win_or_gworld == 1) ? (HBITMAP)hDlg: (HBITMAP)hdc) + ,rect,1,draw_dest); + if (pcs_gworld == NULL) + DeleteObject(from_gworld); + break; + case 9: // B&W + which_g -= 900; + from_gworld = load_pict(875,main_dc); + from_rect = bw_from; + OffsetRect(&from_rect,120 * ((which_g) % 3),120 * ((which_g) / 3)); + if (win_or_gworld == 1) + rect_draw_some_item(from_gworld,from_rect,(HBITMAP) hDlg,rect,0,0); + else rect_draw_some_item(from_gworld,from_rect,(HBITMAP)hdc,rect,0,draw_dest); + DeleteObject(from_gworld); + break; + case 10: // talk face + which_g -= 1000; + from_gworld = load_pict(860,main_dc); + from_rect = face_from; + OffsetRect(&from_rect,32 * ((which_g - 1) % 10),32 * ((which_g - 1) / 10)); + if (win_or_gworld == 1) + rect_draw_some_item(from_gworld,from_rect,(HBITMAP) hDlg,rect,0,0); + else rect_draw_some_item(from_gworld,from_rect,(HBITMAP)hdc,rect,0,draw_dest); + DeleteObject(from_gworld); + break; + case 11: // item info help + from_rect = item_info_from; + rect.right = rect.left + from_rect.right - from_rect.left; + rect.bottom = rect.top + from_rect.bottom - from_rect.top; + rect_draw_some_item(mixed_gworld,from_rect,(HBITMAP) ((win_or_gworld == 1) ? (HBITMAP)hDlg: (HBITMAP)hdc) + ,rect,0,draw_dest); + break; + case 12: // item info help + from_rect = pc_info_from; + rect.right = rect.left + pc_info_from.right - pc_info_from.left; + rect.bottom = rect.top + pc_info_from.bottom - pc_info_from.top; + rect_draw_some_item(mixed_gworld,from_rect,(HBITMAP) ((win_or_gworld == 1) ? (HBITMAP)hDlg: (HBITMAP)hdc) + ,rect,0,draw_dest); + break; + case 14: // button help + which_g -= 1400; + if (which_g >= 10) { + from_gworld = load_pict(900 + which_g,main_dc); + from_rect = large_scen_from; + OffsetRect(&from_rect,64 * (which_g % 10),0); + rect_draw_some_item(from_gworld,from_rect,(HBITMAP) ((win_or_gworld == 1) ? (HBITMAP)hDlg: (HBITMAP)hdc) + ,rect,0,draw_dest); + DeleteObject(from_gworld); + break; + } + from_gworld = load_pict(1401,main_dc); + from_rect = button_help_from; + rect.top += 10; + rect.right = rect.left + from_rect.right; + rect.bottom = rect.top + from_rect.bottom; + OffsetRect(&from_rect,0,100 * which_g); + rect_draw_some_item(from_gworld,from_rect,(HBITMAP) ((win_or_gworld == 1) ? (HBITMAP)hDlg: (HBITMAP)hdc) + ,rect,0,draw_dest); + DeleteObject(from_gworld); + break; + case 13: // combat ap help + from_gworld = load_pict(1402,main_dc); + from_rect = combat_ap_from; + rect.right = rect.left + from_rect.right; + rect.bottom = rect.top + from_rect.bottom; + rect_draw_some_item(from_gworld,from_rect,(HBITMAP) ((win_or_gworld == 1) ? (HBITMAP) (hDlg): (HBITMAP)hdc) + ,rect,0,draw_dest); + DeleteObject(from_gworld); + break; + case 15: // stat symbols help + from_gworld = load_pict(1400,main_dc); + from_rect = stat_symbols_from; + rect.right = rect.left + from_rect.right; + rect.bottom = rect.top + from_rect.bottom; + rect_draw_some_item(from_gworld,from_rect,(HBITMAP) ((win_or_gworld == 1) ? (HBITMAP) (hDlg): (HBITMAP)hdc) + ,rect,0,draw_dest); + DeleteObject(from_gworld); + break; + case 16: + which_g -= 1600; + from_gworld = load_pict(851,main_dc); + from_rect.right = 32; + from_rect.bottom = 32; + OffsetRect(&from_rect,32 * (which_g % 5),32 * (which_g / 5)); + rect.right = rect.left + 32; + rect.bottom = rect.top + 32; + rect_draw_some_item(from_gworld,from_rect,(HBITMAP) ((win_or_gworld == 1) ? (HBITMAP) (hDlg): (HBITMAP)hdc) + ,rect,0,draw_dest); + DeleteObject(from_gworld); + break; + case 17: // dialog + which_g -= 1700; + from_gworld = fields_gworld; + from_rect = calc_rect(which_g % 8, which_g / 8); + if (win_or_gworld == 0) { + old_brush = (HBRUSH) SelectObject(hdc,GetStockObject(BLACK_BRUSH)); + Rectangle(hdc,rect.left,rect.top,rect.right,rect.bottom); + SelectObject(hdc,old_brush); + } + rect_draw_some_item(from_gworld,from_rect,(HBITMAP) ((win_or_gworld == 1) ? (HBITMAP)hDlg: (HBITMAP)hdc) + ,rect,0,draw_dest); + break; + case 20: case 21: case 22: case 23: // dialog + which_g -= 2000; + rect.right = rect.left + 28; + rect.bottom = rect.top + 36; + from_gworld = spec_scen_g; + from_rect = get_custom_rect(which_g); + if ((win_or_gworld == 0) && (do_frame == TRUE)) { + old_brush = (HBRUSH)SelectObject(hdc,GetStockObject(BLACK_BRUSH)); + Rectangle(hdc,rect.left,rect.top,rect.right,rect.bottom); + SelectObject(hdc,old_brush); + } + + rect_draw_some_item(from_gworld,from_rect,(HBITMAP) ((win_or_gworld == 1) ? (HBITMAP) (hDlg): (HBITMAP)hdc) + ,rect,(do_frame == FALSE) ? 1 : 0,draw_dest); + break; + case 24: case 25: case 26: case 27: // dialog + which_g -= 2400; + if (rect.right - rect.left >= 36) + square_size = 36; + from_gworld = spec_scen_g; + from_rect = get_custom_rect(which_g); + to_rect = rect; + to_rect.right = to_rect.left + square_size / 2; + to_rect.bottom = to_rect.top + square_size; + from_rect.right = from_rect.left + square_size / 2; + from_rect.bottom = from_rect.top + square_size; + rect_draw_some_item(from_gworld,from_rect,(HBITMAP) ((win_or_gworld == 1) ? (HBITMAP) (hDlg): (HBITMAP)hdc) + ,to_rect,1,draw_dest); + from_rect = get_custom_rect(which_g + 1); + OffsetRect(&to_rect,square_size / 2,0); + from_rect.right = from_rect.left + square_size / 2; + from_rect.bottom = from_rect.top + square_size; + rect_draw_some_item(from_gworld,from_rect,(HBITMAP) ((win_or_gworld == 1) ? (HBITMAP) (hDlg): (HBITMAP)hdc) + ,to_rect,1,draw_dest); + break; + } + + if ((win_or_gworld == 0) && (dlg_force_dc == NULL)) + fry_dc(hDlg, hdc); + if ((win_or_gworld == 0) && (do_frame == TRUE)){ + rect.bottom--; rect.right--; + frame_dlog_rect(hDlg,rect,3); + } +} + +void showcursor(Boolean a) +{ + short i; + i = ShowCursor(a); + if (a == FALSE) + while (i >= 0) + i = ShowCursor(FALSE); + if (a == TRUE) + while (i < 0) + i = ShowCursor(TRUE); + } + +void ModalDialog() +{ + MSG msg; + + while ((dialog_not_toast == TRUE) && (GetMessage(&msg,NULL,0,0))) + { + if (!TranslateAccelerator(mainPtr, accel, &msg)) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } +} + +RECT calc_rect(short i, short j) +{ + RECT base_rect = {0,0,28,36}; + + OffsetRect(&base_rect,i * 28, j * 36); + return base_rect; +} diff --git a/Win32/Blades of Exile/DLOGTOOL.H b/Win32/Blades of Exile/DLOGTOOL.H new file mode 100644 index 00000000..de164947 --- /dev/null +++ b/Win32/Blades of Exile/DLOGTOOL.H @@ -0,0 +1,61 @@ +#ifndef _DLOGTOOL_H + #define _DLOGTOOL_H + +#include "globvar.h" +#include "graphutl.h" + +void cd_set_flag(short dlog_num,short item_num,short flag); +short cd_get_led(short dlog_num,short item_num); +short cd_create_custom_dialog(HWND parent,char *strs,short pic_num,short buttons[3]); +void frame_di(HWND hDlg, short item_num, short val); +HDC cd_get_dlog_dc(short which_slot); +short cd_get_active(short dlog_num, short item_num); +short cd_create_dialog_parent_num(short dlog_num,short parent); +void cd_init_dialogs(); +short cd_create_dialog(short dlog_num,HWND parent) ; +short cd_kill_dialog(short dlog_num,short parent_message); +short cd_process_click(HWND window,POINT the_point, UINT wparam, LONG lparam,short *item); +short cd_process_syskeystroke(HWND window,UINT wparam, LONG lparam,short *item); +short cd_process_keystroke(HWND window,UINT wparam, LONG lparam,short *item); +void cd_attach_key(short dlog_num,short item_num,char key); +void cd_set_pict(short dlog_num, short item_num, short pict_num); +void cd_activate_item(short dlog_num, short item_num, short status); +void cd_set_item_text(short dlog_num, short item_num, char *str); +void cd_set_item_num(short dlog_num, short item_num, short num); +void cd_set_led(short dlog_num,short item_num,short state); +void cd_text_frame(short dlog_num,short item_num,short frame); +void cd_add_label(short dlog_num, short item_num, char *label, short label_flag); +void cd_key_label(short dlog_num, short item_num,short loc); +void cd_draw_item(short dlog_num,short item_num); +void cd_initial_draw(short dlog_num); +void cd_draw(short dlog_num); +void cd_redraw(HWND window); +void cd_frame_item(short dlog_num, short item_num, short width); +void cd_erase_item(short dlog_num, short item_num); +void cd_press_button(short dlog_num, short item_num); +short cd_get_indices(short dlg_num, short item_num, short *dlg_index, short *item_index); +short cd_get_dlg_index(short dlog_num); +short cd_find_dlog(HWND window, short *dlg_num, short *dlg_key); +short cd_get_item_id(short dlg_num, short item_num); +void center_window(HWND window); +RECT get_item_rect(HWND hDlg, short item_num); +void frame_dlog_rect(HWND hDlg, RECT rect, short val); +void draw_dialog_graphic(HWND hDlg, RECT rect, short which_g, Boolean do_frame,short win_or_gworld) ; +void showcursor(Boolean a); + +void cd_get_text_edit_str(short dlog_num, char *str); +// NOTE!!! Expects a c string +inline void cd_set_text_edit_str(short, char *str) + { if (edit_box != NULL) SetWindowText(edit_box,str); } +inline void cdsin(short dlog_num, short item_num, short num) + { cd_set_item_num(dlog_num, item_num, num); } +inline void csit(short dlog_num, short item_num, char *str) + { cd_set_item_text( dlog_num, item_num, str); } +inline void csp(short dlog_num, short item_num, short pict_num) + { cd_set_pict( dlog_num, item_num, pict_num); } +inline void cd_set_edit_focus() { if (edit_box) SetFocus(edit_box); } +void ModalDialog(); + +RECT calc_rect(short i, short j); + +#endif diff --git a/Win32/Blades of Exile/EXLSOUND.CPP b/Win32/Blades of Exile/EXLSOUND.CPP new file mode 100644 index 00000000..8dcd75a9 --- /dev/null +++ b/Win32/Blades of Exile/EXLSOUND.CPP @@ -0,0 +1,263 @@ +#include "math.h" +#include +#include + +#include "stdio.h" + +#include "global.h" +#include "exlsound.h" +#include "text.h" +#include "fields.h" + +#include "globvar.h" + +#define NUM_SOUNDS 100 + +void load_sounds(HMODULE handle) +{ + short i,t,err; + HRSRC h; + char snd_name[20]; + WAVEOUTCAPS wavecaps; + + hModule = handle; + + t = waveOutGetNumDevs(); + if (t == 0) { + sounds_fucked = TRUE; + return; + } + err = waveOutGetDevCaps(0,&wavecaps,sizeof(WAVEOUTCAPS)); +if (err != 0) { + sounds_fucked = TRUE; + switch (err) { + case MMSYSERR_BADDEVICEID: + MessageBox(mainPtr,"Cannot initialize sounds - No sound device detected. Game can still be played, but quietly.", + "Sound Error",MB_OK | MB_ICONEXCLAMATION); + return; + case MMSYSERR_NODRIVER: + MessageBox(mainPtr,"Cannot initialize sounds - No driver installed. Game can still be played, but quietly.", + "Sound Error",MB_OK | MB_ICONEXCLAMATION); + return; + case MMSYSERR_NOMEM : + MessageBox(mainPtr,"Cannot initialize sounds - can't find enough memory. Game can still be played, but quietly.", + "Sound Error",MB_OK | MB_ICONEXCLAMATION); + return; + case MMSYSERR_ALLOCATED: + MessageBox(mainPtr,"Cannot initialize sounds - sound card already allocated. Game can still be played, but quietly.", + "Sound Error",MB_OK | MB_ICONEXCLAMATION); + return; + case MMSYSERR_ERROR: + MessageBox(mainPtr,"Cannot initialize sounds - internal error. Game can still be played, but quietly.", + "Sound Error",MB_OK | MB_ICONEXCLAMATION); + return; + default: + MessageBox(mainPtr,"Cannot initialize sounds - unidentified error. Game can still be played, but quietly.", + "Sound Error",MB_OK | MB_ICONEXCLAMATION); + return; + + } + + } + + for (i = 0; i < NUM_SOUNDS; i++) { + sound_handles[i] = NULL; + if (load_when_play[i] == FALSE) { + sprintf((char *)snd_name,"#%d",i + 1); + h = FindResource(handle,snd_name,"#100"); + + sound_handles[i] = LoadResource(handle,h); + snds[i] = (char*) LockResource(sound_handles[i]); + } + } + +} + +void play_sound(short which) // if < 0, play asynch +{ + if (play_sounds == TRUE) + force_play_sound(which); +} + + +void force_play_sound(short which) +{ + short i,num_fails = 0; + char snd_name[30]; + Boolean asyn = FALSE,a_sound_did_get_played = FALSE; + Boolean not_asyn = FALSE,check_sound; + HRSRC h; + + if ((sounds_fucked == TRUE) || (play_sounds == FALSE)) + return; + if (which < 0) { + asyn = TRUE; + which = which * -1; + } + if (which >= 1000) { + which -= 1000; + not_asyn = TRUE; + } + + if (which >= 100) + return; + + if ((always_asynch[which] == TRUE) && + ((can_ignore[which] == 1) || (can_ignore[which] >= 3))) + asyn = TRUE; + if ((can_ignore[which] > 0) && (can_ignore[which] < 5) && (party.stuff_done[305][5] == 1)) + return; + if ((can_ignore[which] != 1) && (can_ignore[which] < 3)) + asyn = FALSE; + if ((party.stuff_done[305][5] == 1) && (can_ignore[which] < 5)) + asyn = FALSE; + if (not_asyn == TRUE) + asyn = FALSE; + + if ((load_when_play[which] == TRUE) && (sound_handles[which] == NULL)) { + asyn = FALSE; + sprintf((char *)snd_name,"#%d",which + 1); + h = FindResource(hModule,snd_name,"#100"); + + sound_handles[which] = LoadResource(hModule,h); + snds[which] = (char *) LockResource(sound_handles[which]); + + } + + if (store_last_sound_played == 6) + sndPlaySound(NULL,0); + + if (asyn == TRUE) { + if (can_ignore[which] >= 4) + check_sound = sndPlaySound(snds[which],SND_ASYNC | SND_MEMORY | SND_NOSTOP); + else check_sound = sndPlaySound(snds[which],SND_ASYNC | SND_MEMORY); + + while (check_sound == FALSE) { + + if (can_ignore[store_last_sound_played] == 4) {// then sound goes away + return; + } + + + num_fails++; + if (num_fails < 40) + sound_pause(25); + else { + MessageBox(mainPtr,"Cannot play sounds - Sounds stuck error a. Game can still be played, but quietly. Check to make sure your sound drivers are up to date and not corrupted.", + "Sound Error",MB_OK | MB_ICONEXCLAMATION); + print_nums(111,which,num_fails); + sounds_fucked = TRUE; + return; + } + sndPlaySound(NULL,0); + + if (can_ignore[which] >= 4) + check_sound = sndPlaySound(snds[which],SND_ASYNC | SND_MEMORY | SND_NOSTOP); + else check_sound = sndPlaySound(snds[which],SND_ASYNC | SND_MEMORY); + } + a_sound_did_get_played = TRUE; + } + else { + if (can_ignore[which] >= 4) + check_sound = sndPlaySound(snds[which],SND_SYNC | SND_MEMORY | SND_NOSTOP); + else check_sound = sndPlaySound(snds[which],SND_SYNC | SND_MEMORY); + while (check_sound == FALSE) { + if (can_ignore[store_last_sound_played] == 4) {// then sound goes away + return; + } + + + num_fails++; + if (num_fails < 40) + sound_pause(25); + else { + MessageBox(mainPtr,"Cannot play sounds - Sounds stuck error b. Game can still be played, but quietly. Check to make sure your sound drivers are up to date and not corrupted.", + "Sound Error",MB_OK | MB_ICONEXCLAMATION); + print_nums(222,which,num_fails); + sounds_fucked = TRUE; + return; + } + sndPlaySound(NULL,0); + + if (can_ignore[which] >= 4) + check_sound = sndPlaySound(snds[which],SND_SYNC | SND_MEMORY | SND_NOSTOP); + else check_sound = sndPlaySound(snds[which],SND_SYNC | SND_MEMORY); + } + a_sound_did_get_played = TRUE; + } + + store_last_sound_played = which; + + if ((load_when_play[which] == TRUE) && (asyn == FALSE)) + sound_handles[which] = NULL; + + for (i = 0; i < NUM_SOUNDS; i++) + if ((load_when_play[which] == TRUE) && (sound_handles[which] != NULL) + && (a_sound_did_get_played == TRUE) && (i != which)) + { + sound_handles[i] = NULL; + } + +} + +void kill_sound() +{ + sndPlaySound(NULL,0); +} + +void one_sound(short which) +{ + if (which == last_played) + return; + play_sound(which); + last_played = which; +} + +void sound_pause(long len) { + long t1,t2; + + t1 = (long) GetCurrentTime(); + t2 = t1; + while (t2 - t1 < len) { + t2 = (long)GetCurrentTime(); + } +} +void move_sound(unsigned char ter,short step) +{ + short pic,spec; + + pic = scenario.ter_types[ter].picture; + spec = scenario.ter_types[ter].special; + + if ((monsters_going == FALSE) && (overall_mode < 10) && (party.in_boat >= 0)) { + if (spec == 21) + return; + play_sound(48); + } + else if ((monsters_going == FALSE) && (overall_mode < 10) && (party.in_horse >= 0)) {//// + play_sound(85); + } + else if(scenario.ter_types[ter].special == 5) //if poisoned land don't play squish sound : BoE legacy behavior, can be removed safely + return; +// else if(scenario.ter_types[ter].special == 6) //if diseased land do the same +// return; + else switch(scenario.ter_types[ter].step_sound){ + case 0: + if (step % 2 == 0) //footsteps alternate sound + play_sound(49); + else play_sound(50); + break; + case 1: + play_sound(55); //squish + break; + case 2: + play_sound(47); //crunch + break; + case 3: + break; //silence : do nothing + default: + if (step % 2 == 0) //safety footsteps valve + play_sound(49); + else play_sound(50); + } +} diff --git a/Win32/Blades of Exile/EXLSOUND.H b/Win32/Blades of Exile/EXLSOUND.H new file mode 100644 index 00000000..75d1e3f5 --- /dev/null +++ b/Win32/Blades of Exile/EXLSOUND.H @@ -0,0 +1,14 @@ +#ifndef _EXLSOUND_H + #define _EXLSOUND_H + +#include // for HMODULE + +void move_sound(unsigned char ter,short step); +void one_sound(short which); +void force_play_sound(short which); +void play_sound(short which) ; +void load_sounds (HMODULE handle); +void sound_pause(long len); +void kill_sound(); + +#endif diff --git a/Win32/Blades of Exile/FIELDS.CPP b/Win32/Blades of Exile/FIELDS.CPP new file mode 100644 index 00000000..18e0ab19 --- /dev/null +++ b/Win32/Blades of Exile/FIELDS.CPP @@ -0,0 +1,198 @@ +#include + +#include "global.h" +#include "locutils.h" +#include "fields.h" +#include "globvar.h" + +Boolean is_explored(short i,short j) +{ + if (is_out()) { + if ((i != minmax(0,95,(int)i)) || (j != minmax(0,95,(int)j))) + return FALSE; + return (out_e[i][j] != 0) ? TRUE : FALSE; + } + if (c_town.explored[i][j] & 1) return TRUE; + else return FALSE; +} +void make_explored(short i,short j) +{ + if (is_out()) out_e[i][j] = 1; + c_town.explored[i][j] |= 1; +} + +Boolean is_out() +{ + return ((overall_mode == 0) || (overall_mode == 35))? TRUE : FALSE; +} +Boolean is_town() +{ + return (((overall_mode > 0) && (overall_mode < 10)) || (overall_mode == 36))? TRUE : FALSE; +} +Boolean is_combat() +{ + return (((overall_mode >= 10) && (overall_mode < 20)) || (overall_mode == 37))? TRUE : FALSE; +} + +Boolean special(short i,short j) +{ + if (((misc_i[i][j]) & 2) != 0) + return TRUE; + else return FALSE; +} +void make_web(short i,short j) +/**/{ + if (spot_impassable(i,j) == TRUE) + return; + if ((misc_i[i][j] & 224) || (c_town.explored[i][j] & 238)) + return; + misc_i[i][j] |= 4; + web = TRUE; +} + +void make_fire_barrier(short i,short j) +/**/{ + if ((is_antimagic(i,j)) && (get_ran(1,0,3) < 3)) + return; + if (misc_i[i][j] & 248) + return; + take_web(i,j); + c_town.explored[i][j] = c_town.explored[i][j] & 1; + misc_i[i][j] |= 32; + fire_barrier = TRUE; +} + +void make_force_barrier(short i,short j) +/**/{ + if ((is_antimagic(i,j)) && (get_ran(1,0,2) < 2)) + return; + if (misc_i[i][j] & 248) + return; + take_web(i,j); + c_town.explored[i][j] = c_town.explored[i][j] & 1; + misc_i[i][j] |= 64; + force_barrier = TRUE; +} + +void make_quickfire(short i,short j) +/**/{ + unsigned char ter; + + if ((is_antimagic(i,j)) && (get_ran(1,0,1) == 0)) + return; + if ((is_force_barrier(i,j)) || (is_fire_barrier(i,j))) + return; + ter = coord_to_ter(i,j); + if (scenario.ter_types[ter].blockage == 1) + return; + if (scenario.ter_types[ter].blockage == 5) + return; + c_town.explored[i][j] = c_town.explored[i][j] & 1; + misc_i[i][j] &= 3; + misc_i[i][j] |= 128; + quickfire = TRUE; +} + +void make_force_wall(short i,short j) +/**/{ + if (spot_impassable(i,j) == TRUE) + return; + if ((c_town.explored[i][j] & 74) || (misc_i[i][j] & 248)) + return; + take_web(i,j); + take_fire_wall(i,j); + c_town.explored[i][j] |= 2; + force_wall = TRUE; +} + +void make_fire_wall(short i,short j) +/**/{ + if (spot_impassable(i,j) == TRUE) + return; + if ((c_town.explored[i][j] & 248) || (misc_i[i][j] & 254)) + return; + take_web(i,j); + c_town.explored[i][j] |= 4; + fire_wall = TRUE; +} + +void make_antimagic(short i,short j) +/**/{ + if (spot_impassable(i,j) == TRUE) + return; + if (misc_i[i][j] & 224) + return; + + c_town.explored[i][j] &= 1; + c_town.explored[i][j] |= 8; + antimagic = TRUE; +} + +void make_scloud(short i,short j) +/**/{ + if (spot_impassable(i,j) == TRUE) + return; + + if ((c_town.explored[i][j] & 238) || (misc_i[i][j] & 224)) + return; + c_town.explored[i][j] |= 16; + scloud = TRUE; +} + +void make_ice_wall(short i,short j) +/**/{ + if (spot_impassable(i,j) == TRUE) + return; + if ((c_town.explored[i][j] & 74) || (misc_i[i][j] & 252)) + return; + take_fire_wall(i,j); + take_scloud(i,j); + c_town.explored[i][j] |= 32; + ice_wall = TRUE; +} + +void make_blade_wall(short i,short j) +/**/{ + if (spot_impassable(i,j) == TRUE) + return; + if ((c_town.explored[i][j] & 8) || (misc_i[i][j] & 224)) + return; + c_town.explored[i][j] &= 9; + c_town.explored[i][j] |= 64; + blade_wall = TRUE; +} + +void make_sleep_cloud(short i,short j) +/**/{ + if (spot_impassable(i,j) == TRUE) + return; + if ((c_town.explored[i][j] & 8) || (misc_i[i][j] & 224)) + return; + c_town.explored[i][j] &= 9; + c_town.explored[i][j] |= 128; + sleep_field = TRUE; +} + +void make_sfx(short i,short j, short type) +{ + unsigned char ter; + + if (get_obscurity(i,j) > 0) + return; + ter = coord_to_ter(i,j); + if (terrain_blocked[ter] != 0) + return; + switch (type) { + case 1: case 2: + if (sfx[i][j] == 4) + return; + if (sfx[i][j] < 4) + type = min(3,type + sfx[i][j]); + break; + case 4: + if (sfx[i][j] == 8) + type = 5; + break; + } + sfx[i][j] = s_pow(2,type - 1); +} diff --git a/Win32/Blades of Exile/FIELDS.H b/Win32/Blades of Exile/FIELDS.H new file mode 100644 index 00000000..ec6d6877 --- /dev/null +++ b/Win32/Blades of Exile/FIELDS.H @@ -0,0 +1,66 @@ +#ifndef _FIELDS_H + #define _FIELDS_H + +#include "global.h" +#include "globvar.h" + +inline Boolean is_web(short i,short j) { return (misc_i[i][j] & 4) ? TRUE : FALSE; } +inline void take_web(short i,short j) { misc_i[i][j] &= 251; } +inline Boolean is_crate(short i,short j) { return (misc_i[i][j] & 8) ? TRUE : FALSE; } +inline void make_crate(short i,short j) { misc_i[i][j] = misc_i[i][j] | 8; crate = TRUE; } +inline void take_crate(short i,short j) { misc_i[i][j] &= 247; } +inline Boolean is_barrel(short i,short j) { return (misc_i[i][j] & 16) ? TRUE : FALSE; } +inline void make_barrel(short i,short j) { misc_i[i][j] = misc_i[i][j] | 16; barrel = TRUE; } +inline void take_barrel(short i,short j) { misc_i[i][j] &= 239; } +inline Boolean is_fire_barrier(short i,short j) { return (misc_i[i][j] & 32) ? TRUE : FALSE; } +inline void make_special(short i,short j) { misc_i[i][j] = misc_i[i][j] | (char) (2); } +inline void take_special(short i,short j) { misc_i[i][j] &= 253; } +inline Boolean is_small_blood(short i,short j) { return (sfx[i][j] & 1) ? TRUE : FALSE; } +inline Boolean is_medium_blood(short i,short j) { return (sfx[i][j] & 2) ? TRUE : FALSE; } +inline Boolean is_large_blood(short i,short j) { return (sfx[i][j] & 4) ? TRUE : FALSE; } +inline Boolean is_small_slime(short i,short j) { return (sfx[i][j] & 8) ? TRUE : FALSE; } +inline Boolean is_big_slime(short i,short j) { return (sfx[i][j] & 16) ? TRUE : FALSE; } +inline Boolean is_ash(short i,short j) { return (sfx[i][j] & 32) ? TRUE : FALSE; } +inline Boolean is_bones(short i,short j) { return (sfx[i][j] & 64) ? TRUE : FALSE; } +inline Boolean is_rubble(short i,short j) { return (sfx[i][j] & 128) ? TRUE : FALSE; } + +inline void take_fire_barrier(short i,short j) { misc_i[i][j] &= 223; } +inline Boolean is_force_barrier(short i,short j) { return (misc_i[i][j] & 64) ? TRUE : FALSE; } +inline void take_force_barrier(short i,short j) { misc_i[i][j] &= 191; } +inline Boolean is_quickfire(short i,short j) { return (misc_i[i][j] & 128) ? TRUE : FALSE; } +inline void take_quickfire(short i,short j) { misc_i[i][j] &= 127; } +inline Boolean is_force_wall(short i,short j) { return (c_town.explored[i][j] & 2) ? TRUE : FALSE; } +inline void take_force_wall(short i,short j) { c_town.explored[i][j] &= 253; } +inline Boolean is_fire_wall(short i,short j) { return (c_town.explored[i][j] & 4) ? TRUE : FALSE; } +inline void take_fire_wall(short i,short j) { c_town.explored[i][j] &= 251; } +inline Boolean is_antimagic(short i,short j) { return (c_town.explored[i][j] & 8) ? TRUE : FALSE; } +inline void take_antimagic(short i,short j) { c_town.explored[i][j] &= 247; } +inline Boolean is_scloud(short i,short j) { return (c_town.explored[i][j] & 16) ? TRUE : FALSE; } +inline void take_scloud(short i,short j) { c_town.explored[i][j] &= 239; } +inline Boolean is_ice_wall(short i,short j) { return (c_town.explored[i][j] & 32) ? TRUE : FALSE; } +inline void take_ice_wall(short i,short j) { c_town.explored[i][j] &= 223; } +inline Boolean is_blade_wall(short i,short j) { return (c_town.explored[i][j] & 64) ? TRUE : FALSE; } +inline void take_blade_wall(short i,short j) { c_town.explored[i][j] &= 191; } +inline Boolean is_sleep_cloud(short i,short j) { return (c_town.explored[i][j] & 128) ? TRUE : FALSE; } +inline void take_sleep_cloud(short i,short j) { c_town.explored[i][j] &= 127; } + +Boolean is_explored(short i,short j); +void make_explored(short i,short j); +Boolean is_out(); +Boolean is_town(); +Boolean is_combat(); +Boolean special(short i,short j); +void make_web(short i,short j); +void make_fire_barrier(short i,short j); +void make_force_barrier(short i,short j); +void make_quickfire(short i,short j); +void make_force_wall(short i,short j); +void make_fire_wall(short i,short j); +void make_antimagic(short i,short j); +void make_scloud(short i,short j); +void make_ice_wall(short i,short j); +void make_blade_wall(short i,short j); +void make_sleep_cloud(short i,short j); +void make_sfx(short i,short j, short type); + +#endif diff --git a/Win32/Blades of Exile/FILEIO.CPP b/Win32/Blades of Exile/FILEIO.CPP new file mode 100644 index 00000000..ed886b92 --- /dev/null +++ b/Win32/Blades of Exile/FILEIO.CPP @@ -0,0 +1,2437 @@ + +#include +#include + +#include +#include "global.h" +#include "stdio.h" +#include "fileio.h" +#include "text.h" +#include "town.h" +#include "items.h" +#include "graphics.h" +#include "locutils.h" +#include "fields.h" +#include "newgraph.h" +#include "dlgutils.h" +#include "gutils.h" +#include "infodlgs.h" +#include "graphutl.h" +#include "exlsound.h" + +#include "globvar.h" + +#define DONE_BUTTON_ITEM 1 + +extern BOOL fry_startup; + +typedef struct { + char expl[96][96]; + } out_info_type; + +void port_talk_nodes(); +void port_town(short mode); +void port_t_d(short mode); +void port_scenario(); +void port_party(); +void port_pc(); +void port_item_list(); +void port_stored_items(stored_items_list* list); +void flip_short(short *s); +void flip_long(long *s); +void flip_short(WORD *s); +void flip_rect(RECT *s); +void flip_rect(RECT16* s); +Boolean load_scenario_header(char *filename,short header_entry); +void oops_error(short error); + +void Get_Path(char* path){ + +char file_path[256]=""; // initialization +GetModuleFileName(NULL,file_path,256); // get path to the executable + +int i=255; // initialize the first while loop +while(file_path[i] != '\\') + { + i--; // find the last '\' in the path to the executable + } // in order to get rid of 'blades of exile.exe' + + +int j=0; // initialize the second loop + +for(j=0;j= 16) && + (scenario.ter_types[t_d.terrain[j][k]].special <= 19)) + belt_present = TRUE; + } +force_wall = TRUE;fire_wall = TRUE;antimagic = TRUE;scloud = TRUE;ice_wall = TRUE;blade_wall = TRUE; +sleep_field = TRUE; + center = c_town.p_loc; + load_area_graphics(); + } + + create_clip_region(); + redraw_screen(0); + + current_pc = first_active_pc(); + loaded_yet = TRUE; + + add_string_to_buf("Load: Game loaded. "); + + // Set sounds, map saving, and speed + /* + if (((play_sounds == TRUE) && (party.stuff_done[306][1] == 1)) || + ((play_sounds == FALSE) && (party.stuff_done[306][1] == 0))) { + play_sounds = 1 - play_sounds; + } + */ + give_delays = party.stuff_done[306][2]; + if (party.stuff_done[306][0] == 0) + save_maps = TRUE; + else save_maps = FALSE; + + in_startup_mode = FALSE; + +} + +void save_file(short mode) //mode 0 - normal 1 - save as +{ + HANDLE file_id; + Boolean town_save = FALSE; + + short i, j; + + DWORD count, bytes, dwByteRead; + short flag; + short *store; + party_record_type *party_ptr; + setup_save_type *setup_ptr; + pc_record_type *pc_ptr; + current_town_type *town_ptr; + + char *party_encryptor; + + if ((in_startup_mode == FALSE) && (is_town())) + town_save = TRUE; + + ofn.hwndOwner = mainPtr; + ofn.lpstrFile = szFileName; + ofn.lpstrFileTitle = szTitleName; + ofn.Flags = OFN_OVERWRITEPROMPT; + + if ((mode == 1) || (in_startup_mode == TRUE)) { + if (GetSaveFileName(&ofn) == 0) + return; + } + +/* if (strcmpi(&ofn.lpstrFile[ofn.nFileExtension], "savx") == 0) + { + // for experimental formats of save-game files + }*/ + + file_id = CreateFile(szFileName, GENERIC_WRITE, 0, NULL, + CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + if (file_id == INVALID_HANDLE_VALUE) return; + + SetCurrentDirectory(file_path_name); + + store = &flag; + + flag = (town_save == TRUE) ? 1342 : 5790; + if (WriteFile(file_id, store, sizeof(short), &bytes, NULL) == FALSE) + { + CloseHandle(file_id); + return; + } + flag = (in_startup_mode == FALSE) ? 100 : 200; + if (WriteFile(file_id, store, sizeof(short), &bytes, NULL) == FALSE) + { + CloseHandle(file_id); + return; + } + flag = (save_maps == TRUE) ? 5567 : 3422; + if (WriteFile(file_id, store, sizeof(short), &bytes, NULL) == FALSE) + { + CloseHandle(file_id); + return; + } + + // SAVE PARTY + party_ptr = &party; + + party_encryptor = (char *) party_ptr; + for (count = 0; count < sizeof(party_record_type); count++) + party_encryptor[count] ^= 0x5C; + +/* if (WriteFile(file_id, party_ptr, sizeof(party_record_type), &bytes, NULL) == FALSE) + { + add_string_to_buf("Save: Couldn't write to file. "); + CloseHandle(file_id); + for (count = 0; count < store_len; count++) + party_encryptor[count] ^= 0x5C; + SysBeep(2); + return; + }*/ + + WriteFile(file_id, &party.age, 4, &dwByteRead, NULL); + WriteFile(file_id, &party.gold, 2, &dwByteRead, NULL); + WriteFile(file_id, &party.food, 2, &dwByteRead, NULL); + WriteFile(file_id, party.stuff_done, 310*10, &dwByteRead, NULL); + WriteFile(file_id, party.item_taken, 200*8, &dwByteRead, NULL); + WriteFile(file_id, &party.light_level, 2, &dwByteRead, NULL); + WriteFile(file_id, &party.outdoor_corner.x, 1, &dwByteRead, NULL); + WriteFile(file_id, &party.outdoor_corner.y, 1, &dwByteRead, NULL); + WriteFile(file_id, &party.i_w_c.x, 1, &dwByteRead, NULL); + WriteFile(file_id, &party.i_w_c.y, 1, &dwByteRead, NULL); + WriteFile(file_id, &party.p_loc.x, 1, &dwByteRead, NULL); + WriteFile(file_id, &party.p_loc.y, 1, &dwByteRead, NULL); + WriteFile(file_id, &party.loc_in_sec.x, 1, &dwByteRead, NULL); + WriteFile(file_id, &party.loc_in_sec.y, 1, &dwByteRead, NULL); + + for (i = 0; i < 30; i++) + { + WriteFile(file_id, &party.boats[i].boat_loc.x, 1, &dwByteRead, NULL); + WriteFile(file_id, &party.boats[i].boat_loc.y, 1, &dwByteRead, NULL); + WriteFile(file_id, &party.boats[i].boat_loc_in_sec.x, 1, &dwByteRead, NULL); + WriteFile(file_id, &party.boats[i].boat_loc_in_sec.y, 1, &dwByteRead, NULL); + WriteFile(file_id, &party.boats[i].boat_sector.x, 1, &dwByteRead, NULL); + WriteFile(file_id, &party.boats[i].boat_sector.y, 1, &dwByteRead, NULL); + WriteFile(file_id, &party.boats[i].which_town, 2, &dwByteRead, NULL); + WriteFile(file_id, &party.boats[i].exists, 1, &dwByteRead, NULL); + WriteFile(file_id, &party.boats[i].property, 1, &dwByteRead, NULL); + } + for (i = 0; i < 30; i++) + { + WriteFile(file_id, &party.horses[i].horse_loc.x, 1, &dwByteRead, NULL); + WriteFile(file_id, &party.horses[i].horse_loc.y, 1, &dwByteRead, NULL); + WriteFile(file_id, &party.horses[i].horse_loc_in_sec.x, 1, &dwByteRead, NULL); + WriteFile(file_id, &party.horses[i].horse_loc_in_sec.y, 1, &dwByteRead, NULL); + WriteFile(file_id, &party.horses[i].horse_sector.x, 1, &dwByteRead, NULL); + WriteFile(file_id, &party.horses[i].horse_sector.y, 1, &dwByteRead, NULL); + WriteFile(file_id, &party.horses[i].which_town, 2, &dwByteRead, NULL); + WriteFile(file_id, &party.horses[i].exists, 1, &dwByteRead, NULL); + WriteFile(file_id, &party.horses[i].property, 1, &dwByteRead, NULL); + } + for (i = 0; i < 4; i++) + { + for (j = 0; j < 60; j++) + { + WriteFile(file_id, &party.creature_save[i].dudes[j].active, 2, &dwByteRead, NULL); + WriteFile(file_id, &party.creature_save[i].dudes[j].attitude, 2, &dwByteRead, NULL); + WriteFile(file_id, &party.creature_save[i].dudes[j].number, 1, &dwByteRead, NULL); + WriteFile(file_id, &party.creature_save[i].dudes[j].m_loc.x, 1, &dwByteRead, NULL); + WriteFile(file_id, &party.creature_save[i].dudes[j].m_loc.y, 1, &dwByteRead, NULL); + { + WriteFile(file_id, &party.creature_save[i].dudes[j].m_d.m_num, 1, &dwByteRead, NULL); + WriteFile(file_id, &party.creature_save[i].dudes[j].m_d.level, 1, &dwByteRead, NULL); + WriteFile(file_id, party.creature_save[i].dudes[j].m_d.m_name, 26, &dwByteRead, NULL); + WriteFile(file_id, &party.creature_save[i].dudes[j].m_d.health, 2, &dwByteRead, NULL); + WriteFile(file_id, &party.creature_save[i].dudes[j].m_d.m_health, 2, &dwByteRead, NULL); + WriteFile(file_id, &party.creature_save[i].dudes[j].m_d.mp, 2, &dwByteRead, NULL); + WriteFile(file_id, &party.creature_save[i].dudes[j].m_d.max_mp, 2, &dwByteRead, NULL); + WriteFile(file_id, &party.creature_save[i].dudes[j].m_d.armor, 1, &dwByteRead, NULL); + WriteFile(file_id, &party.creature_save[i].dudes[j].m_d.skill, 1, &dwByteRead, NULL); + WriteFile(file_id, &party.creature_save[i].dudes[j].m_d.a, 2*3, &dwByteRead, NULL); + WriteFile(file_id, &party.creature_save[i].dudes[j].m_d.a1_type, 1, &dwByteRead, NULL); + WriteFile(file_id, &party.creature_save[i].dudes[j].m_d.a23_type, 1, &dwByteRead, NULL); + WriteFile(file_id, &party.creature_save[i].dudes[j].m_d.m_type, 1, &dwByteRead, NULL); + WriteFile(file_id, &party.creature_save[i].dudes[j].m_d.speed, 1, &dwByteRead, NULL); + WriteFile(file_id, &party.creature_save[i].dudes[j].m_d.ap, 1, &dwByteRead, NULL); + WriteFile(file_id, &party.creature_save[i].dudes[j].m_d.mu, 1, &dwByteRead, NULL); + WriteFile(file_id, &party.creature_save[i].dudes[j].m_d.cl, 1, &dwByteRead, NULL); + WriteFile(file_id, &party.creature_save[i].dudes[j].m_d.breath, 1, &dwByteRead, NULL); + WriteFile(file_id, &party.creature_save[i].dudes[j].m_d.breath_type, 1, &dwByteRead, NULL); + WriteFile(file_id, &party.creature_save[i].dudes[j].m_d.treasure, 1, &dwByteRead, NULL); + WriteFile(file_id, &party.creature_save[i].dudes[j].m_d.spec_skill, 1, &dwByteRead, NULL); + WriteFile(file_id, &party.creature_save[i].dudes[j].m_d.poison, 1, &dwByteRead, NULL); + WriteFile(file_id, &party.creature_save[i].dudes[j].m_d.morale, 2, &dwByteRead, NULL); + WriteFile(file_id, &party.creature_save[i].dudes[j].m_d.m_morale, 2, &dwByteRead, NULL); + WriteFile(file_id, &party.creature_save[i].dudes[j].m_d.corpse_item, 2, &dwByteRead, NULL); + WriteFile(file_id, &party.creature_save[i].dudes[j].m_d.corpse_item_chance, 2, &dwByteRead, NULL); + WriteFile(file_id, party.creature_save[i].dudes[j].m_d.status, 2*15, &dwByteRead, NULL); + WriteFile(file_id, &party.creature_save[i].dudes[j].m_d.direction, 1, &dwByteRead, NULL); + WriteFile(file_id, &party.creature_save[i].dudes[j].m_d.immunities, 1, &dwByteRead, NULL); + WriteFile(file_id, &party.creature_save[i].dudes[j].m_d.x_width, 1, &dwByteRead, NULL); + WriteFile(file_id, &party.creature_save[i].dudes[j].m_d.y_width, 1, &dwByteRead, NULL); + WriteFile(file_id, &party.creature_save[i].dudes[j].m_d.radiate_1, 1, &dwByteRead, NULL); + WriteFile(file_id, &party.creature_save[i].dudes[j].m_d.radiate_2, 1, &dwByteRead, NULL); + WriteFile(file_id, &party.creature_save[i].dudes[j].m_d.default_attitude, 1, &dwByteRead, NULL); + WriteFile(file_id, &party.creature_save[i].dudes[j].m_d.summon_type, 1, &dwByteRead, NULL); + WriteFile(file_id, &party.creature_save[i].dudes[j].m_d.default_facial_pic, 1, &dwByteRead, NULL); + WriteFile(file_id, &party.creature_save[i].dudes[j].m_d.res1, 1, &dwByteRead, NULL); + WriteFile(file_id, &party.creature_save[i].dudes[j].m_d.res2, 1, &dwByteRead, NULL); + WriteFile(file_id, &party.creature_save[i].dudes[j].m_d.res3, 1, &dwByteRead, NULL); + WriteFile(file_id, &party.creature_save[i].dudes[j].m_d.picture_num, 2, &dwByteRead, NULL); + } + WriteFile(file_id, &party.creature_save[i].dudes[j].mobile, 1, &dwByteRead, NULL); + WriteFile(file_id, &party.creature_save[i].dudes[j].summoned, 2, &dwByteRead, NULL); + { + WriteFile(file_id, &party.creature_save[i].dudes[j].monst_start.number, 1, &dwByteRead, NULL); + WriteFile(file_id, &party.creature_save[i].dudes[j].monst_start.start_attitude, 1, &dwByteRead, NULL); + WriteFile(file_id, &party.creature_save[i].dudes[j].monst_start.start_loc.x, 1, &dwByteRead, NULL); + WriteFile(file_id, &party.creature_save[i].dudes[j].monst_start.start_loc.y, 1, &dwByteRead, NULL); + WriteFile(file_id, &party.creature_save[i].dudes[j].monst_start.mobile, 1, &dwByteRead, NULL); + WriteFile(file_id, &party.creature_save[i].dudes[j].monst_start.time_flag, 1, &dwByteRead, NULL); + WriteFile(file_id, &party.creature_save[i].dudes[j].monst_start.extra1, 1, &dwByteRead, NULL); + WriteFile(file_id, &party.creature_save[i].dudes[j].monst_start.extra2, 1, &dwByteRead, NULL); + WriteFile(file_id, &party.creature_save[i].dudes[j].monst_start.spec1, 2, &dwByteRead, NULL); + WriteFile(file_id, &party.creature_save[i].dudes[j].monst_start.spec2, 2, &dwByteRead, NULL); + WriteFile(file_id, &party.creature_save[i].dudes[j].monst_start.spec_enc_code, 1, &dwByteRead, NULL); + WriteFile(file_id, &party.creature_save[i].dudes[j].monst_start.time_code, 1, &dwByteRead, NULL); + WriteFile(file_id, &party.creature_save[i].dudes[j].monst_start.monster_time, 2, &dwByteRead, NULL); + WriteFile(file_id, &party.creature_save[i].dudes[j].monst_start.personality, 2, &dwByteRead, NULL); + WriteFile(file_id, &party.creature_save[i].dudes[j].monst_start.special_on_kill, 2, &dwByteRead, NULL); + WriteFile(file_id, &party.creature_save[i].dudes[j].monst_start.facial_pic, 2, &dwByteRead, NULL); + } + } + + WriteFile(file_id, &party.creature_save[i].which_town, 2, &dwByteRead, NULL); + WriteFile(file_id, &party.creature_save[i].friendly, 2, &dwByteRead, NULL); + } + + WriteFile(file_id, &party.in_boat, 2, &dwByteRead, NULL); + WriteFile(file_id, &party.in_horse, 2, &dwByteRead, NULL); + for (i = 0; i < 10; i++) + { + WriteFile(file_id, &party.out_c[i].exists, 1, &dwByteRead, NULL); + WriteFile(file_id, &party.out_c[i].direction, 2, &dwByteRead, NULL); + { + WriteFile(file_id, party.out_c[i].what_monst.monst, 7, &dwByteRead, NULL); + WriteFile(file_id, party.out_c[i].what_monst.friendly, 3, &dwByteRead, NULL); + WriteFile(file_id, &party.out_c[i].what_monst.spec_on_meet, 2, &dwByteRead, NULL); + WriteFile(file_id, &party.out_c[i].what_monst.spec_on_win, 2, &dwByteRead, NULL); + WriteFile(file_id, &party.out_c[i].what_monst.spec_on_flee, 2, &dwByteRead, NULL); + WriteFile(file_id, &party.out_c[i].what_monst.cant_flee, 2, &dwByteRead, NULL); + WriteFile(file_id, &party.out_c[i].what_monst.end_spec1, 2, &dwByteRead, NULL); + WriteFile(file_id, &party.out_c[i].what_monst.end_spec2, 2, &dwByteRead, NULL); + } + WriteFile(file_id, &party.out_c[i].which_sector.x, 1, &dwByteRead, NULL); + WriteFile(file_id, &party.out_c[i].which_sector.y, 1, &dwByteRead, NULL); + WriteFile(file_id, &party.out_c[i].m_loc.x, 1, &dwByteRead, NULL); + WriteFile(file_id, &party.out_c[i].m_loc.y, 1, &dwByteRead, NULL); + } + for (i = 0; i < 5; i++) + for (j = 0; j < 10; j++) + { + WriteFile(file_id, &party.magic_store_items[i][j].variety, 2, &dwByteRead, NULL); + WriteFile(file_id, &party.magic_store_items[i][j].item_level, 2, &dwByteRead, NULL); + WriteFile(file_id, &party.magic_store_items[i][j].awkward, 1, &dwByteRead, NULL); + WriteFile(file_id, &party.magic_store_items[i][j].bonus, 1, &dwByteRead, NULL); + WriteFile(file_id, &party.magic_store_items[i][j].protection, 1, &dwByteRead, NULL); + WriteFile(file_id, &party.magic_store_items[i][j].charges, 1, &dwByteRead, NULL); + WriteFile(file_id, &party.magic_store_items[i][j].type, 1, &dwByteRead, NULL); + WriteFile(file_id, &party.magic_store_items[i][j].magic_use_type, 1, &dwByteRead, NULL); + WriteFile(file_id, &party.magic_store_items[i][j].graphic_num, 1, &dwByteRead, NULL); + WriteFile(file_id, &party.magic_store_items[i][j].ability, 1, &dwByteRead, NULL); + WriteFile(file_id, &party.magic_store_items[i][j].ability_strength, 1, &dwByteRead, NULL); + WriteFile(file_id, &party.magic_store_items[i][j].type_flag, 1, &dwByteRead, NULL); + WriteFile(file_id, &party.magic_store_items[i][j].is_special, 1, &dwByteRead, NULL); + WriteFile(file_id, &party.magic_store_items[i][j].a, 1, &dwByteRead, NULL); + WriteFile(file_id, &party.magic_store_items[i][j].value, 2, &dwByteRead, NULL); + WriteFile(file_id, &party.magic_store_items[i][j].weight, 1, &dwByteRead, NULL); + WriteFile(file_id, &party.magic_store_items[i][j].special_class, 1, &dwByteRead, NULL); + WriteFile(file_id, &party.magic_store_items[i][j].item_loc.x, 1, &dwByteRead, NULL); + WriteFile(file_id, &party.magic_store_items[i][j].item_loc.y, 1, &dwByteRead, NULL); + WriteFile(file_id, party.magic_store_items[i][j].full_name, 25, &dwByteRead, NULL); + WriteFile(file_id, party.magic_store_items[i][j].name, 15, &dwByteRead, NULL); + WriteFile(file_id, &party.magic_store_items[i][j].treas_class, 1, &dwByteRead, NULL); + WriteFile(file_id, &party.magic_store_items[i][j].item_properties, 1, &dwByteRead, NULL); + WriteFile(file_id, &party.magic_store_items[i][j].reserved1, 1, &dwByteRead, NULL); + WriteFile(file_id, &party.magic_store_items[i][j].reserved2, 1, &dwByteRead, NULL); + } + WriteFile(file_id, &party.imprisoned_monst, 2*4, &dwByteRead, NULL); + WriteFile(file_id, party.m_seen, 256, &dwByteRead, NULL); + WriteFile(file_id, party.journal_str, 50, &dwByteRead, NULL); + WriteFile(file_id, party.journal_day, 2*50, &dwByteRead, NULL); + WriteFile(file_id, party.special_notes_str, 2*140*2, &dwByteRead, NULL); + for (i = 0; i < 120; i++) + { + WriteFile(file_id, &party.talk_save[i].personality, 2, &dwByteRead, NULL); + WriteFile(file_id, &party.talk_save[i].town_num, 2, &dwByteRead, NULL); + WriteFile(file_id, &party.talk_save[i].str1, 2, &dwByteRead, NULL); + WriteFile(file_id, &party.talk_save[i].str2, 2, &dwByteRead, NULL); + } + WriteFile(file_id, &party.direction, 2, &dwByteRead, NULL); + WriteFile(file_id, &party.at_which_save_slot, 2, &dwByteRead, NULL); + WriteFile(file_id, party.alchemy, 20, &dwByteRead, NULL); + WriteFile(file_id, party.can_find_town, 200, &dwByteRead, NULL); + WriteFile(file_id, party.key_times, 2*100, &dwByteRead, NULL); + WriteFile(file_id, party.party_event_timers, 2*30, &dwByteRead, NULL); + WriteFile(file_id, party.global_or_town, 2*30, &dwByteRead, NULL); + WriteFile(file_id, party.node_to_call, 2*30, &dwByteRead, NULL); + WriteFile(file_id, party.spec_items, 50, &dwByteRead, NULL); + WriteFile(file_id, party.help_received, 120, &dwByteRead, NULL); + WriteFile(file_id, party.m_killed, 2*200, &dwByteRead, NULL); + WriteFile(file_id, &party.total_m_killed, 4, &dwByteRead, NULL); + WriteFile(file_id, &party.total_dam_done, 4, &dwByteRead, NULL); + WriteFile(file_id, &party.total_xp_gained, 4, &dwByteRead, NULL); + WriteFile(file_id, &party.total_dam_taken, 4, &dwByteRead, NULL); + WriteFile(file_id, party.scen_name, 256, &dwByteRead, NULL); + + for (count = 0; count < sizeof(party_record_type); count++) + party_encryptor[count] ^= 0x5C; + + // SAVE SETUP + setup_ptr = &setup_save; + if (WriteFile(file_id, setup_ptr, sizeof(setup_save_type), &bytes, NULL) == FALSE) + { + CloseHandle(file_id); + return; + } + + // SAVE PCS + for (i = 0; i < 6; i++) { + pc_ptr = &adven[i]; + + party_encryptor = (char *) pc_ptr; + for (count = 0; count < sizeof(pc_record_type); count++) + party_encryptor[count] ^= 0x6B; + if (WriteFile(file_id, pc_ptr, sizeof(pc_record_type), &bytes, NULL) == FALSE) + { + add_string_to_buf("Save: Couldn't write to file. "); + CloseHandle(file_id); + for (count = 0; count < sizeof(pc_record_type); count++) + party_encryptor[count] ^= 0x6B; + MessageBeep(MB_OK); + return; + } + for (count = 0; count < sizeof(pc_record_type); count++) + party_encryptor[count] ^= 0x6B; + } + + if (in_startup_mode == FALSE) { + + // SAVE OUT DATA + if (WriteFile(file_id, out_e, sizeof(out_info_type), &bytes, NULL) == FALSE) + { + CloseHandle(file_id); + return; + } + + if (town_save == TRUE) { + town_ptr = &c_town; + /* + len = sizeof(current_town_type); + if (WriteFile(file_id, town_ptr, sizeof(current_town_type), &bytes, NULL) == FALSE) + { + CloseHandle(file_id); + return; + }*/ + +/** saving c_town **/ + + { + WriteFile(file_id, &c_town.town_num, 2, &dwByteRead, NULL); + WriteFile(file_id, &c_town.difficulty, 2, &dwByteRead, NULL); + WriteFile(file_id, &c_town.town, sizeof(town_record_type), &dwByteRead, NULL); + WriteFile(file_id, c_town.explored, 64 * 64, &dwByteRead, NULL); + WriteFile(file_id, &c_town.hostile, 1, &dwByteRead, NULL); + { + for (j = 0; j < 60; j++) + { + WriteFile(file_id, &c_town.monst.dudes[j].active, 2, &dwByteRead, NULL); + WriteFile(file_id, &c_town.monst.dudes[j].attitude, 2, &dwByteRead, NULL); + WriteFile(file_id, &c_town.monst.dudes[j].number, 1, &dwByteRead, NULL); + WriteFile(file_id, &c_town.monst.dudes[j].m_loc.x, 1, &dwByteRead, NULL); + WriteFile(file_id, &c_town.monst.dudes[j].m_loc.y, 1, &dwByteRead, NULL); + { + WriteFile(file_id, &c_town.monst.dudes[j].m_d.m_num, 1, &dwByteRead, NULL); + WriteFile(file_id, &c_town.monst.dudes[j].m_d.level, 1, &dwByteRead, NULL); + WriteFile(file_id, c_town.monst.dudes[j].m_d.m_name, 26, &dwByteRead, NULL); + WriteFile(file_id, &c_town.monst.dudes[j].m_d.health, 2, &dwByteRead, NULL); + WriteFile(file_id, &c_town.monst.dudes[j].m_d.m_health, 2, &dwByteRead, NULL); + WriteFile(file_id, &c_town.monst.dudes[j].m_d.mp, 2, &dwByteRead, NULL); + WriteFile(file_id, &c_town.monst.dudes[j].m_d.max_mp, 2, &dwByteRead, NULL); + WriteFile(file_id, &c_town.monst.dudes[j].m_d.armor, 1, &dwByteRead, NULL); + WriteFile(file_id, &c_town.monst.dudes[j].m_d.skill, 1, &dwByteRead, NULL); + WriteFile(file_id, &c_town.monst.dudes[j].m_d.a, 2*3, &dwByteRead, NULL); + WriteFile(file_id, &c_town.monst.dudes[j].m_d.a1_type, 1, &dwByteRead, NULL); + WriteFile(file_id, &c_town.monst.dudes[j].m_d.a23_type, 1, &dwByteRead, NULL); + WriteFile(file_id, &c_town.monst.dudes[j].m_d.m_type, 1, &dwByteRead, NULL); + WriteFile(file_id, &c_town.monst.dudes[j].m_d.speed, 1, &dwByteRead, NULL); + WriteFile(file_id, &c_town.monst.dudes[j].m_d.ap, 1, &dwByteRead, NULL); + WriteFile(file_id, &c_town.monst.dudes[j].m_d.mu, 1, &dwByteRead, NULL); + WriteFile(file_id, &c_town.monst.dudes[j].m_d.cl, 1, &dwByteRead, NULL); + WriteFile(file_id, &c_town.monst.dudes[j].m_d.breath, 1, &dwByteRead, NULL); + WriteFile(file_id, &c_town.monst.dudes[j].m_d.breath_type, 1, &dwByteRead, NULL); + WriteFile(file_id, &c_town.monst.dudes[j].m_d.treasure, 1, &dwByteRead, NULL); + WriteFile(file_id, &c_town.monst.dudes[j].m_d.spec_skill, 1, &dwByteRead, NULL); + WriteFile(file_id, &c_town.monst.dudes[j].m_d.poison, 1, &dwByteRead, NULL); + WriteFile(file_id, &c_town.monst.dudes[j].m_d.morale, 2, &dwByteRead, NULL); + WriteFile(file_id, &c_town.monst.dudes[j].m_d.m_morale, 2, &dwByteRead, NULL); + WriteFile(file_id, &c_town.monst.dudes[j].m_d.corpse_item, 2, &dwByteRead, NULL); + WriteFile(file_id, &c_town.monst.dudes[j].m_d.corpse_item_chance, 2, &dwByteRead, NULL); + WriteFile(file_id, c_town.monst.dudes[j].m_d.status, 2*15, &dwByteRead, NULL); + WriteFile(file_id, &c_town.monst.dudes[j].m_d.direction, 1, &dwByteRead, NULL); + WriteFile(file_id, &c_town.monst.dudes[j].m_d.immunities, 1, &dwByteRead, NULL); + WriteFile(file_id, &c_town.monst.dudes[j].m_d.x_width, 1, &dwByteRead, NULL); + WriteFile(file_id, &c_town.monst.dudes[j].m_d.y_width, 1, &dwByteRead, NULL); + WriteFile(file_id, &c_town.monst.dudes[j].m_d.radiate_1, 1, &dwByteRead, NULL); + WriteFile(file_id, &c_town.monst.dudes[j].m_d.radiate_2, 1, &dwByteRead, NULL); + WriteFile(file_id, &c_town.monst.dudes[j].m_d.default_attitude, 1, &dwByteRead, NULL); + WriteFile(file_id, &c_town.monst.dudes[j].m_d.summon_type, 1, &dwByteRead, NULL); + WriteFile(file_id, &c_town.monst.dudes[j].m_d.default_facial_pic, 1, &dwByteRead, NULL); + WriteFile(file_id, &c_town.monst.dudes[j].m_d.res1, 1, &dwByteRead, NULL); + WriteFile(file_id, &c_town.monst.dudes[j].m_d.res2, 1, &dwByteRead, NULL); + WriteFile(file_id, &c_town.monst.dudes[j].m_d.res3, 1, &dwByteRead, NULL); + WriteFile(file_id, &c_town.monst.dudes[j].m_d.picture_num, 2, &dwByteRead, NULL); + } + WriteFile(file_id, &c_town.monst.dudes[j].mobile, 1, &dwByteRead, NULL); + WriteFile(file_id, &c_town.monst.dudes[j].summoned, 2, &dwByteRead, NULL); + { + WriteFile(file_id, &c_town.monst.dudes[j].monst_start.number, 1, &dwByteRead, NULL); + WriteFile(file_id, &c_town.monst.dudes[j].monst_start.start_attitude, 1, &dwByteRead, NULL); + WriteFile(file_id, &c_town.monst.dudes[j].monst_start.start_loc.x, 1, &dwByteRead, NULL); + WriteFile(file_id, &c_town.monst.dudes[j].monst_start.start_loc.y, 1, &dwByteRead, NULL); + WriteFile(file_id, &c_town.monst.dudes[j].monst_start.mobile, 1, &dwByteRead, NULL); + WriteFile(file_id, &c_town.monst.dudes[j].monst_start.time_flag, 1, &dwByteRead, NULL); + WriteFile(file_id, &c_town.monst.dudes[j].monst_start.extra1, 1, &dwByteRead, NULL); + WriteFile(file_id, &c_town.monst.dudes[j].monst_start.extra2, 1, &dwByteRead, NULL); + WriteFile(file_id, &c_town.monst.dudes[j].monst_start.spec1, 2, &dwByteRead, NULL); + WriteFile(file_id, &c_town.monst.dudes[j].monst_start.spec2, 2, &dwByteRead, NULL); + WriteFile(file_id, &c_town.monst.dudes[j].monst_start.spec_enc_code, 1, &dwByteRead, NULL); + WriteFile(file_id, &c_town.monst.dudes[j].monst_start.time_code, 1, &dwByteRead, NULL); + WriteFile(file_id, &c_town.monst.dudes[j].monst_start.monster_time, 2, &dwByteRead, NULL); + WriteFile(file_id, &c_town.monst.dudes[j].monst_start.personality, 2, &dwByteRead, NULL); + WriteFile(file_id, &c_town.monst.dudes[j].monst_start.special_on_kill, 2, &dwByteRead, NULL); + WriteFile(file_id, &c_town.monst.dudes[j].monst_start.facial_pic, 2, &dwByteRead, NULL); + } + } + WriteFile(file_id, &c_town.monst.which_town, 2, &dwByteRead, NULL); + WriteFile(file_id, &c_town.monst.friendly, 2, &dwByteRead, NULL); + } + + WriteFile(file_id, &c_town.in_boat, 1, &dwByteRead, NULL); + WriteFile(file_id, &c_town.p_loc.x, 1, &dwByteRead, NULL); + WriteFile(file_id, &c_town.p_loc.y, 1, &dwByteRead, NULL); + } + +/** end of saving c_town **/ + if (WriteFile(file_id, &t_d, sizeof(big_tr_type), &bytes, NULL) == FALSE) + { + CloseHandle(file_id); + return; + } + + if (WriteFile(file_id, &t_i, sizeof(stored_items_list), &bytes, NULL) == FALSE) + { + CloseHandle(file_id); + return; + } + } + + // Save stored items + for (i = 0; i < 3; i++) + { + if (WriteFile(file_id, &stored_items[i], sizeof(stored_items_list), &bytes, NULL) == FALSE) + { + CloseHandle(file_id); + return; + } + } + + // If saving maps, save maps + if (save_maps == TRUE) { + if (WriteFile(file_id, &(town_maps), sizeof(stored_town_maps_type), &bytes, NULL) == FALSE) + { + CloseHandle(file_id); + return; + } + + if (WriteFile(file_id, &o_maps, sizeof(stored_outdoor_maps_type), &bytes, NULL) == FALSE) + { + CloseHandle(file_id); + return; + } + } + + // SAVE SFX and MISC_I + if (WriteFile(file_id, sfx, (64 * 64), &bytes, NULL) == FALSE) + { + CloseHandle(file_id); + return; + } + if (WriteFile(file_id, misc_i, (64 * 64), &bytes, NULL) == FALSE) + { + CloseHandle(file_id); + return; + } + } + + CloseHandle(file_id); + + if (in_startup_mode == FALSE) + add_string_to_buf("Save: Game saved. "); +} + +void set_terrain(location l, unsigned char terrain_type) +{ + t_d.terrain[l.x][l.y] = terrain_type; + combat_terrain[l.x][l.y] = terrain_type; +} + +// mode 0 want town and talking, 1 talking only, 2 want a string only, and extra is string num +// Hey's let's be kludgy and overload these value again! If extra is -1, and mode 2, that +// means we want to load all the strings and only the strings +void load_town(short town_num,short mode,short extra,char *str) +{ + HANDLE file_id; + short i,j; + long store; + DWORD len, dwBytesRead; + long len_to_jump = 0; + short which_town; + char file_name[256]; + + if (town_num != minmax(0,scenario.num_towns - 1,(int)town_num)) + { + give_error("The scenario tried to place you into a non-existant town.","",0); + return; + } + + which_town = town_num; + + sprintf(file_name,"scenarios/%s",party.scen_name); + + file_id = CreateFile(file_name, GENERIC_READ, FILE_SHARE_READ, NULL, + OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (file_id == INVALID_HANDLE_VALUE) + { + FCD(949,0); + return; + } + + len_to_jump = sizeof(scenario_data_type); + len_to_jump += sizeof(scen_item_data_type); + + for (i = 0; i < 300; i++) len_to_jump += (long) scenario.scen_str_len[i]; + store = 0; + for (i = 0; i < 100; i++) + for (j = 0; j < 2; j++) + store += (long) (scenario.out_data_size[i][j]); + for (i = 0; i < which_town; i++) + for (j = 0; j < 5; j++) + store += (long) (scenario.town_data_size[i][j]); + len_to_jump += store; + + SetFilePointer(file_id, len_to_jump, NULL, FILE_BEGIN); + + // len = 3506; + if (mode == 0) + { + ReadFile(file_id, &c_town.town, sizeof(town_record_type), &dwBytesRead, NULL); + port_town(0); + } + else ReadFile(file_id, &dummy_town, sizeof(town_record_type), &dwBytesRead, NULL); + + switch (scenario.town_size[which_town]) { + case 0: + if (mode == 0) + { + ReadFile(file_id, &t_d, sizeof(big_tr_type), &dwBytesRead, NULL); + port_t_d(0); + } + else SetFilePointer(file_id, sizeof(big_tr_type), NULL, FILE_CURRENT); + break; + + case 1: + if (mode == 0) { + ReadFile(file_id, &ave_t, sizeof(ave_tr_type), &dwBytesRead, NULL); + for (i = 0; i < 48; i++) + for (j = 0; j < 48; j++) { + t_d.terrain[i][j] = ave_t.terrain[i][j]; + t_d.lighting[i / 8][j] = ave_t.lighting[i / 8][j]; + } + for (i = 0; i < 16; i++) t_d.room_rect[i] = ave_t.room_rect[i]; + for (i = 0; i < 40; i++) t_d.creatures[i] = ave_t.creatures[i]; + for (i = 40; i < 60; i++) t_d.creatures[i].number = 0; + port_t_d(0); + } + else SetFilePointer(file_id, sizeof(ave_tr_type), NULL, FILE_CURRENT); + break; + + case 2: + if (mode == 0) { + ReadFile(file_id, &tiny_t, sizeof(tiny_tr_type), &dwBytesRead, NULL); + for (i = 0; i < 32; i++) + for (j = 0; j < 32; j++) { + t_d.terrain[i][j] = tiny_t.terrain[i][j]; + t_d.lighting[i / 8][j] = tiny_t.lighting[i / 8][j]; + } + for (i = 0; i < 16; i++) t_d.room_rect[i] = tiny_t.room_rect[i]; + for (i = 0; i < 30; i++) t_d.creatures[i] = tiny_t.creatures[i]; + for (i = 30; i < 60; i++) t_d.creatures[i].number = 0; + port_t_d(0); + } + else SetFilePointer(file_id, sizeof(tiny_tr_type), NULL, FILE_CURRENT); + break; + } + + for (i = 0; i < 140; i++) { + len = (mode == 0) ? (long) (c_town.town.strlens[i]) : (long) (dummy_town.strlens[i]); + switch (mode) { + case 0: + ReadFile(file_id, &(data_store->town_strs[i]), len, &dwBytesRead, NULL); + data_store->town_strs[i][len] = 0; + break; + + case 1: + SetFilePointer(file_id, len, NULL, FILE_CURRENT); + break; + + case 2: + if (extra < 0) { + ReadFile(file_id, &(data_store->town_strs[i]), len, &dwBytesRead, NULL); + data_store->town_strs[i][len] = 0; + } + else if (i == extra) { + ReadFile(file_id, str, len, &dwBytesRead, NULL); + str[len] = 0; + } + else SetFilePointer(file_id, len, NULL, FILE_CURRENT); + break; + } + } + + if (mode < 2) + { + ReadFile(file_id, &talking, sizeof(talking_record_type), &dwBytesRead, NULL); + port_talk_nodes(); + + for (i = 0; i < 170; i++) + { + len = (long) (talking.strlens[i]); + ReadFile(file_id, &(data_store3->talk_strs[i]), len, &dwBytesRead, NULL); + data_store3->talk_strs[i][len] = 0; + } + + cur_town_talk_loaded = town_num; + } + + if (mode == 0) town_type = scenario.town_size[which_town]; + CloseHandle(file_id); + + // Now more initialization is needed. First need to properly create the misc_i array. + + // Initialize barriers, etc. Note non-sfx gets forgotten if this is a town recently visited. + if (mode == 0) { + for (i = 0; i < 64; i++) + for (j = 0; j < 64; j++) { + misc_i[i][j] = 0; + sfx[i][j] = 0; + } + for (i = 0; i < 50; i++) + if (/* GK (c_town.town.spec_id[i] >= 0) && */(c_town.town.special_locs[i].x < 100)){ + make_special(c_town.town.special_locs[i].x,c_town.town.special_locs[i].y); + } + for (i = 0; i < 50; i++) { + if ((c_town.town.preset_fields[i].field_type > 0) && (c_town.town.preset_fields[i].field_type < 9)) + misc_i[(short) c_town.town.preset_fields[i].field_loc.x][(short) c_town.town.preset_fields[i].field_loc.y] = + misc_i[(short) c_town.town.preset_fields[i].field_loc.x][(short) c_town.town.preset_fields[i].field_loc.y] | + (unsigned char) (s_pow(2,c_town.town.preset_fields[i].field_type - 1)); + if ((c_town.town.preset_fields[i].field_type >= 14) && (c_town.town.preset_fields[i].field_type <= 21)) + sfx[(short) c_town.town.preset_fields[i].field_loc.x][(short) c_town.town.preset_fields[i].field_loc.y] = + sfx[(short) c_town.town.preset_fields[i].field_loc.x][(short) c_town.town.preset_fields[i].field_loc.y] | + (unsigned char) (s_pow(2,c_town.town.preset_fields[i].field_type - 14)); + } + } +} + +void shift_universe_left() +{ + short i,j; + + make_cursor_watch(); + + save_outdoor_maps(); + party.outdoor_corner.x--; + party.i_w_c.x++; + party.p_loc.x += 48; + outdoors[1][0] = outdoors[0][0]; + outdoors[1][1] = outdoors[0][1]; + data_store4->outdoor_text[1][0] = data_store4->outdoor_text[0][0]; + data_store4->outdoor_text[1][1] = data_store4->outdoor_text[0][1]; + + for (i = 48; i < 96; i++) + for (j = 0; j < 96; j++) + out_e[i][j] = out_e[i - 48][j]; + + for (i = 0; i < 48; i++) + for (j = 0; j < 96; j++) + out_e[i][j] = 0; + + for (i = 0; i < 10; i++) { + if (party.out_c[i].m_loc.x > 48) + party.out_c[i].exists = FALSE; + if (party.out_c[i].exists == TRUE) + party.out_c[i].m_loc.x += 48; + } + + load_outdoors(party.outdoor_corner.x,party.outdoor_corner.y,0,0,0,0,NULL); + load_outdoors(party.outdoor_corner.x,party.outdoor_corner.y + 1,0,1,0,0,NULL); + build_outdoors(); + + // reload graphics -- who knows what we added + load_area_graphics(); + SetCursor(sword_curs); +} + +void shift_universe_right() +{ + short i,j; + + make_cursor_watch(); + save_outdoor_maps(); + party.outdoor_corner.x++; + party.i_w_c.x--; + party.p_loc.x -= 48; + outdoors[0][0] = outdoors[1][0]; + outdoors[0][1] = outdoors[1][1]; + data_store4->outdoor_text[0][0] = data_store4->outdoor_text[1][0]; + data_store4->outdoor_text[0][1] = data_store4->outdoor_text[1][1]; + for (i = 0; i < 48; i++) + for (j = 0; j < 96; j++) + out_e[i][j] = out_e[i + 48][j]; + for (i = 48; i < 96; i++) + for (j = 0; j < 96; j++) + out_e[i][j] = 0; + + + for (i = 0; i < 10; i++) { + if (party.out_c[i].m_loc.x < 48) + party.out_c[i].exists = FALSE; + if (party.out_c[i].exists == TRUE) + party.out_c[i].m_loc.x -= 48; + } + load_outdoors(party.outdoor_corner.x + 1,party.outdoor_corner.y,1,0,0,0,NULL); + load_outdoors(party.outdoor_corner.x + 1,party.outdoor_corner.y + 1,1,1,0,0,NULL); + build_outdoors(); + + // reload graphics -- who knows what we added + load_area_graphics(); + SetCursor(sword_curs); + +} + +void shift_universe_up() +{ + short i,j; + + make_cursor_watch(); + save_outdoor_maps(); + party.outdoor_corner.y--; + party.i_w_c.y++; + party.p_loc.y += 48; + outdoors[0][1] = outdoors[0][0]; + outdoors[1][1] = outdoors[1][0]; + + data_store4->outdoor_text[0][1] = data_store4->outdoor_text[0][0]; + data_store4->outdoor_text[1][1] = data_store4->outdoor_text[1][0]; + for (i = 0; i < 96; i++) + for (j = 48; j < 96; j++) + out_e[i][j] = out_e[i][j - 48]; + for (i = 0; i < 96; i++) + for (j = 0; j < 48; j++) + out_e[i][j] = 0; + + for (i = 0; i < 10; i++) { + if (party.out_c[i].m_loc.y > 48) + party.out_c[i].exists = FALSE; + if (party.out_c[i].exists == TRUE) + party.out_c[i].m_loc.y += 48; + } + load_outdoors(party.outdoor_corner.x,party.outdoor_corner.y,0,0,0,0,NULL); + load_outdoors(party.outdoor_corner.x + 1,party.outdoor_corner.y,1,0,0,0,NULL); + + build_outdoors(); + + // reload graphics -- who knows what we added + load_area_graphics(); + SetCursor(sword_curs); + +} + +void shift_universe_down() +{ + short i,j; + + make_cursor_watch(); + + save_outdoor_maps(); + party.outdoor_corner.y++; + party.i_w_c.y--; + party.p_loc.y = party.p_loc.y - 48; + outdoors[0][0] = outdoors[0][1]; + outdoors[1][0] = outdoors[1][1]; + + data_store4->outdoor_text[0][0] = data_store4->outdoor_text[0][1]; + data_store4->outdoor_text[1][0] = data_store4->outdoor_text[1][1]; + for (i = 0; i < 96; i++) + for (j = 0; j < 48; j++) + out_e[i][j] = out_e[i][j + 48]; + for (i = 0; i < 96; i++) + for (j = 48; j < 96; j++) + out_e[i][j] = 0; + + for (i = 0; i < 10; i++) { + if (party.out_c[i].m_loc.y < 48) + party.out_c[i].exists = FALSE; + if (party.out_c[i].exists == TRUE) + party.out_c[i].m_loc.y = party.out_c[i].m_loc.y - 48; + } + load_outdoors(party.outdoor_corner.x,party.outdoor_corner.y + 1,0,1,0,0,NULL); + load_outdoors(party.outdoor_corner.x + 1,party.outdoor_corner.y + 1,1,1,0,0,NULL); + + build_outdoors(); + + // reload graphics -- who knows what we added + load_area_graphics(); + SetCursor(sword_curs); + +} +void position_party(short out_x,short out_y,short pc_pos_x,short pc_pos_y) +{ + short i,j; + + save_outdoor_maps(); + party.p_loc.x = pc_pos_x; + party.p_loc.y = pc_pos_y; + party.loc_in_sec = party.p_loc.toLocal(); + + if ((party.outdoor_corner.x != out_x) || (party.outdoor_corner.y != out_y)) + { + party.outdoor_corner.x = out_x; + party.outdoor_corner.y = out_y; + load_outdoors(party.outdoor_corner.x + 1,party.outdoor_corner.y + 1,1,1,0,0,NULL); + load_outdoors(party.outdoor_corner.x,party.outdoor_corner.y + 1,0,1,0,0,NULL); + load_outdoors(party.outdoor_corner.x + 1,party.outdoor_corner.y,1,0,0,0,NULL); + load_outdoors(party.outdoor_corner.x,party.outdoor_corner.y,0,0,0,0,NULL); + } + party.i_w_c.x = (party.p_loc.x > 47) ? 1 : 0; + party.i_w_c.y = (party.p_loc.y > 47) ? 1 : 0; + for (i = 0; i < 10; i++) party.out_c[i].exists = FALSE; + for (i = 0; i < 96; i++) + for (j = 0; j < 96; j++) + out_e[i][j] = 0; + build_outdoors(); +} + +void build_outdoors() +{ + short i,j; + + for (i = 0; i < 48; i++) + for (j = 0; j < 48; j++) + { + out[i][j] = outdoors[0][0].terrain[i][j]; + out[48 + i][j] = outdoors[1][0].terrain[i][j]; + out[i][48 + j] = outdoors[0][1].terrain[i][j]; + out[48 + i][48 + j] = outdoors[1][1].terrain[i][j]; + } + + fix_boats(); + add_outdoor_maps(); + make_out_trim(); + if (in_startup_mode == FALSE) erase_out_specials(); + + for (i = 0; i < 10; i++) + if (party.out_c[i].exists == TRUE) + if ((party.out_c[i].m_loc.x < 0) || (party.out_c[i].m_loc.y < 0) || + (party.out_c[i].m_loc.x > 95) || (party.out_c[i].m_loc.y > 95)) + party.out_c[i].exists = FALSE; +} + +short onm(char x_sector,char y_sector) +{ + return y_sector * scenario.out_width + x_sector; +} + +// This adds the current outdoor map info to the saved outdoor map info +void save_outdoor_maps() +{ + short i,j; + + for (i = 0; i < 48; i++) + for (j = 0; j < 48; j++) { + if (out_e[i][j] > 0) + o_maps.outdoor_maps[onm(party.outdoor_corner.x,party.outdoor_corner.y)][i / 8][j] = + o_maps.outdoor_maps[onm(party.outdoor_corner.x,party.outdoor_corner.y)][i / 8][j] | + (char) (s_pow(2,i % 8)); + if (party.outdoor_corner.x + 1 < scenario.out_width) { + if (out_e[i + 48][j] > 0) + o_maps.outdoor_maps[onm(party.outdoor_corner.x + 1,party.outdoor_corner.y)][i / 8][j] = + o_maps.outdoor_maps[onm(party.outdoor_corner.x + 1,party.outdoor_corner.y)][i / 8][j] | + (char) (s_pow(2,i % 8)); + } + if (party.outdoor_corner.y + 1 < scenario.out_height) { + if (out_e[i][j + 48] > 0) + o_maps.outdoor_maps[onm(party.outdoor_corner.x,party.outdoor_corner.y + 1)][i / 8][j] = + o_maps.outdoor_maps[onm(party.outdoor_corner.x,party.outdoor_corner.y + 1)][i / 8][j] | + (char) (s_pow(2,i % 8)); + } + if ((party.outdoor_corner.y + 1 < scenario.out_height) && + (party.outdoor_corner.x + 1 < scenario.out_width)) { + if (out_e[i + 48][j + 48] > 0) + o_maps.outdoor_maps[onm(party.outdoor_corner.x + 1,party.outdoor_corner.y + 1)][i / 8][j] = + o_maps.outdoor_maps[onm(party.outdoor_corner.x + 1,party.outdoor_corner.y + 1)][i / 8][j] | + (char) (s_pow(2,i % 8)); + } + } +} + +void add_outdoor_maps() // This takes the existing outdoor map info and supplements it + // with the saved map info +{ + short i,j; + + for (i = 0; i < 48; i++) + for (j = 0; j < 48; j++) { + if ((out_e[i][j] == 0) && + ((o_maps.outdoor_maps[onm(party.outdoor_corner.x,party.outdoor_corner.y)][i / 8][j] & + (char) (s_pow(2,i % 8))) != 0)) + out_e[i][j] = 1; + if (party.outdoor_corner.x + 1 < scenario.out_width) { + if ((out_e[i + 48][j] == 0) && + ((o_maps.outdoor_maps[onm(party.outdoor_corner.x + 1,party.outdoor_corner.y)][i / 8][j] & + (char) (s_pow(2,i % 8))) != 0)) + out_e[i + 48][j] = 1; + } + if (party.outdoor_corner.y + 1 < scenario.out_height) { + if ((out_e[i][j + 48] == 0) && + ((o_maps.outdoor_maps[onm(party.outdoor_corner.x,party.outdoor_corner.y + 1)][i / 8][j] & + (char) (s_pow(2,i % 8))) != 0)) + out_e[i][j + 48] = 1; + } + if ((party.outdoor_corner.y + 1 < scenario.out_height) && + (party.outdoor_corner.x + 1 < scenario.out_width)) { + if ((out_e[i + 48][j + 48] == 0) && + ((o_maps.outdoor_maps[onm(party.outdoor_corner.x + 1,party.outdoor_corner.y + 1)][i / 8][j] & + (char) (s_pow(2,i % 8))) != 0)) + out_e[i + 48][j + 48] = 1; + } + } +} + +void fix_boats() +{ + short i; + + for (i = 0; i < NUM_OF_BOATS; i++) + if ((party.boats[i].exists == TRUE) && (party.boats[i].which_town == INVALID_TOWN)) + { + if (party.boats[i].boat_sector.x == party.outdoor_corner.x) + party.boats[i].boat_loc.x = party.boats[i].boat_loc_in_sec.x; + else if (party.boats[i].boat_sector.x == party.outdoor_corner.x + 1) + party.boats[i].boat_loc.x = party.boats[i].boat_loc_in_sec.x + 48; + else party.boats[i].boat_loc.x = 500; + + if (party.boats[i].boat_sector.y == party.outdoor_corner.y) + party.boats[i].boat_loc.y = party.boats[i].boat_loc_in_sec.y; + else if (party.boats[i].boat_sector.y == party.outdoor_corner.y + 1) + party.boats[i].boat_loc.y = party.boats[i].boat_loc_in_sec.y + 48; + else party.boats[i].boat_loc.y = 500; + } + + for (i = 0; i < NUM_OF_HORSES; i++) + if ((party.horses[i].exists == TRUE) && (party.horses[i].which_town == INVALID_TOWN)) { + if (party.horses[i].horse_sector.x == party.outdoor_corner.x) + party.horses[i].horse_loc.x = party.horses[i].horse_loc_in_sec.x; + else if (party.horses[i].horse_sector.x == party.outdoor_corner.x + 1) + party.horses[i].horse_loc.x = party.horses[i].horse_loc_in_sec.x + 48; + else party.horses[i].horse_loc.x = 500; + if (party.horses[i].horse_sector.y == party.outdoor_corner.y) + party.horses[i].horse_loc.y = party.horses[i].horse_loc_in_sec.y; + else if (party.horses[i].horse_sector.y == party.outdoor_corner.y + 1) + party.horses[i].horse_loc.y = party.horses[i].horse_loc_in_sec.y + 48; + else party.horses[i].horse_loc.y = 500; + } +} + + +void load_outdoors(short to_create_x, short to_create_y, short targ_x, short targ_y, + short mode,short extra,char *str) +{ + HANDLE file_id; + short i,j,out_sec_num; + char file_name[256]; + DWORD len, dwBytesRead; + long len_to_jump = 0,store = 0; + + if ((to_create_x != minmax(0,scenario.out_width - 1,(int)to_create_x)) || + (to_create_y != minmax(0,scenario.out_height - 1,(int)to_create_y))) { // not exist + for (i = 0; i < 48; i++) + for (j = 0; j < 48; j++) + outdoors[targ_x][targ_y].terrain[i][j] = 5; + for (i = 0; i < 18; i++) { + //outdoors[targ_x][targ_y].special_id[i] = -1; + outdoors[targ_x][targ_y].special_id[i] = 0xFF; + outdoors[targ_x][targ_y].special_locs[i].x = 100; + } + return; + } + + sprintf(file_name,"scenarios/%s",party.scen_name); + + file_id = CreateFile(file_name, GENERIC_READ, FILE_SHARE_READ, NULL, + OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (file_id == INVALID_HANDLE_VALUE) return; + + out_sec_num = scenario.out_width * to_create_y + to_create_x; + + len_to_jump = sizeof(scenario_data_type); + len_to_jump += sizeof(scen_item_data_type); + for (i = 0; i < 300; i++) + len_to_jump += (long) scenario.scen_str_len[i]; + store = 0; + for (i = 0; i < out_sec_num; i++) + for (j = 0; j < 2; j++) + store += (long) (scenario.out_data_size[i][j]); + len_to_jump += store; + + SetFilePointer(file_id, len_to_jump, NULL, FILE_BEGIN); + + if (mode == 0) + { + ReadFile(file_id, &outdoors[targ_x][targ_y], sizeof(outdoor_record_type), &dwBytesRead, NULL); + outdoors[targ_x][targ_y].flip(); + } + else ReadFile(file_id, &dummy_out, sizeof(outdoor_record_type), &dwBytesRead, NULL); + + if (mode == 0) { + for (i = 0; i < 9; i++) { + len = (long) (outdoors[targ_x][targ_y].strlens[i]); + ReadFile(file_id, &(data_store4->outdoor_text[targ_x][targ_y].out_strs[i]), len, &dwBytesRead, NULL); + data_store4->outdoor_text[targ_x][targ_y].out_strs[i][len] = 0; + } + } + + if (mode == 1) + { + for (i = 0; i < 120; i++) + { + len = (long) (dummy_out.strlens[i]); + if (i == extra) + { + ReadFile(file_id, str, len, &dwBytesRead, NULL); + str[len] = 0; + } + SetFilePointer(file_id, len, NULL, FILE_CURRENT); + } + } + + CloseHandle(file_id); +} + + +void get_reg_data() +{ + const int BUFFER_LEN = 64; + char buffer[BUFFER_LEN]; + const char * iniFile = "./blades.ini"; + const char * section = "Blades of Exile"; + GetPrivateProfileString(section, "give_intro_hint", "1", buffer, BUFFER_LEN, iniFile); + give_intro_hint = (atoi(buffer))? TRUE : FALSE; + GetPrivateProfileString(section, "play_sounds", "1", buffer, BUFFER_LEN, iniFile); + play_sounds = (atoi(buffer))? TRUE : FALSE; + GetPrivateProfileString(section, "game_run_before", "0", buffer, BUFFER_LEN, iniFile); + game_run_before = (atoi(buffer))? TRUE : FALSE; + GetPrivateProfileString(section, "display_mode", "0", buffer, BUFFER_LEN, iniFile); + display_mode = atoi(buffer); + GetPrivateProfileString(section, "no_instant_help", "0", buffer, BUFFER_LEN, iniFile); + party.stuff_done[SDF_NO_INSTANT_HELP] = atoi(buffer); + GetPrivateProfileString(section, "fancy_startup", "1", buffer, BUFFER_LEN, iniFile); + fry_startup = atoi(buffer); + GetPrivateProfileString(section, "darker_graphics", "0", buffer, BUFFER_LEN, iniFile); + party.stuff_done[307][0] = atoi(buffer); //1 is darker + GetPrivateProfileString(section, "legacy_day_reached", "0", buffer, BUFFER_LEN, iniFile); + party.stuff_done[309][0] = atoi(buffer); //1 is legacy + GetPrivateProfileString(section, "legacy_kill_node", "1", buffer, BUFFER_LEN, iniFile); + party.stuff_done[309][1] = (atoi(buffer))? FALSE : TRUE; //0 is legacy to preserve backwards compatibility, since SDF are initialized at 0. + GetPrivateProfileString(section, "town_waterfalls", "1", buffer, BUFFER_LEN, iniFile); + party.stuff_done[309][2] = (atoi(buffer))? FALSE : TRUE; //0 is legacy to preserve backwards compatibility, since SDF are initialized at 0. + GetPrivateProfileString(section, "display_grass_trims", "0", buffer, BUFFER_LEN, iniFile); + party.stuff_done[309][3] = atoi(buffer); //0 is display + +} + +void build_data_file(short which) // 1 - compatibility ; 2 - preferences +{ + char tmp[] = "?"; + const char * iniFile = "./blades.ini"; + const char * section = "Blades of Exile"; + if(which == 2){ + WritePrivateProfileString(section, "give_intro_hint", (give_intro_hint)? "1" : "0", iniFile); + WritePrivateProfileString(section, "play_sounds", (play_sounds)? "1" : "0", iniFile); + WritePrivateProfileString(section, "game_run_before", (game_run_before)? "1" : "0", iniFile); + WritePrivateProfileString(section, "display_mode", itoa((int) display_mode, tmp, 10), iniFile); + WritePrivateProfileString(section, "no_instant_help", itoa((int) party.stuff_done[SDF_NO_INSTANT_HELP], tmp, 10), iniFile); + WritePrivateProfileString(section, "fancy_startup", (fry_startup == TRUE) ? "1" : "0", iniFile); + WritePrivateProfileString(section, "darker_graphics", (party.stuff_done[307][0] == 0) ? "0": "1", iniFile); + } + if(which == 1){ + WritePrivateProfileString(section, "legacy_day_reached", (party.stuff_done[309][0] == 0)? "0" : "1", iniFile); + WritePrivateProfileString(section, "legacy_kill_node", (party.stuff_done[309][1] == 0)? "1" : "0", iniFile); + WritePrivateProfileString(section, "town_waterfalls", (party.stuff_done[309][2] == 0)? "1" : "0", iniFile); + WritePrivateProfileString(section, "display_grass_trims", (party.stuff_done[309][3] == 0)? "0" : "1", iniFile); + } +} + +// expecting party record to contain name of proper scenario to load +Boolean load_scenario() // OK +{ + short i; + HANDLE file_id; + Boolean file_ok = FALSE; + DWORD len, dwByteRead; + char file_name[256]; + + sprintf(file_name,"scenarios/%s",party.scen_name); + + file_id = CreateFile(file_name, GENERIC_READ, FILE_SHARE_READ, NULL, + OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (file_id == INVALID_HANDLE_VALUE) return FALSE; + + if (ReadFile(file_id, &scenario, sizeof(scenario_data_type), &dwByteRead, NULL) == FALSE) + { + CloseHandle(file_id); + return FALSE; + } + + if ((scenario.flag1 == 10) && (scenario.flag2 == 20) && (scenario.flag3 == 30) + && (scenario.flag4 == 40)) + { + file_ok = TRUE; + cur_scen_is_win = FALSE; + port_scenario(); + } + if ((scenario.flag1 == 20) && (scenario.flag2 == 40) && (scenario.flag3 == 60) + && (scenario.flag4 == 80)) + { + file_ok = TRUE; + cur_scen_is_win = TRUE; + } + + if (file_ok == FALSE) + { + CloseHandle(file_id); + give_error("This is not a legitimate Blades of Exile scenario.","",0); + return FALSE; + } + + // item data + if (ReadFile(file_id, &(data_store2->scen_item_list), sizeof(scen_item_data_type), &dwByteRead, NULL) == FALSE) + { + CloseHandle(file_id); + return FALSE; + } + + port_item_list(); + + for (i = 0; i < 270; i++) { + len = (DWORD) (scenario.scen_str_len[i]); + if (i < 160) + { + ReadFile(file_id, &(data_store5->scen_strs[i]), len, &dwByteRead, NULL); + data_store5->scen_strs[i][len] = 0; + } + else { + ReadFile(file_id, &(scen_strs2[i - 160]), len, &dwByteRead, NULL); + scen_strs2[i - 160][len] = 0; + } + } + + CloseHandle(file_id); + + if (spec_scen_g != NULL) + { + DeleteObject(spec_scen_g); + spec_scen_g = NULL; + } + + sprintf(file_name,"scenarios/%s",party.scen_name); + for (i = 0; i < 256; i++) { + if (file_name[i] == '.') { + file_name[i + 1] = 'b'; + file_name[i + 2] = 'm'; + file_name[i + 3] = 'p'; + i = 256; + } + } + + spec_scen_g = ReadBMP(file_name); + + set_up_ter_pics(); + return TRUE; +} + +void set_up_ter_pics() +{ + for (int i = 0; i < 256; i++) + terrain_blocked[i] = scenario.ter_types[i].blockage; + for (int i = 0; i < 256; i++) + terrain_pic[i] = scenario.ter_types[i].picture; +} + +void oops_error(short error) +{ + char error_str[256]; + + MessageBeep(MB_OK); + sprintf((char *) error_str,"Giving the scenario editor more memory might also help. Be sure to back your scenario up often. Error number: %d.",error); + give_error("The program encountered an error while loading/saving/creating the scenario. To prevent future problems, the program will now terminate. Trying again may solve the problem.",(char *) error_str,0); +} +void build_scen_headers() +{ + short i; + short cur_entry = 0; + HWND listbox; + WORD count; + char filename[256],filename2[256]; + + for (i = 0; i < 100; i++) + scen_headers[i].flag1 = 0; + + listbox = CreateWindow("listbox", NULL, WS_CHILDWINDOW, // 3 + 0,0,0,0, // 7 + mainPtr, // 8 + (HMENU) 1, // 9 + (HINSTANCE) GetWindowLong(mainPtr, GWL_HINSTANCE), // 10 + NULL); // 11 + + SendMessage(listbox,LB_DIR,0x0,(LPARAM) (LPCTSTR) "scenarios/*.exs"); + count = (WORD) SendMessage(listbox,LB_GETCOUNT,0,0L); + + count = min(count,100); + + for (i = 0; i < count; i++) + { + SendMessage(listbox,LB_GETTEXT,i,(LONG) (LPSTR) filename2); + + sprintf((char *) filename,"scenarios/%s",filename2); + + if (load_scenario_header(filename,cur_entry) == TRUE) + { + // now we need to store the file name, first stripping any path that occurs + // before it + strcpy((char *) data_store2->scen_names[cur_entry],(char *) filename2); + cur_entry++; + } + } + + DestroyWindow(listbox); +} + +// This is only called at startup, when bringing headers of active scenarios. +// This wipes out the scenario record, so be sure not to call it while in an active scenario. +Boolean load_scenario_header(char *filename,short header_entry) +{ + short i; + HANDLE file_id; + WORD store; + Boolean file_ok = FALSE; + DWORD len, dwByteRead; + char load_str[256]; + Boolean mac_header = TRUE; + + file_id = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, NULL, + OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (file_id == INVALID_HANDLE_VALUE) return FALSE; + + if (ReadFile(file_id, &(scen_headers[header_entry]), sizeof(scen_header_type), &dwByteRead, NULL) == FALSE) + { + CloseHandle(file_id); + return FALSE; + } + + if ((scen_headers[header_entry].flag1 == 10) && (scen_headers[header_entry].flag2 == 20) + && (scen_headers[header_entry].flag3 == 30) + && (scen_headers[header_entry].flag4 == 40)) + { + file_ok = TRUE; + mac_header = TRUE; + } + if ((scen_headers[header_entry].flag1 == 20) && (scen_headers[header_entry].flag2 == 40) + && (scen_headers[header_entry].flag3 == 60) + && (scen_headers[header_entry].flag4 == 80)) + { + file_ok = TRUE; + mac_header = FALSE; + } + + if (file_ok == FALSE) + { + scen_headers[header_entry].flag1 = 0; + CloseHandle(file_id); + return FALSE; + } + + // So file is OK, so load in string data and close it. + SetFilePointer(file_id, 0, NULL, FILE_BEGIN); + if (ReadFile(file_id, &scenario, sizeof(scenario_data_type), &dwByteRead, NULL) == FALSE) + { + CloseHandle(file_id); + oops_error(29); + return FALSE; + } + store = scenario.rating; + if (mac_header == TRUE) flip_short(&store); + scen_headers[header_entry].default_ground = store; + + SetFilePointer(file_id, sizeof(scen_item_data_type), NULL, FILE_CURRENT); + + for (i = 0; i < 3; i++) + { + store = (WORD) scenario.scen_str_len[i]; + len = (DWORD) (store); + ReadFile(file_id, load_str, len, &dwByteRead, NULL); + load_str[len] = 0; + if (i == 0) load_str[29] = 0; + else load_str[59] = 0; + + strcpy(data_store2->scen_header_strs[header_entry][i],(char *) load_str); + } + + CloseHandle(file_id); + return TRUE; +} + +void port_talk_nodes() +{ + short i; + + if (cur_scen_is_win == TRUE) + return; + for (i = 0; i < 60; i++) { + flip_short(&talking.talk_nodes[i].personality); + flip_short(&talking.talk_nodes[i].type); + flip_short(&talking.talk_nodes[i].extras[0]); + flip_short(&talking.talk_nodes[i].extras[1]); + flip_short(&talking.talk_nodes[i].extras[2]); + flip_short(&talking.talk_nodes[i].extras[3]); + } +} + +void port_town(short mode)//0 scenario port, 1 save port <= check already done in load_file +{ + short i,j; + + if (cur_scen_is_win == TRUE && mode == 0) + return; + flip_short(&c_town.town.town_chop_time); + flip_short(&c_town.town.town_chop_key); + flip_short(&c_town.town.lighting); + for (i =0 ; i < 4; i++) + flip_short(&c_town.town.exit_specs[i]); + flip_rect(&c_town.town.in_town_rect); + for (i =0 ; i < 64; i++) { + flip_short(&c_town.town.preset_items[i].item_code); + flip_short(&c_town.town.preset_items[i].ability); + } + for (i =0 ; i < 50; i++) { + flip_short(&c_town.town.preset_fields[i].field_type); + } + flip_short(&c_town.town.max_num_monst); + flip_short(&c_town.town.spec_on_entry); + flip_short(&c_town.town.spec_on_entry_if_dead); + for (i =0 ; i < 8; i++) + flip_short(&c_town.town.timer_spec_times[i]); + for (i =0 ; i < 8; i++) + flip_short(&c_town.town.timer_specs[i]); + flip_short(&c_town.town.difficulty); + for (i =0 ; i < 100; i++) + c_town.town.specials[i].flip(); + + if(mode == 1){ + flip_short(&c_town.monst.friendly); + flip_short(&c_town.monst.which_town); + + for(i=0;i<60;i++){ + flip_short(&c_town.monst.dudes[i].active); + flip_short(&c_town.monst.dudes[i].attitude); + flip_short(&c_town.monst.dudes[i].summoned); + + flip_short(&c_town.monst.dudes[i].monst_start.spec1); + flip_short(&c_town.monst.dudes[i].monst_start.spec2); + flip_short(&c_town.monst.dudes[i].monst_start.monster_time); + flip_short(&c_town.monst.dudes[i].monst_start.personality); + flip_short(&c_town.monst.dudes[i].monst_start.special_on_kill); + flip_short(&c_town.monst.dudes[i].monst_start.facial_pic); + + for(j=0;j<3;j++) + flip_short(&c_town.monst.dudes[i].m_d.a[j]); + flip_short(&c_town.monst.dudes[i].m_d.corpse_item); + flip_short(&c_town.monst.dudes[i].m_d.corpse_item_chance); + flip_short(&c_town.monst.dudes[i].m_d.health); + flip_short(&c_town.monst.dudes[i].m_d.m_health); + flip_short(&c_town.monst.dudes[i].m_d.m_morale); + flip_short(&c_town.monst.dudes[i].m_d.max_mp); + flip_short(&c_town.monst.dudes[i].m_d.morale); + flip_short(&c_town.monst.dudes[i].m_d.mp); + flip_short(&c_town.monst.dudes[i].m_d.picture_num); + for(j=0;j<15;j++) + flip_short(&c_town.monst.dudes[i].m_d.status[j]); + } + } +} + +/*void port_town(short mode)//0 scenario port, 1 save port <= is_win ? check already done in load_file +{ + short i; + + if (cur_scen_is_win == TRUE && mode == 0) + return; + flip_short(&c_town.town.town_chop_time); + flip_short(&c_town.town.town_chop_key); + flip_short(&c_town.town.lighting); + for (i =0 ; i < 4; i++) + flip_short(&c_town.town.exit_specs[i]); + flip_rect(&c_town.town.in_town_rect); + for (i =0 ; i < 64; i++) { + flip_short(&c_town.town.preset_items[i].item_code); + flip_short(&c_town.town.preset_items[i].ability); + } + for (i =0 ; i < 50; i++) { + flip_short(&c_town.town.preset_fields[i].field_type); + } + flip_short(&c_town.town.max_num_monst); + flip_short(&c_town.town.spec_on_entry); + flip_short(&c_town.town.spec_on_entry_if_dead); + for (i =0 ; i < 8; i++) + flip_short(&c_town.town.timer_spec_times[i]); + for (i =0 ; i < 8; i++) + flip_short(&c_town.town.timer_specs[i]); + flip_short(&c_town.town.difficulty); + for (i =0 ; i < 100; i++) + c_town.town.specials[i].flip(); +}*/ + +void port_t_d(short mode) +{ + short i; + if (cur_scen_is_win == TRUE && mode == 0) + return; + + for (i =0 ; i < 16; i++) + flip_rect(&t_d.room_rect[i]); + for (i =0 ; i < 60; i++) { + flip_short(&t_d.creatures[i].spec1); + flip_short(&t_d.creatures[i].spec2); + flip_short(&t_d.creatures[i].monster_time); + flip_short(&t_d.creatures[i].personality); + flip_short(&t_d.creatures[i].special_on_kill); + flip_short(&t_d.creatures[i].facial_pic); + + } +} + +void port_scenario() +{ + short i,j; + + if (cur_scen_is_win == TRUE) + return; + + flip_short(&scenario.flag_a); + flip_short(&scenario.flag_b); + flip_short(&scenario.flag_c); + flip_short(&scenario.flag_d); + flip_short(&scenario.flag_e); + flip_short(&scenario.flag_f); + flip_short(&scenario.flag_g); + flip_short(&scenario.flag_h); + flip_short(&scenario.flag_i); + flip_short(&scenario.intro_mess_pic); + flip_short(&scenario.intro_mess_len); + flip_short(&scenario.which_town_start); + for (i = 0; i < 200; i++) + for (j = 0; j < 5; j++) + flip_short(&scenario.town_data_size[i][j]); + for (i = 0; i < 10; i++) + flip_short(&scenario.town_to_add_to[i]); + for (i = 0; i < 10; i++) + for (j = 0; j < 2; j++) + flip_short(&scenario.flag_to_add_to_town[i][j]); + for (i = 0; i < 100; i++) + for (j = 0; j < 2; j++) + flip_short(&scenario.out_data_size[i][j]); + for (i = 0; i < 3; i++) + flip_rect(&scenario.store_item_rects[i]); + for (i = 0; i < 3; i++) + flip_short(&scenario.store_item_towns[i]); + for (i = 0; i < 50; i++) + flip_short(&scenario.special_items[i]); + for (i = 0; i < 50; i++) + flip_short(&scenario.special_item_special[i]); + flip_short(&scenario.rating); + flip_short(&scenario.uses_custom_graphics); + for (i = 0; i < 256; i++) { + flip_short(&scenario.scen_monsters[i].health); + flip_short(&scenario.scen_monsters[i].m_health); + flip_short(&scenario.scen_monsters[i].max_mp); + flip_short(&scenario.scen_monsters[i].mp); + flip_short(&scenario.scen_monsters[i].a[1]); + flip_short(&scenario.scen_monsters[i].a[0]); + flip_short(&scenario.scen_monsters[i].a[2]); + flip_short(&scenario.scen_monsters[i].morale); + flip_short(&scenario.scen_monsters[i].m_morale); + flip_short(&scenario.scen_monsters[i].corpse_item); + flip_short(&scenario.scen_monsters[i].corpse_item_chance); + flip_short(&scenario.scen_monsters[i].picture_num); + } + + for (i = 0; i < 256; i++) { + flip_short(&scenario.ter_types[i].picture); + } + for (i = 0; i < 30; i++) { + flip_short(&scenario.scen_boats[i].which_town); + } + for (i = 0; i < 30; i++) { + flip_short(&scenario.scen_horses[i].which_town); + } + for (i = 0; i < 20; i++) + flip_short(&scenario.scenario_timer_times[i]); + for (i = 0; i < 20; i++) + flip_short(&scenario.scenario_timer_specs[i]); + for (i = 0; i < 256; i++) { + scenario.scen_specials[i].flip(); + } + for (i = 0; i < 10; i++) { + flip_short(&scenario.storage_shortcuts[i].ter_type); + flip_short(&scenario.storage_shortcuts[i].property); + for (j = 0; j < 10; j++) { + flip_short(&scenario.storage_shortcuts[i].item_num[j]); + flip_short(&scenario.storage_shortcuts[i].item_odds[j]); + } + } + flip_short(&scenario.last_town_edited); +} + +void port_party(){ + + int i,j,k; + + flip_long(&party.age); + flip_short(&party.food); + flip_short(&party.gold); + flip_short(&party.light_level); + for (i = 0; i < 30; i++) { + flip_short(&party.boats[i].which_town); + } + for (i = 0; i < 30; i++) { + flip_short(&party.horses[i].which_town); + } + for (i = 0; i < 4; i++) + { + for (j = 0; j < 60; j++) + { + flip_short(&party.creature_save[i].dudes[j].active); + flip_short(&party.creature_save[i].dudes[j].attitude); + { + flip_short(&party.creature_save[i].dudes[j].m_d.health); + flip_short(&party.creature_save[i].dudes[j].m_d.m_health); + flip_short(&party.creature_save[i].dudes[j].m_d.mp); + flip_short(&party.creature_save[i].dudes[j].m_d.max_mp); + for(k=0;k<3;k++) + flip_short(&party.creature_save[i].dudes[j].m_d.a[k]); + flip_short(&party.creature_save[i].dudes[j].m_d.morale); + flip_short(&party.creature_save[i].dudes[j].m_d.m_morale); + flip_short(&party.creature_save[i].dudes[j].m_d.corpse_item); + flip_short(&party.creature_save[i].dudes[j].m_d.corpse_item_chance); + for(k=0;k<15;k++) + flip_short(&party.creature_save[i].dudes[j].m_d.status[k]); + flip_short(&party.creature_save[i].dudes[j].m_d.picture_num); + } + flip_short(&party.creature_save[i].dudes[j].summoned); + { + flip_short(&party.creature_save[i].dudes[j].monst_start.spec1); + flip_short(&party.creature_save[i].dudes[j].monst_start.spec2); + flip_short(&party.creature_save[i].dudes[j].monst_start.monster_time); + flip_short(&party.creature_save[i].dudes[j].monst_start.personality); + flip_short(&party.creature_save[i].dudes[j].monst_start.special_on_kill); + flip_short(&party.creature_save[i].dudes[j].monst_start.facial_pic); + } + } + + flip_short(&party.creature_save[i].which_town); + flip_short(&party.creature_save[i].friendly); + } + flip_short(&party.in_boat); + flip_short(&party.in_horse); +for (i = 0; i < 10; i++) + { + flip_short(&party.out_c[i].direction); + { + flip_short(&party.out_c[i].what_monst.spec_on_meet); + flip_short(&party.out_c[i].what_monst.spec_on_win); + flip_short(&party.out_c[i].what_monst.spec_on_flee); + flip_short(&party.out_c[i].what_monst.cant_flee); + flip_short(&party.out_c[i].what_monst.end_spec1); + flip_short(&party.out_c[i].what_monst.end_spec2); + } + } + for (i = 0; i < 5; i++) + for (j = 0; j < 10; j++) + { + flip_short(&party.magic_store_items[i][j].variety); + flip_short(&party.magic_store_items[i][j].item_level); + flip_short(&party.magic_store_items[i][j].value); + } + for(k=0;k<4;k++) + flip_short(&party.imprisoned_monst[k]); + for(k=0;k<50;k++) + flip_short(&party.journal_day[k]); + for(k=0;k<140;k++){ + flip_short(&party.special_notes_str[k][0]); + flip_short(&party.special_notes_str[k][1]); + } + for (i = 0; i < 120; i++) + { + flip_short(&party.talk_save[i].personality); + flip_short(&party.talk_save[i].town_num); + flip_short(&party.talk_save[i].str1); + flip_short(&party.talk_save[i].str2); + } + flip_short(&party.direction); + flip_short(&party.at_which_save_slot); + for(k=0;k<100;k++) + flip_short(&party.key_times[k]); + for(k=0;k<30;k++) + flip_short(&party.party_event_timers[k]); + for(k=0;k<30;k++) + flip_short(&party.global_or_town[k]); + for(k=0;k<30;k++) + flip_short(&party.node_to_call[k]); + for(k=0;k<200;k++) + flip_short(&party.m_killed[k]); + flip_long((long *) &party.total_m_killed); + flip_long((long *) &party.total_dam_done); + flip_long((long *) &party.total_xp_gained); + flip_long((long *) &party.total_dam_taken); +} + +void port_pc(){ + + int i,j; + + for(i=0;i<6;i++){ + flip_short(&adven[i].cur_health); + flip_short(&adven[i].cur_sp); + flip_short(&adven[i].direction); + flip_short(&adven[i].exp_adj); + flip_short(&adven[i].experience); + flip_short(&adven[i].level); + flip_short(&adven[i].main_status); + flip_short(&adven[i].max_health); + flip_short(&adven[i].max_sp); + flip_short(&adven[i].race); + flip_short(&adven[i].skill_pts); + for(j=0;j<30;j++) + flip_short(&adven[i].skills[j]); + for(j=0;j<15;j++) + flip_short(&adven[i].status[j]); + flip_short(&adven[i].weap_poisoned); + flip_short(&adven[i].which_graphic); + for(j=0;j<24;j++){ + flip_short(&adven[i].items[j].item_level); + flip_short(&adven[i].items[j].value); + flip_short(&adven[i].items[j].variety); + } + } + +} + +void port_item_list() +{ + short i; + + if (cur_scen_is_win == TRUE) + return; + + for (i = 0; i < 400; i++) { + flip_short(&(data_store2->scen_item_list.scen_items[i].variety)); + flip_short(&(data_store2->scen_item_list.scen_items[i].item_level)); + flip_short(&(data_store2->scen_item_list.scen_items[i].value)); + } +} + +void port_stored_items(stored_items_list* list) +{ + short i; + + for (i = 0; i < NUM_TOWN_ITEMS; i++) { + flip_short(&(list->items[i].variety)); + flip_short(&(list->items[i].item_level)); + flip_short(&(list->items[i].value)); + } +} + +void outdoor_record_type::flip() +{ + short i; + + if (cur_scen_is_win == TRUE) + return; + + for (i = 0; i < 4; i++) { + flip_short(&(wandering[i].spec_on_meet)); + flip_short(&(wandering[i].spec_on_win)); + flip_short(&(wandering[i].spec_on_flee)); + flip_short(&(wandering[i].cant_flee)); + flip_short(&(wandering[i].end_spec1)); + flip_short(&(wandering[i].end_spec2)); + flip_short(&(special_enc[i].spec_on_meet)); + flip_short(&(special_enc[i].spec_on_win)); + flip_short(&(special_enc[i].spec_on_flee)); + flip_short(&(special_enc[i].cant_flee)); + flip_short(&(special_enc[i].end_spec1)); + flip_short(&(special_enc[i].end_spec2)); + } + for (i = 0; i < 8; i++) + flip_rect(&info_rect[i]); + for (i = 0; i < 60; i++) + specials[i].flip(); +} + +void special_node_type::flip() +{ + flip_short(&type); + flip_short(&sd1); + flip_short(&sd2); + flip_short(&pic); + flip_short(&m1); + flip_short(&m2); + flip_short(&ex1a); + flip_short(&ex1b); + flip_short(&ex2a); + flip_short(&ex2b); + flip_short(&jumpto); +} + +/*void flip_short(short *s) +{ + char store,*s1, *s2; + + s1 = (char *) s; + s2 = s1 + 1; + store = *s1; + *s1 = *s2; + *s2 = store; +}*/ + +void flip_short(short* s){ + *s=((*s&255)<<8)|((*s>>8)&255); +} + +void flip_long(long *s) +{ + char store,*s1, *s2, *s3, *s4; + + s1 = (char *) s; + s2 = s1 + 1; + s3 = s1 + 2; + s4 = s1 + 3; + store = *s1; + *s1 = *s4; + *s4 = store; + store = *s2; + *s2 = *s3; + *s3 = store; +} + + +void flip_short(WORD *s) +{ + BYTE store, *s1, *s2; + + s1 = (BYTE *) s; + s2 = s1 + 1; + store = *s1; + *s1 = *s2; + *s2 = store; +} + +void flip_rect(RECT16 *s) +{ + flip_short((short *) &(s->top)); + flip_short((short *) &(s->bottom)); + flip_short((short *) &(s->left)); + flip_short((short *) &(s->right)); + alter_rect(s); +} diff --git a/Win32/Blades of Exile/FILEIO.H b/Win32/Blades of Exile/FILEIO.H new file mode 100644 index 00000000..afe3563a --- /dev/null +++ b/Win32/Blades of Exile/FILEIO.H @@ -0,0 +1,34 @@ +#ifndef _FILEIO_H + #define _FILEIO_H + +void Get_Path(char* path); +void file_initialize(); +void load_file(); +void save_file(short mode); +void form_template_terrain() ; +void load_town(short town_num,short mode,short extra,char *str); +void shift_universe_left(); +void shift_universe_right(); +void shift_universe_up(); +void shift_universe_down(); +void position_party(short out_x,short out_y,short pc_pos_x,short pc_pos_y); +void build_outdoors(); +void save_outdoor_maps(); +void add_outdoor_maps(); +void fix_boats(); +void load_outdoors(short to_create_x, short to_create_y, short targ_x, short targ_y, + short mode,short extra,char *str); +void get_reg_data(); +long do_waterfall(long flag); +void import_template_terrain(); +void import_anim_terrain(short mode); +void start_data_dump(); +void end_data_dump(); +void set_terrain(location l, unsigned char terrain_type); +void set_up_ter_pics(); +Boolean load_scenario(); +short onm(char x_sector,char y_sector); +void build_scen_headers(); +short get_buf_ptr(short flag); +void build_data_file(short mode); +#endif diff --git a/Win32/Blades of Exile/GAMEDLOG.RC b/Win32/Blades of Exile/GAMEDLOG.RC new file mode 100644 index 00000000..fd8cc77c --- /dev/null +++ b/Win32/Blades of Exile/GAMEDLOG.RC @@ -0,0 +1,1644 @@ +#include + +867 DIALOG 10, 10, 357, 108 + STYLE WS_POPUP | WS_DLGFRAME + { + LTEXT "1_63" 1, 256, 52, 66, 20 + LTEXT "5_716" 2, 6, 6, 36, 36 + LTEXT "You can't start a scenario until you have a party loaded. Click the Load Game or Make New Party button to get a group of adventurers." 3, 49, 6, 273, 43 + } + +868 DIALOG 10, 10, 357, 96 + STYLE WS_POPUP | WS_DLGFRAME + { + LTEXT "1_63" 1, 257, 62, 66, 20 + LTEXT "5_716" 2, 6, 6, 36, 36 + LTEXT "Blades of Exile currently has no scenarios installed. To install a scenario, copy it (with extra graphics files, if any) into the Blades of Exile Scenarios folder." 3, 49, 6, 273, 52 + } + +869 DIALOG 10, 10, 413, 327 +STYLE WS_POPUP | WS_DLGFRAME +{ + LTEXT "1_5", 1, 314, 308, 63, 23 + LTEXT "5_716", 2, 25, 244, 36, 36 + LTEXT "~Start a Scenario:", 3, 130, 9, 126, 17 + LTEXT "5_1410", 4, 10, 42, 64, 64 + LTEXT "=The Valley of Dying Things - Easy Difficulty| The crops have withered, the children are dying, and even the water burns. Can you find the source of the sickness before the entire valley dies?", 5, 81, 34, 292, 80 + LTEXT "0_143", 6, 11, 33, 367, 81 + LTEXT "5_1411", 7, 10, 135, 64, 64 + LTEXT "=A Mild Rebellion - Medium Difficulty| The enemy - a secret band of deadly rebels. The job - infiltrate them, win their trust, and find their leader. The question - are you fighting on the right side?", 8, 81, 127, 292, 80 + LTEXT "0_143", 9, 10, 127, 368, 80 + LTEXT "5_1412", 10, 10, 228, 64, 64 + LTEXT "=The Za-Khazi Run - Hard Difficulty| A fortress is under siege, and only you can get them the weapons they need to survive. You have 20 days to find your way through the nastiest caves in Exile, or all will be lost.", 11, 81, 220, 292, 80 + LTEXT "0_143", 12, 10, 220, 368, 80 +} + +870 DIALOG 10, 10, 334, 74 + STYLE WS_POPUP | WS_DLGFRAME + { + LTEXT "1_65" 1, 244, 39, 58, 20 + LTEXT "0_64" 2, 178, 39, 63, 20 + LTEXT "5_722" 3, 9, 9, 36, 36 + LTEXT "There is a glowing teleporter here. Do you step through?" 4, 51, 4, 251, 32 + } + +871 DIALOG 10, 10, 334, 74 + STYLE WS_POPUP | WS_DLGFRAME + { + LTEXT "1_65" 1, 244, 39, 58, 20 + LTEXT "0_64" 2, 178, 39, 63, 20 + LTEXT "5_711" 3, 9, 9, 36, 36 + LTEXT "There is a large button here, waiting to be pressed. Do you?" 4, 51, 4, 251, 32 + } + +872 DIALOG 10, 10, 334, 74 + STYLE WS_POPUP | WS_DLGFRAME + { + LTEXT "1_65" 1, 244, 39, 58, 20 + LTEXT "0_64" 2, 178, 39, 63, 20 + LTEXT "5_727" 3, 9, 9, 36, 36 + LTEXT "You think you've found a trap. Do you try to disarm it?" 4, 51, 4, 251, 32 + } + +873 DIALOG 10, 10, 252, 82 +STYLE WS_POPUP | WS_DLGFRAME +{ + LTEXT "6_0", 2, 90, 33, 126, 16 + LTEXT "5_716", 3, 8, 8, 36, 36 + LTEXT "~You respond:", 4, 49, 8, 163, 16 + LTEXT "1_63", 5, 190, 59, 60, 15 +} + +880 DIALOG 10, 10, 340, 64 + STYLE WS_POPUP | WS_DLGFRAME + { + LTEXT "1_9" 1, 242, 27, 58, 20 + LTEXT "0_69" 2, 176, 27, 63, 20 + LTEXT "5_719" 3, 8, 8, 36, 36 + LTEXT "You find a stairway heading up." 4, 50, 3, 250, 22 + } + +881 DIALOG 10, 10, 340, 64 + STYLE WS_POPUP | WS_DLGFRAME + { + LTEXT "1_9" 1, 242, 27, 58, 20 + LTEXT "0_69" 2, 176, 27, 58, 20 + LTEXT "5_719" 3, 8, 8, 36, 36 + LTEXT "You find a stairway heading down." 4, 50, 3, 250, 22 + } + +882 DIALOG 10, 10, 340, 64 + STYLE WS_POPUP | WS_DLGFRAME + { + LTEXT "1_9" 1, 243, 35, 58, 20 + LTEXT "0_69" 2, 177, 35, 58, 20 + LTEXT "5_719" 3, 8, 8, 36, 36 + LTEXT "The passageway you're walking down slopes sharply upward here." 4, 50, 3, 251, 31 + } + +883 DIALOG 10, 10, 340, 64 + STYLE WS_POPUP | WS_DLGFRAME + { + LTEXT "1_9" 1, 243, 35, 58, 20 + LTEXT "0_69" 2, 177, 35, 58, 20 + LTEXT "5_719" 3, 8, 8, 36, 36 + LTEXT "The passageway you're walking down slopes sharply downward here." 4, 50, 3, 251, 31 + } + +884 DIALOG 10, 10, 340, 64 + STYLE WS_POPUP | WS_DLGFRAME + { + LTEXT "1_9" 1, 242, 37, 58, 20 + LTEXT "0_69" 2, 176, 37, 58, 20 + LTEXT "5_719" 3, 8, 8, 36, 36 + LTEXT "You find a stairway heading up. The steps are covered with a thin layer of slick, unpleasant slime." 4, 50, 3, 250, 32 + } + +885 DIALOG 10, 10, 340, 64 + STYLE WS_POPUP | WS_DLGFRAME + { + LTEXT "1_9" 1, 243, 45, 58, 20 + LTEXT "0_69" 2, 177, 45, 58, 20 + LTEXT "5_719" 3, 8, 8, 36, 36 + LTEXT "You find a stairway heading down. You will have to be careful - the steps are covered with a thin layer of slick, unpleasant slime." 4, 50, 3, 251, 40 + } + +886 DIALOG 10, 10, 340, 64 + STYLE WS_POPUP | WS_DLGFRAME + { + LTEXT "1_9" 1, 243, 35, 58, 20 + LTEXT "0_69" 2, 177, 35, 58, 20 + LTEXT "5_719" 3, 8, 8, 36, 36 + LTEXT "The passageway you're walking down slopes upward into darkness. " 4, 50, 3, 251, 31 + } + +887 DIALOG 10, 10, 340, 64 + STYLE WS_POPUP | WS_DLGFRAME + { + LTEXT "1_9" 1, 246, 50, 58, 20 + LTEXT "0_69" 2, 180, 50, 58, 20 + LTEXT "5_719" 3, 8, 8, 36, 36 + LTEXT "The passageway you're walking down slopes downward here, descending steeply into total darkness." 4, 50, 3, 254, 45 + } + +900 DIALOG 10, 10, 340, 64 + STYLE WS_POPUP | WS_DLGFRAME + { + } + +901 DIALOG 10, 10, 338, 113 + STYLE WS_POPUP | WS_DLGFRAME + { + LTEXT "1_5" 1, 234, 72, 66, 20 + LTEXT "0_84" 2, 128, 72, 66, 20 + LTEXT "5_716" 3, 6, 6, 36, 36 + LTEXT "Congratulations - you have just completed this scenario! If you want, you can save your adventurers now before returning to the starting screen." 4, 48, 6, 252, 64 + } + +910 DIALOG 10, 10, 352, 85 + STYLE WS_POPUP | WS_DLGFRAME + { + LTEXT "1_63" 1, 246, 50, 58, 20 + LTEXT "5_716" 2, 8, 8, 36, 36 + LTEXT "Some of your items are special, and can't be carried from scenario to scenario. These have been taken away." 3, 50, 3, 254, 45 + } + +911 DIALOG 10, 10, 342, 97 + STYLE WS_POPUP | WS_DLGFRAME + { + LTEXT "1_64" 1, 246, 64, 58, 20 + LTEXT "0_65" 2, 180, 64, 58, 20 + LTEXT "5_716" 3, 8, 8, 36, 36 + LTEXT "You still have some items stored in the last scenario. Do you want them put into your inventory? You can take as many items as you can carry." 4, 50, 3, 255, 54 + } + +912 DIALOG 10, 10, 352, 85 + STYLE WS_POPUP | WS_DLGFRAME + { + LTEXT "1_63" 1, 263, 69, 58, 20 + LTEXT "5_716" 2, 8, 8, 36, 36 + LTEXT "This scenario was created by Blades of Exile v2.0 or later, and can't be run using this copy. You can find an upgrade at www.spidweb.com, or get one from Spiderweb Software." 3, 50, 3, 271, 63 + } + +947 DIALOG 10, 10, 440, 329 +STYLE WS_POPUP | WS_DLGFRAME +{ + LTEXT "1_5", 1, 337, 304, 63, 23 + LTEXT "5_716", 2, 10, 10, 36, 36 + LTEXT "0_2", 3, 62, 304, 63, 20 + LTEXT "0_3", 4, 125, 304, 58, 20 + LTEXT "~Your scenarios:", 5, 58, 6, 199, 18 + LTEXT "5_0", 6, 62, 58, 32, 32 + LTEXT "=", 7, 104, 34, 292, 80 + LTEXT "0_143", 8, 59, 32, 342, 84 + LTEXT "5_0", 9, 62, 149, 32, 32 + LTEXT "=", 10, 104, 125, 292, 80 + LTEXT "0_143", 11, 59, 122, 342, 85 + LTEXT "5_0", 12, 62, 240, 32, 32 + LTEXT "=", 13, 104, 216, 292, 80 + LTEXT "0_143", 14, 59, 213, 342, 86 +} + +/* TODO (#1#): change dialog 949 */ +949 DIALOG 10, 10, 326, 132 + STYLE WS_POPUP | WS_DLGFRAME + { + LTEXT "1_63" 1, 243, 106, 58, 20 + LTEXT "5_723" 2, 6, 6, 36, 36 + LTEXT "For some reason, the game was unable to open scenario files." 3, 50, 6, 252, 98 + } + +958 DIALOG 10, 10, 345, 189 + STYLE WS_POPUP | WS_DLGFRAME + { + LTEXT "1_0" 1, 242, 158, 70, 20 + LTEXT "5_708" 2, 9, 9, 36, 36 + LTEXT "= " 3, 53, 37, 257, 92 + LTEXT "~Tip of the Day:" 4, 53, 9, 257, 19 + LTEXT "0_103" 5, 54, 158, 70, 20 + LTEXT "*See tips upon startup:" 6, 53, 138, 136, 16 + LTEXT "2_0" 7, 192, 141, 28, 16 + } + +960 DIALOG 10, 10, 377, 322 + STYLE WS_POPUP | WS_DLGFRAME + { + LTEXT "1_0" 1, 250, 285, 70, 20 + LTEXT "5_708" 2, 9, 9, 36, 36 + LTEXT "= " 3, 53, 82, 257, 92 + LTEXT "~Conversation Journal:" 4, 53, 9, 257, 19 + LTEXT "= " 5, 53, 181, 257, 92 + LTEXT "*Speaking with:" 6, 53, 36, 105, 16 + LTEXT "+" 7, 165, 36, 146, 16 + LTEXT "*Located in:" 8, 53, 59, 105, 16 + LTEXT "+" 9, 165, 59, 146, 16 + LTEXT "0_2" 10, 39, 285, 63, 23 + LTEXT "0_3" 11, 102, 285, 63, 23 + LTEXT "0_53" 12, 173, 285, 70, 20 + } + +961 DIALOG 10, 10, 423, 375 + STYLE WS_POPUP | WS_DLGFRAME + { + LTEXT "1_0" 1, 319, 341, 70, 20 + LTEXT "5_708" 2, 9, 9, 36, 36 + LTEXT "= " 3, 53, 37, 257, 92 + LTEXT "= " 4, 53, 136, 257, 92 + LTEXT "= " 5, 53, 235, 257, 92 + LTEXT "~Encounter Notes:" 6, 53, 9, 257, 19 + LTEXT "0_2" 7, 48, 340, 63, 23 + LTEXT "0_3" 8, 111, 340, 63, 23 + LTEXT "0_53" 9, 319, 109, 70, 20 + LTEXT "0_53" 10, 319, 208, 70, 20 + LTEXT "0_53" 11, 319, 307, 70, 20 + } + +962 DIALOG 10, 10, 437, 371 + STYLE WS_POPUP | WS_DLGFRAME + { + LTEXT "1_0" 1, 319, 341, 70, 20 + LTEXT "5_708" 2, 9, 9, 36, 36 + LTEXT "= " 3, 121, 37, 257, 92 + LTEXT "= " 4, 121, 136, 257, 92 + LTEXT "= " 5, 121, 235, 257, 92 + LTEXT "~Journal of your Travels:" 6, 53, 9, 257, 19 + LTEXT "0_2" 7, 48, 340, 63, 23 + LTEXT "0_3" 8, 111, 340, 63, 23 + LTEXT "*" 9, 52, 37, 55, 15 + LTEXT "*" 10, 52, 136, 55, 15 + LTEXT "*" 11, 52, 234, 55, 15 + } + +970 DIALOG 10, 10, 346, 167 +STYLE WS_POPUP | WS_DLGFRAME +{ + LTEXT "1_0", 1, 251, 122, 70, 20 + LTEXT "0_68", 2, 8, 122, 70, 20 + LTEXT "5_708", 3, 9, 9, 36, 36 + LTEXT "= ", 4, 55, 8, 257, 105 +} + +971 DIALOG 10, 10, 347, 275 +STYLE WS_POPUP | WS_DLGFRAME +{ + LTEXT "1_0", 1, 248, 252, 70, 20 + LTEXT "0_68", 2, 6, 252, 70, 20 + LTEXT "5_708", 3, 9, 9, 36, 36 + LTEXT "= ", 4, 55, 8, 257, 111 + LTEXT "= ", 5, 55, 127, 257, 111 +} + +972 DIALOG 10, 10, 350, 164 +STYLE WS_POPUP | WS_DLGFRAME +{ + LTEXT "1_0", 1, 247, 160, 70, 20 + LTEXT "0_68", 2, 8, 160, 70, 20 + LTEXT "5_708", 3, 9, 9, 36, 36 + LTEXT "= ", 4, 53, 38, 257, 111 + LTEXT "*", 5, 26, 74, 14, 19 + LTEXT "+", 6, 53, 9, 257, 19 +} + +973 DIALOG 10, 10, 347, 297 +STYLE WS_POPUP | WS_DLGFRAME +{ + LTEXT "1_0", 1, 253, 275, 70, 20 + LTEXT "0_68", 2, 9, 275, 70, 20 + LTEXT "5_708", 3, 9, 9, 36, 36 + LTEXT "= ", 4, 55, 39, 257, 107 + LTEXT "= ", 5, 55, 156, 257, 107 + LTEXT "+", 6, 55, 9, 257, 19 +} + +986 DIALOG 10, 10, 508, 396 + STYLE WS_POPUP | WS_DLGFRAME + { + LTEXT "1_63" 1, 406, 365, 65, 20 + LTEXT "5_716" 2, 6, 6, 36, 36 + LTEXT "Welcome to the wonderful world of Blades of Exile! Blades of Exile is the gateway to a nearly infinite variety of adventures. First, it come with 3 exciting scenarios, filled with many hours of puzzles, fighting, and adventure." 3, 50, 22, 413, 53 + LTEXT "Blades of Exile is, like most games of its type, slightly complicated. Fortunately, there are plenty of places to look for help should you get confused. Be sure to read the online documentation which comes with the game (hit F1 to see it)." 4, 50, 117, 412, 54 + LTEXT "Also be sure to look at the Preferences Window (in the Options menu). It can make the game move faster (very useful for older machines), slower, and even easier, change the display, and remove the special effects." 5, 50, 172, 418, 51 + LTEXT "Be sure to look at the file 'LICENSE.TXT.' By playing this game, you are agreeing to abide by all terms of this license." 6, 50, 280, 421, 28 + LTEXT "Finally, alas, the Windows world nowadays is rife with old drivers and other problems. If you experience crashes playing Blades of Exile, there is troubleshooting info in the file _README.TXT_." 7, 50, 225, 420, 53 + LTEXT "WELCOME TO BLADES OF EXILE!" 8, 136, 4, 265, 16 + LTEXT "Jeff Vogel |Keeper of Exile |Spidweb@spidweb.com |http://www.spidweb.com" 9, 306, 310, 165, 52 + LTEXT "Even better, when you are through with those adventures, you can make your own using the Blades of Exile scenario editor or obtain the adventures other people have made and try them out for yourself!" 10, 50, 76, 413, 40 + } + +987 DIALOG 10, 10, 433, 441 + STYLE WS_POPUP | WS_DLGFRAME + { + LTEXT "1_0" 1, 337, 408, 63, 23 + LTEXT "5_702" 2, 10, 10, 36, 36 + LTEXT "0_35" 3, 89, 354, 23, 23 + LTEXT "0_36" 4, 174, 354, 23, 23 + LTEXT "0_37" 5, 259, 354, 23, 23 + LTEXT "0_38" 6, 89, 397, 23, 23 + LTEXT "0_39" 7, 174, 397, 23, 23 + LTEXT "0_40" 8, 259, 397, 23, 23 + LTEXT "0_27" 9, 342, 5, 58, 20 + LTEXT "0_28" 10, 342, 346, 58, 20 + LTEXT "5_0" 11, 123, 348, 28, 36 + LTEXT "5_0" 12, 208, 348, 28, 36 + LTEXT "5_0" 13, 293, 348, 28, 36 + LTEXT "5_0" 14, 123, 393, 28, 36 + LTEXT "5_0" 15, 208, 393, 28, 36 + LTEXT "5_0" 16, 293, 393, 28, 36 + LTEXT "~You Find:" 17, 64, 6, 199, 18 + LTEXT "+" 18, 73, 31, 327, 309 + LTEXT "8_0" 19, 80, 37, 311, 36 + LTEXT "5_0" 20, 80, 37, 28, 36 + LTEXT "*" 21, 107, 37, 212, 18 + LTEXT "*" 22, 116, 55, 275, 17 + LTEXT "8_0" 23, 80, 74, 311, 36 + LTEXT "5_0" 24, 80, 74, 28, 36 + LTEXT "*" 25, 107, 74, 212, 18 + LTEXT "*" 26, 116, 92, 275, 18 + LTEXT "8_0" 27, 80, 111, 311, 36 + LTEXT "5_0" 28, 80, 111, 28, 36 + LTEXT "*" 29, 107, 111, 212, 18 + LTEXT "*" 30, 116, 129, 275, 18 + LTEXT "8_0" 31, 80, 148, 311, 36 + LTEXT "5_0" 32, 80, 148, 28, 36 + LTEXT "*" 33, 107, 148, 212, 18 + LTEXT "*" 34, 116, 166, 275, 18 + LTEXT "8_0" 35, 80, 185, 311, 36 + LTEXT "5_0" 36, 80, 185, 28, 36 + LTEXT "*" 37, 107, 185, 212, 18 + LTEXT "*" 38, 116, 203, 275, 18 + LTEXT "8_0" 39, 80, 222, 311, 36 + LTEXT "5_0" 40, 80, 222, 28, 36 + LTEXT "*" 41, 107, 222, 212, 18 + LTEXT "*" 42, 116, 240, 275, 18 + LTEXT "8_0" 43, 80, 259, 311, 37 + LTEXT "5_0" 44, 80, 259, 28, 36 + LTEXT "*" 45, 107, 259, 212, 18 + LTEXT "*" 46, 116, 277, 275, 18 + LTEXT "8_0" 47, 80, 297, 311, 36 + LTEXT "5_0" 48, 80, 297, 28, 36 + LTEXT "*" 49, 107, 297, 212, 18 + LTEXT "*" 50, 116, 315, 275, 18 + LTEXT "=Keyboard: To get item, hit 'a' - 'h'. To scroll, hit up and down arrows." 51, 1, 203, 64, 125 + LTEXT "=" 52, 1, 347, 66, 79 + LTEXT "*" 53, 319, 37, 78, 18 + LTEXT "*" 54, 319, 74, 78, 18 + LTEXT "*" 55, 319, 111, 78, 18 + LTEXT "*" 56, 319, 148, 78, 18 + LTEXT "*" 57, 319, 185, 78, 18 + LTEXT "*" 58, 319, 222, 78, 18 + LTEXT "*" 59, 319, 259, 78, 18 + LTEXT "*" 60, 319, 297, 78, 18 + } + +988 DIALOG 10, 10, 330, 174 + STYLE WS_POPUP | WS_DLGFRAME + { + LTEXT "1_5" 1, 238, 145, 58, 20 + LTEXT "0_35" 2, 50, 50, 24, 20 + LTEXT "+(spot empty)" 3, 83, 52, 172, 16 + LTEXT "+" 4, 262, 52, 31, 16 + LTEXT "0_36" 5, 50, 72, 24, 20 + LTEXT "+(spot empty)" 6, 83, 74, 172, 16 + LTEXT "+" 7, 262, 74, 31, 16 + LTEXT "0_37" 8, 50, 94, 24, 20 + LTEXT "+(spot empty)" 9, 83, 96, 172, 16 + LTEXT "+" 10, 262, 96, 31, 16 + LTEXT "0_38" 11, 50, 116, 24, 20 + LTEXT "+(spot empty)" 12, 83, 118, 172, 16 + LTEXT "+" 13, 262, 118, 31, 16 + LTEXT "~Select monster to summon:" 14, 50, 6, 251, 16 + LTEXT "5_713" 15, 6, 6, 36, 36 + LTEXT "~# Monster Cost" 16, 50, 28, 244, 16 + } + +989 DIALOG 10, 10, 545, 347 + STYLE WS_POPUP | WS_DLGFRAME + { + LTEXT "1_0" 1, 455, 320, 58, 20 + LTEXT "~Create/Edit Party:" 2, 50, 16, 205, 16 + LTEXT "*Click PC name to rename." 3, 9, 324, 181, 15 + LTEXT "5_707" 4, 6, 6, 36, 36 + LTEXT "8_1" 5, 93, 60, 152, 20 + LTEXT "0_96" 6, 258, 50, 58, 20 + LTEXT "0_95" 7, 324, 50, 58, 20 + LTEXT "0_31" 8, 390, 50, 58, 20 + LTEXT "~PC #1" 9, 42, 63, 40, 16 + LTEXT "8_1" 10, 93, 105, 152, 20 + LTEXT "0_96" 11, 258, 95, 58, 20 + LTEXT "0_95" 12, 324, 95, 58, 20 + LTEXT "0_31" 13, 390, 95, 58, 20 + LTEXT "~PC #2" 14, 42, 108, 40, 16 + LTEXT "8_1" 15, 93, 150, 152, 20 + LTEXT "0_96" 16, 258, 140, 58, 20 + LTEXT "0_95" 17, 324, 140, 58, 20 + LTEXT "0_31" 18, 390, 140, 58, 20 + LTEXT "~PC #3" 19, 42, 153, 40, 16 + LTEXT "8_1" 20, 93, 195, 152, 20 + LTEXT "0_96" 21, 258, 185, 58, 20 + LTEXT "0_95" 22, 324, 185, 58, 20 + LTEXT "0_31" 23, 390, 185, 58, 20 + LTEXT "~PC #4" 24, 42, 198, 40, 16 + LTEXT "8_1" 25, 93, 240, 152, 20 + LTEXT "0_96" 26, 258, 230, 58, 20 + LTEXT "0_95" 27, 324, 230, 58, 20 + LTEXT "0_31" 28, 390, 230, 58, 20 + LTEXT "~PC #5" 29, 42, 243, 40, 16 + LTEXT "8_1" 30, 93, 285, 152, 20 + LTEXT "0_96" 31, 258, 275, 58, 20 + LTEXT "0_95" 32, 324, 275, 58, 20 + LTEXT "0_31" 33, 390, 275, 58, 20 + LTEXT "~PC #6" 34, 42, 288, 40, 16 + LTEXT "0_97" 35, 455, 50, 58, 20 + LTEXT "0_97" 36, 455, 95, 58, 20 + LTEXT "0_97" 37, 455, 140, 58, 20 + LTEXT "0_97" 38, 455, 185, 58, 20 + LTEXT "0_97" 39, 455, 230, 58, 20 + LTEXT "0_97" 40, 455, 275, 58, 20 + LTEXT "0_67" 41, 498, 4, 21, 16 + LTEXT "5_0" 42, 12, 52, 28, 36 + LTEXT "5_0" 43, 12, 97, 28, 36 + LTEXT "5_0" 44, 12, 142, 28, 36 + LTEXT "5_0" 45, 12, 187, 28, 36 + LTEXT "5_0" 46, 12, 232, 28, 36 + LTEXT "5_0" 47, 12, 277, 28, 36 + } + +991 DIALOG 10, 10, 514, 338 + STYLE WS_POPUP | WS_DLGFRAME + { + // DEFPUSHBUTTON "Button" 1, 289, 83, 31, 10, WS_GROUP + LTEXT "5_714" 2, 6, 6, 36, 36 + LTEXT "2_0" 3, 102, 57, 14, 10 + LTEXT "2_0" 4, 102, 69, 14, 10 + LTEXT "2_0" 5, 102, 81, 14, 10 + LTEXT "2_0" 6, 102, 93, 14, 10 + LTEXT "2_0" 7, 102, 105, 14, 10 + LTEXT "2_0" 8, 102, 117, 14, 10 + LTEXT "2_0" 9, 102, 129, 14, 10 + LTEXT "2_0" 10, 102, 141, 14, 10 + LTEXT "2_0" 11, 102, 153, 14, 10 + LTEXT "2_0" 12, 102, 165, 14, 10 + LTEXT "2_0" 13, 220, 57, 14, 10 + LTEXT "2_0" 14, 220, 69, 14, 10 + LTEXT "2_0" 15, 220, 81, 14, 10 + LTEXT "2_0" 16, 220, 93, 14, 10 + LTEXT "2_0" 17, 220, 105, 14, 10 + LTEXT "2_0" 18, 220, 117, 14, 10 + LTEXT "2_0" 19, 220, 129, 14, 10 + LTEXT "2_0" 20, 220, 141, 14, 10 + LTEXT "2_0" 21, 220, 153, 14, 10 + LTEXT "2_0" 22, 220, 165, 14, 10 + LTEXT "2_0" 23, 338, 57, 14, 10 + LTEXT "2_0" 24, 338, 69, 14, 10 + LTEXT "2_0" 25, 338, 81, 14, 10 + LTEXT "2_0" 26, 338, 93, 14, 10 + LTEXT "2_0" 27, 338, 105, 14, 10 + LTEXT "2_0" 28, 338, 117, 14, 10 + LTEXT "2_0" 29, 338, 129, 14, 10 + LTEXT "2_0" 30, 338, 141, 14, 10 + LTEXT "2_0" 31, 338, 153, 14, 10 + LTEXT "2_0" 32, 338, 165, 14, 10 + LTEXT "2_0" 33, 456, 57, 14, 10 + LTEXT "2_0" 34, 456, 69, 14, 10 + LTEXT "2_0" 35, 456, 81, 14, 10 + LTEXT "2_0" 36, 456, 93, 14, 10 + LTEXT "2_0" 37, 456, 105, 14, 10 + LTEXT "2_0" 38, 456, 117, 14, 10 + LTEXT "2_0" 39, 456, 129, 14, 10 + LTEXT "2_0" 40, 456, 141, 14, 10 + LTEXT "2_0" 41, 102, 188, 14, 10 + LTEXT "2_0" 42, 102, 200, 14, 10 + LTEXT "2_0" 43, 102, 212, 14, 10 + LTEXT "2_0" 44, 102, 224, 14, 10 + LTEXT "2_0" 45, 102, 236, 14, 10 + LTEXT "2_0" 46, 102, 248, 14, 10 + LTEXT "2_0" 47, 102, 260, 14, 10 + LTEXT "2_0" 48, 102, 272, 14, 10 + LTEXT "2_0" 49, 220, 188, 14, 10 + LTEXT "2_0" 50, 220, 200, 14, 10 + LTEXT "2_0" 51, 220, 212, 14, 10 + LTEXT "2_0" 52, 220, 224, 14, 10 + LTEXT "2_0" 53, 220, 236, 14, 10 + LTEXT "2_0" 54, 220, 248, 14, 10 + LTEXT "2_0" 55, 220, 260, 14, 10 + LTEXT "2_0" 56, 220, 272, 14, 10 + LTEXT "2_0" 57, 338, 188, 14, 10 + LTEXT "2_0" 58, 338, 200, 14, 10 + LTEXT "2_0" 59, 338, 212, 14, 10 + LTEXT "2_0" 60, 338, 224, 14, 10 + LTEXT "2_0" 61, 338, 236, 14, 10 + LTEXT "2_0" 62, 338, 248, 14, 10 + LTEXT "2_0" 63, 338, 260, 14, 10 + LTEXT "2_0" 64, 338, 272, 14, 10 + LTEXT "1_0" 65, 422, 310, 63, 23 + LTEXT "0_2" 66, 12, 310, 63, 23 + LTEXT "0_3" 67, 79, 309, 64, 23 + LTEXT "~Spells For:" 68, 53, 15, 83, 16 + LTEXT "+" 69, 146, 15, 186, 16 + } + +993 DIALOG 10, 10, 362, 65 + STYLE WS_POPUP | WS_DLGFRAME + { + LTEXT "1_60" 1, 271, 36, 58, 20 + LTEXT "0_59" 2, 161, 36, 75, 20 + LTEXT "0_58" 3, 50, 36, 75, 20 + LTEXT "This door is locked. What do you do?" 4, 50, 8, 252, 19 + LTEXT "5_112" 5, 8, 8, 28, 36 + } + +996 DIALOG 10, 10, 461, 206 + STYLE WS_POPUP | WS_DLGFRAME + { + LTEXT "~Alchemy known:" 1, 54, 10, 163, 15 + LTEXT "5_720" 2, 6, 6, 36, 36 + LTEXT "1_0" 3, 356, 174, 63, 23 + LTEXT "2_0" 4, 217, 33, 14, 10 + LTEXT "2_0" 5, 217, 47, 14, 10 + LTEXT "2_0" 6, 217, 61, 14, 10 + LTEXT "2_0" 7, 217, 75, 14, 10 + LTEXT "2_0" 8, 217, 89, 14, 10 + LTEXT "2_0" 9, 217, 103, 14, 10 + LTEXT "2_0" 10, 217, 117, 14, 10 + LTEXT "2_0" 11, 217, 131, 14, 10 + LTEXT "2_0" 12, 217, 145, 14, 10 + LTEXT "2_0" 13, 217, 159, 14, 10 + LTEXT "2_0" 14, 402, 33, 14, 10 + LTEXT "2_0" 15, 402, 47, 14, 10 + LTEXT "2_0" 16, 402, 61, 14, 10 + LTEXT "2_0" 17, 402, 75, 14, 10 + LTEXT "2_0" 18, 402, 89, 14, 10 + LTEXT "2_0" 19, 402, 103, 14, 10 + LTEXT "2_0" 20, 402, 117, 14, 10 + LTEXT "2_0" 21, 402, 131, 14, 10 + LTEXT "2_0" 22, 402, 145, 14, 10 + LTEXT "2_0" 23, 402, 159, 14, 10 + LTEXT "Number in ( ) is minimum skill to make." 24, 8, 179, 199, 16 + } + +997 DIALOG 10, 10, 296, 234 + STYLE WS_POPUP | WS_DLGFRAME + { + LTEXT "5_724" 2, 6, 6, 36, 36 + LTEXT "1_0" 3, 199, 202, 63, 23 + LTEXT "0_2" 4, 55, 202, 63, 23 + LTEXT "0_3" 5, 124, 202, 63, 23 + LTEXT "7_0" 6, 55, 17, 179, 16 + LTEXT "=" 7, 17, 55, 238, 129 + } + +998 DIALOG 10, 10, 326, 227 +STYLE WS_POPUP | WS_DLGFRAME +{ + LTEXT "5_0", 1, 8, 9, 28, 36 + LTEXT "~Item Info:", 2, 45, 6, 102, 16 + LTEXT "+", 3, 101, 33, 141, 16 + LTEXT "+", 4, 58, 61, 141, 16 + LTEXT "+", 5, 245, 61, 47, 16 + LTEXT "+", 6, 58, 89, 25, 15 + LTEXT "+", 7, 146, 89, 25, 15 + LTEXT "+", 8, 231, 89, 25, 15 + LTEXT "+", 9, 65, 117, 25, 16 + LTEXT "+", 10, 138, 118, 26, 16 + LTEXT "+", 11, 255, 118, 25, 16 + LTEXT "+", 12, 61, 168, 230, 16 + LTEXT "1_0", 13, 228, 191, 63, 23 + LTEXT "0_2", 14, 84, 191, 63, 23 + LTEXT "0_3", 15, 153, 191, 63, 23 + LTEXT "2_0", 16, 213, 8, 14, 10 + LTEXT "2_0", 17, 280, 8, 14, 10 + LTEXT "+", 20, 60, 142, 44, 15 +} + +999 DIALOG 10, 10, 347, 359 +STYLE WS_POPUP | WS_DLGFRAME +{ + LTEXT "~Immunities:", 1, 21, 209, 137, 16 + LTEXT "~Monster Info:", 2, 54, 7, 106, 16 + LTEXT "1_0", 3, 248, 321, 63, 23 + LTEXT "5_0", 4, 12, 8, 28, 36 + LTEXT "+", 5, 104, 32, 195, 16 + LTEXT "+", 6, 53, 59, 25, 16 + LTEXT "+", 7, 134, 59, 47, 16 + LTEXT "+", 8, 258, 59, 47, 16 + LTEXT "+", 9, 57, 85, 25, 16 + LTEXT "+", 10, 127, 85, 25, 16 + LTEXT "+", 11, 205, 85, 32, 16 + LTEXT "+", 12, 280, 85, 25, 16 + LTEXT "+", 13, 63, 111, 44, 16 + LTEXT "+", 14, 160, 111, 44, 16 + LTEXT "+", 15, 261, 111, 44, 16 + LTEXT "+", 16, 78, 137, 25, 17 + LTEXT "+", 17, 188, 137, 25, 17 + LTEXT "+", 18, 280, 137, 25, 17 + LTEXT "+", 19, 67, 165, 238, 16 + LTEXT "2_0", 20, 118, 227, 14, 10 + LTEXT "2_0", 21, 118, 242, 14, 10 + LTEXT "2_0", 22, 118, 257, 14, 10 + LTEXT "2_0", 23, 118, 272, 14, 10 + LTEXT "2_0", 24, 241, 227, 14, 10 + LTEXT "2_0", 25, 241, 242, 14, 10 + LTEXT "2_0", 26, 241, 257, 14, 10 + LTEXT "2_0", 27, 241, 272, 14, 10 + LTEXT "0_2", 28, 10, 321, 63, 23 + LTEXT "0_3", 29, 73, 321, 63, 23 + LTEXT "*(To make monsters appear in roster menu, cast Scry Monster on them.)", 30, 9, 288, 305, 28 + LTEXT "", 31, 67, 188, 238, 16 +} + +1010 DIALOG 10, 10, 570, 391 + STYLE WS_POPUP | WS_DLGFRAME + { + LTEXT "~Main statistics:" 1, 38, 99, 133, 17 + LTEXT "~Training For:" 2, 56, 8, 110, 16 + LTEXT "0_7" 3, 231, 53, 23, 20 + LTEXT "0_6" 4, 256, 53, 23, 20 + LTEXT "0_7" 5, 231, 75, 23, 20 + LTEXT "0_6" 6, 256, 75, 23, 20 + LTEXT "0_7" 7, 231, 119, 23, 20 + LTEXT "0_6" 8, 256, 119, 23, 20 + LTEXT "0_7" 9, 231, 141, 23, 20 + LTEXT "0_6" 10, 256, 141, 23, 20 + LTEXT "0_7" 11, 231, 163, 23, 20 + LTEXT "0_6" 12, 256, 163, 23, 20 + LTEXT "0_7" 13, 231, 204, 23, 20 + LTEXT "0_6" 14, 256, 204, 23, 20 + LTEXT "0_7" 15, 231, 226, 23, 20 + LTEXT "0_6" 16, 256, 226, 23, 20 + LTEXT "0_7" 17, 231, 248, 23, 20 + LTEXT "0_6" 18, 256, 248, 23, 20 + LTEXT "0_7" 19, 231, 270, 23, 20 + LTEXT "0_6" 20, 256, 270, 23, 20 + LTEXT "0_7" 21, 231, 292, 23, 20 + LTEXT "0_6" 22, 256, 292, 23, 20 + LTEXT "0_7" 23, 231, 314, 23, 20 + LTEXT "0_6" 24, 256, 314, 23, 20 + LTEXT "0_7" 25, 472, 74, 23, 20 + LTEXT "0_6" 26, 497, 74, 23, 20 + LTEXT "0_7" 27, 472, 96, 23, 20 + LTEXT "0_6" 28, 497, 96, 23, 20 + LTEXT "0_7" 29, 472, 118, 23, 20 + LTEXT "0_6" 30, 497, 118, 23, 20 + LTEXT "0_7" 31, 472, 140, 23, 20 + LTEXT "0_6" 32, 497, 140, 23, 20 + LTEXT "0_7" 33, 472, 162, 23, 20 + LTEXT "0_6" 34, 497, 162, 23, 20 + LTEXT "0_7" 35, 472, 206, 23, 20 + LTEXT "0_6" 36, 497, 206, 23, 20 + LTEXT "0_7" 37, 472, 228, 23, 20 + LTEXT "0_6" 38, 497, 228, 23, 20 + LTEXT "0_7" 39, 472, 250, 23, 20 + LTEXT "0_6" 40, 497, 250, 23, 20 + LTEXT "0_7" 41, 472, 272, 23, 20 + LTEXT "0_6" 42, 497, 272, 23, 20 + LTEXT "0_7" 43, 472, 294, 23, 20 + LTEXT "0_6" 44, 497, 294, 23, 20 + LTEXT "5_707" 45, 6, 7, 36, 36 + LTEXT "" 46, 148, 344, 75, 16 + LTEXT "" 47, 300, 344, 75, 16 + LTEXT "0_4" 48, 403, 355, 63, 25 + LTEXT "0_2" 49, 403, 329, 63, 23 + LTEXT "0_3" 50, 470, 329, 63, 23 + LTEXT "" 51, 177, 8, 166, 16 + LTEXT "" 52, 194, 56, 28, 15 + LTEXT "" 53, 194, 77, 28, 15 + LTEXT "" 54, 194, 121, 28, 15 + LTEXT "" 55, 194, 143, 28, 15 + LTEXT "" 56, 194, 165, 28, 15 + LTEXT "" 57, 194, 207, 28, 15 + LTEXT "" 58, 194, 229, 28, 15 + LTEXT "" 59, 194, 251, 28, 15 + LTEXT "" 60, 194, 272, 28, 15 + LTEXT "" 61, 194, 294, 28, 15 + LTEXT "" 62, 194, 316, 28, 15 + LTEXT "" 63, 435, 76, 28, 15 + LTEXT "" 64, 435, 98, 29, 15 + LTEXT "" 65, 435, 121, 29, 15 + LTEXT "" 66, 435, 142, 29, 15 + LTEXT "" 67, 435, 164, 29, 15 + LTEXT "" 68, 434, 208, 29, 15 + LTEXT "" 69, 434, 230, 29, 15 + LTEXT "" 70, 434, 252, 29, 15 + LTEXT "" 71, 434, 274, 29, 15 + LTEXT "" 72, 434, 296, 29, 15 + LTEXT "1_5" 73, 470, 355, 63, 25 + LTEXT "~Skill: Cost: Level:" 74, 56, 32, 228, 16 + LTEXT "~Skill: Cost: Level:" 75, 292, 32, 228, 16 + LTEXT "~Warrior Skills:" 76, 38, 185, 133, 17 + LTEXT "~Magic Skills:" 77, 292, 53, 133, 17 + LTEXT "~Other Skills:" 78, 292, 185, 133, 17 + LTEXT "*Cost: (Skill pts./Gold) Right-click for description" 79, 6, 365, 382, 16 + LTEXT "*Skill Pts.:" 80, 71, 344, 68, 16 + LTEXT "*Gold:" 81, 252, 344, 42, 16 + LTEXT "0_67" 82, 506, 6, 17, 17 + } + +1011 DIALOG 10, 10, 328, 78 + STYLE WS_POPUP | WS_DLGFRAME + { + LTEXT "1_9" 1, 236, 48, 58, 20 + LTEXT "0_61" 2, 168, 48, 58, 20 + LTEXT "5_412" 3, 6, 6, 36, 36 + LTEXT "This item is clearly someone's property. Do you steal it?" 4, 48, 6, 246, 35 + } + +1012 DIALOG 10, 10, 327, 167 +STYLE WS_POPUP | WS_DLGFRAME +{ + LTEXT "6_0", 2, 90, 33, 75, 20 + LTEXT "5_702", 3, 8, 8, 36, 36 + LTEXT "~How many?", 4, 49, 8, 163, 16 + LTEXT "1_63", 5, 141, 65, 75, 16 +} + +1013 DIALOG 10, 10, 525, 379 + STYLE WS_POPUP | WS_DLGFRAME + { + LTEXT "~Special Characteristics:" 1, 55, 9, 181, 16 + LTEXT "5_707" 2, 6, 6, 36, 36 + LTEXT "1_0" 3, 423, 349, 63, 23 + LTEXT "2_0" 4, 161, 55, 14, 10 + LTEXT "2_0" 5, 289, 55, 14, 10 + LTEXT "2_0" 6, 447, 55, 14, 11 + LTEXT "2_0" 7, 215, 97, 14, 10 + LTEXT "2_0" 8, 215, 112, 14, 10 + LTEXT "2_0" 9, 215, 127, 14, 10 + LTEXT "2_0" 10, 215, 142, 14, 10 + LTEXT "2_0" 11, 215, 157, 14, 10 + LTEXT "2_0" 12, 416, 97, 14, 10 + LTEXT "2_0" 13, 416, 112, 14, 10 + LTEXT "2_0" 14, 416, 127, 14, 10 + LTEXT "2_0" 15, 416, 142, 14, 10 + LTEXT "2_0" 16, 416, 157, 14, 10 + LTEXT "~Species:" 17, 55, 30, 65, 18 + LTEXT "" 18, 254, 352, 50, 16 + LTEXT "=Select species and traits." 19, 15, 282, 469, 59 + LTEXT "*Human (%0)" 20, 55, 53, 75, 15 + LTEXT "*Nephilim (%12)" 21, 186, 53, 75, 15 + LTEXT "*Slithzerikai (%20)" 22, 316, 53, 92, 15 + LTEXT "*Toughness (%10)" 23, 55, 95, 75, 15 + LTEXT "*Magically Apt. (%20)" 24, 55, 110, 75, 15 + LTEXT "*Ambidextrous (%8)" 25, 55, 125, 116, 15 + LTEXT "*Nimble Fingers (%10)" 26, 55, 140, 75, 15 + LTEXT "*Cave Lore (%4)" 27, 55, 155, 75, 15 + LTEXT "*Woodsman (%6)" 28, 236, 95, 126, 15 + LTEXT "*Sluggish (%-10) " 29, 55, 197, 116, 15 + LTEXT "*Magically Inept (%-8) " 30, 55, 212, 75, 15 + LTEXT "*Frail (%-8) " 31, 55, 227, 75, 15 + LTEXT "*Chronic Disease (%-20) " 32, 55, 242, 126, 15 + LTEXT "Experience needed to gain each level:" 33, 19, 352, 216, 16 + LTEXT "~Advantages" 34, 55, 74, 75, 16 + LTEXT "~Disadvantages" 35, 55, 178, 75, 16 + LTEXT "2_0" 36, 237, 198, 14, 10 + LTEXT "2_0" 37, 237, 213, 14, 10 + LTEXT "2_0" 38, 237, 228, 14, 10 + LTEXT "2_0" 39, 237, 243, 14, 10 + LTEXT "2_0" 40, 237, 258, 14, 10 + LTEXT "*Good Constitution (%10)" 41, 236, 110, 126, 15 + LTEXT "*Highly Alert (%7)" 42, 236, 125, 126, 15 + LTEXT "*Exceptional Strength (%12)" 43, 236, 140, 126, 15 + LTEXT "*Recuperation (%15)" 44, 236, 155, 126, 15 + LTEXT "*Bad Back (%-8) " 45, 55, 257, 126, 15 + LTEXT "Number in () is how much having that trait affects the experience you need to gain a level." 46, 289, 223, 204, 43 + } + +1014 DIALOG 10, 10, 355, 124 + STYLE WS_POPUP | WS_DLGFRAME + { + LTEXT "1_0" 1, 260, 93, 63, 23 + LTEXT "=Fred" 2, 47, 9, 273, 77 + LTEXT "5_0" 3, 9, 10, 28, 36 + } + +1017 DIALOG 10, 10, 243, 86 +STYLE WS_POPUP | WS_DLGFRAME +{ + LTEXT "6_0", 2, 88, 30, 100, 24 + LTEXT "~Ask about what?", 3, 55, 6, 141, 16 + LTEXT "5_708", 4, 8, 8, 36, 36 + LTEXT "1_63", 5, 146, 64, 75, 16 +} + +1018 DIALOG 10, 10, 311, 220 + STYLE WS_POPUP | WS_DLGFRAME + { + LTEXT "*Hit a button or type '1'-'6'." 1, 11, 190, 184, 18 + LTEXT "5_706" 2, 8, 8, 36, 36 + LTEXT "0_11" 3, 69, 31, 58, 20 + LTEXT "0_12" 4, 69, 56, 58, 20 + LTEXT "0_13" 5, 69, 81, 58, 20 + LTEXT "0_14" 6, 69, 106, 58, 20 + LTEXT "0_15" 7, 69, 131, 58, 20 + LTEXT "0_16" 8, 69, 156, 58, 20 + LTEXT "+" 9, 138, 35, 139, 16 + LTEXT "+" 10, 138, 60, 139, 16 + LTEXT "+ " 11, 138, 85, 139, 16 + LTEXT "+" 12, 138, 110, 139, 16 + LTEXT "+" 13, 138, 135, 139, 16 + LTEXT "+" 14, 138, 160, 139, 16 + LTEXT "~Select a PC:" 15, 49, 10, 228, 16 + LTEXT "1_5" 16, 214, 187, 63, 25 + } + +1019 DIALOG 10, 10, 512, 372 + STYLE WS_POPUP | WS_DLGFRAME + { + LTEXT "1_0" 1, 418, 339, 58, 20 + LTEXT "0_2" 2, 289, 339, 58, 20 + LTEXT "0_3" 3, 352, 339, 58, 20 + LTEXT "0_75" 4, 144, 310, 106, 20 + LTEXT "0_76" 5, 257, 310, 106, 20 + LTEXT "0_77" 6, 370, 310, 106, 20 + LTEXT "5_0" 7, 9, 10, 28, 36 + LTEXT "~Info on:" 8, 48, 6, 75, 16 + LTEXT "~" 9, 127, 6, 174, 16 + LTEXT "~Level:" 10, 48, 29, 53, 16 + LTEXT "~" 11, 103, 29, 29, 16 + LTEXT "~Experience:" 12, 134, 29, 78, 16 + LTEXT "~" 13, 215, 29, 38, 16 + LTEXT "~Next level:" 14, 258, 29, 78, 16 + LTEXT "~" 15, 339, 29, 38, 16 + LTEXT "~Statistics:" 16, 10, 51, 95, 16 + LTEXT "*" 17, 24, 70, 97, 16 + LTEXT "*" 18, 128, 70, 38, 16 + LTEXT "*" 19, 24, 88, 97, 16 + LTEXT "*" 20, 128, 88, 38, 16 + LTEXT "*" 21, 24, 106, 97, 16 + LTEXT "*" 22, 128, 106, 38, 16 + LTEXT "*" 23, 24, 129, 97, 16 + LTEXT "*" 24, 128, 129, 38, 16 + LTEXT "*" 25, 24, 147, 97, 16 + LTEXT "*" 26, 128, 147, 38, 16 + LTEXT "*" 27, 24, 165, 97, 16 + LTEXT "*" 28, 128, 165, 38, 16 + LTEXT "*" 29, 24, 183, 97, 16 + LTEXT "*" 30, 128, 183, 38, 16 + LTEXT "*" 31, 24, 201, 97, 16 + LTEXT "*" 32, 128, 201, 38, 16 + LTEXT "*" 33, 24, 219, 97, 16 + LTEXT "*" 34, 128, 219, 38, 16 + LTEXT "*" 35, 171, 70, 92, 16 + LTEXT "*" 36, 266, 70, 38, 16 + LTEXT "*" 37, 171, 88, 92, 16 + LTEXT "*" 38, 266, 88, 38, 16 + LTEXT "*" 39, 171, 106, 92, 16 + LTEXT "*" 40, 266, 106, 38, 16 + LTEXT "*" 41, 171, 124, 92, 16 + LTEXT "*" 42, 266, 124, 38, 16 + LTEXT "*" 43, 171, 142, 92, 16 + LTEXT "*" 44, 266, 142, 38, 16 + LTEXT "*" 45, 171, 165, 92, 16 + LTEXT "*" 46, 266, 165, 38, 16 + LTEXT "*" 47, 171, 183, 92, 16 + LTEXT "*" 48, 266, 183, 38, 16 + LTEXT "*" 49, 171, 201, 92, 16 + LTEXT "*" 50, 266, 201, 38, 16 + LTEXT "*" 51, 171, 219, 92, 16 + LTEXT "*" 52, 266, 219, 38, 16 + LTEXT "*" 53, 24, 242, 97, 16 + LTEXT "*" 54, 128, 242, 38, 16 + LTEXT "*Weapon 1:" 55, 314, 131, 75, 16 + LTEXT "*" 56, 325, 150, 155, 18 + LTEXT "*" 57, 325, 170, 155, 18 + LTEXT "*Weapon 2:" 58, 315, 191, 75, 16 + LTEXT "*" 59, 326, 210, 154, 18 + LTEXT "*" 60, 326, 230, 154, 18 + LTEXT "~Total encumbrance:" 61, 11, 265, 139, 17 + LTEXT "*" 62, 156, 265, 38, 16 + LTEXT "Defense skill reduces this during combat." 63, 199, 265, 250, 16 + LTEXT "Health" 64, 314, 50, 75, 16 + LTEXT "*" 65, 325, 69, 155, 18 + LTEXT "Spell Pts." 66, 314, 89, 75, 16 + LTEXT "*" 67, 325, 108, 155, 18 + LTEXT "0_89" 68, 176, 339, 106, 20 + LTEXT "=" 69, 11, 285, 387, 17 + LTEXT "~Skill Pts.:" 70, 382, 29, 62, 16 + LTEXT "~" 71, 445, 29, 32, 16 + } + +1020 DIALOG 10, 10, 338, 80 + STYLE WS_POPUP | WS_DLGFRAME + { + LTEXT "1_9" 1, 244, 46, 58, 20 + LTEXT "0_88" 2, 176, 46, 58, 20 + LTEXT "5_213" 3, 8, 9, 36, 36 + LTEXT "There is a stout wooden lever protruding from the ground here. Pull it?" 4, 50, 4, 253, 34 + } + +1021 DIALOG 10, 10, 367, 135 + STYLE WS_POPUP | WS_DLGFRAME + { + LTEXT "~Buying Food:" 2, 59, 8, 106, 17 + LTEXT "5_703" 3, 9, 8, 36, 36 + LTEXT "" 5, 103, 55, 28, 16 + LTEXT "" 7, 173, 55, 21, 16 + LTEXT "" 10, 103, 77, 63, 16 + LTEXT "0_8" 11, 200, 103, 63, 23 + LTEXT "" 13, 228, 77, 63, 16 + LTEXT "1_0" 14, 271, 103, 63, 23 + LTEXT "" 15, 120, 32, 171, 16 + LTEXT "0_26" 16, 129, 103, 63, 23 + LTEXT "~Buying:" 17, 59, 32, 55, 16 + LTEXT "~Cost:" 18, 59, 55, 39, 16 + LTEXT "~Per:" 19, 137, 55, 39, 16 + LTEXT "~food." 20, 201, 55, 39, 16 + LTEXT "~Gold:" 21, 59, 77, 39, 16 + LTEXT "~Food:" 22, 182, 77, 39, 16 + } + +1045 DIALOG 10, 10, 276, 84 + STYLE WS_POPUP | WS_DLGFRAME + { + LTEXT "1_5" 1, 182, 53, 58, 20 + LTEXT "0_62" 2, 114, 53, 58, 20 + LTEXT "5_710" 3, 6, 6, 36, 36 + LTEXT "This creature isn't hostile. |Attack anyway?" 4, 48, 6, 192, 40 + } + +1046 DIALOG 152, 16, 146, 146 +STYLE WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_VISIBLE +CAPTION "Blades of Exile Map" +{ + PUSHBUTTON "OK", 1, 102, 131, 40, 11 +} + +1047 DIALOG 10, 10, 512, 338 + STYLE WS_POPUP | WS_DLGFRAME + { + LTEXT "1_5" 1, 415, 303, 58, 20 + LTEXT "~Alchemy:" 2, 53, 8, 71, 16 + LTEXT "~For:" 3, 53, 29, 32, 16 + LTEXT "" 4, 89, 29, 165, 16 + LTEXT "5_720" 5, 8, 8, 36, 36 + LTEXT "*(Difficulty follows in parenthesis.)" 6, 5, 307, 259, 17 + LTEXT "~#" 7, 79, 54, 22, 16 + LTEXT "~Make:" 8, 109, 54, 75, 16 + LTEXT "0_35" 9, 76, 73, 23, 20 + LTEXT "" 10, 109, 75, 160, 16 + LTEXT "0_36" 11, 76, 96, 23, 20 + LTEXT "" 12, 109, 98, 160, 16 + LTEXT "0_37" 13, 76, 119, 23, 20 + LTEXT "" 14, 109, 121, 160, 16 + LTEXT "0_38" 15, 76, 142, 23, 20 + LTEXT "" 16, 109, 144, 160, 16 + LTEXT "0_39" 17, 76, 165, 23, 20 + LTEXT "" 18, 109, 167, 160, 16 + LTEXT "0_40" 19, 76, 188, 23, 20 + LTEXT "" 20, 109, 190, 160, 16 + LTEXT "0_41" 21, 76, 211, 23, 20 + LTEXT "" 22, 109, 213, 160, 16 + LTEXT "0_42" 23, 76, 234, 23, 20 + LTEXT "" 24, 109, 236, 160, 16 + LTEXT "0_43" 25, 76, 257, 23, 20 + LTEXT "" 26, 109, 259, 160, 16 + LTEXT "0_44" 27, 76, 280, 23, 20 + LTEXT "" 28, 109, 282, 160, 16 + LTEXT "0_45" 29, 278, 73, 23, 20 + LTEXT "" 30, 311, 75, 160, 16 + LTEXT "0_46" 31, 278, 96, 23, 20 + LTEXT "" 32, 311, 98, 160, 16 + LTEXT "0_47" 33, 278, 119, 23, 20 + LTEXT "" 34, 311, 121, 160, 16 + LTEXT "0_48" 35, 278, 142, 23, 20 + LTEXT "" 36, 311, 144, 160, 16 + LTEXT "0_49" 37, 278, 165, 23, 20 + LTEXT "" 38, 311, 167, 160, 16 + LTEXT "0_50" 39, 278, 188, 23, 20 + LTEXT "" 40, 311, 190, 160, 16 + LTEXT "0_90" 41, 278, 211, 23, 20 + LTEXT "" 42, 311, 213, 160, 16 + LTEXT "0_140" 43, 278, 234, 23, 20 + LTEXT "" 44, 311, 236, 160, 16 + LTEXT "0_141" 45, 278, 257, 23, 20 + LTEXT "" 46, 311, 259, 160, 16 + LTEXT "0_142" 47, 278, 280, 23, 20 + LTEXT "" 48, 311, 282, 160, 16 + LTEXT "0_67" 49, 448, 8, 58, 20 + } + +1048 DIALOG 10, 10, 358, 86 + STYLE WS_POPUP | WS_DLGFRAME + { + LTEXT "5_726" 2, 6, 6, 36, 36 + LTEXT "" 4, 54, 10, 262, 16 + LTEXT "~Gold:" 5, 53, 57, 44, 16 + LTEXT "" 6, 102, 57, 63, 16 + LTEXT "0_8" 7, 190, 54, 64, 23 + LTEXT "" 8, 102, 33, 63, 16 + LTEXT "1_5" 9, 261, 54, 63, 23 + LTEXT "~Cost:" 10, 53, 33, 44, 16 + } + +1049 DIALOG 10, 10, 338, 60 + STYLE WS_POPUP | WS_DLGFRAME + { + LTEXT "1_63" 1, 249, 30, 58, 20 + LTEXT "5_702" 2, 8, 8, 36, 36 + LTEXT "No room in your inventory." 3, 52, 4, 255, 18 + } + +1050 DIALOG 10, 10, 466, 326 + STYLE WS_POPUP | WS_DLGFRAME + { + LTEXT "1_0" 1, 371, 297, 56, 20 + LTEXT "5_707" 2, 6, 6, 36, 36 + LTEXT "~Select a graphic for your PC:" 3, 50, 6, 248, 16 + LTEXT "0_5" 4, 300, 297, 60, 20 + LTEXT "2_1" 5, 55, 29, 16, 17 + LTEXT "2_0" 6, 55, 74, 16, 18 + LTEXT "2_0" 7, 55, 119, 16, 18 + LTEXT "2_0" 8, 54, 164, 17, 18 + LTEXT "2_0" 9, 54, 209, 17, 18 + LTEXT "2_0" 10, 54, 254, 17, 18 + LTEXT "2_0" 11, 117, 29, 16, 17 + LTEXT "2_0" 12, 117, 74, 16, 18 + LTEXT "2_0" 13, 117, 119, 16, 18 + LTEXT "2_0" 14, 116, 164, 17, 18 + LTEXT "2_0" 15, 116, 209, 17, 18 + LTEXT "2_0" 16, 116, 254, 17, 18 + LTEXT "2_0" 17, 179, 30, 16, 17 + LTEXT "2_0" 18, 179, 75, 16, 18 + LTEXT "2_0" 19, 179, 120, 16, 18 + LTEXT "2_0" 20, 178, 165, 17, 18 + LTEXT "2_0" 21, 178, 210, 17, 18 + LTEXT "2_0" 22, 178, 255, 17, 18 + LTEXT "2_0" 23, 245, 30, 16, 17 + LTEXT "2_0" 24, 245, 75, 16, 18 + LTEXT "2_0" 25, 245, 120, 16, 18 + LTEXT "2_0" 26, 244, 165, 17, 18 + LTEXT "2_0" 27, 244, 210, 17, 18 + LTEXT "2_0" 28, 244, 255, 17, 18 + LTEXT "2_0" 29, 312, 30, 16, 17 + LTEXT "2_0" 30, 312, 75, 16, 18 + LTEXT "2_0" 31, 312, 120, 16, 18 + LTEXT "2_0" 32, 311, 165, 17, 18 + LTEXT "2_0" 33, 311, 210, 17, 18 + LTEXT "2_0" 34, 311, 255, 17, 18 + LTEXT "2_0" 35, 378, 30, 16, 17 + LTEXT "2_0" 36, 378, 75, 16, 18 + LTEXT "2_0" 37, 378, 120, 16, 18 + LTEXT "2_0" 38, 377, 165, 17, 18 + LTEXT "2_0" 39, 377, 210, 17, 18 + LTEXT "2_0" 40, 377, 255, 17, 18 + LTEXT "5_400" 41, 76, 29, 28, 35 + LTEXT "5_401" 42, 76, 74, 28, 35 + LTEXT "5_402" 43, 76, 119, 28, 35 + LTEXT "5_403" 44, 76, 164, 28, 35 + LTEXT "5_404" 45, 76, 209, 28, 35 + LTEXT "5_405" 46, 76, 254, 28, 35 + LTEXT "5_406" 47, 138, 29, 28, 35 + LTEXT "5_407" 48, 138, 74, 28, 35 + LTEXT "5_408" 49, 138, 119, 28, 35 + LTEXT "5_409" 50, 138, 164, 28, 35 + LTEXT "5_410" 51, 138, 209, 28, 35 + LTEXT "5_411" 52, 138, 254, 28, 35 + LTEXT "5_412" 53, 200, 30, 28, 35 + LTEXT "5_413" 54, 200, 75, 28, 35 + LTEXT "5_414" 55, 200, 120, 28, 35 + LTEXT "5_415" 56, 200, 165, 28, 35 + LTEXT "5_416" 57, 200, 210, 28, 35 + LTEXT "5_417" 58, 200, 255, 28, 35 + LTEXT "5_418" 59, 266, 30, 28, 35 + LTEXT "5_419" 60, 266, 75, 28, 35 + LTEXT "5_420" 61, 266, 120, 28, 35 + LTEXT "5_421" 62, 266, 165, 28, 35 + LTEXT "5_422" 63, 266, 210, 28, 35 + LTEXT "5_423" 64, 266, 255, 28, 35 + LTEXT "5_424" 65, 333, 30, 28, 35 + LTEXT "5_425" 66, 333, 75, 28, 35 + LTEXT "5_426" 67, 333, 120, 28, 35 + LTEXT "5_427" 68, 333, 165, 28, 35 + LTEXT "5_428" 69, 333, 210, 28, 35 + LTEXT "5_429" 70, 333, 255, 28, 35 + LTEXT "5_430" 71, 399, 30, 28, 35 + LTEXT "5_431" 72, 399, 75, 28, 35 + LTEXT "5_432" 73, 399, 120, 28, 35 + LTEXT "5_433" 74, 399, 165, 28, 35 + LTEXT "5_434" 75, 399, 210, 28, 35 + LTEXT "5_435" 76, 399, 255, 28, 35 + LTEXT "Click button to left of graphic to select." 77, 2, 308, 245, 16 + } + +1051 DIALOG 10, 10, 303, 121 +STYLE WS_POPUP | WS_DLGFRAME +{ + LTEXT "6_0", 2, 118, 36, 148, 19 + LTEXT "5_707", 3, 8, 8, 36, 36 + LTEXT "~Select a name for your PC:", 4, 53, 6, 222, 20 + LTEXT "~Name:", 5, 53, 38, 58, 16 + LTEXT "", 6, 53, 65, 217, 16 + LTEXT "1_63", 7, 209, 90, 65, 22 +} + +1053 DIALOG 10, 10, 332, 116 + STYLE WS_POPUP | WS_DLGFRAME + { + LTEXT "1_65" 1, 239, 84, 58, 20 + LTEXT "0_64" 2, 172, 84, 58, 20 + LTEXT "5_707" 3, 6, 6, 36, 36 + LTEXT "You are about to consign this character to the eternal void.||Are you sure you want to do this?" 4, 48, 6, 249, 67 + } + +1054 DIALOG 10, 10, 330, 66 + STYLE WS_POPUP | WS_DLGFRAME + { + LTEXT "1_64" 1, 239, 37, 58, 20 + LTEXT "0_65" 2, 170, 37, 58, 20 + LTEXT "5_707" 3, 6, 6, 36, 36 + LTEXT "Would you like to create another PC?" 4, 48, 6, 249, 21 + } + +1061 DIALOG 10, 10, 332, 78 + STYLE WS_POPUP | WS_DLGFRAME + { + LTEXT "1_9" 1, 239, 49, 58, 20 + LTEXT "0_66" 2, 150, 49, 78, 20 + LTEXT "5_722" 3, 6, 6, 36, 36 + LTEXT "There is a glowing portal here. " 4, 48, 6, 249, 33 + } + +1062 DIALOG 10, 10, 529, 316 +STYLE WS_POPUP | WS_DLGFRAME +{ + LTEXT "1_63", 1, 435, 299, 61, 20 + LTEXT "5_716", 2, 6, 6, 36, 36 + LTEXT "Classic Blades of Exile Beta 1 | Copyright 1997, Spiderweb Software, Inc., All rights reserved.||Blades of Exile is distributed for free under GNU General Public License version 2.", 3, 50, 6, 420, 33 + LTEXT "Comments? Questions? Bugs? Post them at the Blades section of the Irony Central Board: www.ironycentral.com/forum/", 5, 50, 226, 354, 32 + LTEXT "Blades of Exile is brought to you by Spiderweb Software - | _Where our aberrations become your reality._ |_Blades of Exile_ and Spiderweb Software are trademarks of Spiderweb Software.", 7, 50, 160, 410, 51 + LTEXT "ORIGINAL CREDITS: | Concept, Design, Programming: Jeff Vogel | Graphics: Andrew Hunter (Wormius@aol.com) | Business Manager: Mariann Krizsan (krizsan@spidweb.com)| Title Screen: James Ernest (ernest@speakeasy.org)", 8, 50, 82, 434, 67 +} + +1063 DIALOG 10, 10, 324, 58 + STYLE WS_POPUP | WS_DLGFRAME + { + LTEXT "1_63" 1, 246, 31, 58, 20 + LTEXT "5_723" 2, 6, 6, 36, 36 + LTEXT "This is not a Blades of Exile save file." 3, 50, 6, 254, 16 + } + +1064 DIALOG 10, 10, 322, 68 + STYLE WS_POPUP | WS_DLGFRAME + { + LTEXT "1_63" 1, 245, 34, 58, 20 + LTEXT "5_723" 2, 6, 6, 36, 36 + LTEXT "Loading Blades of Exile save file failed.|" 3, 50, 6, 253, 19 + } + +1065 DIALOG 10, 10, 340, 201 +STYLE WS_POPUP | WS_DLGFRAME +{ + LTEXT "1_52", 1, 248, 179, 58, 20 + LTEXT "0_5", 2, 51, 179, 58, 20 + LTEXT "5_707", 3, 8, 8, 36, 36 + LTEXT "CREATING A PARTY: |You are now going to the party creation screen. You will be given a prefabricated party. To create new characters from scratch, press the Delete button by the existing characters.", 4, 50, 3, 253, 88 + LTEXT "Slithzerikai and Nephilim get bonuses to their statistics, and characters with Mage and Priest Spell skill get bonuses to their spell points. These bonuses are added after character creation is completed.", 5, 50, 98, 255, 79 +} + +1066 DIALOG 10, 10, 336, 64 + STYLE WS_POPUP | WS_DLGFRAME + { + LTEXT "1_84" 1, 230, 31, 80, 20 + LTEXT "0_85" 2, 122, 31, 77, 20 + LTEXT "0_5" 3, 54, 31, 58, 20 + LTEXT "5_723" 4, 9, 9, 36, 36 + LTEXT "~Do you want to save before quitting?" 5, 52, 5, 254, 18 + } + +1067 DIALOG 10, 10, 336, 78 + STYLE WS_POPUP | WS_DLGFRAME + { + LTEXT "1_5" 1, 248, 46, 58, 20 + LTEXT "0_83" 2, 178, 46, 63, 20 + LTEXT "5_723" 3, 9, 9, 36, 36 + LTEXT "Warning: If you quit now, your game will be lost." 4, 51, 5, 255, 32 + } + +1069 DIALOG 10, 10, 372, 178 + STYLE WS_POPUP | WS_DLGFRAME + { + LTEXT "1_81" 1, 278, 125, 66, 20 + LTEXT "0_82" 2, 210, 125, 65, 20 + LTEXT "0_83" 3, 141, 125, 66, 20 + LTEXT "5_3732" 4, 6, 6, 36, 36 + LTEXT "Unfortunately, the latter fate is the one that just befell you. Easy come, easy go. Care to make another attempt?" 5, 85, 77, 252, 44 + LTEXT "Being an adventurer is unpredictable work. Sometimes, you becomes heroes, wealthy as Croesus and famous beyond words. And, sometimes your gnawed bones are left to dry out in some shadowy, forgotten hole." 6, 85, 6, 260, 68 + LTEXT "5_3733" 7, 42, 6, 36, 36 + LTEXT "5_3734" 8, 6, 42, 36, 36 + LTEXT "5_3735" 9, 42, 42, 36, 36 + } + +1072 DIALOG 10, 10, 535, 415 + STYLE WS_POPUP | WS_DLGFRAME + { + LTEXT "1_63" 1, 441, 391, 58, 20 + LTEXT "5_724" 2, 6, 6, 36, 36 + LTEXT "There are a wide variety of magical walls and barriers which you can create and will encounter..." 3, 60, 23, 418, 27 + LTEXT "BLADES OF EXILE HELP: MAGIC BARRIERS" 4, 50, 6, 329, 16 + LTEXT "Wall of Fire - The weakest wall. Short lived and low damage. | |Wall of Force - Does more damage than a Wall of Fire and lasts a bit longer." 5, 51, 55, 181, 86 + LTEXT "Stinking Cloud - Lasts a short time, and curses anyone who enters." 6, 51, 253, 179, 40 + LTEXT "Web - Lasts until walked through. Slows down the victim, and interfers with attacks. Pause to clean off webs. | |Antimagic Field - Spells cannot be casts while in this, nor may they be targeted into it. It fades eventually." 7, 284, 54, 219, 104 + LTEXT "Wall of Ice - Does as much damage as a Wall of Force, but lasts much longer. | |Wall of Blades - Long lasting, and does the most damage of the wall spells." 8, 51, 154, 182, 86 + LTEXT "Fire Barrier - Permanent. Only removable by Dispel Barrier spell. Damages anyone who walks into it. Blocks quickfire. |Force Barrier - Like Fire Barrier, but cannot be moved through." 9, 284, 169, 216, 81 + LTEXT "Quickfire - The most deadly of the barriers, once created it spreads through the dungeon/town destroying everything. It can only be blocked by the two barrier spells. Antimagic fields slow it down." 10, 49, 348, 449, 41 + LTEXT "5_1709" 11, 15, 59, 28, 36 + LTEXT "5_1708" 12, 15, 108, 28, 36 + LTEXT "5_1712" 13, 15, 158, 28, 36 + LTEXT "5_1713" 14, 15, 207, 28, 36 + LTEXT "5_1711" 15, 15, 257, 28, 36 + LTEXT "5_1715" 16, 15, 352, 28, 36 + LTEXT "5_1705" 17, 250, 62, 28, 36 + LTEXT "5_1710" 18, 250, 123, 28, 36 + LTEXT "5_1716" 19, 250, 177, 28, 36 + LTEXT "Barrels,Crates - Can be pushed around. Have items in them sometimes." 20, 86, 309, 411, 28 + LTEXT "5_1707" 21, 15, 306, 28, 36 + LTEXT "5_1706" 22, 53, 306, 28, 36 + LTEXT "Sleep Wall - Walking through can put character to sleep. Very dangerous." 23, 284, 261, 215, 43 + LTEXT "5_1714" 24, 250, 265, 28, 36 + } + +1079 DIALOG 10, 10, 518, 410 + STYLE WS_POPUP | WS_DLGFRAME + { + LTEXT "1_63" 1, 424, 381, 58, 20 + LTEXT "5_724" 2, 8, 8, 36, 36 + LTEXT "To move, click on the terrain screen in the direction you want to move, or use the keypad. To wait, click on your party.|The buttons on the bottom act as follows:" 3, 65, 31, 422, 34 + LTEXT "BLADES OF EXILE HELP: OUTDOOR COMMANDS" 4, 52, 10, 292, 16 + LTEXT "To read a sign or search something, stand adjacent to it and look at it. To enter a town/dungeon/tower/pit. etc., move onto it." 5, 69, 209, 417, 33 + LTEXT "To board a boat, move onto it. To disembark, steer it onto land. To investigate a special (specials are marked with small white circles), move onto it. Boats cannot move diagonally." 6, 69, 292, 417, 50 + LTEXT "SECRET PASSAGES: Some walls have secret passages. To find them, walk into the wall." 7, 69, 343, 416, 33 + LTEXT "TIME SAVER: Hitting 'l' and then pressing a direction on the keypad has you look at thing right next to you in that direction. This works in towns (and for talking, etc.) too." 8, 69, 243, 416, 48 + LTEXT "5_1400" 9, 118, 78, 320, 100 + } + +1080 DIALOG 10, 10, 525, 401 + STYLE WS_POPUP | WS_DLGFRAME + { + LTEXT "1_63" 1, 432, 388, 58, 20 + LTEXT "5_724" 2, 8, 8, 36, 36 + LTEXT "To move, click on the terrain screen in the direction you want to move, or use the keypad. To wait, click on your party.|The action buttons (and the equivalent keys) are:" 3, 62, 29, 423, 48 + LTEXT "BLADES OF EXILE HELP: TOWN COMMANDS" 4, 52, 11, 292, 16 + LTEXT "To read a sign, open a chest, or search a barrel/crate/etc., stand adjacent to it and look at it. To leave town, keep moving towards the border of the map. Move into a door to open it." 5, 61, 278, 430, 48 + LTEXT "To board a boat, move onto it. To leave it, steer it onto land. |You close a door by Using it. Some doors are locked - you can pick or bash open the lock when you move into them." 6, 61, 329, 430, 51 + LTEXT "When talking, looking, or using, first click on the appropriate button, and then click on the space to act on. When looking, you can click on the terrain screen border to scroll the view." 7, 61, 227, 428, 49 + LTEXT "5_1402" 8, 107, 87, 320, 100 + } + +1081 DIALOG 10, 10, 590, 412 + STYLE WS_POPUP | WS_DLGFRAME + { + LTEXT "1_63" 1, 500, 403, 58, 20 + LTEXT "5_724" 2, 9, 9, 36, 36 + LTEXT "Your PCs will act one at a time. To move, click on the terrain screen in the direction you want to move, or use the keypad. To have the PC stand ready, click on him/her. |The buttons on the bottom act as follows:" 3, 66, 26, 473, 49 + LTEXT "BLADES OF EXILE HELP: COMBAT COMMANDS" 4, 53, 9, 322, 16 + LTEXT "Outdoors, you can only end combat when all foes are dead.|In an outdoor combat, to flee, move everyone off the border of the battlefield. To flee in town, leave combat mode and leave town." 5, 66, 348, 476, 49 + LTEXT "Make Active - This either makes only current character active, or switches back to having entire party active.|" 6, 66, 206, 475, 35 + LTEXT "Each PC gets a base 4 action pts. Each action uses some up. Heavy armor and being webbed or slowed reduces the total, and being hasted increases it. The cost of each action is ..." 7, 23, 260, 257, 81 + LTEXT "5_1401" 8, 147, 79, 320, 100 + LTEXT "5_1300" 9, 284, 242, 275, 100 + } + +1082 DIALOG 10, 10, 504, 365 + STYLE WS_POPUP | WS_DLGFRAME + { + LTEXT "1_63" 1, 405, 342, 58, 20 + LTEXT "5_724" 2, 8, 8, 36, 36 + LTEXT "BLADES OF EXILE HELP: PARTY STATUS SCREEN" 3, 52, 12, 235, 16 + LTEXT "This area lists the names of your party members, their health and magic points, and two buttons:" 4, 61, 29, 394, 33 + LTEXT "After each PCs name are graphics to show its status:" 5, 61, 151, 379, 16 + LTEXT "5_1200" 6, 168, 66, 75, 16 + LTEXT "To have two PCs switch places, click on their switch places buttons. To get a full description of a character, click on the '?' button." 7, 61, 102, 401, 46 + LTEXT "5_1500" 8, 73, 173, 386, 94 + LTEXT "Active PC: The character whose name is in italics is the active character. This is the PC who will cast spells selected from the cast spells menus. and who is shopping in stores. To make a PC active, click on its name or type '1'-'6." 9, 61, 276, 401, 65 + } + +1084 DIALOG 10, 10, 559, 269 + STYLE WS_POPUP | WS_DLGFRAME + { + LTEXT "1_63" 1, 471, 242, 58, 20 + LTEXT "5_724" 2, 6, 6, 36, 36 + LTEXT "~Bugs and Stuff:" 3, 50, 6, 131, 18 + LTEXT "Need a Hint?" 4, 50, 69, 84, 13 + LTEXT "To order Blades of Exile, click on How To Order on the title screen to get full ordering instructions." 5, 50, 139, 473, 28 + LTEXT "COMMENTS: |We LOVE to hear what you have to say. Comments, questions, complaints, etc. can be sent to the addresses on the About Blades of Exile page. Also, be sure to visit Spiderweb Software's web site: || http://www.spidweb.com" 6, 50, 174, 480, 65 + LTEXT "Alas, though we tried, we probably didn't get all the bugs and typos out of Blades of Exile. Should you find one, a bug report form is enclosed with the game. Also, an E-mail address for comments is on the About Blades of Exile page." 7, 50, 26, 475, 41 + LTEXT "Can't get into the School of Magery? The Valley plague getting you down? Can't get to the end of the Za-Khazi Run in time? Help is available! When you register, the documentation comes with a hint book for the 3 Blades of Exile scenarios!" 8, 50, 84, 474, 54 + } + +1086 DIALOG 10, 10, 338, 76 + STYLE WS_POPUP | WS_DLGFRAME + { + LTEXT "1_80" 1, 246, 46, 58, 20 + LTEXT "0_79" 2, 177, 46, 58, 20 + LTEXT "You have come to a dock/bridge. Pilot under it or land?" 3, 50, 3, 254, 32 + LTEXT "5_302" 4, 6, 6, 36, 36 + } + +1088 DIALOG 10, 10, 535, 418 + STYLE WS_POPUP | WS_DLGFRAME + { + LTEXT "1_63" 1, 442, 389, 58, 20 + LTEXT "5_724" 2, 6, 6, 36, 36 + LTEXT "There are two sorts of magic spells: mage spells and priest spells. There are 62 spells of each type, each with a level from one to seven." 3, 60, 23, 427, 28 + LTEXT "BLADES OF EXILE HELP: MAGIC" 4, 50, 6, 235, 16 + LTEXT "You can only cast mage (or priest) spells of a level as high as your Mage (or Priest) Spells skill. There are two ways to cast a spell:" 5, 60, 52, 420, 28 + LTEXT "Mage spells cannot be cast by someone wearing bulky armor (although armor can be put on after you're through casting spells). |WARNING: Spells cast by a PC with 1, 2 or 3 intelligence will be very weak!" 6, 60, 277, 438, 54 + LTEXT "You start automatically knowing most spells up to level 3. Other spells you have to track down. Some are known by sages who can teach them to you (for a price). Others must be found in dungeons and ruins." 7, 60, 235, 438, 41 + LTEXT "When you decide to cast a spell, you will be a given a list of spells with green lights next to the spells you are currently able to cast (and not those that you are, say, too low a level to cast)." 8, 60, 193, 436, 41 + LTEXT "Note that spell effects are cumulative. Two poison spells do more than twice the damage of one poison spell. If a fear spell doesn't work, the next one will be more likely to. Casting 3 bless spells on a PC will make him/her a powerhouse." 9, 60, 332, 440, 54 + LTEXT "SPELL MENUS - The Cast Mage and Cast Priest menus are automatically updated to contain the spells the active PC can cast. To have a PC cast a spell, click on that PC's name to the upper right, and select the spell to cast from these menus." 10, 77, 81, 397, 54 + LTEXT "SPELL CASTING WINDOW - Press the mage or priest spell button to the lower left (or type 'm' or 'p'). Press the number of the character to cast, the button by the spell, and then the target button by the PC to cast the spell on (if needed)." 11, 77, 136, 398, 54 + } + +1089 DIALOG 10, 10, 532, 404 + STYLE WS_POPUP | WS_DLGFRAME + { + // DEFPUSHBUTTON "OK" 1, 219, 187, 31, 10, WS_GROUP + LTEXT "To get anywhere in Exile, you will need to talk at great length to the people around you. To talk to someone, click on the mouth button and then on the person to talk to." 4, 60, 27, 423, 48 + LTEXT "EXILE HELP: TALKING AND SHOPS" 5, 50, 6, 235, 16 + LTEXT "In the talk window, type the thing to ask about (always a single word) and hit enter. Everyone responds to:| 'look' 'name' 'job'|Saying 'bye' ends the conversation. " 6, 60, 77, 424, 65 + LTEXT "Talking to people is how you buy things, such as food or training. Usually, just saying 'buy' works. Sometimes, however, you have to say the specific thing they sell: if Albert says _I identify things._ ask about 'identify.'" 7, 60, 263, 436, 66 + LTEXT "Some people may provide valuable hints about what others know about. For example, if someone says _You should ask Tor about supplies,_ when you meet Tor 'supplies' should be one of the first things you ask about." 8, 60, 196, 424, 65 + LTEXT "You can figure out other things to ask the people about by picking words out of what they say. If JimBob says _I love killing Nephilim,_ 'killing' and 'Nephilim' are likely bets." 9, 60, 144, 436, 50 + LTEXT "Due to finite memory, people will generally not have more to say about everything they talk about, just the important things." 10, 60, 331, 436, 34 + } + +1090 DIALOG 10, 10, 525, 418 + STYLE WS_POPUP | WS_DLGFRAME + { + LTEXT "1_63" 1, 435, 384, 58, 20 + LTEXT "5_724" 2, 9, 9, 36, 36 + LTEXT "During your adventures, you will come across mind-boggling quantities of stuff. To pick up some of it, move your party (or active PC) near it, and hit the get button (or 'g'). Then, on the Get Item window, click on the item to grab." 3, 63, 30, 423, 64 + LTEXT "BLADES OF EXILE HELP: ITEM INFO SCREEN" 4, 53, 13, 235, 16 + LTEXT "Once there, to equip (i.e. use) or unequip (take off) an item, click on its name. Other buttons will appear enabling you do to other things:" 5, 63, 131, 283, 57 + LTEXT "Items from slain monsters normally appear unidentified. To identify them, take them to a sage (such as Habecker in Fort Emergence). Also, buying Item Lore skill sometimes makes monster's treasure appear already identified." 6, 63, 274, 429, 50 + LTEXT "Once obtained, items show up in this window. Type '1'-'6' or click on the numbered button to bring up a character's inventory. " 7, 63, 95, 424, 33 + LTEXT "5_1100" 8, 350, 136, 129, 132 + LTEXT "The Sell, ID, and Enchant buttons only appear when talking to a person who can do these things. Many shopkeepers will buy your items, and certain sages can identify and even enchant them." 9, 63, 189, 281, 84 + LTEXT "Finally, hitting the Jobs button (or typing '8') takes you to the jobs page, where you can see what jobs you currently have. Hitting the 'Spec' button (or typing '9') brings up whatever special items you have." 10, 63, 325, 427, 50 + } + +1091 DIALOG 10, 10, 333, 74 + STYLE WS_POPUP | WS_DLGFRAME + { + LTEXT "1_5" 1, 244, 45, 58, 20 + LTEXT "0_78" 2, 134, 45, 78, 20 + LTEXT "5_723" 3, 9, 9, 36, 36 + LTEXT "Starting over will delete the current party. Are you sure you want to do this?" 4, 53, 6, 249, 31 + } + +1092 DIALOG 10, 10, 580, 430 + STYLE WS_POPUP | WS_DLGFRAME + { + // DEFPUSHBUTTON "OK" 1, 242, 201, 31, 10, WS_GROUP + LTEXT "While playing Exile, you will meet many, many beings who want to kill you, both outdoors and in dungeons. When you are attacked outdoors, a battlefield will appear. When attacked in town, press the sword button to start combat. " 4, 60, 27, 482, 65 + LTEXT "EXILE HELP: COMBAT" 5, 50, 6, 235, 16 + LTEXT "During combat, each of your characters go, one after another, then the monsters act. Move into a monster to attack it. If you press the 'Active' button, only the currently active PC will act until you press it again." 6, 60, 160, 483, 50 + LTEXT "When monsters hit you, you are damaged and lose health points. When a blow would take you below 0 health, you end up at 0 health. If you take damage when at 0 health, you die. If you take a lot of damage while at 0 health, you turn to dust." 7, 60, 93, 483, 66 + LTEXT "When you use poison during combat, you poison your melee weapon or arrows (thrown weapons cannot be poisoned). The next several monsters you hit will take a lot of extra damage over time. " 8, 60, 344, 482, 49 + LTEXT "There are five sorts of weapons: edged, bashing, and pole, which are hand-to-hand weapons, and bow and thrown missile, which are missile weapons. You can buy skill in each of the five weapon types, which makes them hit more often." 9, 60, 211, 483, 66 + LTEXT "Equipping armor makes monster's blows do less damage. However, heavy armor makes you less likely to hit. Don't wear heavy armor if your weapon skill is low. You can equip two weapons, but this makes you MUCH less likely to hit." 10, 60, 278, 483, 65 + } + +1093 DIALOG 10, 10, 332, 78 +STYLE WS_POPUP | WS_DLGFRAME +{ + LTEXT "1_5", 1, 238, 42, 58, 20 + LTEXT "0_63", 2, 169, 42, 58, 20 + LTEXT "5_702", 3, 8, 8, 36, 36 + LTEXT "~This item will be gone forever. Still drop it?", 4, 51, 2, 248, 33 +} + +1095 DIALOG 10, 10, 573, 384 + STYLE WS_POPUP | WS_DLGFRAME + { + // DEFPUSHBUTTON "OK" 1, 242, 178, 31, 10, WS_GROUP + LTEXT "SCROLLING THE SCREEN - When looking in town or combat, clicking the gray border of the view screen shifts the view around. Similarly, you can target people offscreen in combat by clicking on the terrain border." 4, 60, 27, 481, 48 + LTEXT "EXILE HELP: VALUABLE INFO" 5, 50, 6, 235, 16 + LTEXT "For every (about) 100 experience a character gets, he/she gains a level. With each level comes more health and skill points. The latter may be traded at a trainer for better skills. " 6, 60, 126, 483, 50 + LTEXT "EXPERIENCE - When you kill a monster, the character striking the death blow gets a bunch of experience, and everyone else gets a lesser amount. When a monster dies of poison, everyone splits the experience." 7, 60, 76, 482, 49 + LTEXT "STORING ITEMS - Should you get too many items to carry, there are 3 places in the game where they can be stored. You only have to find them." 8, 60, 177, 489, 33 + LTEXT "SAVING MAPS - Your maps are saved in your save files. To stop doing this (and make the save files much smaller) you can turn off Saved Maps on the Preferences screen.|HELPFUL HINTS - Many useful tips are available under the 'Library' menu." 9, 60, 211, 483, 66 + LTEXT "SEARCHING - To search a barrel, crate, desk, etc. or open a chest, stand adjacent and look at it." 10, 60, 278, 483, 35 + LTEXT "HEALTH WARNING - When a blow knocks you down to 0 health, you are warned by a coughing noise." 11, 60, 314, 482, 34 + } + +1096 DIALOG 10, 10, 298, 286 + STYLE WS_POPUP | WS_DLGFRAME + { + LTEXT "5_724" 2, 8, 8, 36, 36 + LTEXT "+" 3, 55, 27, 182, 16 + LTEXT "+" 4, 70, 55, 167, 16 + LTEXT "+" 5, 109, 80, 41, 16 + LTEXT "+" 6, 215, 80, 28, 16 + LTEXT "=" 7, 21, 151, 241, 93 + LTEXT "1_0" 8, 201, 254, 63, 23 + LTEXT "0_2" 9, 22, 254, 63, 23 + LTEXT "0_3" 10, 85, 254, 64, 23 + LTEXT "+" 11, 73, 105, 167, 17 + LTEXT "*Spell Info:" 12, 55, 6, 83, 16 + LTEXT "*Name:" 13, 15, 55, 48, 16 + LTEXT "*Level/Cost:" 14, 15, 80, 87, 16 + LTEXT "*Range:" 15, 156, 80, 51, 16 + LTEXT "*When:" 16, 15, 105, 49, 17 + LTEXT "~Description:" 17, 15, 128, 89, 16 + } + +1097 DIALOG 10, 10, 299, 364 + STYLE WS_POPUP | WS_DLGFRAME + { + LTEXT "5_724" 1, 8, 8, 36, 36 + LTEXT "*" 2, 191, 90, 12, 13 + LTEXT "+" 3, 106, 30, 156, 16 + LTEXT "+" 4, 133, 57, 29, 15 + LTEXT "+" 5, 218, 57, 45, 15 + LTEXT "+" 6, 96, 83, 28, 15 + LTEXT "=" 7, 21, 130, 241, 88 + LTEXT "=" 8, 21, 250, 241, 74 + LTEXT "0_2" 9, 19, 332, 63, 23 + LTEXT "0_3" 10, 82, 332, 63, 23 + LTEXT "1_0" 11, 202, 332, 63, 23 + LTEXT "~Skill Info:" 12, 53, 6, 134, 16 + LTEXT "~Cost:" 13, 15, 57, 41, 16 + LTEXT "*Skill Pts.:" 14, 59, 57, 66, 16 + LTEXT "*Gold:" 15, 172, 57, 39, 15 + LTEXT "*Max. Level:" 16, 15, 83, 73, 16 + LTEXT "~Description:" 17, 15, 106, 75, 16 + LTEXT "~Tips:" 18, 16, 229, 75, 16 + LTEXT "*Name:" 19, 53, 30, 46, 16 + } + +1098 DIALOG 10, 10, 557, 417 + STYLE WS_POPUP | WS_DLGFRAME + { + // DEFPUSHBUTTON "Button" 1, 289, 83, 31, 10, WS_GROUP + LTEXT "5_712" 2, 9, 9, 36, 36 + LTEXT "~Select a Spell:" 3, 54, 6, 141, 18 + LTEXT "0_11" 4, 10, 81, 58, 20 + LTEXT "0_12" 5, 10, 105, 58, 20 + LTEXT "0_13" 6, 10, 129, 58, 20 + LTEXT "0_14" 7, 10, 153, 58, 20 + LTEXT "0_15" 8, 10, 177, 58, 20 + LTEXT "0_16" 9, 10, 201, 58, 20 + LTEXT "0_35" 10, 235, 82, 23, 23 + LTEXT "0_36" 11, 235, 106, 23, 23 + LTEXT "0_37" 12, 235, 130, 23, 23 + LTEXT "0_38" 13, 235, 154, 23, 23 + LTEXT "0_39" 14, 235, 178, 23, 23 + LTEXT "0_40" 15, 235, 202, 23, 23 + LTEXT "0_5" 16, 389, 394, 63, 25 + LTEXT "1_17" 17, 459, 394, 63, 25 + LTEXT "" 18, 88, 84, 122, 16 + LTEXT "" 19, 88, 108, 122, 16 + LTEXT "" 20, 88, 132, 122, 16 + LTEXT "" 21, 88, 156, 122, 16 + LTEXT "" 22, 88, 180, 122, 16 + LTEXT "" 23, 88, 204, 122, 16 + LTEXT "" 24, 265, 85, 32, 16 + LTEXT "" 25, 265, 109, 32, 16 + LTEXT "" 26, 265, 133, 32, 16 + LTEXT "" 27, 265, 156, 32, 16 + LTEXT "" 28, 265, 181, 32, 16 + LTEXT "" 29, 265, 205, 32, 16 + LTEXT "" 30, 304, 85, 32, 16 + LTEXT "" 31, 304, 109, 32, 16 + LTEXT "" 32, 304, 133, 32, 16 + LTEXT "" 33, 304, 156, 32, 16 + LTEXT "" 34, 304, 181, 32, 16 + LTEXT "" 35, 304, 205, 32, 16 + LTEXT "+Pick spell to cast." 36, 30, 400, 186, 16 + LTEXT "2_0" 37, 114, 247, 14, 10 + LTEXT "2_0" 38, 114, 261, 14, 10 + LTEXT "2_0" 39, 114, 275, 14, 10 + LTEXT "2_0" 40, 114, 289, 14, 10 + LTEXT "2_0" 41, 114, 303, 14, 10 + LTEXT "2_0" 42, 114, 317, 14, 10 + LTEXT "2_0" 43, 114, 331, 14, 10 + LTEXT "2_0" 44, 114, 345, 14, 10 + LTEXT "2_0" 45, 114, 359, 14, 10 + LTEXT "2_0" 46, 114, 373, 14, 10 + LTEXT "2_0" 47, 247, 247, 14, 10 + LTEXT "2_0" 48, 247, 261, 14, 10 + LTEXT "2_0" 49, 247, 275, 14, 10 + LTEXT "2_0" 50, 247, 289, 14, 10 + LTEXT "2_0" 51, 247, 303, 14, 10 + LTEXT "2_0" 52, 247, 317, 14, 10 + LTEXT "2_0" 53, 247, 331, 14, 10 + LTEXT "2_0" 54, 247, 345, 14, 10 + LTEXT "2_0" 55, 247, 359, 14, 10 + LTEXT "2_0" 56, 247, 373, 14, 10 + LTEXT "2_0" 57, 379, 247, 14, 10 + LTEXT "2_0" 58, 379, 261, 14, 10 + LTEXT "2_0" 59, 379, 275, 14, 10 + LTEXT "2_0" 60, 379, 289, 14, 10 + LTEXT "2_0" 61, 379, 303, 14, 10 + LTEXT "2_0" 62, 379, 317, 14, 10 + LTEXT "2_0" 63, 379, 331, 14, 10 + LTEXT "2_0" 64, 379, 345, 14, 10 + LTEXT "2_0" 65, 379, 359, 14, 10 + LTEXT "2_0" 66, 379, 373, 14, 10 + LTEXT "2_0" 67, 508, 247, 14, 10 + LTEXT "2_0" 68, 508, 261, 14, 10 + LTEXT "2_0" 69, 508, 275, 14, 10 + LTEXT "2_0" 70, 508, 289, 14, 10 + LTEXT "2_0" 71, 508, 303, 14, 10 + LTEXT "2_0" 72, 508, 317, 14, 10 + LTEXT "2_0" 73, 508, 331, 14, 10 + LTEXT "2_0" 74, 508, 345, 14, 10 + LTEXT "0_25" 75, 281, 394, 102, 25 + LTEXT "~Caster:" 76, 9, 60, 75, 16 + LTEXT "~Target: HP: SP: Status:" 77, 209, 60, 223, 16 + LTEXT "Keyboard: Type '1'-'6' to pick caster, Shift-'1' - '6' to select target, 'space' for Other Spells, key by spell to cast spell. Right-click spell name for description." 78, 202, 0, 290, 57 + LTEXT "0_67" 79, 506, 6, 17, 17 + LTEXT "*" 80, 10, 227, 100, 16 + LTEXT "*" 81, 132, 227, 100, 16 + LTEXT "*" 82, 266, 227, 100, 16 + LTEXT "*" 83, 396, 227, 100, 16 + } + +1099 DIALOG 10, 10, 470, 510 +STYLE WS_POPUP | WS_DLGFRAME +{ + LTEXT "1_63", 1, 354, 480, 58, 20 + LTEXT "0_5", 2, 281, 480, 62, 20 + LTEXT "", 3, 64, 48, 277, 102 + LTEXT "2_0", 4, 147, 88, 16, 18 + LTEXT "2_0", 5, 72, 55, 16, 18 + LTEXT "2_0", 6, 213, 55, 16, 18 + LTEXT "2_0", 7, 72, 126, 16, 18 + LTEXT "2_0", 8, 213, 126, 16, 18 + LTEXT "2_0", 9, 66, 159, 16, 18 + LTEXT "~Display alignment:", 10, 59, 26, 182, 17 + LTEXT "*Top Left", 11, 90, 53, 54, 16 + LTEXT "*Top Right", 12, 231, 53, 62, 16 + LTEXT "*Bottom Left ", 13, 90, 124, 104, 16 + LTEXT "*Bottom Right", 14, 231, 124, 104, 16 + LTEXT "*Center", 15, 165, 86, 75, 16 + LTEXT "~Blades of Exile Preferences:", 16, 49, 6, 218, 16 + LTEXT "*Small Window (not full screen)", 17, 86, 157, 228, 15 + LTEXT "2_0", 18, 53, 282, 17, 18 + LTEXT "*Don't Save Maps", 19, 72, 278, 120, 16 + LTEXT "2_0", 20, 228, 280, 17, 18 + LTEXT "*No Sounds", 21, 247, 278, 117, 16 + LTEXT "2_0", 22, 58, 241, 17, 18 + LTEXT "*No graphics frills (lose special effects)", 23, 77, 236, 335, 16 + LTEXT "2_0", 24, 53, 300, 17, 18 + LTEXT "*Show room description more than once", 25, 72, 296, 287, 16 + LTEXT "5_716", 26, 8, 8, 36, 36 + LTEXT "2_0", 27, 53, 318, 17, 18 + LTEXT "*Never show instant help", 28, 72, 314, 306, 15 + LTEXT "2_0", 29, 53, 336, 17, 18 + LTEXT "*Reset instant help (all help windows will reappear)", 30, 72, 332, 340, 16 + LTEXT "~Game speed:", 31, 54, 181, 182, 17 + LTEXT "2_0", 32, 69, 202, 17, 18 + LTEXT "*Fast", 33, 88, 200, 53, 16 + LTEXT "2_0", 34, 151, 202, 17, 18 + LTEXT "*Medium", 35, 170, 200, 53, 16 + LTEXT "2_0", 36, 244, 202, 17, 18 + LTEXT "*Slow", 37, 263, 200, 53, 16 + LTEXT "2_0", 38, 53, 354, 17, 18 + LTEXT "*Make game easier (monsters much weaker)", 39, 72, 350, 352, 16 + LTEXT "2_0", 40, 53, 372, 17, 18 + LTEXT "*Fewer wandering monsters", 41, 72, 368, 340, 16 + LTEXT "~For older machines:", 42, 54, 221, 182, 17 + LTEXT "2_0", 43, 58, 262, 17, 18 + LTEXT "*Turn off terrain animation", 44, 77, 254, 147, 16 + LTEXT "2_0", 45, 233, 262, 17, 18 + LTEXT "*Turn off frills on shore", 46, 252, 254, 167, 16 + LTEXT "2_0", 47, 328, 202, 17, 18 + LTEXT "*Quite Slow", 48, 347, 200, 70, 16 + LTEXT "2_0", 50, 53, 390, 17, 18 + LTEXT "*No targeting line (use if getting crashes)", 51, 72, 386, 353, 16 + LTEXT "2_0", 52, 53, 408, 17, 18 + LTEXT "*Fewer sounds (use if getting crashes)", 53, 72, 404, 340, 16 + LTEXT "2_0", 54, 53,426,17,18 + LTEXT "*Picture and music at startup",55,72,422,340,16 + LTEXT "2_0", 56, 53 , 444,17,18 + LTEXT "*Faster Boom Space Effects",57,72,440,340,16 + LTEXT "2_0", 58, 53, 462,17,18 + LTEXT "*Use Darker (Mac) Graphics (Restart the game after changing)",59,72,458,340,16 +} +1100 DIALOG 10, 10, 450, 451 +STYLE WS_POPUP | WS_DLGFRAME +{ + LTEXT "1_63", 1, 354, 422, 58, 20 + LTEXT "0_5", 2, 281, 422, 62, 20 + LTEXT "5_716", 3, 8, 8, 36, 36 + LTEXT "Blades of Exile", 4, 49, 6, 182, 17 + LTEXT "Compatibility Options:", 5, 54, 26, 182, 17 + LTEXT "Legacy Day Reached (+20 days to specified day)", 6, 70 ,62 ,182 ,17 + LTEXT "2_0", 7, 49, 66, 17, 18 + LTEXT "Legacy Kill Node (Kills empty PC slots)", 8, 70 ,82 ,182 ,17 + LTEXT "2_0", 9, 49, 86, 17, 18 + LTEXT "Waterfalls won't work on Town (Legacy behavior)", 10, 70 ,102 ,182 ,17 + LTEXT "2_0", 11, 49, 106, 17, 18 + LTEXT "Display Grass Trims", 12, 70 ,122 ,182 ,17 + LTEXT "2_0", 13, 49, 126, 17, 18 +} +1101 DIALOG 10, 10, 252, 82 +STYLE WS_POPUP | WS_DLGFRAME +{ + LTEXT "6_0", 2, 90, 33, 126, 16 + LTEXT "5_716", 3, 8, 8, 36, 36 + LTEXT "~Enter Stuff Done Flag Part A (between 1 and 299):", 4, 49, 8, 163, 16 + LTEXT "1_63", 5, 190, 59, 60, 15 +} diff --git a/Win32/Blades of Exile/GAMESTR.RC b/Win32/Blades of Exile/GAMESTR.RC new file mode 100644 index 00000000..c1b0c240 --- /dev/null +++ b/Win32/Blades of Exile/GAMESTR.RC @@ -0,0 +1,2622 @@ +STRINGTABLE +{ + 301, "Cave Floor" + 302, "Cave Floor" + 303, "Grass" + 304, "Grass" + 305, "Grass" + 306, "Cave Wall" + 307, "Cave Wall" + 308, "Cave Wall" + 309, "Cave Wall" + 310, "Cave Wall" + 311, "Cave Wall" + 312, "Cave Wall" + 313, "Cave Wall" + 314, "Cave Wall" + 315, "Cave Wall" + 316, "Cave Wall" + 317, "Cave Wall" + 318, "Cave Wall" + 319, "Cave Wall" + 320, "Cave Wall" + 321, "Cave Wall" + 322, "Cave Wall" + 323, "Cave Wall" + 324, "High Mountains" + 325, "Mountains" + 326, "Mountains" + 327, "Mountains" + 328, "Mountains" + 329, "Mountains" + 330, "Mountains" + 331, "Mountains" + 332, "Mountains" + 333, "Mountains" + 334, "Mountains" + 335, "Mountains" + 336, "Mountains" + 337, "Hills" + 338, "Hills" + 339, "Hills" + 340, "Hills" + 341, "Hills" + 342, "Hills" + 343, "Hills" + 344, "Hills" + 345, "Hills" + 346, "Hills" + 347, "Hills" + 348, "Hills" + 349, "Hills" + 350, "Hills" + 351, "Water" + 352, "Water" + 353, "Water" + 354, "Water" + 355, "Water" + 356, "Water" + 357, "Water" + 358, "Water" + 359, "Water" + 360, "Water" + 361, "Water" + 362, "Water" + 363, "Water" + 364, "Small Island" + 365, "Rock in Water" + 366, "Bridge" + 367, "Bridge" + 368, "Bridge" + 369, "Bridge" + 370, "Bridge" + 371, "Bridge" + 372, "Water" + 373, "Bridge" + 374, "Bridge" + 375, "Rock in Water" + 376, "Lava" + 377, "Lava" + 378, "Waterfall" + 379, "Portal" + 380, "Rubble" + 381, "Rubble" + 382, "Rubble" + 383, "Cave Tree" + 384, "Cave Tree" + 385, "Mushrooms" + 386, "Mushrooms" + 387, "Pit/Combat Border" + 388, "Small Pool" + 389, "Swamp" + 390, "Boulder" + 391, "Swamp" + 392, "Tree" + 393, "Tree" + 394, "Small Trees" + 395, "Shrub" + 396, "Stalagmites" + 397, "Small Stalagmites" + 398, "Rubble" + 399, "Rubble" + 400, "Rubble" + 401, "Wall" + 402, "Wall" + 403, "Wall (w. Secret Door)" + 404, "Wall w. Door" + 405, "Wall w. Door" + 406, "Wall w. Door" + 407, "Wall w. Door" + 408, "Open Door" + 409, "Closed Portcullis" + 410, "Open Portcullis" + 411, "Wall w. Sign" + 412, "Cracked Wall" + 413, "Moldy Wall" + 414, "Wall" + 415, "Wall w. Crossed Weapons" + 416, "Wall w. Painting" + 417, "Wall w. Window" + 418, "Basalt Wall" + 419, "Basalt Wall" + 420, "Basalt Wall w. Secret Door" + 421, "Basalt Wall w. Door" + 422, "Basalt Wall w. Door" + 423, "Basalt Wall w. Door" + 424, "Basalt Wall w. Door" + 425, "Basalt Wall w. Open Door" + 426, "Basalt Wall w. Closed Portcullis" + 427, "Basalt Wall w. Open Portcullis" + 428, "Basalt Wall w. Runes" + 429, "Cracked Basalt Wall" + 430, "Moldy Basalt Wall" + 431, "Basalt Wall" + 432, "Basalt Wall w. Window" + 433, "Adobe Wall" + 434, "Adobe Wall" + 435, "Adobe Wall w. Secret Door" + 436, "Adobe Wall w. Door" + 437, "Adobe Wall w. Door" + 438, "Adobe Wall w. Door" + 439, "Adobe Wall w. Door" + 440, "Adobe Wall w. Open Door" + 441, "Adobe Wall w. Closed Portcullis" + 442, "Adobe Wall w. Open Portcullis" + 443, "Adobe Wall w. Sign" + 444, "Cracked Adobe Wall" + 445, "Moldy Adobe Wall" + 446, "Adobe Wall" + 447, "Adobe Wall w. Grisly Trophy" + 448, "Adobe Wall w. Window" + 449, "Stone Fence" + 450, "Stone Fence" + 451, "Floor" + 452, "Floor" + 453, "Floor" + 454, "Floor w. Runes" + 455, "Pedestal" + 456, "Desk" + 457, "Counter" + 458, "Counter" + 459, "Counter" + 460, "Book on Pedestal" + 461, "Pillar" + 462, "Potted Plant" + 463, "Statue" + 464, "Statue" + 465, "Bookshelf" + 466, "Brazier" + 467, "Good Altar" + 468, "Chest" + 469, "Chair" + 470, "Chair" + 471, "Chair" + 472, "Chair" + 473, "Bed" + 474, "Throne" + 475, "Dresser" + 476, "Table w. Food" + 477, "Table w. Food" + 478, "Table" + 479, "Table" + 480, "Counter" + 481, "Counter" + 482, "Counter" + 483, "Cauldron" + 484, "Dark Altar" + 485, "Rug" + 486, "Anvil" + 487, "Tile Floor" + 488, "Tile Floor" + 489, "Good Altar" + 490, "Dark Altar" + 491, "Brazier" + 492, "Throne" + 493, "Pillar" + 494, "Green Tile Floor" + 495, "Vahnatai Statue" + 496, "Sleeping Pad" + 497, "Round Rug" + 498, "Crystal Box" + 499, "Pedestal w. Crystal" + 500, "Case" + 501, "Green Tile Floor w. Runes" + 502, "Delicate Seat" + 503, "Stone Table" + 504, "Stone Table" + 505, "Stone Table" + 506, "Stone Table" + 507, "Stone Table" + 508, "Fire Pit" + 509, "Box" + 510, "Body" + 511, "Pile of Filth" + 512, "Bonfire" + 513, "Bedding" + 514, "Sign" + 515, "Obelisk" + 516, "Totems" + 517, "Statue" + 518, "Town" + 519, "Tower" + 520, "Town" + 521, "Small Building" + 522, "City" + 523, "Cavern" + 524, "Cavern" + 525, "Cavern" + 526, "Cavern" + 527, "Pit" + 528, "Tower" + 529, "Stone Fence" + 530, "Stone Fence" + 531, "City" + 532, "City" + 533, "Road" + 534, "Road" + 535, "Road" + 536, "Torch on Wall" + 537, "Torch on Wall" + 538, "Special Encounter" + 539, "Special Encounter" + 540, "Special Encounter" + 541, "Special Encounter" + 542, "Special Encounter" + 543, "Special Encounter" + 544, "Lever (set to the right)" + 545, "Lever (set to the left)" + 546, "Walkway" + 547, "Walkway" + 548, "Conveyor Belt" + 549, "Conveyor Belt" + 550, "Conveyor Belt" + 551, "Conveyor Belt" + 552, "Crops" + 553, "Sign on Grass" + 554, "Huge Wall" + 555, "Huge Wall" + 601, "Townsperson" + 602, "Townsperson" + 603, "Townsperson" + 604, "Townsperson" + 605, "Townsperson" + 606, "Townsperson" + 607, "Townsperson" + 608, "Townsperson" + 609, "Child" + 610, "Child" + 611, "Beggar" + 612, "Guard" + 613, "Soldier" + 614, "Captain" + 615, "Champion" + 616, "Bladesman" + 617, "Empire Dervish" + 618, "Brigand" + 619, "Archer" + 620, "Empire Archer" + 621, "Acolyte" + 622, "Priest" + 623, "High Priest" + 624, "Evil Acolyte" + 625, "Evil Priest" + 626, "Evil High Priest" + 627, "Apprentice Mage" + 628, "Mage" + 629, "Wizard" + 630, "Order Mage" + 631, "Witch" + 632, "Witch" + 633, "Official" + 634, "Official" + 635, "Assassin" + 636, "Monk" + 637, "Mad Monk" + 638, "Goblin" + 639, "Goblin Fighter" + 640, "Nephil" + 641, "Nephil Warrior" + 642, "Nephil Archer" + 643, "Nephil Shaman" + 644, "Nephil Chief" + 645, "Ogre" + 646, "Ogre Mage" + 647, "Slith" + 648, "Slith Warrior" + 649, "Slith Priest" + 650, "Slith Mage" + 651, "Slith High Priest" + 652, "Slith Archmage" + 653, "Slith Chief" + 654, "Cave Giant" + 655, "Giant Shaman" + 656, "Giant Chief" + 657, "Mutant Giant" + 658, "Skeleton" + 659, "Ruby Skeleton" + 660, "Zombie" + 661, "Ghost" + 662, "Ghoul" + 663, "Ghast" + 664, "Quickghast" + 665, "Spirit" + 666, "Wight" + 667, "Spectre" + 668, "Vampire" + 669, "Lich" + 670, "Hraithe" + 671, "Vahnavoi" + 672, "Giant Lizard" + 673, "Fire Lizard" + 674, "Ice Lizard" + 675, "Cave Slime" + 676, "Ice Slime" + 677, "Viscous Goo" + 678, "Cave Rat" + 679, "Vapor Rat" + 680, "Mung Rat" + 681, "Shambler" + 682, "Bat" + 683, "Drake" + 684, "Imp" + 685, "Demon" + 686, "Mung Demon" + 687, "Haakai" + 688, "Hordling" + 689, "Vahnatai" + 690, "Vahnatai Child" + 691, "Vahnatai Warrior" + 692, "Vahnatai Warrior" + 693, "Vahnatai Shaper" + 694, "Vahnatai Shaper" + 695, "Vahnatai Keeper" + 696, "Vahnatai Keeper" + 697, "Vahnatai Blademaster" + 698, "Vahnatai Lord" + 699, "Serpent" + 700, "Asp" + 701, "Gazer" + 702, "Eyebeast" + 703, "Basilisk" + 704, "Ur-Basilisk" + 705, "Statue" + 706, "Living Statue" + 707, "Crystal Soul" + 708, "Lizard" + 709, "Cat" + 710, "Dog" + 711, "Cave Cow" + 712, "Cow" + 713, "Chicken" + 714, "Sheep" + 715, "Wolf" + 716, "Worg" + 717, "Bear" + 718, "Giant Spider" + 719, "Talking Spider" + 720, "Gremlin" + 721, "Black Shade" + 722, "Guardian" + 723, "Doomguard" + 724, "Poison Fungi" + 725, "Shade" + 726, "Deva" + 727, "Salamander" + 728, "Ice Drake" + 729, "Ice Pudding" + 730, "Chitrach" + 731, "Chitrach Larva" + 732, "Null Bug" + 733, "Giant Slug" + 734, "Spore Beast" + 735, "Rakshasa" + 736, "Naga" + 737, "Efreet" + 738, "Amber Slime" + 739, "Ochre Slime" + 740, "Emerald Slime" + 741, "Mauve Slime" + 742, "Alien Slime" + 743, "Cockroach" + 744, "Large Roach" + 745, "Giant Roach" + 746, "Mung Roach" + 747, "Guardian Roach" + 748, "Big Roach" + 749, "Troglodyte" + 750, "Troglodyte Warrior" + 751, "Troglodyte Shaman" + 752, "Troglodyte Khazi" + 753, "Troglodyte Defender" + 754, "Troglodyte Lord" + 755, "Hill Giant" + 756, "Hill Giant Fighter" + 757, "Hill Giant Shaman" + 758, "Hill Giant Chief" + 759, "Golem of Blades" + 760, "Fire Golem" + 761, "Ice Golem" + 762, "Jeweled Golem" + 763, "Demon Golem" + 764, "Power Crystal" + 765, "Mind Crystal" + 766, "Alien Beast" + 767, "Pack Leader" + 768, "Dark Wyrm" + 769, "Dryad" + 770, "Drake Lord" + 771, "Spiny Worm" + 772, "Ursag" + 773, "Gorgon" + 774, "Unicorn" + 775, "Slime Zombie" + 776, "Mung Slime" + 777, "Rentar-Ihrno" + 778, "Athron" + 779, "Sulfras" + 780, "Erika" + 781, "Chevyn" + 782, "Solberg" + 783, "Prazak" + 784, "Khoth" + 785, "Gunston" + 786, "Carol" + 787, "Jordan" + 788, "Elhioc" + 789, "Siobahn" + 790, "Eurydice" + 1501, "This makes you more resistant to damage. Blows of all sorts have less of an effect on you." + 1502, "The possessor of this advantage will find that his or her spells will function better. This helps both Priest and Mage spells." + 1503, "An ambidextrous warrior will be able to use one weapon in each hand without any penalties. Normally, using two weapons makes both of them much less likely to hit." + 1504, "Having nimble fingers improves one's chances of picking locks and disarming traps." + 1505, "When underground, knowledge of Cave Lore helps one hunt and forage for food and deal better with special circumstances." + 1506, "When roaming the surface of the world, a Woodsman is able to hunt and bring down food, find useful herbs, and deal with circumstances involving nature's adversity." + 1507, "Someone with a Good Constitution will find that poison and disease have a reduced (although not eliminated) effect." + 1508, "Highly Alert people have the edginess that helps them resist magical sleep. In addition, having someone in your group who is Highly Alert may help keep you from being surprised." + 1509, "An Exceptionally Strong character will be able to carry much more stuff, and, in addition, will do a small amount more damage in combat." + 1510, "A very few adventurers have magical blood running in their veins, causing them to heal damage to their bodies at an amazing rate." + 1511, "Sluggish characters just can't move that quickly, even when circumstances seem to demand it. A sluggish character gets fewer action points in combat." + 1512, "Magically Inept characters, for some reason, resist the effects of magical items, and are unable to use them. Potions and scrolls won't work for them at all, although worn items, such as rings and armor, will have a small effect." + 1513, "Frail characters are cursed at birth with a weak constitution. Poison and disease will have a greater effect on such characters." + 1514, "Chronic Disease is the worst disadvantage a character may possess. Such characters have a slow, lingering, incurable physical ailment, causing them to occasionally suffer the effects of a mild disease." + 1515, "A character with a Bad Back cannot bear to haul too much weight. Such a person cannot carry as much as he or she might have been able to otherwise." + 1516, "Human is the default species in Blades of Exile. Humans have skins of a variety of hues, and are soft, generally fragile, and incredibly resourceful." + 1517, "The Nephilim are a race of feline humanoids. Once common on the surface world, they have been hunted to near extinction, although some now remain in Exile. Nephilim characters start with better dexterity, and are much better at using missile weapons." + 1518, "The Slithzerikai (sliths for short) are a race of lizard men, both strong and smart. Once unknown on the surface world, they are starting to appear there. Slith characters get bonuses to strength and intelligence, and are better at using pole weapons." + 1519, "Blades of Exile Prefs" + 2101, "Light" + 2102, "Creates a weak light." + 2103, "Spark" + 2104, "Fires a weak bolt of electricity at an enemy." + 2105, "Minor Haste" + 2106, "Makes the selected PC move faster for a while. All haste spells take effect at the beginning of the next round." + 2107, "Strength" + 2108, "Makes the selected PC more skilled for a short time. Works like the priest spell 'Bless.'" + 2109, "Scare" + 2110, "Decreases the morale of the victim. Casting this on a weak foe will make the foe flee. Even if the monster doesn't flee, later castings have a higher chance of success." + 2111, "Flame Cloud" + 2112, "This spell fills the selected space with a short-lasting wall of fire." + 2113, "Identify" + 2114, "This draining spell identifies all the unidentified items being held by your characters." + 2115, "Scry Monster" + 2116, "This spell is cast during combat. When cast, you receive information about the monster you target: current health, spell points, morale, etc." + 2117, "Goo" + 2118, "This spell covers the target with sticky goo, slowing it down and interfering with its attacks." + 2119, "True Sight" + 2120, "This spell lets you see everything in a short radius around you, even spaces blocked off by walls. It's useful for finding secret passages, for example." + 2121, "Minor Poison" + 2122, "Poisons the target creature. This does a fair amount of damage, but it takes time to happen." + 2123, "Flame" + 2124, "Fires a decent-sized bolt of flame at the target. The damage done increases with the level of the caster." + 2125, "Slow" + 2126, "Makes the victim get half its usual number of actions for a while." + 2127, "Dumbfound" + 2128, "Makes the victim incompetent: easier to hit, easier to damage, and less able to attack you." + 2129, "Envenom" + 2130, "This spell puts poison on the weapon of the selected PC, with no chance of failure or accidental poisoning." + 2131, "Stinking Cloud" + 2132, "When cast, a 3x3 area you select becomes filled with choking gasses. Anyone entering will have far less effective attacks for a short time. The gas will slowly fade on its own." + 2133, "Summon Beast" + 2134, "This spell summons one low-level, non-magical monster to fight on your side. It disappears after a short time." + 2135, "Conflagration" + 2136, "This spell makes the air in a radius 2 circle burst into flames, charring anyone inside the cloud. After creation, the cloud will rapidly fade." + 2137, "Dispel Fields" + 2138, "This spell dispels magical fields in the selected area. It removes blade walls, ice walls, and similar fields. Note, however, that the spell doesn't work on Fire and Force Barriers." + 2139, "Sleep Cloud" + 2140, "This spell creates a small cloud of sleep gas. There is a chance that anyone passing through the cloud will fall asleep (note that some creatures, like slimes, never sleep)." + 2141, "Unlock Doors" + 2142, "Some doors are magically locked, and others are just hard to open. This spell can unlock them. However, it isn't guaranteed to succeed, and won't work on all doors." + 2143, "Haste" + 2144, "Makes the selected PC get twice the usual number of actions for a long time. All haste spells take effect at the beginning of the next round." + 2145, "Fireball" + 2146, "Fires a powerful ball of flame, which affects the target space and every adjacent space. The damage done increases with the level of the caster." + 2147, "Long Light" + 2148, "Like the first level light spell, but much more effective." + 2149, "Fear" + 2150, "Like scare, but much more powerful. " + 2151, "Wall of Force" + 2152, "This powerful spell creates a line of force walls, which are like fire walls but more damaging and lasting. Hitting the space bar while targeting makes the wall rotate." + 2153, "Weak Summoning" + 2154, "When cast, a group of monsters appears and attacks all enemies of the caster. The number of monsters depends on the level of the caster. After a time, they disappear." + 2155, "Flame Arrows" + 2156, "This spell is like flame, but the caster gets to select several targets. The number of missiles increases with the level of the caster. If you don't want to use all the missiles, hit the space bar to cast the spell." + 2157, "Web" + 2158, "This spell covers a large circle with icky webs, slowing down everyone inside. The webs last until torn down." + 2159, "Resist Magic" + 2160, "You can cast this spell on another PC to make him/her resistant to magical damage and effects. Note this does not help against damage from fire or cold." + 2161, "Poison" + 2162, "This makes poison run thick in the veins of the target. Repeated castings will have a devastating effect." + 2163, "Ice Bolt" + 2164, "Slams the target with a heavy, pointed bolt of ice. Effective against monsters who are resistant to fire. Damage increases as the level of the caster increases." + 2165, "Slow Group" + 2166, "Makes all monsters within a 12 space radius move at half speed for a time." + 2167, "Magic Map" + 2168, "When cast in town, this powerful spell gives you a vision - your map will show you the entire area. However, to cast this spell you need a sapphire." + 2169, "Capture Soul" + 2170, "This spell stores a target monster in your mind, so that it may later be created with the Simulacrum spell." + 2171, "Simulacrum" + 2172, "This spell summons a monster you have memorized using Capture Soul. The cost depends on the level of the monster being summoned." + 2173, "Venom Arrows" + 2174, "This spell is similar to Flame Arrows, except that your targets are poisoned." + 2175, "Wall of Ice" + 2176, "This spell is similar to Wall of Force, except that it creates an ice wall. Ice walls do as much damage as force walls, but last a lot longer." + 2177, "Stealth" + 2178, "This powerful spell makes monsters less likely to see you for a time (duration depends on your level). Try casting it before walking through a room crowded with monsters." + 2179, "Major Haste" + 2180, "Gives the entire party double its actions (duration depends on the level of the caster). All haste spells take effect at the beginning of the next round." + 2181, "Fire Storm" + 2182, "This spell is like fireball, but does more damage, and affects all creatures within two spaces of the space you target. Be careful not to fry your party!" + 2183, "Dispel Barrier" + 2184, "This spell has a chance (increasing with level) of destroying magical barriers. Some barriers are harder to dispel than others; some cannot be dispelled. Some barriers can be walked through." + 2185, "Fire Barrier" + 2186, "This spell creates a single fire barrier at the target space. Fire barriers are damaging and permanent." + 2187, "Summoning" + 2188, "This spell is like Minor Summoning, but summons more powerful monsters." + 2189, "Shockstorm" + 2190, "This spell creates a large sphere of force walls." + 2191, "Spray Fields" + 2192, "This spell creates a large number of small fields of a random sort, each of which may be individually targeted. The number of fields increases with the level of the caster." + 2193, "Major Poison" + 2194, "This spell makes the targeted monster very poisoned. This spell does a huge amount of damage, but it takes time to take effect." + 2195, "Group Fear" + 2196, "When cast, the caster begins to radiate a horrible aura of fear. All monsters within 12 spaces lose a lot of morale. This spell gains effectiveness rapidly with the level of the caster." + 2197, "Kill" + 2198, "The deadly Kill spell deals a devastating blow to one target you select." + 2199, "Paralyze" + 2200, "This spell affects several monsters - the number affected increases with your level and intelligence. Whoever you cast this on will be immobilized for a very long time. Powerful monsters might resist this spell." + 2201, "Daemon" + 2202, "This dangerous spell summons a beast from the netherworld to fight at your side." + 2203, "Antimagic Cloud" + 2204, "This spell creates a spherical field, from which no spells may be cast and in which no spells may be targeted. After creation, it slowly fades." + 2205, "Mindduel" + 2206, "When cast on a magic-using enemy, the two creatures get in a mental battle, absorbing spell points from each other. The loser may end up dumbfounded or killed. Requires a Smoky Crystal to cast." + 2207, "Flight" + 2208, "When cast outdoors, the party can fly for a short time." + 2209, "Shockwave" + 2210, "This spell sends a wave of force out from the caster, damaging everyone nearby. The farther someone is from the caster, the more damage is taken, out to a radius of 10. Don't cast in towns." + 2211, "Major Blessing" + 2212, "When cast, the entire party is blessed and hasted, and has their weapons mildly poisoned." + 2213, "Mass Paralysis" + 2214, "When cast, every monsters within a small radius of the caster will become paralyzed for quite some time. There is a chance they might resist the spell." + 2215, "Protection" + 2216, "One of the most powerful spells in the mage's repertoire. It makes the whole party temporarily magic resistant, and makes one PC you select immune to ALL damage for a short time." + 2217, "Major Summoning" + 2218, "This spell works like Summoning, but brings forth much more powerful creatures." + 2219, "Force Barrier" + 2220, "This spell creates an impenetrable, permanent barrier. Be careful not to trap yourself." + 2221, "Quickfire" + 2222, "Devastating beyond words, this spell creates a space of quickfire, which will sweep over the area killing everyone and everything." + 2223, "Death Arrows" + 2224, "This spell is like the previous Arrow spells, but strikes each target with a kill spell. The number of arrows increases with the level of the caster." + 2401, "Minor Bless" + 2402, "Makes the character harder to hit and take less damage from blows. It also makes the PC hit more often, and his or her blows do more damage. Its effects decay with time." + 2403, "Minor Heal" + 2404, "Increases the health of the selected PC a small amount, up to the PC's maximum health." + 2405, "Weaken Poison" + 2406, "Reduces the amount of poison running around in the veins of the selected PC." + 2407, "Turn Undead" + 2408, "When cast on an undead creature, it usually does a reasonable amount of damage to it. It has no effect on non-undead." + 2409, "Location" + 2410, "Displays the party's x-y location in the town." + 2411, "Sanctuary" + 2412, "The target of this spell becomes magically shielded. For a time, monsters probably won't be able to attack him/her. The effects disappear when the PC attacks someone." + 2413, "Symbiosis" + 2414, "This spell has the caster absorb the damage taken by another character. The higher the level, the less damage the caster takes per health point healed." + 2415, "Minor Manna" + 2416, "Casting this spell gives the party a little more food." + 2417, "Ritual - Sanctify" + 2418, "When cast on a location filled with evil magic, the location receives a blessing. This might drive out the evil magic. Then again, it might not." + 2419, "Stumble" + 2420, "The victim of this spell moves more slowly and has less effective attacks for a short time." + 2421, "Bless" + 2422, "Like Minor Bless, but better. Its effect increases with the level of the caster." + 2423, "Cure Poison" + 2424, "Like Weaken Poison, but better. Its effect increases with the level of the caster." + 2425, "Curse" + 2426, "The opposite of bless. It makes everything much worse for the victim, for a time. Hitting someone with this spell several times vastly increases the effect." + 2427, "Light" + 2428, "Creates a short duration magical light source." + 2429, "Wound" + 2430, "Deals a painful blow to the targeted victim. The damage increases with your level." + 2431, "Summon Spirit" + 2432, "This spell summons a shade from the netherworld to aid you. It will disappear after a short time." + 2433, "Move Mountains" + 2434, "When cast on a fragile wall or outcropping of rock, the wall or outcropping crumbles into rubble. It doesn't work on all walls." + 2435, "Charm Foe" + 2436, "This spell has a chance of making the target monster start to fight for the party. The chance of it working drops sharply with the level of the monster." + 2437, "Disease" + 2438, "The victim of this spell is afflicted by a disease, which slowly weakens it. The disease lasts a long time." + 2439, "Awaken" + 2440, "Casting this on a sleeping character instantly wakes that character up." + 2441, "Heal" + 2442, "A much better version of Minor Heal." + 2443, "Light Heal All" + 2444, "Casts one minor heal on each PC." + 2445, "Holy Scourge" + 2446, "This spell gives the victim a powerful curse, the effect of which increases with the level of the caster." + 2447, "Detect Life" + 2448, "This spell causes all other living things to appear on your map for a short time. Note, however, that this spell only detects creatures in areas you have explored." + 2449, "Cure Paralysis" + 2450, "This spell instantly removes the effects of paralysis." + 2451, "Manna" + 2452, "This spell magically creates a lot of food for the party." + 2453, "Forcefield" + 2454, "This spell fills an area with walls of force, which are fairly damaging and reasonably long lasting." + 2455, "Cure Disease" + 2456, "Casting this spell on a PC cures all his/her disease." + 2457, "Restore Mind" + 2458, "This spell completely unfeebleminds the recipient." + 2459, "Smite" + 2460, "This spell fires a number of bolts of divinely inspired cold, the number of which increases with the level of the caster. To cast without using all of the targets, hit the space bar." + 2461, "Cure All Poison" + 2462, "Causes everyone to become less poisoned. Useful for dealing with those nasty swamps." + 2463, "Curse All" + 2464, "Causes all monsters within ten spaces to receive a powerful curse." + 2465, "Dispel Undead" + 2466, "Deals a deadly blow to the targeted undead nasty. The chance of the spell having an effect increases with the caster's level." + 2467, "Remove Curse" + 2468, "Occasionally, you will put on an item which then refuses to be taken off. Casting this spell has a chance of removing the curse." + 2469, "Sticks to Snakes" + 2470, "This spell summons a bunch of snakes to aid the party. Skillful casters have a chance of getting asps instead of the weaker giant snakes." + 2471, "Martyr's Shield" + 2472, "When something strikes the recipient of this spell in hand-to-hand combat, it takes as much damage as the victim. The duration of this spell increases with the level of the caster." + 2473, "Cleanse" + 2474, "This spell purifies the recipient. The beneficiary is completely unwebbed, and all disease is cured." + 2475, "Firewalk" + 2476, "When cast, for a short time everyone in the party can walk across lava with no damage. The duration increases slowly with the level of the caster." + 2477, "Bless Party" + 2478, "Much like Bless, but affects everyone." + 2479, "Major Heal" + 2480, "Works like the Heal spell, but gives much more bang for the spell points." + 2481, "Raise Dead" + 2482, "This spell returns a body to life. You need Resurrection Balm to cast this. There is a small chance (decreasing with level) that it turns the body to dust. A dusted character can only be raised with a Resurrect spell. Raising a PC reduces his/her stats." + 2483, "Flamestrike" + 2484, "The first 'area of affect' offensive priest spell. It chars all beings adjacent to the space you target. The damage done increases with level." + 2485, "Mass Sanctuary" + 2486, "This spell hides all PCs (like a sanctuary spell). As before, the effect for a PC is voided when that PC attacks." + 2487, "Summon Host" + 2488, "This powerful spell summons four spirits, and a magical being to lead them. They then fight on the side of the caster for a little while. " + 2489, "Shatter" + 2490, "This spell strikes every space adjacent to the party with a Move Mountains spell." + 2491, "Dispel Fields" + 2492, "All magical walls, etc. in the large area affected by this spell will be dispelled. It has a small chance of affecting quickfire." + 2493, "Heal All" + 2494, "Like the Heal spell, but affects the whole party. Very efficient." + 2495, "Revive" + 2496, "This spell heals all damage and cures all poison for one PC." + 2497, "Hyperactivity" + 2498, "This powerful spell instantly wakes up any sleeping characters in the party. What's more, it provides total resistance to magical sleep for a short time. Finally, it speeds back up any slowed character." + 2499, "Destone" + 2500, "Certain rare monsters can turn one of your characters to stone. This valuable spell undoes the damage." + 2501, "Summon Guardian" + 2502, "This spell summons a powerful, invisible being to fight on the side of the party. Be careful not to damage it by mistake!" + 2503, "Mass Charm" + 2504, "When cast, all creatures within eight spaces of the caster have a chance of coming under his/her control." + 2505, "Protective Circle" + 2506, "A very unusual and effective spell for a party on the defensive. The caster is surrounded by several layers of magical fields, which fend off anyone attacking." + 2507, "Pestilence" + 2508, "This spell afflicts everyone within eight spaces with an effective but slow-acting disease." + 2509, "Revive All" + 2510, "When cast, the party receives a powerful healing (increasing with level of the caster) and has poison cured as well." + 2511, "Ravage Spirit" + 2512, "Demons are resistant to most magic. This spell gives them a blow which usually does a lot of damage. The chance of success increases with the level of the caster." + 2513, "Resurrect" + 2514, "Like raise dead, but much more effective, and works on even a dusted character. It also has a smaller chance of lowering the character's stats. It still requires Resurrection Balm to cast." + 2515, "Divine Thud" + 2516, "The most powerful offensive priest spell. It delivers a stunning blow of force to all beings within two spaces of the targeted space." + 2517, "Avatar" + 2518, "This spell temporarily makes the caster an invulnerable, incredibly powerful avatar of the gods. " + 2519, "Wall of Blades" + 2520, "This spell creates a wall of the most damaging (and long lasting) of the magic walls. Rotate the wall by hitting space." + 2521, "Word of Recall" + 2522, "This spell returns the party to the town where they began the scenario. Because of the danger of teleporting from narrow, windy tunnels, it can only be cast outdoors." + 2523, "Major Cleansing" + 2524, "This spell removes all webs and disease from the party." + 2701, "Strength" + 2702, "Measures how much brute strength the character possesses. High strength increases damage done in combat, improves odds of kicking down doors, and has other, more subtle effects." + 2703, "Dexterity" + 2704, "Measure how nimble the character is. High dexterity gives a better chance of hitting in combat (esp. with missile weapons) and makes the character harder to hit. High dexterity also makes picking locks and disarming traps easier." + 2705, "Intelligence" + 2706, "Measures mental strength and dexterity. High intelligence also makes your spells more effective, sometimes very much so. Intelligence below 4 makes your spells works poorly." + 2707, "Edged Weapons" + 2708, "Makes you better at using daggers, swords, axes, etc." + 2709, "Bashing Weapons" + 2710, "Makes you better at using clubs, maces, hammers, flails, etc." + 2711, "Pole Weapons" + 2712, "Makes you better at using spears of all sorts, halberds, etc." + 2713, "Thrown Missiles" + 2714, "Makes you better at using darts, javelins, and throwing axes." + 2715, "Archery" + 2716, "Makes you better at using a bow and arrows, crossbows, or slings." + 2717, "Defense" + 2718, "This skill has three effects. It determines how well a character does at parrying, decreases the penalty in combat from bulky armor, and occasionally decreases the damage taken from enemies weapons.|" + 2719, "Mage Spells" + 2720, "Having a certain level of this skill enables you to cast mage spells of up to that level." + 2721, "Priest Spells" + 2722, "Having a certain level of this skill enables you to cast priest spells of up to that level." + 2723, "Mage Lore" + 2724, "You will occasionally need to decipher strange magical readings. This skill determines how good you are at this. If your skill is high enough, you may gain a spell or a valuable piece of information." + 2725, "Alchemy" + 2726, "You will eventually gain the ability to make magic potions. To make a given potion, however, your Alchemy skill much be above a certain level. The higher it is above this level, the better the chance of succeeding." + 2727, "Item Lore" + 2728, "Having Item Lore skill gives you a chance of having the items from slain monsters be identified when you find them. The more of this skill that is present, the higher the chance of this happening." + 2729, "Disarm Traps" + 2730, "Many chests and some corridors will have traps on them, which can be devastating. The higher this skill, the better your chance of disarming them." + 2731, "Lockpicking" + 2732, "Many towns and dungeons will have locked doors. A PC with some of this skill and lock picks equipped can try to pick them. The higher this skill, the better." + 2733, "Assassination" + 2734, "Sometimes, when a character attacks a much weaker monster, the blow will do a good deal of extra damage. The more of this skill you have, the better the chance of this happening, and the stronger the monsters it can happen to." + 2735, "Poison" + 2736, "You will find poisons, which you can put on your weapons for a extra damage. Having a few levels in this skill will make it more likely you will put the poison on at full strength, and the less likely you will nick yourself with the poison accidentally." + 2737, "Luck" + 2738, "This skill is expensive, but can be a bargain at twice the cost. Its effects are pervasive, subtle, powerful, and sometimes irreplaceable." + 3001, "Welcome to Blades of Exile. These windows will pop up occasionally to explain what is going on. If they annoy you, they can be turned off in the Preferences screen (access from Options menu)." + 3002, "In general, you can get help by clicking on the '?' buttons or typing '?'. For now, you should get equipment, explore this fort, and get your orders. Press the hand buttons (or type 'g') to pick up the nearby items." + 3005, "Everyone responds to 'Look', 'Name', and 'Job' (use the buttons at the bottom). To ask about something people mention, click on the word (click on 'Demon' to ask about demons). Certain people respond to 'Buy' and 'Sell', which puts you in shopping mode. " + 3006, "Shortcuts: To get previous response, press the Back button (or hit space). You can press any of the bottom buttons by typing the first letter in the word. Hit Record to write notes in journal, and hit Bye (or type Escape) to stop talking." + 3007, "To cast a spell, first click on the number of the person to cast (to the upper left). Then click on the button by the spell to cast (hit Space to see other spells). Finally, if it's a spell cast on a party member, click on the correct Target button." + 3008, "Shortcut: Typing the letter after a spell picks the spell, and typing '1'-'6' picks a caster. Option clicking a spell button brings up a spell description. Finally, you can often cast spells faster using the Mage Spells and Priest spells menus." + 3009, "This menu always contains all the spells an active PC can cast. Click on the name of a PC to make him/her active. Then select a spell from this menu to cast. Then, if you need to pick someone to cast the spell on, a window will come up for you to do so." + 3010, "This is where you improve a character's skills when creating or training him/her. Press the '+' button to buy a skill, and the '-' button to undo the choice. The Cancel button undoes your work, and Keep keeps your choices." + 3011, "Option-click the buttons by a skill to get a description of the skill and advice on how much to buy. When training a character, you need both gold and skill points (which you get by killing things and getting experience)." + 3012, "This menu contains the monsters you have magically obtained information about. To make a monster appear here, cast Scry Monster on it." + 3020, "Sometimes, outdoors or in stores, you will find ingredients to make alchemical potions, using recipes you buy from sages in town. To make a potion, select an active PC by clicking on his/her name or typing '1'-'6'. Then access this window." + 3021, "To make a potion, click the appropriate button. The character needs a high enough alchemy skill and the right ingredient. For a full description of all potions, select Alchemy & Poison from the Library menu." + 3022, "Here is where you edit your party before beginning the game. You start with 6 pre-fabricated characters. To replace them with characters of your own, hit the delete button and then click on the 'Hit here to Create' button. " + 3023, "Press a PCs name to rename it, the Race button to edit his/her race and advantages/disadvantages, the Graphic button to pick a new graphic, and the Train button to adjust the character's starting skills. When ready to start the game, Press Done." + 3024, "You don't have enough gold on you to buy this skill. The cost to buy a level of a skill is the number after the slash in parentheses. Skills you can buy have the numbers given in red." + 3025, "You don't have enough skill points on you to buy this skill. The number of skill pts. to buy a level of a skill is the number before the slash in parentheses. To get skill points, kill enough monsters to gain a level." + 3026, "Here, you can spend your hard earned cash on miscellaneous goodies. To select a character to do the buying, click on the character's name (or type '1' - '6'). Click on the name of an item or type 'a'-'h' to buy something." + 3027, "To get info on an item (if available) click on the little 'I' button to the right of the item's name. Finally, when through shopping, hit Escape or click on the done button." + 3028, "One of your characters has just become dumbfounded. This takes your ability to cast spells. You lose higher level spells first, then lower level spells. To remove this, cast Restore Mind or visit a healer. Dumbfounding is permanent until cured." + 3029, "One of your characters has just become diseased. This slowly, gradually causes a wide variety of damaging effects. Healers and certain priest spells can cure disease, or it slowly fades over time." + 3030, "One of your characters has just magically made to fall asleep. He/she will eventually wake up, or an Awaken or Hyperactivity spell can hasten the process." + 3031, "One of your characters has just been covered with webs. This will slow the character down in combat and make his/her fighting much less effective. To clean off the webs, pause repeatedly (click on the PC or type '5' on the keypad)." + 3032, "One of your characters has just been paralyzed. He/she will not be able to move for quite some time. This can be cured by the spell Cure Paralysis or by going to a healer. This is a pretty nasty effect." + 3033, "One of your characters has just been poisoned. This character will take damage every few moves until the poison wears off. Several priest spells cure poison." + 3034, "One of your characters has just been blessed. This PC will be better in combat, and he/she will be protected from the attacks of others. The effects of blessing are cumulative: blessing a PC twice is well over twice as affecting as blessing it once." + 3035, "One of your characters has just been slowed/hasted. A slowed PC loses one out of every two turns in combat. A hasted PC gets twice the action points in combat. Both effects wear off fairly quickly." + 3036, "From here, you can select which nearby items to pick up. Click an item (or type 'a'-'h') to pick it up. To have someone else pick stuff up, click the appropriate button at the bottom (or type '1'-'6')." + 3037, "If no hostile monsters are near, you can pick up everything nearby. Otherwise, you can only grab adjacent items. Some items are not yours ... taking them may make the townsfolk miffed at you." + 3038, "Each character can only carry so many stones worth of stuff, and you are trying to pick up too much. Increasing a character's strength increases the weight you can carry." + 3039, "Some spells are cast on another character in your party. You tried to select a spell without also selecting someone to cast it on. Try again, but this time, after picking the spell, use the buttons to the right of the character's names to pick a target." + 3040, "Wearing armor with a total encumbrance of more that 1 spoils any mage spell you try to cast in combat. High defense skill sometimes prevents this from happening, but it will only go so far. If any single item has encumb. higher than 2, spells always fail." + 3041, "One of your characters just learned a new magical spell. Before you can cast it, however, you need to get enough spell points and a Mage (or Priest) Spells skill as high as the level of the spell." + 3042, "This person has looked over your items and maybe offered to buy some of them. Click on the 'Sell' button to sell it, for the amount to the right of the button. Some people only try to buy certain sorts of items." + 3043, "Merchants will only buy items that have been identified. If you want to sell something, you may need to find a sage to identify it (such as Habecker in Fort Emergence)." + 3044, "This character will, for a fee, identify some of your items whose nature is, as yet, unknown to you. Click on the 'ID' button by the item to get it identified." + 3045, "This merchant has offered to magically improve one of your weapons. Click on the 'Ench' button by the weapon to pay for this service. You can only augment identified weapons that aren't magic already." + 3047, "You have just opened a door. To open any door, walk into it. Some walls have secret doors in them. To search a wall for secret doors, walk into it. Many special things are hidden in the dungeons." + 3048, "You have just entered combat mode! To start using a weapon, click on that weapon's name. Your characters will now move one at a time ... to attack a bad guy, walk into it. For more information on combat mechanics, type '?'." + 3049, "When fighting early in the game, when you're still weak, rely heavily on magical spells (make sure to have a character with Mage Spells skill of 3). Your melee people won't be strong for a while. Hit the 'End' button to leave combat." + 3050, "You've just brought up the list of your Special Items. Each has an 'Info' button. Some (such as maps) have a 'Use' button to activate them. Others (such as keys) are used automatically when you can use them (such as when you find the correct door)." + 3051, "You can now get a regular job. Click the 'Take' button to accept it. Doing the job gets you a reward. Warning - if you don't do the job in time, this person won't give you any new jobs for a while. You can have a maximum of 4 jobs." + 3052, "This is the inventory page where you can see what jobs you currently have. You get jobs from people in the major surface cities; they're a good way to earn some easy money." + 3053, "You have just made this town angry at you, by stealing something or damaging a friendly person with a weapon or a damaging spell (like Shockwave). If you leave and visit other towns for a while, they'll stop being mad at you." + 3054, "You have just reached a special encounter. Many special encounters are marked by white spots. Others are invisible, and activated by stepping on them or by searching the right spot. Special stuff can be hidden in all terrain types." + 3055, "At the Preferences window, you can select options to speed up the game, change how the game window is positioned, turn the sound on and off, and make the game easier or harder." + 3056, "You are now creating a new character. First you can choose its race and advantages/disadvantages (choose carefully - these cannot be changed later). Then you can assign it skills, a graphic, and a name." + 3057, "You've just written what this person just said down in your talking journal. To review it later, select See Talking Notes from the Options menu." + 3058, "You've just written what this special encounter says down in your adventure journal. To review it later, select See Encounter Notes from the Options menu." + 3059, "One of your characters has just been cursed. That character will function worse in combat, be hit more easily, and take more damage from blows for a while. Curses wear off fairly quickly." + 3060, "You have mounted a horse. A horse doubles your speed when moving outdoors: you'll spend much less time moving from town to town and will have an easier time evading monsters. To dismount, pause (by clicking on your party or hitting '5' on the keypad)." + 3061, "You have just boarded a boat. Steer the boat onto land to get out. Certain boats can pass over lava. When using a boat outdoors, you can enter towns on the shore by steering the boat into them." + 3062, "This command bring up a map of the area you're in. Generally, maps of dungeons and the outdoors will be remembered. However, if a town undergoes some sort of major change, you'll lose your map for that town." + 3063, "Your health is a measure of how much punishment you can take before dying - the more the better. Whenever you get hit, you lose some health. Taking damage when your health is down to 0 will kill you." + 3064, "Your spell points are what you expend to cast spells. Each spell drains away some of your spell points. Time and rest restore them. When creating a character, you get 3 bonus spell points for every level of Mage and Priest Spells skill you buy." + 3065, "Some doors can't be opened no matter what you try. For example, portcullises can almost never be opened by picking locks or bashing." + 3110, "This is a temporary menu with some legacy compatibility options. Its main purpose is to test several changes introduces with code revisions.|Compatibilities options can be set anytime, anywhere and reverted back the same." + 3111, "Should you find a legacy compatibility breaking, please report it to the Irony Central board." + 3301, "Can cast everywhere." + 3302, "Combat only." + 3303, "Town only." + 3304, "Town and outdoor only." + 3305, "Town & combat only." + 3306, "Outdoor only." + 3307, " " + 3308, "Mage Spells" + 3309, "Priest Spells" + 3310, "Blades of Exile was created on a PowerMac 6100 using CodeWarrior, development system of the Gods. It is written in C. Plain, ordinary C." + 3311, "Many thanks to Comedy Central, for providing many hours of bliss during those late night programming binges. The Daily Show added meaning to my lame life." + 3312, "This fine program was brought to you by coffee. _Coffee - it's what's for dinner._" + 3313, "No Vahnatai were harmed during the making of Exile III: Ruined World." + 3314, "Exile III: Ruined World is a work of fiction. Any similarity between its characters and persons living or dead is coincidental. Unless, of course, it isn't." + 3315, "Thirty Helens Agree: Honesty is the best policy." + 3316, "This will be the last Exile game for a long, long time. Please don't be mad." + 3317, "Over 200 double tall iced lattes were consumed during the making of Exile III: Ruined World. Chemical dependence can be your friend too!" + 3318, "Many thanks to all the fine role-playing games that preceded the Exile series, for providing many wonderful ideas to steal." + 3319, "Some groups listened to while coding Exile III: Silly Wizard, Patti Rothberg, The Chieftains, Pearl Jam, Nirvana, Indigo Girls, Nine Inch Nails, Tori Amos, Everclear, REM, Smashing Pumpkins, Enya, Green Day, Sheryl Crow, Jethro Tull, and Janis." + 3320, "Some other things listened to while coding Exile III: Lots of They Might Be Giants, the Rent Cast Album, Oasis, Uncle Bonsai and the Electric Bonsai Band, Joan Osborne, more Joan Osborne, and even more Joan Osborne." + 3321, "A friendly warning. If you leave a message on Spiderweb Software, Inc's answering machine, don't leave a phone number or E-mail address, and mumble your name, please don't be surprised if I don't get back to you." + 3322, "Tips for aspiring programmers: Buy Macintosh Programming Techniques, by Dan Parks Sydow, and Tricks of the Mac Game Programming Gurus, by several people. You can't go wrong." + 3601, "When below 4, the health the character gains at each level will be sharply reduced. Also, more strength enables you to carry more stuff." + 3602, "Before a character does ANY fighting or fires any missiles, this skill should be at least 3." + 3603, "If the character is going to cast spells, make this skill at least 4. If not, ignore it." + 3604, "Edged weapons are the most common." + 3605, "Bashing weapons are common and cheap." + 3606, "Pole weapons are, in general, the most expensive, the most rare, and the most powerful." + 3607, "Thrown missiles are common and many are magical. Also, this skill is cheap. However, thrown weapons cannot be poisoned." + 3608, "Bows are expensive, and so is this skill. However, poisoned arrows are extremely powerful." + 3609, "Buy a few levels for anyone in heavy armor." + 3610, "Try to start with at least one character with level three in this." + 3611, "Try to start with at least one character with level three in this." + 3612, "Spread this around the party. Don't buy more than 25 points total (over the whole game)." + 3613, "Have only one character buy this, but get a lot. Alchemy is very useful." + 3614, "Expensive, but very useful. Knowing what items are when trapped deep in a dungeon can save your life." + 3615, "Traps are deadly in Exile. Have only one character buy this, but get a lot." + 3616, "Not necessary, but very useful. Unlock Door spells are expensive, and bashing is slow, damaging, and very unreliable." + 3617, "Wait on this. It's very effective when your level is high." + 3618, "You really only need 3-4 levels of this. More helps, but not too much." + 3619, "Although it costs no gold, hold off on buying this until your level is high. Luck can help A LOT, but at low levels other things help more." + 3650, "Drinking many, many cups of espresso often greatly heightens one's Blades of Exile experience. The author recommends a nice iced latte. Double tall." + 3651, "Be sure to look for Exile: Escape From the Pit, Exile II: Crystal Souls and Exile III: Ruined World: the hit award-winning trilogy that spawned Blades of Exile. http://www.spidweb.com." + 3652, "Need a hint? Run the Blades of Exile Instructions program. It has a full hint book for the first scenario." + 3653, "Low on gold? Read the Blades of Exile documentation. The Hints on Getting Started section has a plethora of hints for finding loot." + 3654, "Having trouble reaching somewhere? Walk into the walls/barriers/trees/whatever is in your way. Some things have secret doors or entrances." + 3655, "Casting repeated blesses multiplies the effect. Two bless spells on somebody are more than twice as powerful as one." + 3656, "Want more adventures? Go to www.spidweb.com, and download a new Blades of Exile scenario!" + 3657, "It's all fun and games until someone loses an eye." + 3658, "To play a customized scenario, copy it into your Blades of Exile Scenarios folder, run the game, and click Custom Scenario on the title screen. You can find new scenarios at www.spidweb.com." + 3659, "Some scenarios have horses in them. Buy some, if possible. Traveling outdoors is slow, and you'll use up a lot less food when you don't travel on foot." + 3660, "Items need to be identified before you can sell them. In the first scenario, Axel (in Sweetgrove) will identify items cheaply. Also, there are people in plenty of other towns who will perform this service." + 3661, "Move Mountains and Dispel Barrier are very useful spells. Haste will save your party from many a nasty fight." + 3662, "Can't cast a mage spell you've learned? Make sure your Mage Spells skill is up to at least the level of the spell. Then make sure you're not dumbfounded (Restore Mind cures this). Then make sure you have enough spell points." + 3663, "The Blades of Exile Editor can help you out in a lot of nasty situations, even when it's unregistered. Take a look!" + 3664, "Someone important not there? The friendly people in the town suddenly mad at you and you're not sure why? You may have clipped them with Mass Charm or Shockwave. Visit a few other towns and return, and you'll have been forgiven." + 3665, "Low on gold? Look around for side adventurers. For example, Valley of Dying Things has several other dungeons." + 3666, "Trapped in a scenario? You can often leave it by returning to the town you started in. If you're trapped, run the Blades of Exile character editor. It can pull you out of a scenario (even when unregistered)." + 3667, "Be sure to talk to everyone in town. This is often your only route to important tips. For example, in Valley of Dying Things, Avizo, in the first town, knows something very important. You just have to find out what to ask him." + 3668, "Have a tip, bug report, question, or comment? Send it to SpidWeb@spidweb.com." + 3669, "Make sure everyone has a strength of at least 3. Make sure mages have plenty of intelligence. Make sure everyone who does a lot of melee combat has a high dexterity." + 3670, "Some dungeon trips are long, and require lots of healing and endurance. It is at these times that Alchemy can be very useful." + 3671, "If you get lost, be sure to use the automap. It can tell you where you have and haven't been." + 3672, "If you need a hint, look in the online documentation. There's a full hint guide for Valley of Dying Things. When you register, you get a full hint book for Blades of Exile." + 3673, "To cast spells quickly, click on his/her name on the upper right, and select the spell from the Mage Spells or Priest Spells menu." + 3674, "To make a character active (and see its inventory) quickly, type '1'-'6'." + 3675, "Sometimes you'll find a place where you know there's a dungeon, but you can't see or enter it. That's because someone somewhere else needs to tell you where it is. Go talk to people in towns." + 3676, "One nice shortcut: typing capital 'M' has whoever cast your last mage spell cast it again. 'P' works the same way for priest spells." + 3677, "Beware when using the Long Rest feature in dungeons. Monsters are taking advantage of those pauses to get reinforcements." + 3678, "Game too slow? Look in the Preferences menu. There are several options to speed things up." + 3679, "Have to go through a dungeon, but you keep getting killed? Stock up on potions. Buy scrolls. Learn alchemy. Go in, kill a bunch of monsters, and leave to rest (if you can)." + 3680, "One nice shortcut: typing capital 'M' has whoever cast your last mage spell cast it again. 'P' works the same way for priest spells." + 3681, "Beware when using the Long Rest feature in dungeons. Monsters are taking advantage of those pauses to get reinforcements." + 3682, "When launching Exile III, you can hold the space bar down to do a limited launch. This eliminates the opening fades and music, and sometimes makes the game go faster. " + 3901, "Alchemy and Poison" + 3902, "22" + 3903, "Alchemy can be incredibly useful. Potions can give you the added boost you may need to get through a long grueling dungeon, and you cannot raise the dead without the right concoction." + 3904, "You need three things to make a potion:|1. High alchemy skill. When a character tries to make a potion, his/her alchemy skill must be above a certain level. The higher above that level, the better the chance for success." + 3905, "2. The right ingredient. Ingredients are usually found at special encounters outdoors, and regenerate themselves after a time. Generally, the person who teaches a recipe tells you what plant it needs." + 3906, "3. The recipe. These are usually bought in towns. You only need to buy each recipe once for the entire party." + 3907, "When you have all these things, go into a town and click on the blue bottle button. Pick the PC with the highest alchemy skill to make the potion. Hope." + 3908, "Here is a list of the alchemical concoctions, with min. skill to make:|Weak Poison| Min. Skill - 1|Need toadstools or spider glands. The lowest level poison." + 3909, "Weak Curing| Min. Skill - 1|Need comfrey root. Cures poison somewhat." + 3910, "Weak Healing| Min. Skill - 2|Need comfrey root. Provides mild healing." + 3911, "Medium Poison| Min. Skill - 4|Need toadstools or spider glands. A stronger poison." + 3912, "Medium Curing Potion| Min. Skill - 5|Need glowing nettle. A decent antidote for poison." + 3913, "Medium Healing Potion| Min. Skill - 5|Need glowing nettle. Quality healing." + 3914, "Strong Poison| Min. Skill - 5|Need crypt shrooms or asp fangs. Powerful stuff." + 3915, "Graymold Salve| Min. Skill - ???|???" + 3916, "Resurrection Balm| Min. Skill - 8|Need ember flowers. Necessary to cast Raise Dead or Resurrection." + 3917, "Weak Energy Potion| Min. Skill - 10|Need crypt shrooms. Restores some of your spell points." + 3918, "Strong Healing Potion| Min. Skill - 10|Need ember flowers. Provides excellent healing." + 3919, "Killer Poison| Min. Skill - 12|Need asptongue mold. The strongest poison." + 3920, "One of the most useful things you can make with alchemy is poison, a powerful weapon in the magic-poor world of Exile." + 3921, "Many monsters are immune to magic and fire. However, not many are poison-resistant. This makes poison an excellent mage-killer." + 3922, "To poison a weapon, use it during combat. Your hand-to-hand weapon (the first one, if two are equipped) or arrows will become poisoned. Each time you attack, the level of poison decreases." + 3923, "Don't poison a weapon too long before combat. Its effectiveness decreases with time. Also, switching weapons makes the poison disappear." + 3924, "Poisoning an already poisoned weapon doesn't do much good. The weapon gets the maximum poison level of the poison being added or the poison already there, no more." + 6001, "No special ability" + 6002, "Throws darts (dam 1-6)" + 6003, "Shoots arrows (dam 2-12)" + 6004, "Throws spears (dam 3-18)" + 6005, "Throws rocks (dam 4-24)" + 6006, "Throws rocks (dam 5-30)" + 6007, "Throws rocks (dam 6-36)" + 6008, "Throws razordisks (4-24)" + 6009, "Petrification ray" + 6010, "Spell point drain ray" + 6011, "Heat ray" + 6012, "Invisible" + 6013, "Splits when hit" + 6014, "Mindless (resists fear)" + 6015, "Breathes stinking clouds" + 6016, "Icy touch" + 6017, "Experience draining touch" + 6018, "Icy and draining touch" + 6019, "Slowing touch" + 6020, "Shoots webs" + 6021, "Good archer (dam 7-42)" + 6022, "Steals food when hits" + 6023, "Permanent martyr's shield" + 6024, "Paralysis ray" + 6025, "Dumbfounding touch" + 6026, "Disease touch" + 6027, "Absorb spells" + 6028, "Web touch" + 6029, "Sleep touch" + 6030, "Paralysis touch" + 6031, "Petrification touch" + 6032, "Acid touch" + 6033, "Breathe sleep clouds" + 6034, "Acid spit" + 6035, "Shoot spines (dam 7-42)" + 6036, "Death touch (use with care)" + 6037, "Invulnerable (use with care)" + 6038, "Guard" + 6050, "No ability" + 6051, "Radiate fire fields" + 6052, "Radiate ice fields" + 6053, "Radiate shock fields" + 6054, "Radiate antimagic fields" + 6055, "Radiate sleep fields" + 6056, "Radiate stink clouds" + 6057, "Unused" + 6058, "Unused" + 6059, "Unused" + 6060, "Summon (%5 chance)" + 6061, "Summon (%20 chance)" + 6062, "Summon (%50 chance)" + 6063, "Unused" + 6064, "Unused" + 6065, "Death triggers global special" + 6080, "Unused" + 6081, "Percentage chance (1-100%)" + 6082, "Percentage chance (1-100%)" + 6083, "Percentage chance (1-100%)" + 6084, "Percentage chance (1-100%)" + 6085, "Percentage chance (1-100%)" + 6086, "Percentage chance (1-100%)" + 6087, "Unused" + 6088, "Unused" + 6089, "Unused" + 6090, "Number of creature to summon" + 6091, "Number of creature to summon" + 6092, "Number of creature to summon" + 6093, "Unused" + 6094, "Unused" + 6095, "Number of special to call" + 6130, "Hits" + 6131, "Claws" + 6132, "Bites" + 6133, "Slimes" + 6134, "Punches" + 6135, "Stings" + 6136, "Clubs" + 6137, "Burns" + 6138, "Harms" + 6139, "Stabs" + 6150, "Human" + 6151, "Reptile" + 6152, "Beast" + 6153, "Important" + 6154, "Mage" + 6155, "Priest" + 6156, "Humanoid" + 6157, "Demon" + 6158, "Undead" + 6159, "Giant" + 6160, "Slime" + 6161, "Stone" + 6162, "Bug" + 6163, "Dragon" + 6164, "Magical Creature" + 6301, "None" + 6302, "Change when step on" + 6303, "Does fire damage" + 6304, "Does cold damage" + 6305, "Does magical damage" + 6306, "Poison land" + 6307, "Diseased land" + 6308, "Crumbling terrain" + 6309, "Lockable terrain" + 6310, "Unlockable terrain" + 6311, "Unlockable/bashable" + 6312, "Is a sign" + 6313, "Call local special" + 6314, "Call scenario special" + 6315, "Is a container" + 6316, "Waterfall" + 6317, "Conveyor (north)" + 6318, "Conveyor (east)" + 6319, "Conveyor (south)" + 6320, "Conveyor (west)" + 6321, "Blocked to monsters" + 6322, "Town entrance" + 6323, "Can be used" + 6324, "Call special when used" + 6340, "Unused" + 6341, "What to change to?" + 6342, "Amount of damage done" + 6343, "Amount of damage done" + 6344, "Amount of damage done" + 6345, "Strength (1-8)" + 6346, "Strength (1-8)" + 6347, "Unused" + 6348, "Terrain to change to when locked" + 6349, "Terrain to change to when unlocked" + 6350, "Terrain to change to when unlocked" + 6351, "Unused" + 6352, "Number of special to call" + 6353, "Number of special to call" + 6354, "Unused" + 6355, "Unused" + 6356, "Unused" + 6357, "Unused" + 6358, "Unused" + 6359, "Unused" + 6360, "Unused" + 6361, "Terrain type if hidden" + 6362, "Terrain to change to when used" + 6363, "Number of scenario spec. to call" + 6380, "Unused" + 6381, "Number of sound (200 - no sound)" + 6382, "Damage multiplier" + 6383, "Damage multiplier" + 6384, "Damage multiplier" + 6385, "Percentage chance (1-100)" + 6386, "Percentage chance (1-100)" + 6387, "Unused" + 6388, "Unused" + 6389, "Difficulty (0-10)" + 6390, "Difficulty (0-10)" + 6391, "Unused" + 6392, "Unused" + 6393, "Unused" + 6394, "Unused" + 6395, "Unused" + 6396, "Unused" + 6397, "Unused" + 6398, "Unused" + 6399, "Unused" + 6400, "Unused" + 6401, "Unused" + 6402, "Number of sound (200 - no sound)" + 6403, "Unused" + 6601, "No Special" + 6602, "Set Flag" + 6603, "Increment Flag" + 6604, "Display Message" + 6605, "Secret Passage" + 6606, "Display Small Message" + 6607, "Flip Flag" + 6608, "Out Block" + 6609, "Town Block" + 6610, "Combat Block" + 6611, "Looking Block" + 6612, "Can't Enter" + 6613, "Change Time" + 6614, "Start General Timer" + 6615, "Play a Sound" + 6616, "Change Horse Possession" + 6617, "Change Boat Possession" + 6618, "Show/Hide Town" + 6619, "Major Event Has Occured" + 6620, "Forced Give" + 6621, "Buy Items of Type" + 6622, "Call Global Special" + 6623, "Set Many Flags" + 6624, "Copy Flag" + 6625, "Ritual of Sanct. Block" + 6626, "Have a Rest" + 6627, "Wandering will fight" + 6651, "Give Item" + 6652, "Give Special Item" + 6653, "One-Time Do Nothing" + 6654, "One-Time and Set" + 6655, "One-Time Text Message" + 6656, "Display Dialog (Dialog pic)" + 6657, "Display Dialog (Terrain pic)" + 6658, "Display Dialog (Monster pic)" + 6659, "Give Item (Dialog pic)" + 6660, "Give Item (Terrain pic)" + 6661, "Give Item (Monster pic)" + 6662, "One-Time Place Outdoor Enc." + 6663, "One-Time Place Town Enc." + 6664, "Trap" + 6681, "Select a PC" + 6682, "Do Damage" + 6683, "Affect Health" + 6684, "Affect Spell Points" + 6685, "Affect Experience" + 6686, "Affect Skill Points" + 6687, "Kill/Raise Dead" + 6688, "Affect Poison" + 6689, "Affect Slow/Haste" + 6690, "Affect Invulnerability" + 6691, "Affect Magic Resistance" + 6692, "Affect Webs" + 6693, "Affect Disease" + 6694, "Affect Sanctuary" + 6695, "Affect Martyr's Shield" + 6696, "Affect Dumbfounding" + 6697, "Affect Sleep" + 6698, "Affect Paralysis" + 6699, "Affect Statistic" + 6700, "Give Mage Spell" + 6701, "Give Priest Spell" + 6702, "Affect Gold" + 6703, "Affect Food" + 6704, "Affect Alchemy" + 6705, "Affect Stealth" + 6706, "Affect Firewalk" + 6707, "Affect Flying" + 6731, "Stuff Done Flag?" + 6732, "Town Number?" + 6733, "Random Number?" + 6734, "Have Special Item?" + 6735, "Stuff Done Compare?" + 6736, "Terrain this type? (town)" + 6737, "Terrain this type? (out)" + 6738, "Has gold?" + 6739, "Has food?" + 6740, "Item Class on Space?" + 6741, "Have Item With Class?" + 6742, "Equipped Item With Class?" + 6743, "Has Gold? (+ take)" + 6744, "Has Food? (+ take)" + 6745, "Item Class on Space? (+ take)" + 6746, "Have Item With Class? (+ take)" + 6747, "Equip Item W. Class? (+ take)" + 6748, "Day Reached?" + 6749, "Any Barrels?" + 6750, "Any Crates?" + 6751, "Special Thing Happened?" + 6752, "Has Cave Lore?" + 6753, "Has Woodsman?" + 6754, "Has Enough Mage Lore?" + 6755, "Text Response?" + 6771, "Town Hostile" + 6772, "Change Terrain" + 6773, "Swap Terrain" + 6774, "Transform Terrain" + 6775, "Move Party" + 6776, "Hit Space" + 6777, "Explosion on Space" + 6778, "Lock Space" + 6779, "Unlock Space" + 6780, "Do sfx Burst" + 6781, "Make Wandering Monster" + 6782, "Place a Monster" + 6783, "Destroy Monster" + 6784, "Destroy All Monsters" + 6785, "Generic Lever" + 6786, "Generic Portal" + 6787, "Generic Button" + 6788, "Generic Stairway" + 6789, "Lever" + 6790, "Portal" + 6791, "Stairway" + 6792, "Relocate Outdoors" + 6793, "Place Item" + 6794, "Split Party" + 6795, "Reunite Party" + 6796, "Start General Timer" + 6797, "Unused" + 6798, "Unused" + 6799, "Unused" + 6800, "Unused" + 6801, "Place Fire Wall" + 6802, "Place Force Wall" + 6803, "Place Ice Wall" + 6804, "Place Blade Wall" + 6805, "Place Stinking Cloud" + 6806, "Place Sleep Field" + 6807, "Place Quickfire" + 6808, "Place Fire Barrier" + 6809, "Place Force Barrier" + 6810, "Cleanse Rectangle" + 6811, "Place SFX" + 6812, "Place Barrels, Etc." + 6813, "Move Items" + 6814, "Destroy Items" + 6815, "Change Rectange Terrain" + 6816, "Swap Rectangle Terrain" + 6817, "Transform Rectangle Terrain" + 6818, "Lock Rectangle" + 6819, "Unlock Rectangle" + 6826, "Make Outdoor Wandering" + 6827, "Change Out Terrain" + 6828, "Place Outdoor Encounter" + 6829, "Outdoor Move Party" + 6830, "Outdoor Store" + 6901, "No ability" + 6902, "Flaming Weapon" + 6903, "Demon Slayer" + 6904, "Undead Slayer" + 6905, "Lizard Slayer" + 6906, "Giant Slayer" + 6907, "Mage Slayer" + 6908, "Priest Slayer" + 6909, "Bug Slayer" + 6910, "Acidic Weapon" + 6911, "Soulsucker" + 6912, "Drain Missiles" + 6913, "Weak Weapon" + 6914, "Causes Fear" + 6915, "Poisoned Weapon" + 6931, "Protection" + 6932, "Full Protection" + 6933, "Fire Protection" + 6934, "Cold Protection" + 6935, "Poison Protection" + 6936, "Magic Protection" + 6937, "Acid Protection" + 6938, "Skill" + 6939, "Strength" + 6940, "Dexterity" + 6941, "Intelligence" + 6942, "Accuracy" + 6943, "Thieving" + 6944, "Giant Strength" + 6945, "Lighter Object" + 6946, "Heavier Object" + 6947, "Occasional Bless" + 6948, "Occasional Haste" + 6949, "Life Saving" + 6950, "Prot. From Petrify" + 6951, "Regenerate" + 6952, "Poison Augment" + 6953, "Disease Party" + 6954, "Will" + 6955, "Free Action" + 6956, "Speed" + 6957, "Slow Wearer" + 6958, "Protection from Undead" + 6959, "Protection from Demons" + 6960, "Prot. from Humanoids" + 6961, "Prot. from Reptiles" + 6962, "Prot. from Giants" + 6963, "Prot. from Disease" + 6971, "Poison Weapon" + 6972, "Curse/Bless User" + 6973, "Cure/Cause Poison" + 6974, "Speed/Slow User" + 6975, "Add/Lose Invulnerability" + 6976, "Add/Lose Magic Res." + 6977, "Add/Lose Web" + 6978, "Cause/Cure Disease" + 6979, "Add/Lose Sanctuary" + 6980, "Cure/Cause Dumbfound" + 6981, "Add/Lose Martyr's Shield" + 6982, "Cure/Cause Sleep" + 6983, "Cure/Cause Paralysis" + 6984, "Cure/Cause Acid" + 6985, "Bliss" + 6986, "Add/Lose Experience" + 6987, "Add/Lose Skill Pts." + 6988, "Add/Lose Health" + 6989, "Add/Lose Spell Points" + 6990, "Doom" + 6991, "Light" + 6992, "Stealth" + 6993, "Firewalk" + 6994, "Flying" + 6995, "Major Healing" + 7011, "Flame" + 7012, "Fireball" + 7013, "Firestorm" + 7014, "Kill" + 7015, "Ice Bolt" + 7016, "Slow" + 7017, "Shockwave" + 7018, "Dispel Undead" + 7019, "Dispel Spirit" + 7020, "Summoning" + 7021, "Mass Summoning" + 7022, "Acid Spray" + 7023, "Stinking Cloud" + 7024, "Sleep Field" + 7025, "Venom" + 7026, "Shockstorm" + 7027, "Paralysis" + 7028, "Web Spell" + 7029, "Strengthen Target" + 7030, "Quickfire" + 7031, "Mass Charm" + 7032, "Magic Map" + 7033, "Dispel Barrier" + 7034, "Make Ice Wall" + 7035, "Charm Spell" + 7036, "Antimagic Cloud" + 7051, "Holly/Toadstool" + 7052, "Comfrey Root" + 7053, "Glowing Nettle" + 7054, "Crypt Shroom/Wormgr." + 7055, "Asptongue Mold" + 7056, "Ember Flowers" + 7057, "Graymold" + 7058, "Mandrake" + 7059, "Sapphire" + 7060, "Smoky Crystal" + 7061, "Ressurection Balm" + 7062, "Lockpicks" + 7071, "Returning" + 7072, "Lightning" + 7073, "Exploding" + 7074, "Acid" + 7075, "Slay Undead" + 7076, "Slay Demon" + 7077, "Heal Target" + 7501, "Alchemy and Poison" + 7502, "30" + 7503, "Alchemy can be incredibly useful. Potions can give you the added boost you may need to get through a long grueling dungeon, and you cannot raise the dead without the right concoction." + 7504, "You need three things to make a potion:|1. High alchemy skill. When a character tries to make a potion, his/her alchemy skill must be above a certain level. The higher above that level, the better the chance for success." + 7505, "2. The right ingredient. Ingredients are usually found at special encounters outdoors, and regenerate themselves after a time. Generally, the person who teaches a recipe tells you what plant it needs." + 7506, "3. The recipe. These are usually bought in towns. You only need to buy each recipe once for the entire party." + 7507, "When you have all these things, go into a town and click on the blue bottle button. Pick the PC with the highest alchemy skill to make the potion. Hope." + 7508, "Here is a list of the alchemical concoctions, with min. skill to make: |Weak Curing | Min. Skill - 1 |Need holly. Cures poison somewhat." + 7509, "Weak Healing | Min. Skill - 1 |Need comfrey root. Provides mild healing.|" + 7510, "Weak Poison | Min. Skill - 1 |Need holly or spider glands. The lowest level poison." + 7511, "Weak Speed | Min. Skill - 3 |Need comfrey root and wormgrass. Hastes drinker." + 7512, "Medium Poison | Min. Skill - 3 |Need wormgrass or spider glands. A stronger poison." + 7513, "Medium Healing Potion | Min. Skill - 4 |Need glowing nettle. Quality healing." + 7514, "Strong Curing Potion | Min. Skill - 5 |Need glowing nettle. A decent antidote for poison." + 7515, "Medium Speed | Min. Skill - 5 |Need glowing nettle and wormgrass. Hastes drinker a lot." + 7516, "Graymold Salve | Min. Skill - 7 |Need graymold. Cures disease of all sorts." + 7517, "Weak Energy Potion | Min. Skill - 9 |Need wormgrass and asptongue mold. Restores some of your spell points." + 7518, "Potion of Clarity | Min. Skill - 9 |Need graymold and holly. Cures dumbfounding." + 7519, "Strong Poison | Min. Skill - 10 |Need asptongue mold. Powerful stuff." + 7520, "Strong Healing Potion | Min. Skill - 12 |Need graymold and comfrey root. Provides excellent healing." + 7521, "Killer Poison | Min. Skill - 12 |Need mandrake root. The strongest poison." + 7522, "Resurrection Balm | Min. Skill - 9 |Need ember flowers. Necessary to cast Raise Dead or Resurrection." + 7523, "Medium Power Potion | Min. Skill - 14 |Need mandrake root and asptongue mold. Restores a fair amount of spell points." + 7524, "Knowledge Brew | Min. Skill - 19 |This most powerful of potions requires Mandrake and Ember Flowers for its creation." + 7525, "Strength Potion | Min. Skill - 10 |This brew is a great aid in combat. Making it requires ember flowers and glowing nettle." + 7526, "Bliss | Min. Skill - 16 |Combining the best elements of healing and strength potions, bliss potions contain asptongue mold and graymold." + 7527, "Strong Energy Potion | Min. Skill - 20 |This is the hardest potion to make, and require ember flowers and mandrake. The energy boost it provides, however, can't be matched." + 7528, "One of the most useful things you can make with alchemy is poison, a powerful weapon in the magic-poor world of Exile." + 7529, "Many monsters are immune to magic and fire. However, not many are poison-resistant. This makes poison an excellent mage-killer." + 7530, "To poison a weapon, use it during combat. Your hand-to-hand weapon (the first one, if two are equipped) or arrows will become poisoned. Each time you attack, the level of poison decreases." + 7531, "Don't poison a weapon too long before combat. It's effectiveness decreases with time. Also, switching weapons makes the poison disappear." + 7532, "Poisoning an already poisoned weapon doesn't do much good. The weapon gets the maximum poison level of the poison being added or the poison already there, no more." + 9001, "Unused" + 9002, "Value to change to" + 9003, "Increase/Decrease by" + 9004, "Unused" + 9005, "Unused" + 9006, "Unused" + 9007, "Unused" + 9008, "0 - can enter, 1 - no enter" + 9009, "0 - can enter, 1 - no enter" + 9010, "0 - can enter, 1 - no enter" + 9011, "Unused" + 9012, "0 - can enter, 1 - no enter" + 9013, "Number of moves to set forward" + 9014, "Number of moves to set the timer" + 9015, "Which sound" + 9016, "Horse to set (0 .. 29)" + 9017, "Boat to set (0 .. 29)" + 9018, "Town to show/hide" + 9019, "Number of Special Event (0 .. 9)" + 9020, "Item To Give" + 9021, "Item Class to Take Away" + 9022, "Usused" + 9023, "Value to change the 10 flags to" + 9024, "Flag to change to Part A" + 9025, "Unused" + 9026, "Number of moves that pass" + 9027, "0 - no attack, 1 - attack" + 9051, "Item to give" + 9052, "Number of spec. item to give (0 .. 49)" + 9053, "Unused" + 9054, "Unused" + 9055, "Unused" + 9056, "Label of 2nd button (-1 - no button)" + 9057, "Label of 2nd button (-1 - no button)" + 9058, "Label of 2nd button (-1 - no button)" + 9059, "Item to give" + 9060, "Item to give" + 9061, "Item to give" + 9062, "Special outdoor enc. to place (0 .. 3)" + 9063, "Spec. encounter code to activate (0 .. 9)" + 9064, "Type of trap (see docs. for list)" + 9081, "0 - only living, 1 - any PC" + 9082, "Number of dice" + 9083, "Amount" + 9084, "Amount" + 9085, "Amount (0 .. 100)" + 9086, "Amount (0 .. 10)" + 9087, "0 - dead, 1 - dust, 2- stoned" + 9088, "Amount (0 .. 8)" + 9089, "Amount (0 .. 8)" + 9090, "Amount (0 .. 8)" + 9091, "Amount (0 .. 8)" + 9092, "Amount (0 .. 8)" + 9093, "Amount (0 .. 8)" + 9094, "Amount (0 .. 8)" + 9095, "Amount (0 .. 8)" + 9096, "Amount (0 .. 7)" + 9097, "Amount (0 .. 8)" + 9098, "Amount (0 .. 5000)" + 9099, "Amount (0 .. 10)" + 9100, "Amount (0 .. 61)" + 9101, "Amount (0 .. 61)" + 9102, "Amount (0 .. 25000)" + 9103, "Amount (0 .. 25000)" + 9104, "Amount (0 .. 19)" + 9105, "Amount (0 .. 250)" + 9106, "Amount (0 .. 250)" + 9107, "Amount (0 .. 250)" + 9131, "If at least this value ..." + 9132, "If in this town ..." + 9133, "If random # (1 - 100) less than ..." + 9134, "If has spec. item ..." + 9135, "Stuff Done flag 2 Part A" + 9136, "X coordinate of space" + 9137, "X coordinate of space" + 9138, "If party has this much gold ..." + 9139, "If party has this much food ..." + 9140, "X coordinate of space" + 9141, "If has item of this special class ..." + 9142, "If has equipped item of this special ..." + 9143, "If party has this much gold ..." + 9144, "If party has this much food ..." + 9145, "X coordinate of space" + 9146, "If has item of this special class ..." + 9147, "If has equipped item of this class ..." + 9148, "If this day has been reached ..." + 9149, "Unused" + 9150, "Unused" + 9151, "If this day has been reached ..." + 9152, "Unused" + 9153, "Unused" + 9154, "If the party has this much Mage Lore ..." + 9155, "Number of a SCENARIO special message" + 9171, "Unused" + 9172, "X coordinate of space" + 9173, "X coordinate of space" + 9174, "X coordinate of space" + 9175, "X coordinate of space" + 9176, "X coordinate of space" + 9177, "X coordinate of space" + 9178, "X coordinate of space" + 9179, "X coordinate of space" + 9180, "X coordinate of space" + 9181, "Unused" + 9182, "X coordinate of space to place" + 9183, "Type of creature to remove" + 9184, "0 - all, 1 - friendly, 2 - hostile" + 9185, "Unused" + 9186, "X coordinate to telep. to" + 9187, "Unused" + 9188, "X coordinate to go to " + 9189, "Unused" + 9190, "X coordinate to telep. to" + 9191, "X coordinate to place at" + 9192, "X coordinate of outdoor section" + 9193, "X coordinate to place at" + 9194, "X coordinate to place lone PC at" + 9195, "0 - no sound, 1 - teleport sound" + 9196, "Number of moves until event" + 9201, "Top of rectangle" + 9202, "Top of rectangle" + 9203, "Top of rectangle" + 9204, "Top of rectangle" + 9205, "Top of rectangle" + 9206, "Top of rectangle" + 9207, "Top of rectangle" + 9208, "Top of rectangle" + 9209, "Top of rectangle" + 9210, "Top of rectangle" + 9211, "Top of rectangle" + 9212, "Top of rectangle" + 9213, "Top of rectangle" + 9214, "Top of rectangle" + 9215, "Top of rectangle" + 9216, "Top of rectangle" + 9217, "Top of rectangle" + 9218, "Top of rectangle" + 9219, "Top of rectangle" + 9226, "Unused" + 9227, "X coordinate of space" + 9228, "Number of special encounter (0 .. 3)" + 9229, "X coordinate of space" + 9230, "Number of first item in store" + 9301, "Unused" + 9302, "Unused" + 9303, "0 - increase, 1 - decrease" + 9304, "Unused" + 9305, "Unused" + 9306, "Unused" + 9307, "Unused" + 9308, "Unused" + 9309, "Unused" + 9310, "Unused" + 9311, "Unused" + 9312, "Unused" + 9313, "Unused" + 9314, "Special to call when timer runs out" + 9315, "Unused" + 9316, "Unused" + 9317, "Unused" + 9318, "Unused" + 9319, "Unused" + 9320, "Unused" + 9321, "Special to call if no items taken" + 9322, "Unused" + 9323, "Unused" + 9324, "Flag to change to Part B" + 9325, "Special if not casting ritual" + 9326, "Health and spell pts. to give" + 9351, "Amount of gold to give" + 9352, "0 - give item, 1 - take away" + 9353, "Unused" + 9354, "Unused" + 9355, "Unused" + 9356, "Special if button 2 pressed" + 9357, "Special if button 2 pressed" + 9358, "Special if button 2 pressed" + 9359, "Amount of gold to give" + 9360, "Amount of gold to give" + 9361, "Amount of gold to give" + 9362, "Unused" + 9363, "Unused" + 9364, "Trap severity (0 .. 3)" + 9381, "Special if Cancel button pressed" + 9382, "Number of 'sides' on dice" + 9383, "0 - raise, 1 - lower" + 9384, "0 - raise, 1 - lower" + 9385, "0 - raise, 1 - lower" + 9386, "0 - raise, 1 - lower" + 9387, "0 - raise dead, 1 - hurt" + 9388, "0 - cure, 1 - inflict" + 9389, "0 - cure, 1 - inflict" + 9390, "0 - cure, 1 - inflict" + 9391, "0 - cure, 1 - inflict" + 9392, "0 - cure, 1 - inflict" + 9393, "0 - cure, 1 - inflict" + 9394, "0 - adds, 1 - removes" + 9395, "0 - adds, 1 - removes" + 9396, "0 - cure, 1 - inflict" + 9397, "0 - cure, 1 - inflict" + 9398, "0 - cure, 1 - inflict" + 9399, "0 - increase, 1 - decrease" + 9400, "Unused" + 9401, "Unused" + 9402, "0 - increase, 1 - decrease" + 9403, "0 - increase, 1 - decreaseUnused" + 9404, "Unused" + 9405, "Unused" + 9406, "Unused" + 9407, "Unused" + 9431, "Call this special ..." + 9432, "Call this special ..." + 9433, "Call this special ..." + 9434, "Call this special ..." + 9435, "Stuff Done flag 2 Part B" + 9436, "Y coordinate of space" + 9437, "Y coordinate of space" + 9438, "Call this special ..." + 9439, "Call this special ..." + 9440, "Y coordinate of space" + 9441, "Call this special ..." + 9442, "Call this special ..." + 9443, "Call this special ..." + 9444, "Call this special ..." + 9445, "Y coordinate of space" + 9446, "Call this special ..." + 9447, "Call this special ..." + 9448, "Call this special ..." + 9449, "If any barrels, call this special ..." + 9450, "If any crates, call this special ..." + 9451, "And this event didn't happen before it ..." + 9452, "If any Cave Lore, call this special ..." + 9453, "If any Woodsman, call this special ..." + 9454, "Call this special ..." + 9455, "If answer matches, call this special ..." + 9471, "Unused" + 9472, "Y coordinate of space" + 9473, "Y coordinate of space" + 9474, "Y coordinate of space" + 9475, "Y coordinate of space" + 9476, "Y coordinate of space" + 9477, "Y coordinate of space" + 9478, "Y coordinate of space" + 9479, "Y coordinate of space" + 9480, "Y coordinate of space" + 9481, "Unused" + 9482, "Y coordinate of space to place" + 9483, "Unused" + 9484, "Unused" + 9485, "If Pulled, call this special ..." + 9486, "Y coordinate to telep. to" + 9487, "If Pushed, call this special ..." + 9488, "Y coordinate to go to" + 9489, "If Pulled, call this special ..." + 9490, "Y coordinate to telep. to" + 9491, "Y coordinate to place at" + 9492, "Y coordinate of outdoor section" + 9493, "Y coordinate to place at" + 9494, "Y coordinate to place lone PC at" + 9495, "Unused" + 9496, "Call this special when time runs out ..." + 9501, "Left of rectangle" + 9502, "Left of rectangle" + 9503, "Left of rectangle" + 9504, "Left of rectangle" + 9505, "Left of rectangle" + 9506, "Left of rectangle" + 9507, "Left of rectangle" + 9508, "Left of rectangle" + 9509, "Left of rectangle" + 9510, "Left of rectangle" + 9511, "Left of rectangle" + 9512, "Left of rectangle" + 9513, "Left of rectangle" + 9514, "Left of rectangle" + 9515, "Left of rectangle" + 9516, "Left of rectangle" + 9517, "Left of rectangle" + 9518, "Left of rectangle" + 9519, "Left of rectangle" + 9526, "Unused" + 9527, "Y coordinate of space" + 9528, "Unused" + 9529, "Y coordinate of space" + 9530, "Store type (see docs. for list)" + 9601, "Unused" + 9602, "Unused" + 9603, "Unused" + 9604, "Unused" + 9605, "Unused" + 9606, "Unused" + 9607, "Unused" + 9608, "Unused" + 9609, "Unused" + 9610, "Unused" + 9611, "Unused" + 9612, "Unused" + 9613, "Unused" + 9614, "Unused" + 9615, "Unused" + 9616, "0 - becomes property, 1 - not property" + 9617, "0 - becomes property, 1 - not property" + 9618, "Unused" + 9619, "Unused" + 9620, "Unused" + 9621, "Amount to pay for each item" + 9622, "Unused" + 9623, "Unused" + 9624, "Unused" + 9625, "Unused" + 9626, "Unused" + 9651, "Amount of food to give" + 9652, "Unused" + 9653, "Unused" + 9654, "Unused" + 9655, "Unused" + 9656, "Label of 3rd button (-1 - no button)" + 9657, "Label of 3rd button (-1 - no button)" + 9658, "Label of 3rd button (-1 - no button)" + 9659, "Amount of food to give" + 9660, "Amount of food to give" + 9661, "Amount of food to give" + 9662, "Unused" + 9663, "Unused" + 9664, "Disarming penalty (0 .. 100, higher is harder)" + 9681, "Amount of extra damage" + 9682, "Unused" + 9683, "Unused" + 9684, "Unused" + 9685, "Unused" + 9686, "Unused" + 9687, "Unused" + 9688, "Unused" + 9689, "Unused" + 9690, "Unused" + 9691, "Unused" + 9692, "Unused" + 9693, "Unused" + 9694, "Unused" + 9695, "Unused" + 9696, "Unused" + 9697, "Unused" + 9698, "Unused" + 9699, "Stat. to adjust (see docs. for list)" + 9700, "Unused" + 9701, "Unused" + 9702, "Unused" + 9703, "Unused" + 9704, "Unused" + 9705, "Unused" + 9706, "Unused" + 9707, "Unused" + 9731, "If less than this ..." + 9732, "Unused" + 9733, "Unused" + 9734, "Unused" + 9735, "Unused" + 9736, "If space is this terrain type ..." + 9737, "If space is this terrain type ..." + 9738, "Unused" + 9739, "Unused" + 9740, "If item of this class on space ..." + 9741, "Unused" + 9742, "Unused" + 9743, "Unused" + 9744, "Unused" + 9745, "If item of this class on space ..." + 9746, "Unused" + 9747, "Unused" + 9748, "Unused" + 9749, "Unused" + 9750, "Unused" + 9751, "Unused" + 9752, "Unused" + 9753, "Unused" + 9754, "Unused" + 9755, "Number of a SCENARIO special message" + 9771, "Unused" + 9772, "Terrain to change to" + 9773, "Swap this terrain ..." + 9774, "Unused" + 9775, "0 - Just move, 1 - Teleport" + 9776, "Damage to inflict (0 .. 1000)" + 9777, "Damage to inflict (0 .. 1000)" + 9778, "Unused" + 9779, "Unused" + 9780, "0 - fire, 1 - elec., 2 - telep." + 9781, "Unused" + 9782, "Number of creature to place" + 9783, "Unused" + 9784, "Unused" + 9785, "Unused" + 9786, "Unused" + 9787, "Unused" + 9788, "Number of town to place party in" + 9789, "Unused" + 9790, "Unused" + 9791, "Number of town to place party in" + 9792, "X coordinate inside section " + 9793, "Item to place" + 9794, "0 - no telep. noise, 1 - play telep. noise" + 9795, "Unused" + 9796, "Unused" + 9801, "Bottom of rectangle" + 9802, "Bottom of rectangle" + 9803, "Bottom of rectangle" + 9804, "Bottom of rectangle" + 9805, "Bottom of rectangle" + 9806, "Bottom of rectangle" + 9807, "Bottom of rectangle" + 9808, "Bottom of rectangle" + 9809, "Bottom of rectangle" + 9810, "Bottom of rectangle" + 9811, "Bottom of rectangle" + 9812, "Bottom of rectangle" + 9813, "Bottom of rectangle" + 9814, "Bottom of rectangle" + 9815, "Bottom of rectangle" + 9816, "Bottom of rectangle" + 9817, "Bottom of rectangle" + 9818, "Bottom of rectangle" + 9819, "Bottom of rectangle" + 9826, "Unused" + 9827, "Terrain to change to" + 9828, "Special wand. enc. to place (0 .. 3)" + 9829, "Unused" + 9830, "Number of items in store (1 .. 40)" + 9901, "Unused" + 9902, "Unused" + 9903, "Unused" + 9904, "Unused" + 9905, "Unused" + 9906, "Unused" + 9907, "Unused" + 9908, "Unused" + 9909, "Unused" + 9910, "Unused" + 9911, "Unused" + 9912, "Unused" + 9913, "Unused" + 9914, "Unused" + 9915, "Unused" + 9916, "Unused" + 9917, "Unused" + 9918, "Unused" + 9919, "Unused" + 9920, "Special if item not given" + 9921, "Unused" + 9922, "Unused" + 9923, "Unused" + 9924, "Unused" + 9925, "Unused" + 9926, "Unused" + 9951, "Special if item not given" + 9952, "Unused" + 9953, "Unused" + 9954, "Unused" + 9955, "Unused" + 9956, "Special if button 3 pressed" + 9957, "Special if button 3 pressed" + 9958, "Special if button 3 pressed" + 9959, "Special if item IS taken" + 9960, "Special if item IS taken" + 9961, "Special if item IS taken" + 9962, "Unused" + 9963, "Unused" + 9964, "Unused" + 9965, "Unused" + 9981, "Unused" + 9982, "Type of damage (for list, see docs.)" + 9983, "Unused" + 9984, "Unused" + 9985, "Unused" + 9986, "Unused" + 9987, "Unused" + 9988, "Unused" + 9989, "Unused" + 9990, "Unused" + 9991, "Unused" + 9992, "Unused" + 9993, "Unused" + 9994, "Unused" + 9995, "Unused" + 9996, "Unused" + 9997, "Unused" + 9998, "Unused" + 9999, "Unused" + 10000, "Unused" + 10001, "Unused" + 10002, "Unused" + 10003, "Unused" + 10004, "Unused" + 10005, "Unused" + 10006, "Unused" + 10007, "Unused" + 10031, "Call this special ..." + 10032, "Unused" + 10033, "Unused" + 10034, "Unused" + 10035, "Call this special is 2nd flag lower ..." + 10036, "Call this special ..." + 10037, "Call this special ..." + 10038, "Unused" + 10039, "Unused" + 10040, "Call this special ..." + 10041, "Unused" + 10042, "Unused" + 10043, "Unused" + 10044, "Unused" + 10045, "Call this special ..." + 10046, "Unused" + 10047, "Unused" + 10048, "Unused" + 10049, "Unused" + 10050, "Unused" + 10051, "Call this special ..." + 10052, "Unused" + 10053, "Unused" + 10054, "Unused" + 10055, "If answer matches, call this special ..." + 10071, "Unused" + 10072, "Unused" + 10073, "With this terrain ..." + 10074, "Unused" + 10075, "Unused" + 10076, "Unused" + 10077, "Type of damage (for list, see docs.)" + 10078, "Unused" + 10079, "Unused" + 10080, "Unused" + 10081, "Unused" + 10082, "0 - don't force, 1 - force" + 10083, "Unused" + 10084, "Unused" + 10085, "Unused" + 10086, "Unused" + 10087, "Unused" + 10088, "What text? (see docs.)" + 10089, "Unused" + 10090, "Unused" + 10091, "Unused" + 10092, "Y coordinate inside section " + 10093, "Unused" + 10094, "Unused" + 10095, "Unused" + 10096, "Unused" + 10101, "Right of rectangle" + 10102, "Right of rectangle" + 10103, "Right of rectangle" + 10104, "Right of rectangle" + 10105, "Right of rectangle" + 10106, "Right of rectangle" + 10107, "Right of rectangle" + 10108, "Right of rectangle" + 10109, "Right of rectangle" + 10110, "Right of rectangle" + 10111, "Right of rectangle" + 10112, "Right of rectangle" + 10113, "Right of rectangle" + 10114, "Right of rectangle" + 10115, "Right of rectangle" + 10116, "Right of rectangle" + 10117, "Right of rectangle" + 10118, "Right of rectangle" + 10119, "Right of rectangle" + 10126, "Unused" + 10127, "Unused" + 10128, "Unused" + 10129, "Unused" + 10130, "Cost adjust (0 .. 6, lower = cheaper)" + 10501, "Scen name" + 10502, "Who wrote 1 " + 10503, "Who wrote 2" + 10504, "Contact info" + 10511, "Begin journal strs" + 10560, "End journal strs" + 10561, "Unused Special Item" + 10563, "Unused Special Item" + 10565, "Unused Special Item" + 10567, "Unused Special Item" + 10569, "Unused Special Item" + 10571, "Unused Special Item" + 10573, "Unused Special Item" + 10575, "Unused Special Item" + 10577, "Unused Special Item" + 10579, "Unused Special Item" + 10581, "Unused Special Item" + 10583, "Unused Special Item" + 10585, "Unused Special Item" + 10587, "Unused Special Item" + 10589, "Unused Special Item" + 10591, "Unused Special Item" + 10593, "Unused Special Item" + 10595, "Unused Special Item" + 10597, "Unused Special Item" + 10599, "Unused Special Item" + 10601, "Unused Special Item" + 10603, "Unused Special Item" + 10605, "Unused Special Item" + 10607, "Unused Special Item" + 10609, "Unused Special Item" + 10611, "Unused Special Item" + 10613, "Unused Special Item" + 10615, "Unused Special Item" + 10617, "Unused Special Item" + 10619, "Unused Special Item" + 10621, "Unused Special Item" + 10623, "Unused Special Item" + 10625, "Unused Special Item" + 10627, "Unused Special Item" + 10629, "Unused Special Item" + 10631, "Unused Special Item" + 10633, "Unused Special Item" + 10635, "Unused Special Item" + 10637, "Unused Special Item" + 10639, "Unused Special Item" + 10641, "Unused Special Item" + 10643, "Unused Special Item" + 10645, "Unused Special Item" + 10647, "Unused Special Item" + 10649, "Unused Special Item" + 10651, "Unused Special Item" + 10653, "Unused Special Item" + 10655, "Unused Special Item" + 10657, "Unused Special Item" + 10659, "Unused Special Item" + 10660, "End special item descs" + 10661, "*Begin special strs" + 10662, "*" + 10663, "*" + 10664, "*" + 10665, "*" + 10666, "*" + 10667, "*" + 10668, "*" + 10669, "*" + 10670, "*" + 10671, "*" + 10672, "*" + 10673, "*" + 10674, "*" + 10675, "*" + 10676, "*" + 10677, "*" + 10678, "*" + 10679, "*" + 10680, "*" + 10681, "*" + 10682, "*" + 10683, "*" + 10684, "*" + 10685, "*" + 10686, "*" + 10687, "*" + 10688, "*" + 10689, "*" + 10690, "*" + 10691, "*" + 10692, "*" + 10693, "*" + 10694, "*" + 10695, "*" + 10696, "*" + 10697, "*" + 10698, "*" + 10699, "*" + 10700, "*" + 10701, "*" + 10702, "*" + 10703, "*" + 10704, "*" + 10705, "*" + 10706, "*" + 10707, "*" + 10708, "*" + 10709, "*" + 10710, "*" + 10711, "*" + 10712, "*" + 10713, "*" + 10714, "*" + 10715, "*" + 10716, "*" + 10717, "*" + 10718, "*" + 10719, "*" + 10720, "*" + 10721, "*" + 10722, "*" + 10723, "*" + 10724, "*" + 10725, "*" + 10726, "*" + 10727, "*" + 10728, "*" + 10729, "*" + 10730, "*" + 10731, "*" + 10732, "*" + 10733, "*" + 10734, "*" + 10735, "*" + 10736, "*" + 10737, "*" + 10738, "*" + 10739, "*" + 10740, "*" + 10741, "*" + 10742, "*" + 10743, "*" + 10744, "*" + 10745, "*" + 10746, "*" + 10747, "*" + 10748, "*" + 10749, "*" + 10750, "*" + 10751, "*" + 10752, "*" + 10753, "*" + 10754, "*" + 10755, "*" + 10756, "*" + 10757, "*" + 10758, "*" + 10759, "*" + 10760, "*End special strs" + 10761, "From here on, reserved for furute use" + 10801, "Town name" + 10802, "Rectangle 1" + 10803, "Rectangle 2" + 10804, "Rectangle 3" + 10805, "Rectangle 4" + 10806, "Rectangle 5" + 10807, "Rectangle 6" + 10808, "Rectangle 7" + 10809, "Rectangle 8" + 10810, "Rectangle 9" + 10811, "Rectangle 10" + 10812, "Rectangle 11" + 10813, "Rectangle 12" + 10814, "Rectangle 13" + 10815, "Rectangle 14" + 10816, "Rectangle 15" + 10817, "Rectangle 16" + 10818, "Comment 1" + 10819, "Comment 2" + 10820, "Comment 3" + 10821, "*Begin special strs" + 10822, "*" + 10823, "*" + 10824, "*" + 10825, "*" + 10826, "*" + 10827, "*" + 10828, "*" + 10829, "*" + 10830, "*" + 10831, "*" + 10832, "*" + 10833, "*" + 10834, "*" + 10835, "*" + 10836, "*" + 10837, "*" + 10838, "*" + 10839, "*" + 10840, "*" + 10841, "*" + 10842, "*" + 10843, "*" + 10844, "*" + 10845, "*" + 10846, "*" + 10847, "*" + 10848, "*" + 10849, "*" + 10850, "*" + 10851, "*" + 10852, "*" + 10853, "*" + 10854, "*" + 10855, "*" + 10856, "*" + 10857, "*" + 10858, "*" + 10859, "*" + 10860, "*" + 10861, "*" + 10862, "*" + 10863, "*" + 10864, "*" + 10865, "*" + 10866, "*" + 10867, "*" + 10868, "*" + 10869, "*" + 10870, "*" + 10871, "*" + 10872, "*" + 10873, "*" + 10874, "*" + 10875, "*" + 10876, "*" + 10877, "*" + 10878, "*" + 10879, "*" + 10880, "*" + 10881, "*" + 10882, "*" + 10883, "*" + 10884, "*" + 10885, "*" + 10886, "*" + 10887, "*" + 10888, "*" + 10889, "*" + 10890, "*" + 10891, "*" + 10892, "*" + 10893, "*" + 10894, "*" + 10895, "*" + 10896, "*" + 10897, "*" + 10898, "*" + 10899, "*" + 10900, "*" + 10901, "*" + 10902, "*" + 10903, "*" + 10904, "*" + 10905, "*" + 10906, "*" + 10907, "*" + 10908, "*" + 10909, "*" + 10910, "*" + 10911, "*" + 10912, "*" + 10913, "*" + 10914, "*" + 10915, "*" + 10916, "*" + 10917, "*" + 10918, "*" + 10919, "*" + 10920, "*" + 11101, "Area name" + 11102, "Rectangle 1" + 11103, "Rectangle 2" + 11104, "Rectangle 3" + 11105, "Rectangle 4" + 11106, "Rectangle 5" + 11107, "Rectangle 6" + 11108, "Rectangle 7" + 11109, "Rectangle 8" + 11110, "Comment" + 11111, "*Begin special strs" + 11112, "*" + 11113, "*" + 11114, "*" + 11115, "*" + 11116, "*" + 11117, "*" + 11118, "*" + 11119, "*" + 11120, "*" + 11121, "*" + 11122, "*" + 11123, "*" + 11124, "*" + 11125, "*" + 11126, "*" + 11127, "*" + 11128, "*" + 11129, "*" + 11130, "*" + 11131, "*" + 11132, "*" + 11133, "*" + 11134, "*" + 11135, "*" + 11136, "*" + 11137, "*" + 11138, "*" + 11139, "*" + 11140, "*" + 11141, "*" + 11142, "*" + 11143, "*" + 11144, "*" + 11145, "*" + 11146, "*" + 11147, "*" + 11148, "*" + 11149, "*" + 11150, "*" + 11151, "*" + 11152, "*" + 11153, "*" + 11154, "*" + 11155, "*" + 11156, "*" + 11157, "*" + 11158, "*" + 11159, "*" + 11160, "*" + 11161, "*" + 11162, "*" + 11163, "*" + 11164, "*" + 11165, "*" + 11166, "*" + 11167, "*" + 11168, "*" + 11169, "*" + 11170, "*" + 11171, "*" + 11172, "*" + 11173, "*" + 11174, "*" + 11175, "*" + 11176, "*" + 11177, "*" + 11178, "*" + 11179, "*" + 11180, "*" + 11181, "*" + 11182, "*" + 11183, "*" + 11184, "*" + 11185, "*" + 11186, "*" + 11187, "*" + 11188, "*" + 11189, "*" + 11190, "*" + 11191, "*" + 11192, "*" + 11193, "*" + 11194, "*" + 11195, "*" + 11196, "*" + 11197, "*" + 11198, "*" + 11199, "*" + 11200, "*End of special strs" + 11209, "From here on, reserved for future use" + 11401, "Poison" + 11402, "Ice Bolt" + 11403, "Slow Group" + 11404, "Magic Map" + 11405, "Capture Soul" + 11406, "Simulacrum" + 11407, "Venom Arrows" + 11408, "Wall of Ice" + 11409, "Stealth" + 11410, "Major Haste" + 11411, "Firestorm" + 11412, "Dispel Barrier" + 11413, "Fire Barrier" + 11414, "Summoning" + 11415, "Shockstorm" + 11416, "Spray Fields" + 11417, "Major Poison" + 11418, "Group Fear" + 11419, "Kill" + 11420, "Paralyze" + 11421, "Daemon" + 11422, "Antimagic Cloud" + 11423, "Mindduel" + 11424, "Flight" + 11425, "Shockwave" + 11426, "Major Blessing" + 11427, "Mass Paralysis" + 11428, "Protection" + 11429, "Major Summoning" + 11430, "Force Barrier" + 11431, "Quickfire" + 11432, "Death Arrows" + 11450, "Cure All Poison" + 11451, "Curse All" + 11452, "Dispel Undead" + 11453, "Remove Curse" + 11454, "Sticks to Snakes" + 11455, "Martyr's Shield" + 11456, "Cleanse" + 11457, "Firewalk" + 11458, "Bless Party" + 11459, "Major Heal" + 11460, "Raise Dead" + 11461, "Flamestrike" + 11462, "Mass Sanctuary" + 11463, "Summon Host" + 11464, "Shatter" + 11465, "Dispel Fields" + 11466, "Heal All" + 11467, "Revive" + 11468, "Hyperactivity" + 11469, "Destone" + 11470, "Summon Guardian" + 11471, "Mass Charm" + 11472, "Protective Circle" + 11473, "Pestilence" + 11474, "Revive All" + 11475, "Ravage Spirit" + 11476, "Resurrect" + 11477, "Divine Thud" + 11478, "Avatar" + 11479, "Wall of Blades" + 11480, "Word of Recall" + 11481, "Major Cleansing" + 11500, "Weak Curing" + 11501, "Weak Healing" + 11502, "Weak Poison" + 11503, "Weak Speed" + 11504, "Medium Poison" + 11505, "Medium Healing" + 11506, "Strong Curing" + 11507, "Medium Speed" + 11508, "Graymold Salve" + 11509, "Weak Power" + 11510, "Potion of Clarity" + 11511, "Strong Poison" + 11512, "Strong Healing" + 11513, "Killer Poison" + 11514, "Resurrection Balm" + 11515, "Medium Power" + 11516, "Knowledge Brew" + 11517, "Strong Strength" + 11518, "Bliss" + 11519, "Strong Power" + 12001, "Regular speech" + 12002, "Unused" + 12003, "Unused" + 12004, "Unused" + 12005, "Unused" + 12006, "First part of response ..." + 12007, "Second part of response ..." + 12008, "Response depends on flag" + 12009, "Stuff Done flag Pt. A" + 12010, "Stuff Done flag Pt. B" + 12011, "Value to compare to" + 12012, "Unused" + 12013, "Response if less than or equal to" + 12014, "Response if greater than" + 12015, "Set flag to 1" + 12016, "Stuff Done flag Pt. A" + 12017, "Stuff Done flag Pt. B" + 12018, "Unused" + 12019, "Unused" + 12020, "First part of response ..." + 12021, "Second part of response ..." + 12022, "Inn" + 12023, "Cost of Inn" + 12024, "Quality of Inn (0 .. 3)" + 12025, "Move party to X" + 12026, "Move party to Y" + 12027, "Response if can afford it ..." + 12028, "Response if not enough money ..." + 12029, "Depends on Day" + 12030, "Day when response changes" + 12031, "Unused" + 12032, "Unused" + 12033, "Unused" + 12034, "Response if day not reached ..." + 12035, "Response if day reached ..." + 12036, "Depends on time (and event)" + 12037, "If this day has been reached ..." + 12038, "And this event did not heppen before it ..." + 12039, "Unused" + 12040, "Unused" + 12041, "Respond with this ..." + 12042, "Otherwise respond with this ..." + 12043, "Depends on town" + 12044, "Town to check" + 12045, "Unused" + 12046, "Unused" + 12047, "Unused" + 12048, "Response if in this town ..." + 12049, "Otherwise respond ..." + 12050, "Buy Items" + 12051, "Cost adjustment (0 .. 6)" + 12052, "Number of first item in shop" + 12053, "Total number of items in shop" + 12054, "Unused" + 12055, "Name of shop" + 12056, "Unused" + 12057, "Receive Training" + 12058, "Unused" + 12059, "Unused" + 12060, "Unused" + 12061, "Unused" + 12062, "Unused" + 12063, "Unused" + 12064, "Mage Spell Shop" + 12065, "Cost adjustment (0 .. 6)" + 12066, "Number of first spell in shop" + 12067, "Total number of spells in shop" + 12068, "Unused" + 12069, "Name of shop" + 12070, "Unused" + 12071, "Priest Spell Shop" + 12072, "Cost adjustment (0 .. 6)" + 12073, "Number of first spell in shop" + 12074, "Total number of spells in shop" + 12075, "Unused" + 12076, "Name of shop" + 12077, "Unused" + 12078, "Alchemy Shop" + 12079, "Cost adjustment (0 .. 6)" + 12080, "Number of first recipe in shop" + 12081, "Total number of recipes in shop" + 12082, "Unused" + 12083, "Name of shop" + 12084, "Unused" + 12085, "Healer" + 12086, "Cost adjustment (0 .. 6)" + 12087, "Unused" + 12088, "Unused" + 12089, "Unused" + 12090, "Name of healer" + 12091, "Unused" + 12092, "Sell Weapons" + 12093, "Unused" + 12094, "Unused" + 12095, "Unused" + 12096, "Unused" + 12097, "Buyer's response" + 12098, "Unused" + 12099, "Sell Armor" + 12100, "Unused" + 12101, "Unused" + 12102, "Unused" + 12103, "Unused" + 12104, "Buyer's response" + 12105, "Unused" + 12106, "Sell All Items" + 12107, "Unused" + 12108, "Unused" + 12109, "Unused" + 12110, "Unused" + 12111, "Buyer's response" + 12112, "Unused" + 12113, "Identify Items" + 12114, "Cost to identify" + 12115, "Unused" + 12116, "Unused" + 12117, "Unused" + 12118, "Person identifying items says:" + 12119, "Unused" + 12120, "Enchant Weapons" + 12121, "Type of enchantment (See docs. for list)" + 12122, "Unused" + 12123, "Unused" + 12124, "Unused" + 12125, "Person augmenting items says:" + 12126, "Unused" + 12127, "Pay For Response" + 12128, "Amount of gold taken" + 12129, "Unused" + 12130, "Unused" + 12131, "Unused" + 12132, "Response if party has gold" + 12133, "Response if they don't" + 12134, "Buy response, Change Flag" + 12135, "Amount of gold taken" + 12136, "Stuff Done Flag, Pt. A" + 12137, "Stuff Done Flag, Pt. B" + 12138, "Change flag to" + 12139, "Response if party has gold" + 12140, "Response if they don't" + 12141, "Ship Shop" + 12142, "Cost of Boat" + 12143, "Number of first boat sold" + 12144, "Total number of boats sold" + 12145, "Unused" + 12146, "Response if party has gold" + 12147, "Response if they don't" + 12148, "Horse Shop" + 12149, "Cost of Horse" + 12150, "Number of first horse sold" + 12151, "Total number of horses sold" + 12152, "Unused" + 12153, "Response if party has gold" + 12154, "Response if they don't" + 12155, "Buy Special Item" + 12156, "Number of item being sold" + 12157, "Cost of item" + 12158, "Unused" + 12159, "Unused" + 12160, "Response if party buys it" + 12161, "Response if party can't afford it" + 12162, "Buy Stuff Done flag change" + 12163, "Amount of Gold taken" + 12164, "Stuff Done Flag, Pt. A" + 12165, "Stuff Done Flag, Pt. B" + 12166, "Value to change flag to" + 12167, "Response if party buys it" + 12168, "Response if party can't afford it" + 12169, "Reveal Town Location" + 12170, "Cost to know where town is" + 12171, "Number of town to reveal" + 12172, "Unused" + 12173, "Unused" + 12174, "Response if party can pay" + 12175, "Response if party can't afford it" + 12176, "Force Conversation End" + 12177, "Unused" + 12178, "Unused" + 12179, "Unused" + 12180, "Unused" + 12181, "First part of response" + 12182, "Second part of response" + 12183, "Hostile Conversation End" + 12184, "Unused" + 12185, "Unused" + 12186, "Unused" + 12187, "Unused" + 12188, "First part of response" + 12189, "Second part of response" + 12190, "Town Hostile Conv. End" + 12191, "Unused" + 12192, "Unused" + 12193, "Unused" + 12194, "Unused" + 12195, "First part of response" + 12196, "Second part of response" + 12197, "Eliminate Creature" + 12198, "Unused" + 12199, "Unused" + 12200, "Unused" + 12201, "Unused" + 12202, "First part of response" + 12203, "Second part of response" + 12204, "Call Town Special" + 12205, "Number of town special node to call" + 12206, "Unused" + 12207, "Unused" + 12208, "Unused" + 12209, "First part of response (if no other response given in special)" + 12210, "Second part of response (if no other response given in special)" + 12211, "Call Scenario Special" + 12212, "Number of scenario special node to call" + 12213, "Unused" + 12214, "Unused" + 12215, "Unused" + 12216, "First part of response (if no other response given in special)" + 12217, "Second part of response (if no other response given in special)" +} diff --git a/Win32/Blades of Exile/GLOBAL.CPP b/Win32/Blades of Exile/GLOBAL.CPP new file mode 100644 index 00000000..55f22fd9 --- /dev/null +++ b/Win32/Blades of Exile/GLOBAL.CPP @@ -0,0 +1,129 @@ +#include +#include "global.h" +#include "math.h" +#include "globvar.h" + +RECT RECT16::rect32() +{ + RECT tmp; + tmp.left = left; + tmp.top = top; + tmp.right = right; + tmp.bottom = bottom; + return tmp; +} + +RECT16::RECT16 (const RECT & tmp) +{ + left = tmp.left; + top = tmp.top; + right = tmp.right; + bottom = tmp.bottom; +} + +RECT16 & RECT16::operator=(const RECT & tmp) +{ + left = tmp.left; + top = tmp.top; + right = tmp.right; + bottom = tmp.bottom; + return (*this); +} + +POINT MAKEPOINT(LONG lParam) +{ + POINT point; + + point.x = LOWORD(lParam); + point.y = HIWORD(lParam); + + return point; +} + +void DebugQuit(char * msg) +{ + MessageBox(0, msg, "DebugQuit", MB_OK); + PostQuitMessage(EXIT_FAILURE); + PostQuitMessage(EXIT_FAILURE); + PostQuitMessage(EXIT_FAILURE); +} + +void alter_rect(RECT *r) +{ + long a; + + a = r->top; + r->top = r->left; + r->left = a; + a = r->bottom; + r->bottom = r->right; + r->right = a; +} + +void alter_rect(RECT16 *r) +{ + short a; + + a = r->top; + r->top = r->left; + r->left = a; + a = r->bottom; + r->bottom = r->right; + r->right = a; +} + +short get_ran (short times, short min, short max) +{ + short store; + short i, to_ret = 0; + + if ((max - min + 1) == 0) + return 0; + + for (i = 1; i < times + 1; i++) + { + store = rand() % (max - min + 1); + to_ret = to_ret + min + store; + } + return to_ret; +} + +Boolean same_point(location p1,location p2) +{ + if ((p1.x == p2.x) && (p1.y == p2.y)) + return TRUE; + else return FALSE; +} + +short s_pow(short x,short y) +{ + if (y == 0) + return 1; + return (short) pow((double) x, (double) y); +} + +void Delay(short val, long *) +{ + long then,now,wait_val; + + wait_val = (long) val; + wait_val = wait_val * 16; + then = (long)GetCurrentTime(); + now = then; + while (now - then < wait_val) { + now = (long) GetCurrentTime(); + } +} + +void pause(short length) +{ + if (give_delays == 0) Delay(length, NULL); +} + +// stuff done legit, i.e. flags are within proper ranges for stuff done flag +Boolean sd_legit(short a, short b) +{ + if ((minmax(0,299,(int)a) == a) && (minmax(0,9,(int)b) == b)) + return TRUE; + return FALSE; +} diff --git a/Win32/Blades of Exile/GLOBAL.H b/Win32/Blades of Exile/GLOBAL.H new file mode 100644 index 00000000..38637ac5 --- /dev/null +++ b/Win32/Blades of Exile/GLOBAL.H @@ -0,0 +1,466 @@ +#ifndef _GLOBAL_H + #define _GLOBAL_H + +#include +#include /* for sprintf */ +#include +#include + +#include "consts.h" +#include "item.h" +#include "location.h" +#include "pc.h" + +#define huge + + + +/*GK+*/ +typedef unsigned char BYTE; + +POINT MAKEPOINT(LONG lparam); +extern HINSTANCE store_hInstance; +void DebugQuit(char * msg); + +struct RECT16 +{ + short left; + short top; + short right; + short bottom; + + RECT rect32(); + RECT16 () {} + RECT16 (const RECT & ); + RECT16 & operator=(const RECT &); +}; + +#define T_M 60 + +#define NUM_TOWN_ITEMS 115 + +#define BITMAP_WIDTH 28 +#define BITMAP_HEIGHT 36 + +#define STORED_GRAPHICS 240 + +#define PC_WIN_UL_X 291 +#define PC_WIN_UL_Y 5 +#define ITEM_WIN_UL_X 291 +#define ITEM_WIN_UL_Y 130 +#define TEXT_WIN_UL_X 291 +#define TEXT_WIN_UL_Y 283 +#define NUM_BUTTONS 15 +#define ASB add_string_to_buf +#define PSD party.stuff_done +#define FCD fancy_choice_dialog +#define NUM_MONST_G 173 + +typedef char Boolean; + +struct shortloc { short x, y; }; + +struct special_node_type +{ + short type,sd1,sd2,pic,m1,m2,ex1a,ex1b,ex2a,ex2b,jumpto; + + void flip(); /* reverse byte order */ +}; + +typedef struct { + short personality,type; + char link1[4],link2[4]; + short extras[4]; + } talking_node_type; + +typedef struct { + unsigned char strlens[200]; + talking_node_type talk_nodes[60]; + } talking_record_type; + +typedef struct { + short picture; + unsigned char blockage,flag1,flag2,special,trans_to_what,fly_over,boat_over; + unsigned char block_horse,light_radius,step_sound,shortcut_key,res1,res2,res3; + } terrain_type_type; + +struct wandering_type +{ + unsigned char monst[4]; + + bool isNull() const; +}; + +struct out_wandering_type +{ + unsigned char monst[7]; + unsigned char friendly[3]; + short spec_on_meet,spec_on_win,spec_on_flee,cant_flee; + short end_spec1,end_spec2; + + bool isNull() const; +}; + +struct outdoor_record_type +{ + unsigned char terrain[48][48]; + location special_locs[18]; + unsigned char special_id[18]; + location exit_locs[8]; + char exit_dests[8]; + location sign_locs[8]; + out_wandering_type wandering[4],special_enc[4]; + location wandering_locs[4]; + RECT16 info_rect[8]; + unsigned char strlens[180]; + special_node_type specials[60]; + + void flip(); /* reverse byte order */ +}; + +typedef struct { + unsigned char number; + unsigned char start_attitude; + location start_loc; + unsigned char mobile; + unsigned char time_flag; + unsigned char extra1,extra2; + short spec1, spec2; + char spec_enc_code, time_code; + short monster_time,personality; + short special_on_kill,facial_pic; + } creature_start_type; + +typedef struct { + location item_loc; + short item_code,ability; + unsigned char charges,always_there,property,contained; + } preset_item_type; + +typedef struct { + location field_loc; + short field_type; + } preset_field_type; + +struct town_record_type +{ + short town_chop_time,town_chop_key; + wandering_type wandering[4]; + location wandering_locs[4]; + location special_locs[50]; + unsigned char spec_id[50]; + location sign_locs[15]; + short lighting; + location start_locs[4]; + location exit_locs[4]; + short exit_specs[4]; + RECT16 in_town_rect; + preset_item_type preset_items[64]; + short max_num_monst; + preset_field_type preset_fields[50]; + short spec_on_entry,spec_on_entry_if_dead; + short timer_spec_times[8]; + short timer_specs[8]; + unsigned char strlens[180]; + special_node_type specials[100]; + unsigned char specials1,specials2,res1,res2; + short difficulty; + + /* functions */ + location getSpecLoc(int spec); +}; + +struct big_tr_type +{ + unsigned char terrain[64][64]; + RECT16 room_rect[16]; + creature_start_type creatures[60]; + unsigned char lighting[8][64]; +}; + +typedef struct { + unsigned char terrain[48][48]; + RECT16 room_rect[16]; + creature_start_type creatures[40]; + unsigned char lighting[6][48]; + } ave_tr_type; + +typedef struct { + unsigned char terrain[32][32]; + RECT16 room_rect[16]; + creature_start_type creatures[30]; + unsigned char lighting[4][32]; + } tiny_tr_type; + +typedef struct { + item_record_type scen_items[400]; + char monst_names[256][20]; + char ter_names[256][30]; + } scen_item_data_type; + +typedef struct { + short ter_type,item_num[10],item_odds[10],property; + } item_storage_shortcut_type; + +typedef struct { + unsigned char m_num,level,m_name[26]; + short health,m_health,mp,max_mp; + unsigned char armor,skill; + short a[3]; + unsigned char a1_type,a23_type,m_type,speed,ap,mu,cl,breath,breath_type,treasure,spec_skill,poison; + short morale,m_morale; + short corpse_item,corpse_item_chance; + short status[15]; + unsigned char direction,immunities,x_width,y_width,radiate_1,radiate_2; + unsigned char default_attitude,summon_type,default_facial_pic,res1,res2,res3; + short picture_num; + } monster_record_type; + +/* CREATURE_DATA_TYPE */ +class creature_data_type +{ + /* variables */ +public: + short active,attitude; + unsigned char number; + location m_loc; + monster_record_type m_d; + Boolean mobile; + short summoned; + creature_start_type monst_start; + + /* functions */ +private: + void adjustMagic(short *how_much); +public: + void poison(short how_much); + void acid(short how_much); + void slow(short how_much); + void curse(short how_much); + void web(short how_much); + void scare(short how_much); + void disease(short how_much); + void dumbfound(short how_much); + void charm(short penalty, short which_status, short amount); + void record(); +}; + +typedef struct { + location horse_loc,horse_loc_in_sec,horse_sector; + short which_town; + Boolean exists,property; + } horse_record_type; + +typedef struct { + location boat_loc,boat_loc_in_sec,boat_sector; + short which_town; + Boolean exists,property; +} boat_record_type; + +typedef struct { + unsigned char flag1, flag2, flag3, flag4; + unsigned char ver[3],min_run_ver,prog_make_ver[3],num_towns; + unsigned char out_width,out_height,difficulty,intro_pic,default_ground; + } scen_header_type; + +typedef struct { + unsigned char flag1, flag2, flag3, flag4; + unsigned char ver[3],min_run_ver,prog_make_ver[3],num_towns; + unsigned char out_width,out_height,difficulty,intro_pic,default_ground; + unsigned char town_size[200]; + unsigned char town_hidden[200],a; + short flag_a; + short intro_mess_pic,intro_mess_len; + location where_start,out_sec_start,out_start; + short which_town_start; + short flag_b; + short town_data_size[200][5]; + short town_to_add_to[10]; + short flag_to_add_to_town[10][2]; + short flag_c; + short out_data_size[100][2]; + RECT16 store_item_rects[3]; + short store_item_towns[3]; + short flag_e; + short special_items[50]; + short special_item_special[50]; + short rating,uses_custom_graphics; + short flag_f; + monster_record_type scen_monsters[256]; + boat_record_type scen_boats[30]; + horse_record_type scen_horses[30]; + short flag_g; + terrain_type_type ter_types[256]; + short scenario_timer_times[20]; + short scenario_timer_specs[20]; + short flag_h; + special_node_type scen_specials[256]; + item_storage_shortcut_type storage_shortcuts[10]; + short flag_d; + unsigned char scen_str_len[300]; + short flag_i; + location last_out_edited; + short last_town_edited; + } scenario_data_type; + +// for game +typedef struct { + short personality; + short town_num; + short str1,str2; + } talk_save_type; + +typedef struct { + creature_data_type dudes[60]; + short which_town; + short friendly; + } creature_list_type; + +struct current_town_type +{ + short town_num, difficulty; + town_record_type town; + char explored[64][64]; + Boolean hostile; + creature_list_type monst; + Boolean in_boat; + location p_loc; + + /* functions */ + short placeMonster(unsigned char which, location where); + short countMonsters(); + void activateMonsters(short code); +}; + +struct outdoor_creature_type +{ + Boolean exists; + short direction; + out_wandering_type what_monst; + location which_sector,m_loc; +}; + +struct party_record_type +{ + long age; + unsigned short gold,food; + unsigned char stuff_done[310][10],item_taken[200][8]; //stuff_done[309] is compatibility switch + short light_level; + location outdoor_corner,i_w_c,p_loc,loc_in_sec; + boat_record_type boats[30]; + horse_record_type horses[30]; + creature_list_type creature_save[4]; + short in_boat,in_horse; + outdoor_creature_type out_c[10]; + item_record_type magic_store_items[5][10]; + short imprisoned_monst[4]; + char m_seen[256]; + char journal_str[50]; + short journal_day[50]; + short special_notes_str[140][2]; + talk_save_type talk_save[120]; + short direction,at_which_save_slot; + char alchemy[20]; + Boolean can_find_town[200]; + short key_times[100]; + short party_event_timers[30]; + short global_or_town[30]; + short node_to_call[30]; + char spec_items[50],help_received[120]; + short m_killed[200]; + unsigned long total_m_killed,total_dam_done,total_xp_gained,total_dam_taken; + char scen_name[256]; + + /* functions */ + bool isFlying() { return (bool) stuff_done[305][1]; } + + void giveGold(short amount, bool print_result); + bool takeGold(short amount, bool print_result); + void giveFood(short amount, bool print_result); + short takeFood(short amount, bool print_result); +}; + +typedef struct { char town_maps[200][8][64]; } stored_town_maps_type; +typedef struct { char town_strs[180][256]; } piles_of_stuff_dumping_type; + +typedef struct { + char scen_header_strs[100][3][80]; + char scen_names[100][256]; + scen_item_data_type scen_item_list; + } piles_of_stuff_dumping_type2; + +typedef struct { char talk_strs[170][256]; } piles_of_stuff_dumping_type3; +typedef struct { char out_strs[9][256]; } outdoor_strs_type; +typedef struct { outdoor_strs_type outdoor_text[2][2]; } piles_of_stuff_dumping_type4; +typedef struct { char scen_strs[160][256]; } piles_of_stuff_dumping_type5; + +class pc_array +{ +private: + //pc_record_type pc[6]; + pc_record_type pc[NUM_OF_PCS]; + +public: + pc_record_type & operator[](int num) { return pc[num]; } + + /* remember - all this functions refer to all PCs */ + void affect(short type, short how_much); + void cure(short how_much); /* cure all */ + void disease(short how_much); /* disease all */ + void dumbfound(short how_much); /* dumb all */ + void damage(short how_much, short damage_type); /* damage all */ + void heal(short how_much); /* heal all */ + void kill(short mode); /* kill all */ + void poison(short how_much); /* poison all */ + + void drainXP(short how_much); // drain experience points + + void giveXP(short how_much); // give experience points + + void restoreSP(short how_much); // restore spell points + + bool hasAbil(short ability); + + bool isPoisoned(); /* is someone posioned? */ + + short getMageLore(); /* count total mage lore */ + short getTotalLevel(); + short getTotalLuck(); + + bool checkClass(short item_class,short mode); +}; + +typedef struct { unsigned char setup[4][64][64]; } setup_save_type; +typedef struct { unsigned char pattern[9][9]; } effect_pat_type; +typedef struct { item_record_type items[NUM_TOWN_ITEMS]; } stored_items_list; +typedef struct { char outdoor_maps[100][6][48]; } stored_outdoor_maps_type; + +short s_pow(short x,short y); +short get_ran (short times, short min, short max); +Boolean same_point(location p1,location p2); +void pause(short length); +void Delay(short val,long *dummy); +void alter_rect(RECT *r) ; +void alter_rect(RECT16 *r) ; +Boolean sd_legit(short a, short b); + +template +T minmax(T min, T max, T k) +{ + return (k < min)? min : (k > max)? max : k; +}; + +template +T ex_abs(T value) +{ + return (value < 0)? (-value) : value; +}; + +template +void move_to_zero(T & value) +{ + if (value > 0) --value; + else if (value < 0) ++value; +}; + +#endif diff --git a/Win32/Blades of Exile/GLOBVAR.CPP b/Win32/Blades of Exile/GLOBVAR.CPP new file mode 100644 index 00000000..933748ea --- /dev/null +++ b/Win32/Blades of Exile/GLOBVAR.CPP @@ -0,0 +1,965 @@ +#include "globvar.h" + +RECT bottom_buttons[7]; +RECT town_buttons[10]; +RECT combat_buttons[9]; +RECT world_screen = {23, 23, 274,346}; +RECT item_screen_button_rects[9] = +{ + {11,126,28,140},{40,126,57,140},{69,126,86,140}, + {98,126,115,140},{127,126,144,140},{156,126,173,140}, + {176,126,211,141},{213,126,248,141},{251,127,267,139} +}; +RECT border_rect[4] = +{ + {5, 5, 283, 15}, {5, 5, 15, 355}, + {5, 345, 283, 355}, {273, 5, 283, 355} +}; +RECT medium_buttons[4] = +{ + {190, 383,225,401}, {190, 402, 225, 420}, + {227, 383, 263, 401}, {227, 402, 263,420} +}; +RECT startup_top; +RECT item_buttons[8][6]; // name, use, give, drip, info, sell/id +RECT pc_buttons[6][5]; // name, hp, sp, info, trade +short special_queue[20]; +Boolean end_scenario = FALSE; +// For menu spell casting, some info needs to be stored up here. +short mage_need_select[62] = {0,0,1,1,0,0,0,0,0,0, 0,0,0,0,1,0,0,0,0,0, 0,1,0,0,0,0,0,0,0,1, + 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,1,0,0,0,0}; +short priest_need_select[62] = {1,1,1,0,0,1,1,0,0,0, 1,1,0,0,0,0,0,0,0,1, 1,0,0,0,1,0,0,1,1,0, + 0,0,0,1,0,1,1,0, 0,1,2,0,0,0,0,0, 0,1,0,2,0,0,0,0, 0,0,2,0,0,0,0,0}; +// 0 - no select 1 - active only 2 - any existing +Boolean item_area_button_active[8][6]; +Boolean pc_area_button_active[6][5]; +short item_bottom_button_active[9] = {0,0,0,0,0, 0,1,1,1}; +RECT pc_help_button,pc_area_rect,item_area_rect; +short num_out_moves = 0; +short store_drop_item; +short current_switch = 6; +out_wandering_type store_wandering_special; +short store_shop_type; +short debug_ok = 0; +short store_selling_values[8] = {0,0,0,0,0,0,0,0}; +char *dir_string[] = {"North", "NorthEast", "East", "SouthEast", "South", "SouthWest", "West", "NorthWest"}; +char get_new_terrain(); +item_record_type start_items[6] = +{ + {1,4, 0,1,0,0,1,0, 45,0,0,0,0,0, 2, 7,0, location(),"Bronze Knife","Knife",0,1,0,0}, + {12,1,1,0,0,0,0,0, 65,0,0,0,0,0, 2, 20,0, location(),"Crude Buckler","Buckler",0,1,0,0}, + {4,0,0,0,0,0,0,0, 10,0,0,0,0,0, 15, 20,0, location(),"Cavewood Bow","Bow",0,1,0,0}, + {5,12,0,0,0,12,0,0, 47,0,0,0,0,0, 1, 1,0, location(),"Arrows","Arrows",0,1,0,0}, + {2,9,0,0,0,0,3,0, 4,0,0,0,0,0, 10, 30,0, location(),"Stone Spear","Spear",0,1,0,0}, + {14,1,0,0,0,0,0,0, 66,0,0,0,0,0, 6, 15,0, location(),"Leather Helm","Helm",0,1,0,0} +}; +// 0 - whole area, 1 - active area 2 - graphic 3 - item name +// 4 - item cost 5 - item extra str 6 - item help button +RECT shopping_rects[8][7]; +unsigned char out[96][96]; +unsigned char out_e[96][96]; +unsigned char misc_i[64][64],sfx[64][64]; +/* Mac stuff globals */ +HWND text_sbar = NULL,item_sbar = NULL,shop_sbar = NULL; +RECT sbar_rect = {545,284,562,421}; +RECT shop_sbar_rect = {258,67,274,357}; +RECT item_sbar_rect = {545,146,562,254}; +int dialog_answer; +POINT store_anim_ul; +Boolean All_Done = FALSE, dialog_not_toast = FALSE; +Boolean in_startup_mode = TRUE; +Boolean play_sounds; +Boolean spell_forced = FALSE,startup_loaded = FALSE; +Boolean save_maps = TRUE,party_in_memory = FALSE,in_scen_debug = FALSE; +Boolean window_in_front = FALSE; +Boolean belt_present = FALSE; +Boolean game_run_before = TRUE; +Boolean debug_on = FALSE, give_intro_hint = TRUE; +short on_spell_menu[2][62]; +short on_monst_menu[256]; +short current_cursor = 120; +HCURSOR arrow_curs[3][3], sword_curs, key_curs, target_curs,talk_curs,look_curs; +/* Adventure globals */ +party_record_type party; +outdoor_record_type outdoors[2][2]; +current_town_type c_town; +big_tr_type t_d; +stored_items_list t_i; +setup_save_type setup_save; +location monster_targs[T_M]; +/* Display globals */ +short combat_posing_monster = -1, current_working_monster = -1; // 0-5 PC 100 + x - monster x +Boolean fast_bang = FALSE; +short spec_item_array[60]; +short overall_mode = 45,current_spell_range; +Boolean first_update = TRUE,anim_onscreen = FALSE,frills_on = TRUE,suppress_stat_screen = FALSE; +short stat_window = 0; +Boolean monsters_going = FALSE,boom_anim_active = FALSE,cartoon_happening = FALSE; +short give_delays = 0; +Boolean modeless_exists[18] = {FALSE,FALSE,FALSE,FALSE,FALSE,FALSE, + FALSE,FALSE,FALSE,FALSE,FALSE,FALSE, + FALSE,FALSE,FALSE,FALSE,FALSE,FALSE}; +HWND modeless_dialogs[18] = {NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL}; +short town_size[3] = {64,48,32}; +short ulx = 0, uly = 0; +short display_mode = 0; // 0 - center 1- ul 2 - ur 3 - dl 4 - dr 5 - small win +short current_ground = 0,stat_screen_mode = 0; +long anim_ticks = 0; +// Spell casting globals +short store_mage = 0, store_priest = 0; +short store_mage_lev = 0, store_priest_lev = 0; +short store_spell_target = 6,pc_casting; +short pc_last_cast[2][6] = {{1,1,1,1,1,1},{1,1,1,1,1,1}}; +int num_targets_left = 0; +location spell_targets[8]; +long store_mouse; +/* Combat globals */ +short which_combat_type,town_type; +location center; +unsigned char combat_terrain[64][64]; +location pc_pos[6]; +short current_pc; +short combat_active_pc; +effect_pat_type current_pat; +short monst_target[T_M]; // 0-5 target that pc 6 - no target 100 + x - target monster x +short spell_caster, missile_firer,current_monst_tactic; +short store_current_pc = 0; +stored_items_list stored_items[3]; +stored_outdoor_maps_type o_maps; +// Special stuff booleans +Boolean web,crate,barrel,fire_barrier,force_barrier,quickfire,force_wall,fire_wall,antimagic,scloud,ice_wall,blade_wall; +Boolean sleep_field; +/* Windoze stuff globals */ +Boolean cursor_shown = TRUE; +HWND mainPtr; +HFONT font,fantasy_font,small_bold_font,italic_font,underline_font,bold_font,tiny_font; +HDC main_dc,main_dc2,main_dc3; +HINSTANCE store_hInstance; +HACCEL accel; +BOOL event_handled; +scenario_data_type scenario; +talking_record_type talking; +char scen_strs2[110][256]; +stored_town_maps_type town_maps; +char szWinName[] = "BoE Dialogs"; +char szAppName[] = "BoE for Win32"; +char file_path_name[256]; +Boolean block_erase = FALSE; +/* dynamically allocated */ +piles_of_stuff_dumping_type *data_store; +piles_of_stuff_dumping_type2 *data_store2; +piles_of_stuff_dumping_type3 *data_store3; +piles_of_stuff_dumping_type4 *data_store4; +piles_of_stuff_dumping_type5 *data_store5; +/* end of dynamically allocated */ +char create_line[60]; +short spell_being_cast; +short missile_inv_slot, ammo_inv_slot; +short force_wall_position = 10; // 10 -> no force wall +Boolean processing_fields = TRUE; +short futzing; +unsigned char store_sum_monst; +short store_sum_monst_cost; +location out_start_loc = location(20,23); +short hit_chance[51] = {20,30,40,45,50,55,60,65,69,73, + 77,81,84,87,90,92,94,96,97,98,99 + ,99,99,99,99,99,99,99,99,99,99 + ,99,99,99,99,99,99,99,99,99,99, + 99,99,99,99,99,99,99,99,99,99}; +short s_cost[2][62] = {{1,1,1,1,1,2,50,2,1,3, 2,3,2,2,2,2,4,4,2,6, 3,3,5,3,3,5,6,4,6,4, + 4,5,4,8,30,-1,8,6, 5,8,8,6,9,10,6,6, 7,6,8,7,12,10,12,20, 12,8,20,10,14,10,50,10}, + {1,1,1,2,1,1,3,5,50,1, 2,2,2,2,3,5,8,6,4,2, 3,4,3,3,3,10,5,3,4,6, + 5,5,5,15,6,5,5,8, 6,7,25,8,10,12,12,6, 8,7,8,8,14,17,8,7, 10,10,35,10,12,12,30,10}}; +short mage_range[80] = {0,6,0,0,7,7,0,14,8,0, 6,8,7,10,0,8,3,8,10,6, 0,0,12,0,10,12,4,10,8,0, + 8,12,12,0,10,4,8,8, 0,0,14,0,2,4,10,12, 8,12,6,8,5,8,4,0, 0,0,8,0,4,2,4,6 + ,10,8,8,12,8,10,10,10, 10,10,10,10,10,10,10,10,10,10}; +short priest_range[62] = {0,0,0,8,0,0,0,0,0,10, 0,0,10,0,6,4,0,6,6,8, 0,0,8,0,10,0,8,0,0,8, + 0,10,8,0,6,0,0,0, 0,0,0,9,0,4,0,8, 0,0,10,0,4,8,0,8, 0,4,0,12,0,10,0,0}; +short monst_mage_cost[27] = {1,1,1,1,2, 2,2,2,2,4, 2,4,4,3,4, 4,4,5,5,5, 5,6,6,6,7, 7,7}; +short monst_mage_area_effect[27] = {0,0,0,0,0, 0,0,0,1,0, 1,1,0,1,0, 0,0,0,1,0, 1,0,0,0,0, 0,0}; +short monst_priest_cost[26] = {1,1,1,1,2, 2,2,4,2,3, 3,3,4,4,4, 5,5,5,10,6, 6,10,8,8,8, 8}; +short monst_priest_area_effect[26] = {0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,1,0,0, 0,0,0,0,0, 1}; +char *d_string[] = +{ + "North", + "NorthEast", + "East", + "SouthEast", + "South", + "SouthWest", + "West", + "NorthWest" +}; +short pc_marked_damage[6]; +short monst_marked_damage[T_M]; +location hor_vert_place[14] = + { + location(0,0),location(-1,1),location(1,1),location(-2,2),location(0,2), + location(2,2),location(0,1),location(-1,2),location(1,2),location(-1,3), + location(1,3),location(0,3),location(0,4),location(0,5) + }; +location diag_place[14] = + { + location(0,0),location(-1,0),location(0,1),location(-1,1),location(-2,0), + location(0,2),location(-2,1),location(-1,2),location(-2,2),location(-3,2), + location(-2,3),location(-3,3),location(-4,3),location(-3,4) + }; +effect_pat_type single = {{{0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0}, + {0,0,0,0,1,0,0,0,0}, + {0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0}}}; +effect_pat_type t = {{{0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0}, + {0,0,0,0,1,0,0,0,0}, + {0,0,0,1,1,1,0,0,0}, + {0,0,0,0,1,0,0,0,0}, + {0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0}}}; +effect_pat_type small_square = {{{0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0}, + {0,0,0,0,1,1,0,0,0}, + {0,0,0,0,1,1,0,0,0}, + {0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0}}}; +effect_pat_type square = {{{0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0}, + {0,0,0,1,1,1,0,0,0}, + {0,0,0,1,1,1,0,0,0}, + {0,0,0,1,1,1,0,0,0}, + {0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0}}}; +effect_pat_type radius2 = +{{{0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0}, + {0,0,0,1,1,1,0,0,0}, + {0,0,1,1,1,1,1,0,0}, + {0,0,1,1,1,1,1,0,0}, + {0,0,1,1,1,1,1,0,0}, + {0,0,0,1,1,1,0,0,0}, + {0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0}}}; +effect_pat_type radius3 = {{{0,0,0,0,0,0,0,0,0}, + {0,0,0,1,1,1,0,0,0}, + {0,0,1,1,1,1,1,0,0}, + {0,1,1,1,1,1,1,1,0}, + {0,1,1,1,1,1,1,1,0}, + {0,1,1,1,1,1,1,1,0}, + {0,0,1,1,1,1,1,0,0}, + {0,0,0,1,1,1,0,0,0}, + {0,0,0,0,0,0,0,0,0}}}; +effect_pat_type field[8] = {{{{0,0,0,0,1,1,0,0,0}, + {0,0,0,0,1,1,0,0,0}, + {0,0,0,0,1,1,0,0,0}, + {0,0,0,0,1,1,0,0,0}, + {0,0,0,0,1,1,0,0,0}, + {0,0,0,0,1,1,0,0,0}, + {0,0,0,0,1,1,0,0,0}, + {0,0,0,0,1,1,0,0,0}, + {0,0,0,0,1,1,0,0,0}}}, + {{{0,0,0,0,0,0,0,0,1}, + {0,0,0,0,0,0,0,1,1}, + {0,0,0,0,0,0,1,1,0}, + {0,0,0,0,0,1,1,0,0}, + {0,0,0,0,1,1,0,0,0}, + {0,0,0,1,1,0,0,0,0}, + {0,0,1,1,0,0,0,0,0}, + {0,1,1,0,0,0,0,0,0}, + {1,1,0,0,0,0,0,0,0}}}, + {{{0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0}, + {1,1,1,1,1,1,1,1,1}, + {1,1,1,1,1,1,1,1,1}, + {0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0}}}, + {{{1,0,0,0,0,0,0,0,0}, + {1,1,0,0,0,0,0,0,0}, + {0,1,1,0,0,0,0,0,0}, + {0,0,1,1,0,0,0,0,0}, + {0,0,0,1,1,0,0,0,0}, + {0,0,0,0,1,1,0,0,0}, + {0,0,0,0,0,1,1,0,0}, + {0,0,0,0,0,0,1,1,0}, + {0,0,0,0,0,0,0,1,1}}}, + {{{0,0,0,1,1,0,0,0,0}, + {0,0,0,1,1,0,0,0,0}, + {0,0,0,1,1,0,0,0,0}, + {0,0,0,1,1,0,0,0,0}, + {0,0,0,1,1,0,0,0,0}, + {0,0,0,1,1,0,0,0,0}, + {0,0,0,1,1,0,0,0,0}, + {0,0,0,1,1,0,0,0,0}, + {0,0,0,1,1,0,0,0,0}}}, + {{{0,0,0,0,0,0,0,1,1}, + {0,0,0,0,0,0,1,1,0}, + {0,0,0,0,0,1,1,0,0}, + {0,0,0,0,1,1,0,0,0}, + {0,0,0,1,1,0,0,0,0}, + {0,0,1,1,0,0,0,0,0}, + {0,1,1,0,0,0,0,0,0}, + {1,1,0,0,0,0,0,0,0}, + {1,0,0,0,0,0,0,0,0}}}, + {{{0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0}, + {1,1,1,1,1,1,1,1,1}, + {1,1,1,1,1,1,1,1,1}, + {0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0}}}, + {{{1,1,0,0,0,0,0,0,0}, + {0,1,1,0,0,0,0,0,0}, + {0,0,1,1,0,0,0,0,0}, + {0,0,0,1,1,0,0,0,0}, + {0,0,0,0,1,1,0,0,0}, + {0,0,0,0,0,1,1,0,0}, + {0,0,0,0,0,0,1,1,0}, + {0,0,0,0,0,0,0,1,1}, + {0,0,0,0,0,0,0,0,1}}}}; +short last_attacked[6],pc_dir[6],pc_parry[6],pc_moves[6]; +Boolean center_on_monst; +short store_sign_mode; +short store_tip_page_on = 0; +// Talking vars +short store_pre_talk_mode,store_personality,shop_identify_cost; +HBITMAP talk_gworld ; +Boolean talk_end_forced; +char old_str1[256]; +char old_str2[256]; +char one_back1[256]; +char one_back2[256]; +RECT talk_area_rect = {5,5,284,420}, word_place_rect = {7,44,257,372},talk_help_rect = {254,5,272,21}; +/**/ +char title_string[50]; +unsigned char store_monst_type; +short store_m_num; +RECT dummy_rect = {0,0,0,0}; +short strnum1,strnum2,oldstrnum1,oldstrnum2; +short store_talk_face_pic,cur_town_talk_loaded = -1; +// Shopping vars +// 1 - 499 ... regular items +// 500 alchemy +// 600-620 ... food +// 700+ i - that healing +// 800 + - mage spells +// 900 + - priest spells +// n000 + i - magic store n item i +short store_shop_items[30]; +short store_shop_costs[30]; +// talk_area_rect and talk_help_rect used for this too +short store_shop_min,store_shop_max,store_pre_shop_mode,store_cost_mult; +char store_store_name[256]; +// 0 - whole area, 1 - active area 2 - graphic 3 - item name +// 4 - item cost 5 - item extra str 6 - item help button +RECT bottom_help_rects[4] = {{6,356,250,368},{6,374,270,386},{6,386,250,398},{6,398,250,410}}; +RECT shop_frame = {10,62,269,352}; +RECT shop_done_rect = {212,388,275,411}; /**/ +char *heal_types[] = {"Heal Damage","Cure Poison","Cure Disease","Cure Paralysis", + "Uncurse Items","Cure Stoned Character","Raise Dead","Resurrection","Cure Dumbfounding"}; +short heal_costs[9] = {50,30,80,100,250,500,1000,3000,100}; +long cost_mult[7] = {5,7,10,13,16,20,25}; +short cur_display_mode; +short terrain_pic[256]; +scen_header_type scen_headers[100]; +short store_scen_page_on,store_num_scen; +#define ND 15 +#define NI 500 +#define NL 100 +#define NUM_DLOG_B 53 +char text_long_str[10][256]; +char text_short_str[140][35]; +char labels[NL][25]; +Boolean label_taken[NL]; +HWND edit_box ; +HWND store_edit_parent; // kludgy +HDC dlg_force_dc ; // save HDCs when dealing with dlogs +short store_free_slot,store_dlog_num; +HWND store_parent; +short available_dlog_buttons[NUM_DLOG_B] = {0,63,64,65,1,4,5,8, + 128, + 9, + 10, // 10 + 11,12,13, + 14,15,16,17,29, 51, + 60,61,62, // 20 + 66,69,70, 71,72,73,74,79, + 80,83,86,87,88, 91,92,93,99,100, + 101,102,104, 129,130,131,132,133,134,135,136,137}; +short button_type[150] = {1,1,4,5,1,1,0,0,1,1, + 1,1,1,1,1,1,1,1,8,8, + 9,9,9,1,1,2,1,6,7,1, + 1,12,1,1,2,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0, + 0,1,1,1,2,1,1,1,2,2, // 50 + 1,1,1,1,1,1,2,3,1,1, + 1,1,1,1,2,2,2,2,2,1, + 1,1,1,1,2,2,1,1,1,2, + 0,1,1,1,14,13,12,12,12,1, + 1,1,1,2,1,2,2,2,2,1, // 100 + 2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,1,1, + 1,1,1,1,1,1,1,1,0,0, + 0,0,0,0,0,0,0,0,0,0}; +char *button_strs[150] = {"Done ","Ask"," "," ","Keep", "Cancel","+","-","Buy","Leave", + "Get","1","2","3","4","5","6","Cast"," "," ", + " "," "," ","Buy","Sell","Other Spells","Buy x10"," "," ","Save", + "Race","Train","Items","Spells","Heal Party","1","2","3","4","5", + "6","7","8","9","10","11","12","13","14","15", + /*50*/ "16","Take","Create","Delete","Race/Special","Skill","Name","Graphic","Bash Door","Pick Lock", + "Leave","Steal","Attack","OK","Yes","No","Step In"," ","Record","Climb", + "Flee","Onward","Answer","Drink","Approach","Mage Spells","Priest Spells","Advantages","New Game","Land", + "Under","Restore","Restart","Quit","Save First","Just Quit","Rest","Read","Pull","Alchemy", + "17","Push","Pray","Wait","","","Delete","Graphic","Create","Give", + /*100*/ "Destroy","Pay","Free","Next Tip","Touch", "Select Icon","Create/Edit","Clear Special","Edit Abilities","Choose", + "Go Back","Create New","General","One Shots","Affect PCs","If-Thens","Town Specs","Out Specs","Advanced","Weapon Abil", + "General Abil.","NonSpell Use","Spell Usable","Reagents","Missiles","Abilities","Pick Picture","Animated","Enter","Burn", + "Insert","Remove","Accept","Refuse","Open","Close","Sit","Stand","","", + "18","19","20","Invisible!","","","","","",""}; +short button_left_adj[150] = {0,0,0,0,0, 0,0,0,0,0, + 0,0,0,0,0, 0,0,0,0,0, + 0,0,0,0,0, 0,0,0,0,0, + 0,0,0,0,0, 0,0,0,0,0, + 0,0,0,0,0, 0,0,0,0,0, + 0,0,0,0,0, 0,0,0,0,0, // 50 + 0,0,0,0,0, 0,0,0,0,0, + 0,0,0,0,0, 0,0,0,0,0, + 0,0,0,0,0, 0,0,0,0,0, + 0,0,0,0,0, 0,0,0,0,0, + 0,0,0,0,0, 0,0,0,0,0, + 0,0,0,0,0, 0,0,0,0,0, + 0,0,0,0,0, 0,0,0,0,0, + 0,0,0,0,0, 0,0,0,0,0, + 0,0,0,0,0, 0,0,0,0,0}; +char button_def_key[150] = {0,0,20,21,'k', 24,0,0,0,0, + 'g','1','2','3','4', '5','6',0,0,0, + 0,0,0,0,0,' ',0,22,23,0, + 0,0,0,0,0,'1','2','3','4','5', + '6','7','8','9','a', 'b','c','d','e','f', + 'g',0,0,0,0,0,0,0,0,0, + 0,0,0,0,'y','n',0,'?','r',0, + 0,0,0,0,0,0,0,0,0, 0, + 0,0,0,0,0,0,0,0,0,0, + 'g',0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0 +}; +// specials ... 20 - <- 21 - -> 22 up 23 down 24 esc +// 25-30 ctrl 1-6 31 - return +short button_ul_x[15] = {0,46,0,126,0, 0,126,126,126,138, 166,0,0,126,172}; +short button_ul_y[15] = {0,0,132,23,46, 69,46,69,36,36, 36,23,92,92,0}; +short button_width[15] = {23,63,102,16,63, 63,63,63,6,14, 14,63,63,63,30}; +short button_height[15] = {23,23,23,13,23, 23,23,23,6,10,10,23,40,40,30}; +BOOL CALLBACK dummy_dialog_proc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam); +LRESULT CALLBACK fresh_edit_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); +DLGPROC d_proc; +WNDPROC edit_proc; +WNDPROC old_edit_proc; +#define NUM_SOUNDS 100 +HGLOBAL sound_handles[NUM_SOUNDS]; +char * snds[NUM_SOUNDS]; +short last_played = 10000; +short store_last_sound_played = 0; +HMODULE hModule; +Boolean always_asynch[100] = {FALSE,FALSE,FALSE,FALSE,FALSE, + TRUE,TRUE,FALSE,FALSE,FALSE, + TRUE,FALSE,FALSE,FALSE,FALSE, // 10 + FALSE,FALSE,FALSE,FALSE,FALSE, + FALSE,FALSE,TRUE,FALSE,TRUE, // 20 + TRUE,FALSE,FALSE,FALSE,FALSE, + FALSE,FALSE,FALSE,FALSE,TRUE, // 30 + FALSE,FALSE,TRUE,FALSE,TRUE, + FALSE,TRUE,TRUE,TRUE,TRUE, // 40 + TRUE,TRUE,TRUE,TRUE,TRUE, + TRUE,FALSE,FALSE,TRUE,FALSE, // 50 + TRUE,FALSE,FALSE,FALSE,FALSE, + FALSE,TRUE,FALSE,FALSE,FALSE, // 60 + FALSE,FALSE,FALSE,FALSE,FALSE, + FALSE,FALSE,FALSE,FALSE,FALSE, // 70 + FALSE,TRUE,TRUE,TRUE,TRUE, + TRUE,TRUE,TRUE,TRUE,FALSE, // 80 + TRUE,FALSE,FALSE,FALSE,FALSE, + FALSE,TRUE,FALSE,FALSE,FALSE, // 90 + FALSE,FALSE,FALSE,FALSE,FALSE}; +Boolean load_when_play[100] = { + 0,0,1,1,1,0,0,1,1,1, + 0,0,0,1,0,1,1,1,1,1, + 1,1,0,1,1,1,1,0,1,1, + 1,1,1,1,0,1,1,0,1,1, + 1,1,1,1,1,1,1,0,0,0, + 0,1,1,0,1,0,1,1,1,1, // 50 + 1,0,1,1,1,1,1,1,1,0, + 0,0,0,0,0,0,0,0,0,0, // 70 + 1,1,1,1,1,0,0,0,0,0, + 1,0,1,1,1,1,1,1,1,0 +}; +short can_ignore[100] = { + 0,0,0,0,0,5,3,0,0,0, + 5,5,5,0,5,0,0,0,0,0, + 0,0,5,0,0,0,0,0,0,2, + 2,2,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,1,1,1, + 1,0,0,5,0,1,0,0,0,0, // 50 + 0,0,0,0,5,0,0,0,0,0, + 0,0,0,0,0, 0,5,5,5,5, // 70 + 4,4,4,4,0,0,0,0,0,0, + 0,5,5,0,0,0,0,0,0,0}; +// 1 - polite asych, 1 or 2 or 3- lose easily when pref is set for fewer snds +// 3 can be async +// 4 - nostop asynch ... when 4, this sound is NOSTOP, i.e. when played, is played +// asynch, and refuses all other sounds. Sounds that come in are ignored, and +// disappear into the ether +// 5 - finally, bold asynch ... when 5, this sound is NOSTOP, i.e. when played, is played +// asynch, and refuses all other sounds. When a sound is played on top of this, game +// hangs on until sound is done, and then and only then plays later sound. +Boolean sounds_fucked = FALSE; +long intro_music_start_time = -1; +HBITMAP spec_scen_g ; +typedef struct { + char expl[96][96]; +} out_info_type; +Boolean loaded_yet = FALSE; +Boolean cur_scen_is_win = TRUE; +void print_write_position (); +char szFileName [128] = "blades.sav"; +char szTitleName [128] = "blades.sav"; +OPENFILENAME ofn; +// Trying this to fix bug. Hope it works. +tiny_tr_type tiny_t; +ave_tr_type ave_t; +outdoor_record_type dummy_out;//// +town_record_type dummy_town; +HBITMAP bg_bitmap[14]; +HBRUSH checker_brush ; +HBITMAP checker_bitmap ,bw_bitmap; +HBITMAP startup_button_orig,startup_button_g,anim_mess ; +Boolean done_fancy_startup_once = FALSE; +short terrain_there[9][9]; // this is an optimization variabel. Keeps track of what terrain +// is in the terrain spot, so things don't get redrawn. +// 0 - 299 just terrain graphic in place +// 300 - blackness +// -1 - nothign worth saving +// 0 - terrain 1 - buttons 2 - pc stats +// 3 - item stats 4 - text bar 5 - text area (not right) +RECT win_from_rects[6] = {{0,0,279,351},{0,0,258,37},{0,0,288,115},{0,0,288,143},{0,0,279,21},{0,0,288,0}}; +RECT win_to_rects[6] = {{5,5,284,356},{5,383,263,420},{0,0,271,116},{0,0,271,144},{5,358,284,379},{0,0,256,138}}; +// 0 - title 1 - button 2 - credits 3 - base button +RECT startup_from[4] = {{0,0,602,274},{0,274,301,322},{301,0,579,67},{301,274,341,314}}; //// +RECT trim_rects[8] = {{0,0,28,5},{0,31,28,36},{0,0,5,36},{24,0,28,36}, + {0,0,5,5},{24,0,28,5},{24,31,28,36},{0,31,5,36}}; /**/ +short which_graphic_index[6] = {50,50,50,50,50,50}; +short remember_tiny_text = 300; // Remembers what's in the tiny text-bar, to prevent redrawing. +// 50 indicates area name, other number indicates which-rect. +// Add 200 if last mess. was in town +char light_area[13][13]; +char unexplored_area[13][13]; +// Declare the graphics +HBITMAP mixed_gworld, pc_stats_gworld, item_stats_gworld, text_area_gworld; +HBITMAP storage_gworld,terrain_screen_gworld,text_bar_gworld,orig_text_bar_gworld,buttons_gworld; +HBITMAP party_template_gworld,items_gworld,tiny_obj_gworld,fields_gworld; +HBITMAP dlg_buttons_gworld,missiles_gworld,dlogpics_gworld,small_temp_gworld; +HBITMAP dialog_pattern_gworld,pattern_gworld,status_pattern_gworld; +// Startup graphics, will die when play starts +HBITMAP startup_gworld; +HRGN clip_region; +HBRUSH gbrush; +HPEN gpen; +// Graphics storage vals +short which_g_stored[STORED_GRAPHICS]; +// 0 - 299 terrain graphic 300 + i monster graphic i, face right 600 + i face left +// 1000 + 100 * j + i anim i pos j 2300 + i combat monster graphic i, face right 2600 + i face left +short wish_list[STORED_GRAPHICS]; +short storage_status[STORED_GRAPHICS]; // 0 - empty 1 - in use 2 - there, not in use +Boolean currently_loading_graphics = FALSE; +// Variables to store trim. Makes game faster, but wastes 15K. We'll see how it works... +char out_trim[96][96]; +char town_trim[64][64]; +// Array to store which spots have been seen. Time-saver for drawing fields +char spot_seen[9][9]; +short startup_anim_pos = 43; +Boolean supressing_some_spaces = FALSE; +location ok_space[4]; +char combat_string[100]; +short dlog_pat_placed = 0; +short current_pattern = -1; +RECT boat_rects[4] = {{0,0,28,36}, {28,0,56,36},{56,0,84,36},{84,0,112,36}}; /**/ +Boolean gave_no_g_error = FALSE; +unsigned char m_pic_index[200] = {//// + 1,2,3,4,5,6,7,8,9,10, + 11,12,13,14,15,16,17,18,19,20, + 21,22,23,24,25, 26,27,28,29,30, + 31,32,33,34,35, 36,37,38,39,40, + 41,42,43,44,46,47,48,49,50,51, + 53,55,57,59,60,61,62,63,64,65, + 66,67,68,69,70, 71,72,73,74,75, + 76,77,78,79,81, 82,83,85,86,87, + 88,89,90,91,92, 93,94,95,96,97, + 98,99,100,101,102, 103,104,105,106,107, + 108,109,111,112,113, 114,116,117,118,119, //100 + 120,122,123,125,127, 128,129,130,131,135, + 136,137,139,140,141,142,143,144,145,146, + 147,148,149,150,151,152,153,154,155,159, + 160,164,166,168,170,171,172,173,174,175, + 176,177,178,179,180,181,182,183,184,185, + 186,187,188,189,190,191,192,193,194,195, + 196,197,198,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0}; +unsigned char m_pic_index_x[200] = { + 1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1, + 1,1,1,2,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1, + 1,2,1,1,1,2,1,1,1,1, // 100 + 2,1,1,1,1,1,1,1,2,1, + 1,2,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,2,1, + 2,2,2,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1}; +unsigned char m_pic_index_y[200] = { + 1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,2, + 2,2,2,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,2,1,1,1, + 1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1, + 1,1,2,2,1,1,1,1,2,1, + 1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,2,1, + 2,1,1,2,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1}; +short mage_spell_pos = 0,priest_spell_pos = 0,skill_pos = 0; +pc_record_type *store_pc; +creature_data_type *store_m; +short store_trait_mode,store_item_pc,store_pc_num; +item_record_type store_i; +Boolean full_roster = FALSE; +// Displaying string vars +short store_which_string_dlog; +short store_page_on,store_num_i; +short store_str_label_1,store_str_label_2,store_str_label_1b,store_str_label_2b; +// Misc dialog vars +short store_display_mode,store_displayed_item,position,cur_entry,num_entries,store_help_mode; +creature_data_type hold_m; +//// +Boolean equippable[26] = {FALSE,TRUE,TRUE,FALSE,TRUE, TRUE,TRUE,FALSE,FALSE,FALSE, + TRUE,FALSE,TRUE,TRUE,TRUE, TRUE,TRUE,TRUE,TRUE,TRUE, + FALSE,FALSE,TRUE,TRUE,TRUE,TRUE}; +short num_hands_to_use[26] = {0,1,2,0,0, 0,0,0,0,0 ,0,0,1,0,0, 0,1,0,0,0, 0,0,0,0,0, 0}; +short num_that_can_equip[26] = {0,2,1,0,1, 1,1,0,0,0, 1,0,1,1,1, 1,1,1,2,1, 0,0,1,1,1, 1}; +// For following, if an item of type n is equipped, no other items of type n can be equipped, +// if n > 0 +short excluding_types[26] = {0,0,0,0,2, 1,1,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,2,1, 2}; +short item_max = 0; +short first_item_shown,store_get_mode,current_getting_pc,store_pcnum,total_items_gettable; // these 5 used for get items dialog +short item_array[130]; // NUM_TOWN_ITEMS + a bit +char *store_str; +short store_dnum; +char terrain_blocked[256] = {0,0,0,0,0,5,5,1,5,5, + 1,5,5,1,5,5,1,5,5,5, + 5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0, + 3,3,3,3,3,3,3,3,3,3, + 3,3,3,0,3,0,0,0,0,0, + 0,3,0,0,3,2,2,4,2,0, + 0,0,4,0,0,0,3,4,0,0, + 0,5,5,0,0,4,0,0,0,0, + 5,5,1,5,5,5,5,0,4,0, + 5,4,5,5,5,5,4,5,5,1, + 5,5,5,5,0,4,0,5,5,5, + 5,4,5,5,1,5,5,5,5,0, + 4,0,5,5,5,5,5,4,4,4, + 0,0,2,0,4,4,4,4,4,4, + 4,4,4,4,5,4,4,4,0,0, + 0,0,0,0,4,4,4,4,4,4, + 4,4,4,4,0,4,0,2,4,4, + 4,0,4,0,4,0,0,0,4,4, + 0,0,4,4,4,4,4,4,4,0, + 0,4,0,4,4,0,4,2,2,2, + 2,2,2,2,2,2,2,2,5,5, + 2,2,0,0,0,0,0,2,2,2, + 2,2,2,2,2,0,0,0,0,0, + 0,0,4,4,4,3}; +short short_can_see(); +Boolean combat_pt_in_light(); +location which_party_sec; +short charm_odds[20] = {90,90,85,80,78, 75,73,60,40,30, 20,10,5,2,1, 0,0,0,0,0}; +creature_start_type null_start_type = {0,0,location(80,80),1,0,0,0,0,0,0,0, 0,-1,-1,-1}; +HRGN oval_region ,dark_mask_region,temp_rect_rgn; +short skill_cost[20] = {3,3,3,2,2,2, 1,2,2,6, + 5, 1,2,4,2,1, 4,2,5,0}; +short skill_g_cost[20] = {50,50,50,40,40,40,30,50,40,250, + 250,25,100,200,30,20,100,80,0,0}; +short skill_bonus[21] = {-3,-3,-2,-1,0,0,1,1,1,2, + 2,2,3,3,3,3,4,4,4,5,5}; +short spell_level[62] = {1,1,1,1,1,1,1,1,1,1, 2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3,3,3, + 4,4,4,4,4,4,4,4, 5,5,5,5,5,5,5,5, 6,6,6,6,6,6,6,6, 7,7,7,7,7,7,7,7}; +short spell_cost[2][62] = {{1,1,1,1,1,2,50,2,1,3, 2,3,2,2,2,2,4,4,2,6, 3,3,5,3,3,5,6,4,6,4, + 4,5,4,8,30,-1,8,6, 5,8,8,6,9,10,6,6, 7,6,8,7,12,10,12,20, 12,8,20,10,14,10,50,10}, + {1,1,1,2,1,1,3,5,50,1, 2,2,2,2,3,5,8,6,4,2, 3,4,3,3,3,10,5,3,4,6, + 5,5,5,15,6,5,5,8, 6,7,25,8,10,12,12,6, 8,7,8,8,14,17,8,7, 10,10,35,10,12,12,30,10}}; +const char *mage_s_name[] = +{ + "Light", + "Spark", + "Minor Haste", + "Strength", + "Scare", + "Flame Cloud", + "Identify", + "Scry Monster", + "Goo", + "True Sight", + "Minor Poison", + "Flame", + "Slow", + "Dumbfound", + "Envenom", + "Stinking Cloud", + "Summon Beast", + "Conflagration", + "Dispel Field", + "Sleep Cloud", + "Unlock", + "Haste", + "Fireball", + "Long Light", + "Fear", + "Wall of Force", + "Weak Summoning", + "Flame Arrows", + "Web", + "Resist Magic", + "Poison", + "Ice Bolt", + "Slow Group", + "Magic Map", + "Capture Soul", + "Simulacrum", + "Venom Arrows", + "Wall of Ice", + "Stealth", + "Major Haste", + "Fire Storm", + "D. Barrier", + "Fire Barrier", + "Summoning", + "Shockstorm", + "Spray Fields", + "Major Poison", + "Group Fear", + "Kill", + "Paralysis", + "Daemon", + "Antimagic Cloud", + "MindDuel", + "Flight", + "Shockwave", + "M. Blessing", + "Mass Paralysis", + "Protection", + "Major Summon", + "Force Barrier", + "Quickfire", + "Death Arrows"}; +char *priest_s_name[] = {"Minor Bless","Minor Heal","Weaken Poison","Turn Undead","Location", + "Sanctuary","Symbiosis","Minor Manna","Ritual - Sanctify","Stumble", + "Bless","Cure Poison","Curse","Light","Wound", + "Summon Spirit","Move Mountains","Charm Foe","Disease","Awaken", + "Heal","Light Heal All","Holy Scourge","Detect Life","Cure Paralysis", + "Manna","Forcefield","Cure Disease","Restore Mind","Smite", + "Cure Party","Curse All","Dispel Undead","Remove Curse", + "Sticks to Snakes","Martyr's Shield","Cleanse","Firewalk", + "Bless Party","Major Heal","Raise Dead","Flamestrike", + "Mass Sanctuary","Summon Host","Shatter","Dispel Fields", + "Heal All","Revive","Hyperactivity","Destone", + "Guardian","Mass Charm","Protective Circle","Pestilence", + "Revive All","Ravage Spirit","Resurrect","Divine Thud", + "Avatar","Wall of Blades","Word of Recall","Major Cleansing"}; +char *alch_names[] = {"Weak Curing Potion (1)","Weak Healing Potion (1)","Weak Poison (1)", + "Weak Speed Potion (3)","Medium Poison (3)", + "Medium Heal Potion (4)","Strong Curing (5)","Medium Speed Potion (5)", + "Graymold Salve (7)","Weak Energy Potion (9)", + "Potion of Clarity (9)","Strong Poison (10)","Strong Heal Potion (12)","Killer Poison (12)", + "Resurrection Balm (9)","Medium Energy Ptn. (14)","Knowledge Brew (19)" , + "Strong Strength (10)","Bliss (16)","Strong Power (20)" +}; +char *alch_names_short[] = {"Weak Curing Potion","Weak Healing Potion","Weak Poison", + "Weak Speed Potion","Medium Poison", + "Medium Heal Potion","Strong Curing","Medium Speed Potion", + "Graymold Salve","Weak Energy Potion", + "Potion of Clarity","Strong Poison","Strong Heal Potion","Killer Poison", + "Resurrection Bal","Medium Energy Ptn.","Knowledge Brew", + "Strong Strength","Bliss","Strong Power" +}; +short spell_w_cast[2][62] = {{0,1,1,1,1,1,3,4,1,2, 1,1,1,1,1,1,4,1,4,1, 2,1,1,0,1,1,4,1,1,0, + 1,1,1,2,4,1,1,1, 2,1,1,2,4,4,1,1, 1,1,1,1,4,4,1,5, 1,4,1,4,4,4,4,1}, + {1,0,0,1,3,1,1,3,2,1, 1,0,1,0,1,4,2,1,1,0, 0,0,1,2,0,3,1,0,0,1, + 0,1,1,3,4,1,0,0, 1,0,3,1,1,4,2,4, 0,0,0,3,4,1,1,1, 0,1,3,1,4,1,5,0}}; +// 0 - everywhere 1 - combat only 2 - town only 3 - town & outdoor only 4 - town & combat only 5 - outdoor only +short combat_percent[20] = {150,120,100,90,80,80,80,70,70,70, + 70,70,67,62,57,52,47,42,40,40}; +short town_spell,who_cast,which_pc_displayed; +char c_line[60]; +// Variables for spell selection +short store_situation,store_last_target_darkened,on_which_spell_page = 0; +short store_last_cast_mage = 6,store_last_cast_priest = 6; +short spell_index[38] = {38,39,40,41,42,43,44,45,90,90,46,47,48,49,50,51,52,53,90,90, + 54,55,56,57,58,59,60,61,90,90, 90,90,90,90,90,90,90,90}; +// Says which buttons hit which spells on second spell page, 90 means no button +Boolean can_choose_caster; +// Variables for spending xp +short store_skills[20],store_h,store_sp,i,store_skp,which_skill; +long store_g; +short store_train_mode,store_train_pc; +HBITMAP pcs_gworld; +// Dialog vars +short store_mage_store ; +short store_priest_store ; +short store_store_target; +short store_graphic_pc_num ; +short store_graphic_mode ; +short store_pc_graphic; +pc_array adven; +Boolean can_draw_pcs = TRUE; +short store_item_spell_level = 10; +Boolean special_in_progress = FALSE; +short spec_str_offset[3] = {160,10,20}; +short current_pc_picked_in_spec_enc = -1; // pc that's been selected, -1 if none +location store_special_loc; +short boom_gr[8] = {3,0,2,1,1,4,3,3}; +short skill_max[20] = {20,20,20,20,20,20,20,20,20,7, + 7,20,20,10,20,20,20,20,20}; +// 0 - everywhere 1 - combat only 2 - town only 3 - town & combat only 4 - can't use 5 - outdoor +// + 10 - mag. inept can use +short abil_chart[200] = {4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4, // 50 + 4,4,4,4,4,4,4,4,4,4, + 13,0,0,0,3, 3,3,0,3,3, + 3,3,3,3,3, 0,0,0,0,3, + 13,3,3,5,0, 0,0,0,0,0, + 4,4,4,4,4,4,4,4,4,4, // 100 + 1,1,1,1,1, 1,1,1,1,3, + 3,1,1,1,1, 1,1,1,1,3, + 1,2,2,1,1, 1,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4, // 150 + 4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4}; +RECT startup_button[6]; +short buf_pointer = 30; +char store_string[256]; +char store_string2[256]; +short mark_where_printing_long; +Boolean printing_long = FALSE; +RECT item_buttons_from[7] = {{0,12,14,24},{14,12,28,24},{28,12,42,24},{42,12,56,24}, + {0,24,30,36},{30,24,60,36},{0,36,30,48}}; /**/ +Boolean string_added = FALSE; +short store_text_x = 0, store_text_y = 0; +short current_item_button[6] = {-1,-1,-1,-1,-1,-1}; +short pc_button_state[6] = {-1,-1,-1,-1,-1,-1}; +char *m_mage_sp[] = {"Spark","Minor Haste","Strength","Flame Cloud","Flame", + "Minor Poison","Slow","Dumbfound","Stinking Cloud","Summon Beast", + "Conflagration","Fireball","Weak Summoning","Web","Poison", + "Ice Bolt","Slow Group","Major Haste","Firestorm","Summoning", + "Shockstorm","Major Poison","Kill","Daemon","Major Blessing", + "Major Summoning","Shockwave"}; +char *m_priest_sp[] = {"Minor Bless","Light Heal","Wrack","Stumble","Bless", + "Curse","Wound","Summon Spirit","Disease","Heal", + "Holy Scourge","Smite","Curse All","Sticks to Snakes","Martyr's Shield", + "Bless All","Major Heal","Flamestrike","Summon Host","Heal All", + "Unholy Ravaging","Summon Guardian","Pestilence","Revive All","Avatar", + "Divine Thud"}; +// extra devices for maps +HBRUSH hbrush[6] = {NULL, NULL, NULL, NULL, NULL, NULL}; +HPEN hpen[6]; +RECT store_map_window_rect = {0,0,0,0}; +Boolean need_map_full_refresh = TRUE; +HBITMAP map_gworld; +HBRUSH bg[14]; +HBRUSH map_brush[25]; +HBITMAP map_bitmap[25]; +unsigned char map_pats[256] = {1,1,2,2,2,7,7,7,7,7, //// + 7,7,7,7,7,7,7,7,3,3, + 3,3,3,3,3,3,3,3,3,3, + 3,3,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,4,4,4,4, + 4,4,4,4,4,4,4,4,4,0, // 50 + 0,0,0,0,0,0,0,24,24,24, + 16,16,25,25,0,0,0,0,18,8, + 8,9,2,15,15,10,10,10,6,0, + 0,0,0,0,0,0,0,0,0,0, + 19,0,0,0,0,0,0,0,0,0, // 100 + 23,0,0,0,0,0,0,0,0,0, + 0,0,0,11,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,12,0,0, // 150 + 0,0,0,13,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0, + 0,18,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0, // 200 + 0,0,0,0,0,17,17,0,17,17, + 17,17,17,17,17,17,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0};// 250 +unsigned char anim_map_pats[18] = {14,0,0,0,22, 0,0,21,20,21, 20,0,0,0,0, 0,0,0}; +location town_map_adj; +short town_force = INVALID_TOWN; +location town_force_loc; +unsigned char map_graphic_placed[8][64]; // keeps track of what's been filled on map +Boolean kludge_force_full_refresh = FALSE; +word_rect_type preset_words[9] = {{"Look",{4,366,54,389}},{"Name",{70,366,130,389}},{"Job",{136,366,186,389}}, + {"Buy",{4,389,54,412}},{"Sell",{70,389,120,412}},{"Record",{121,389,186,412}}, + {"Done",{210,389,270,412}},{"Go Back",{190,366,270,389}}, + {"Ask About...",{4,343,134,366}}}; +word_rect_type store_words[50]; +// Animation vars +short store_anim_type; diff --git a/Win32/Blades of Exile/GLOBVAR.H b/Win32/Blades of Exile/GLOBVAR.H new file mode 100644 index 00000000..140cae95 --- /dev/null +++ b/Win32/Blades of Exile/GLOBVAR.H @@ -0,0 +1,606 @@ +#ifndef _GLOBVAR_H + #define _GLOBVAR_H + +#include +#include "global.h" +#include "newgraph.h" + +extern RECT bottom_buttons[7]; +extern RECT town_buttons[10]; +extern RECT combat_buttons[9]; +extern RECT world_screen; +extern RECT item_screen_button_rects[9]; +extern RECT border_rect[4]; +extern RECT medium_buttons[4]; +extern RECT startup_top; +extern RECT item_buttons[8][6]; // name, use, give, drip, info, sell/id +extern RECT pc_buttons[6][5]; // name, hp, sp, info, trade +extern short special_queue[20]; +extern Boolean end_scenario ; +extern short refer_priest[62]; +extern short mage_need_select[62]; +extern short priest_need_select[62]; + +extern Boolean item_area_button_active[8][6]; +extern Boolean pc_area_button_active[6][5]; +extern short item_bottom_button_active[9]; + +extern RECT pc_help_button,pc_area_rect,item_area_rect; + +extern short current_terrain_type, num_out_moves; +extern short door_pc,store_drop_item; +extern short current_switch; +extern out_wandering_type store_wandering_special; +extern long dummy; +extern short store_shop_type; + +extern short debug_ok; +extern short store_selling_values[8]; + +extern char *dir_string[8]; +extern char get_new_terrain(); +extern creature_start_type save_monster_type; + +extern short wand_loc_count; +extern short monst_place_count; // 1 - standard place 2 - place last + +extern item_record_type start_items[6]; + +extern RECT shopping_rects[8][7]; + +extern unsigned char out[96][96]; +extern unsigned char out_e[96][96]; +extern unsigned char misc_i[64][64],sfx[64][64]; +/* Mac stuff globals */ + +extern HWND text_sbar, item_sbar, shop_sbar; +extern RECT sbar_rect; +extern RECT shop_sbar_rect; +extern RECT item_sbar_rect; +extern int dialog_answer; +extern POINT store_anim_ul; +extern Boolean All_Done, dialog_not_toast; +extern Boolean in_startup_mode ; +extern Boolean play_sounds; +extern Boolean diff_depth_ok ,spell_forced ,startup_loaded ; +extern Boolean save_maps ,party_in_memory ,in_scen_debug ; +extern Boolean window_in_front ; +extern Boolean belt_present ; +extern Boolean game_run_before ; +extern Boolean debug_on , give_intro_hint ; +extern short on_spell_menu[2][62]; +extern short on_monst_menu[256]; +extern short current_cursor; +extern HCURSOR arrow_curs[3][3], sword_curs, key_curs, target_curs,talk_curs,look_curs; + +extern party_record_type party; +extern outdoor_record_type outdoors[2][2]; +extern current_town_type c_town; +extern big_tr_type t_d; +extern stored_items_list t_i; +extern setup_save_type setup_save; +extern location monster_targs[T_M]; + +extern short combat_posing_monster, current_working_monster; // 0-5 PC 100 + x - monster x +extern Boolean fast_bang ; +extern short spec_item_array[60]; +extern short overall_mode,current_spell_range; +extern Boolean first_update ,anim_onscreen ,frills_on ,sys_7_avail,suppress_stat_screen ; +extern short stat_window,store_modifier; +extern Boolean monsters_going ,boom_anim_active ,cartoon_happening ; +extern short give_delays; +extern Boolean modeless_exists[18]; +extern short modeless_key[18]; +extern HWND modeless_dialogs[18]; + +extern short town_size[3]; +extern short which_item_page[6]; // Remembers which of the 2 item pages pc looked at +extern short ulx, uly; +extern short display_mode; // 0 - center 1- ul 2 - ur 3 - dl 4 - dr 5 - small win +extern short current_ground,stat_screen_mode; +extern long anim_ticks; + +// Spell casting globals +extern short store_mage, store_priest; +extern short store_mage_lev, store_priest_lev; +extern short store_spell_target,pc_casting; +extern short pc_last_cast[2][6]; +extern int num_targets_left; +extern location spell_targets[8]; + +extern long store_mouse; + +/* Combat globals */ +extern short which_combat_type,town_type; +extern location center; +extern unsigned char combat_terrain[64][64]; +extern location pc_pos[6]; +extern short current_pc; +extern short combat_active_pc; +extern effect_pat_type current_pat; +extern short monst_target[T_M]; // 0-5 target that pc 6 - no target 100 + x - target monster x +extern short spell_caster, missile_firer,current_monst_tactic; +extern short store_current_pc; +extern stored_items_list stored_items[3]; +extern stored_outdoor_maps_type o_maps; + +// Special stuff booleans +extern Boolean web,crate,barrel,fire_barrier,force_barrier,quickfire,force_wall,fire_wall,antimagic,scloud,ice_wall,blade_wall; +extern Boolean sleep_field; + +extern long last_anim_time; + +/* Windoze stuff globals */ +extern Boolean cursor_shown ; +extern short store_pc_being_created; + +extern HWND mainPtr; +extern HWND force_dlog; +extern HFONT font,fantasy_font,small_bold_font,italic_font,underline_font,bold_font,tiny_font; +extern HBITMAP bmap; +extern HDC main_dc,main_dc2,main_dc3; +extern HINSTANCE store_hInstance; +extern HACCEL accel; +extern BOOL event_handled; +extern scenario_data_type scenario; +extern talking_record_type talking; +extern char scen_strs2[110][256]; +extern stored_town_maps_type town_maps; + +extern char szWinName[12]; +extern char szAppName[14]; + +extern char file_path_name[256]; + +extern Boolean block_erase ; + +/* dynamically allocated */ +extern piles_of_stuff_dumping_type *data_store; +extern piles_of_stuff_dumping_type2 *data_store2; +extern piles_of_stuff_dumping_type3 *data_store3; +extern piles_of_stuff_dumping_type4 *data_store4; +extern piles_of_stuff_dumping_type5 *data_store5; +/* end of dynamically allocated */ + +extern char create_line[60]; +extern short spell_being_cast; +extern short missile_inv_slot, ammo_inv_slot; +extern short force_wall_position; // 10 -> no force wall +extern Boolean processing_fields ; +extern short futzing; +extern unsigned char store_sum_monst; +extern short store_sum_monst_cost; + +extern location out_start_loc; +extern short hit_chance[51]; +extern short abil_range[40]; +extern short abil_odds[40]; +extern short s_cost[2][62] ; + +extern short mage_range[80]; +extern short priest_range[62]; +extern short monst_mage_spell[55]; +extern short monst_cleric_spell[55]; +extern short monst_mage_cost[27]; +extern short monst_mage_area_effect[27]; +extern short monst_priest_cost[26]; +extern short monst_priest_area_effect[26]; + +extern char *d_string[8]; + +extern short pc_marked_damage[6]; +extern short monst_marked_damage[T_M]; + +extern location hor_vert_place[14]; +extern location diag_place[14]; + +extern unsigned char beasts[5]; +extern unsigned char m1[20]; +extern unsigned char m2[16]; +extern unsigned char m3[16]; + +extern short mage_caster_array[7][18]; +extern short mage_emer_spells[7][4]; +extern short priest_caster_array[7][10]; +extern short priest_emer_spells[7][4]; +extern effect_pat_type null_pat; +extern effect_pat_type single; +extern effect_pat_type t; +extern effect_pat_type small_square; +extern effect_pat_type square; + +extern effect_pat_type open_square; +extern effect_pat_type radius2; +extern effect_pat_type radius3; +extern effect_pat_type field[8]; + +extern short last_attacked[6],pc_dir[6],pc_parry[6],pc_moves[6]; +extern Boolean center_on_monst; + +extern short sign_mode,person_graphic,store_person_graphic,store_sign_mode; +extern long num_talk_entries; +extern short store_tip_page_on; + +extern short store_pre_talk_mode,store_personality,store_personality_graphic,shop_identify_cost; +extern HBITMAP talk_gworld; +extern Boolean talk_end_forced; +extern char old_str1[256]; +extern char old_str2[256]; +extern char one_back1[256]; +extern char one_back2[256]; +extern RECT talk_area_rect, word_place_rect,talk_help_rect; +/**/ +extern char title_string[50]; +extern unsigned char store_monst_type; +extern short store_m_num; +extern RECT dummy_rect; +extern short strnum1,strnum2,oldstrnum1,oldstrnum2; +extern short store_talk_face_pic,cur_town_talk_loaded; + +extern short store_shop_items[30]; +extern short store_shop_costs[30]; +extern short store_shop_min,store_shop_max,store_pre_shop_mode,store_cost_mult; +extern char store_store_name[256]; +extern RECT bottom_help_rects[4]; +extern RECT shop_frame; +extern RECT shop_done_rect; /**/ + +extern char *heal_types[9]; +extern short heal_costs[9]; +extern long cost_mult[7]; +extern short cur_display_mode; + +extern short terrain_pic[256]; + +extern scen_header_type scen_headers[100]; + +extern short store_scen_page_on,store_num_scen; + +#define ND 15 +#define NI 500 +#define NL 100 +#define NUM_DLOG_B 53 + +extern char text_long_str[10][256]; +extern char text_short_str[140][35]; +extern char labels[NL][25]; +extern Boolean label_taken[NL]; + +extern HWND edit_box; +extern HWND store_edit_parent; // kludgy + +extern HDC dlg_force_dc; // save HDCs when dealing with dlogs + +extern short store_free_slot,store_dlog_num; +extern HWND store_parent; + +extern short available_dlog_buttons[NUM_DLOG_B]; +extern short button_type[150]; +extern char *button_strs[150]; + +extern short button_left_adj[150]; +extern char button_def_key[150]; +extern short button_ul_x[15]; +extern short button_ul_y[15]; +extern short button_width[15]; +extern short button_height[15]; + +extern DLGPROC d_proc; +extern WNDPROC edit_proc; +extern WNDPROC old_edit_proc; + +#define NUM_SOUNDS 100 + +extern HGLOBAL sound_handles[NUM_SOUNDS]; +extern char * snds[NUM_SOUNDS]; + +extern short last_played; +extern short store_last_sound_played; +extern HMODULE hModule; + +extern Boolean always_asynch[100]; +extern Boolean load_when_play[100]; + +extern short can_ignore[100]; + +extern short num_devs; +extern Boolean sounds_fucked ; +extern long intro_music_start_time; + +extern HWND the_dialog; +extern HBITMAP spec_scen_g; + +extern Boolean loaded_yet , got_nagged ,ae_loading ; +extern Boolean cur_scen_is_win ; + +extern void print_write_position (); + +extern char last_load_file[63]; +extern char szFileName [128]; +extern char szTitleName [128]; +extern OPENFILENAME ofn; +extern OFSTRUCT save_dir,save_dir2; + +// Trying this to fix bug. Hope it works. +extern tiny_tr_type tiny_t; +extern ave_tr_type ave_t; + +extern outdoor_record_type dummy_out;//// +extern town_record_type dummy_town; +extern short jl; + +extern HBITMAP bg_bitmap[14]; +extern HBRUSH checker_brush; +extern HBITMAP checker_bitmap,bw_bitmap; +extern HBITMAP startup_button_orig,startup_button_g,anim_mess ; + +extern Boolean done_fancy_startup_once ; + +extern short terrain_there[9][9]; +extern RECT win_from_rects[6]; +extern RECT win_to_rects[6]; + +// 0 - title 1 - button 2 - credits 3 - base button +extern RECT startup_from[4]; +extern RECT trim_rects[8]; +extern RECT top_left_rec; +extern short which_graphic_index[6]; + +extern char combat_graphics[5]; +extern short debug_nums[6]; +extern short remember_tiny_text; // Remembers what's in the tiny text-bar, to prevent redrawing. + +extern char light_area[13][13]; +extern char unexplored_area[13][13]; + +// Declare the graphics +extern HBITMAP mixed_gworld, pc_stats_gworld, item_stats_gworld, text_area_gworld; +extern HBITMAP storage_gworld,terrain_screen_gworld,text_bar_gworld,orig_text_bar_gworld,buttons_gworld; +extern HBITMAP party_template_gworld,items_gworld,tiny_obj_gworld,fields_gworld; +extern HBITMAP dlg_buttons_gworld,missiles_gworld,dlogpics_gworld,small_temp_gworld; + +extern HBITMAP dialog_pattern_gworld,pattern_gworld,status_pattern_gworld; + +// Startup graphics, will die when play starts +extern HBITMAP startup_gworld; + +extern HRGN clip_region; +extern HBRUSH gbrush; +extern HPEN gpen; + +// Graphics storage vals +extern short which_g_stored[STORED_GRAPHICS]; +extern short wish_list[STORED_GRAPHICS]; +extern short storage_status[STORED_GRAPHICS]; // 0 - empty 1 - in use 2 - there, not in use + +extern Boolean has_run_anim ,currently_loading_graphics ; + +extern RECT main_win_rect; +extern RECT main_win2_source_rect; +extern RECT main_win2_rect ; + +extern RECT tiny_world_1_source_rect,tiny_world_1_rect; + +extern RECT share_mess_source_rect, + share_mess_rect; +extern RECT start_buttons_source_rect, + start_buttons_rect; /**/ + +// Variables to store trim. Makes game faster, but wastes 15K. We'll see how it works... +extern char out_trim[96][96]; +extern char town_trim[64][64]; + +// Array to store which spots have been seen. Time-saver for drawing fields +extern char spot_seen[9][9]; + + +extern short startup_anim_pos; + +extern Boolean supressing_some_spaces ; +extern location ok_space[4]; + +extern char combat_string[100]; + +extern BOOL pal_ok ; +extern Boolean syscolors_stored ; +extern int elements[5]; +extern COLORREF store_element_colors[5]; +extern short dlog_pat_placed; +extern short current_pattern; + +extern RECT boat_rects[4]; /**/ +extern Boolean gave_no_g_error ; + +extern unsigned char m_pic_index[200]; +extern unsigned char m_pic_index_x[200]; +extern unsigned char m_pic_index_y[200]; + +extern short mage_spell_pos,priest_spell_pos,skill_pos; +extern pc_record_type *store_pc; +extern creature_data_type *store_m; +extern short store_trait_mode,store_item_pc,store_pc_num; +extern item_record_type store_i; + +extern Boolean full_roster ; + +extern location source_locs[6]; + +// Displaying string vars +extern short store_str1a; +extern short store_str1b; +extern short store_str2a; +extern short store_str2b; +extern short store_which_string_dlog; +extern short store_page_on,store_num_i; +extern short store_str_label_1,store_str_label_2,store_str_label_1b,store_str_label_2b; + +// Misc dialog vars +extern short store_display_mode,store_displayed_item,position,cur_entry,num_entries,store_help_mode; +extern creature_data_type hold_m; + +//// +extern Boolean equippable[26]; +extern short num_hands_to_use[26]; +extern short num_that_can_equip[26]; + +// For following, if an item of type n is equipped, no other items of type n can be equipped, +// if n > 0 +extern short excluding_types[26]; + +extern short selected,item_max; + +extern short first_item_shown,store_get_mode,current_getting_pc,store_pcnum,total_items_gettable; // these 5 used for get items dialog +extern short item_array[130]; // NUM_TOWN_ITEMS + a bit + +extern short answer_given; + +extern char *store_str; +extern short store_dnum; + +extern HWND test_dlog3; +extern HWND store_focus; + +extern short being_created; +extern short procinst_exists[18]; + +extern char terrain_blocked[256]; + +extern short short_can_see(); +extern Boolean combat_pt_in_light(); +extern location obs_sec; +extern location which_party_sec; + +extern location light_locs[40]; +extern short num_lights; +extern char d_s[60]; + +extern short charm_odds[20]; + +extern creature_start_type null_start_type; + +extern short monsters_faces[190]; + +extern HRGN oval_region,dark_mask_region,temp_rect_rgn; + +extern short skill_cost[20]; +extern short skill_g_cost[20]; +extern short skill_bonus[21]; + +extern short spell_level[62]; +extern short spell_cost[2][62]; +extern const char *mage_s_name[]; + +extern char *priest_s_name[]; +extern char *alch_names[]; +extern char *alch_names_short[]; +extern short spell_w_cast[2][62]; +// 0 - everywhere 1 - combat only 2 - town only 3 - town & outdoor only 4 - town & combat only 5 - outdoor only +extern Boolean get_mage[30]; +extern Boolean get_priest[30]; +extern short combat_percent[20]; + +extern short town_spell,who_cast,which_pc_displayed; +extern Boolean spell_button_active[90]; + +extern char empty_string[256]; + +extern char c_line[60]; + +// Variables for spell selection +extern short store_situation,store_last_target_darkened,on_which_spell_page; +extern short store_last_cast_mage ,store_last_cast_priest ; +extern short buttons_on[38]; + // buttons_on determines which buttons can be hit when on the second spell page +extern short spell_index[38]; + // Says which buttons hit which spells on second spell page, 90 means no button +extern Boolean can_choose_caster; + +// Variables for spending xp +extern Boolean talk_done ; +extern long val_for_text; +extern Boolean keep_change ; +extern short store_skills[20],store_h,store_sp,i,store_skp,which_skill; +extern long store_g; +extern short store_train_mode,store_train_pc; + +extern HBITMAP pcs_gworld; + +// Dialog vars +extern short store_mage_store ; +extern short store_priest_store ; +extern short store_store_target; +extern short store_graphic_pc_num ; +extern short store_graphic_mode ; +extern short store_pc_graphic; + +extern pc_array adven; + +extern Boolean can_draw_pcs ; +extern short store_item_spell_level; +extern Boolean special_in_progress ; + +extern item_record_type null_item; +extern short spec_str_offset[3]; +extern short current_pc_picked_in_spec_enc ; // pc that's been selected, -1 if none +extern location store_special_loc; +extern short boom_gr[8] ; +extern short skill_max[20]; + +extern short abil_chart[200]; + +extern RECT startup_button[6]; + +extern short buf_pointer , lines_to_print, num_added_since_stop ; +extern char store_string[256]; +extern char store_string2[256]; +extern short start_print_point; +extern short mark_where_printing_long; +extern Boolean printing_long ; +extern char c_str[256]; +extern Boolean save_mess_given ; + +extern RECT status_panel_clip_rect,item_panel_clip_rect; + +extern RECT item_buttons_from[7]; /**/ + +extern short store_mode; +extern Boolean string_added ; +extern short store_text_x , store_text_y ; + +extern short current_item_button[6]; +extern short pc_button_state[6]; + +extern char *m_mage_sp[]; +extern char *m_priest_sp[]; + +// extra devices for maps +extern HBRUSH hbrush[6]; +extern HPEN hpen[6]; + +extern RECT store_map_window_rect; + +extern Boolean need_map_full_refresh ,forcing_map_button_redraw ; +extern HBITMAP map_gworld; +extern HBRUSH bg[14]; +extern HBRUSH map_brush[25]; +extern HBITMAP map_bitmap[25]; + +extern unsigned char map_pats[256];// 250 +extern unsigned char anim_map_pats[18]; + +extern location town_map_adj ; +extern short town_force,store_min,store_max,store_shop; +extern location town_force_loc; +extern Boolean shop_button_active[12]; +extern RECT map_title_rect; /**/ +extern RECT map_bar_rect; +extern unsigned char map_graphic_placed[8][64]; // keeps track of what's been filled on map +extern Boolean kludge_force_full_refresh ; + +extern word_rect_type preset_words[9]; +extern word_rect_type store_words[50]; + +// Animation vars +extern short store_anim_type; + +#endif diff --git a/Win32/Blades of Exile/GRAPHICS.CPP b/Win32/Blades of Exile/GRAPHICS.CPP new file mode 100644 index 00000000..c29439ed --- /dev/null +++ b/Win32/Blades of Exile/GRAPHICS.CPP @@ -0,0 +1,2169 @@ +#include + +#include "string.h" +#include "stdio.h" +#include "global.h" +#include "graphics.h" +#include "newgraph.h" +#include "gutils.h" +#include "monster.h" +#include "dlogtool.h" +#include "locutils.h" +#include "fields.h" +#include "text.h" +#include "exlsound.h" +#include "graphutl.h" + +#include "globvar.h" + +BOOL fry_startup = FALSE; + +void adjust_window_mode() +{ + create_clip_region(); + undo_clip(); + if (overall_mode != 45) { + if (in_startup_mode == TRUE) + draw_startup(0); + if (in_startup_mode == FALSE) + refresh_screen(0); + } + MoveWindow(text_sbar,ulx + 547,uly + 283,15,138,TRUE); + MoveWindow(item_sbar,ulx + 547,uly + 147,15,107,TRUE); + MoveWindow(shop_sbar,ulx + 258,uly + 67,16,290,TRUE); +} + +void plop_fancy_startup() +{ + HBITMAP pict_to_draw = NULL; + short i,j; + + RECT from_rect = {0,0,350,350},to_rect,whole_window; + POINT graphic_ul; + HBRUSH old_brush; + long cur_time; + + GetClientRect(mainPtr,&whole_window); + + if (done_fancy_startup_once == FALSE) + { + // initialize buffers and rects + for (i = 0; i < STORED_GRAPHICS; i++) + { + storage_status[i] = which_g_stored[i] = (i < 50) ? i : 0; + wish_list[i] = 0; + } + + for (i = 0; i < 9; i++) + for (j = 0; j < 9; j++) + terrain_there[i][j] = -1; + + OffsetRect(&win_to_rects[5],TEXT_WIN_UL_X,TEXT_WIN_UL_Y); + OffsetRect(&win_to_rects[2],PC_WIN_UL_X,PC_WIN_UL_Y); + OffsetRect(&win_to_rects[3],ITEM_WIN_UL_X,ITEM_WIN_UL_Y); + + main_dc = GetDC(mainPtr); + SelectObject(main_dc,font); + SetBkMode(main_dc,TRANSPARENT); + + main_dc2 = CreateCompatibleDC(main_dc); + SetMapMode(main_dc2,GetMapMode((HDC)mainPtr)); + + main_dc3 = CreateCompatibleDC(main_dc); + SetMapMode(main_dc3,GetMapMode((HDC) mainPtr)); + + SetStretchBltMode(main_dc,STRETCH_DELETESCANS); + SetStretchBltMode(main_dc2,STRETCH_DELETESCANS); + SetStretchBltMode(main_dc3,STRETCH_DELETESCANS); + } + + old_brush = (HBRUSH) SelectObject(main_dc,GetStockObject(BLACK_BRUSH)); + Rectangle(main_dc, whole_window.left,whole_window.top, + whole_window.right,whole_window.bottom); + + //pict_to_draw = ReadBMP("blscened/SPIDLOGO.BMP"); + pict_to_draw = load_pict(3001, (HDC) 0); + + graphic_ul.x = (whole_window.right - 350) / 2 - ulx; + graphic_ul.y = (whole_window.bottom - 350) / 2 - uly - 10; + to_rect = from_rect; + OffsetRect(&to_rect,graphic_ul.x,graphic_ul.y); + rect_draw_some_item(pict_to_draw,from_rect,pict_to_draw,to_rect,0,1); + //play_sound(95); + DeleteObject(pict_to_draw); + + cur_time = GetCurrentTime(); + while (GetCurrentTime() - cur_time < 1500); + + +if(fry_startup == TRUE){ + + pict_to_draw = load_pict(3000, (HDC) 0); + + RECT big_pic_from = {2,48,641,434}; + from_rect = big_pic_from; + to_rect = from_rect; + graphic_ul.x = (whole_window.right - 639) / 2 - ulx; + graphic_ul.y = (whole_window.bottom - 486) / 2 - uly + 46; + + OffsetRect(&to_rect,-1 * to_rect.left + graphic_ul.x,-1 * to_rect.top + graphic_ul.y); + rect_draw_some_item(pict_to_draw,from_rect,pict_to_draw,to_rect,0,1); + play_sound(22); + DeleteObject(pict_to_draw); + + cur_time = GetCurrentTime(); + while (GetCurrentTime() - cur_time < 5000); +} + if (done_fancy_startup_once == FALSE) + { + done_fancy_startup_once = TRUE; + Set_up_win(); + init_startup(); + } + + + + Rectangle(main_dc, whole_window.left,whole_window.top, whole_window.right,whole_window.bottom); + SelectObject(main_dc,old_brush); +} + +void init_startup() +{ + startup_loaded = TRUE; + + gbrush = CreateSolidBrush(RGB(204,204,204)); + gpen = CreatePen(PS_SOLID,1,RGB(204,204,204)); + + startup_gworld = load_pict(830,main_dc); + startup_button_orig = load_pict(832,main_dc); + startup_button_g = load_pict(832,main_dc); + anim_mess = load_pict(831,main_dc); +} + +void draw_startup(short but_type) +{ + RECT to_rect; + RECT r1 = {-1000,-1000,1000,5},r2 = {-1000,-1000,5,1000},r3 = {-1000,418,1000,2000}, + r4 = {579,-1000,2500,1000}; + short i; + + if (startup_loaded == FALSE) + return; + + r1.bottom = uly + 5; + paint_pattern(NULL,1,r1,0); + r2.right = ulx + 5; + paint_pattern(NULL,1,r2,0); + r3.top += uly + 5; + paint_pattern(NULL,1,r3,0); + r4.left += ulx + 5; + paint_pattern(NULL,1,r4,0); + to_rect = startup_from[0]; + OffsetRect(&to_rect,5,5); + rect_draw_some_item(startup_gworld,startup_from[0],startup_gworld,to_rect,0,1); + + for (i = 0; i < 5; i++) { + rect_draw_some_item(startup_gworld,startup_from[1],startup_gworld,startup_button[i],0,1); + draw_start_button(i,but_type); + } + + draw_startup_anim(); + draw_startup_stats(); + } + +void draw_startup_stats() +{ + RECT from_rect,to_rect,party_from = {0,0,28,36},pc_rect,frame_rect; + short i; + char str[256]; + COLORREF colors[5] = {RGB(0,0,0),RGB(255,255,255),RGB(0,204,255),RGB(0,160,0),RGB(0,0,255)}; + HBRUSH hbrush; + + to_rect = startup_top; + OffsetRect(&to_rect, 20, 35); + hbrush = CreateSolidBrush(colors[2]); + + SetTextColor(main_dc,colors[1]); + + if (party_in_memory == FALSE) + { + SelectObject(main_dc,fantasy_font); + OffsetRect(&to_rect,175,40); + char_win_draw_string(main_dc,to_rect,"No Party in Memory",0,18); + } + + if (party_in_memory == TRUE) + { + frame_rect = startup_top; + InflateRect(&frame_rect,-50,-50); + frame_rect.top += 30; + OffsetRect(&frame_rect,ulx ,uly + 10); + FrameRect(main_dc,&frame_rect,hbrush); + + SelectObject(main_dc,fantasy_font); + OffsetRect(&to_rect,213,25); + char_win_draw_string(main_dc,to_rect, "Your party:",0,18); + + SelectObject(main_dc,small_bold_font); + + /* at this point everything is ok */ + + for (i = 0; i < 6; i++) + { + pc_rect = startup_top; + + pc_rect.right = pc_rect.left + 300; // width = 300 + pc_rect.bottom = pc_rect.top + 79; // height = 79 + + // 1) move 85 to right and 95 down + // 2) move 85 to right and 140 down + // 3) move 85 to right and 185 down + // 4) move 292 to right and 95 down + // 5) move 292 to right and 140 down + // 6) move 292 to right and 185 down + OffsetRect(&pc_rect, 85 + 232 * (i / 3), 95 + 45 * (i % 3)); + + if (adven[i].main_status > MAIN_STATUS_ABSENT) + { + from_rect = party_from; // width = 28, height = 36 + // 1) 0 right, 36 down + // 2) 0 r, 72 down + // 3) 0 r, 108 down + // 4) 56 right, 36 down + // 5) 56 r, 72 down + // 6) 56 r, 108 down + OffsetRect(&from_rect, 56 * (i / 3), 36 * (i % 3)); + + to_rect = party_from; // width = 28, height = 36 + OffsetRect(&to_rect,pc_rect.left,pc_rect.top + 2); + rect_draw_some_item(party_template_gworld,from_rect,party_template_gworld,to_rect,0,1); + InflateRect(&to_rect,1,1); + OffsetRect(&to_rect,ulx,uly); + FrameRect(main_dc,&to_rect,hbrush); + + SelectObject(main_dc, bold_font); + OffsetRect(&pc_rect,35,0); + char_win_draw_string(main_dc, pc_rect, adven[i].name, 0, 18); + OffsetRect(&to_rect,pc_rect.left + 8,pc_rect.top + 8); + } + + OffsetRect(&pc_rect,12,16); + SelectObject(main_dc,small_bold_font); + + switch (adven[i].main_status) + { + case MAIN_STATUS_ALIVE: + switch (adven[i].race) + { + case 0: sprintf((char *) str,"Level %d Human",adven[i].level); break; + case 1: sprintf((char *) str,"Level %d Nephilim",adven[i].level); break; + case 2: sprintf((char *) str,"Level %d Slithzerikai",adven[i].level); break; + } + char_win_draw_string(main_dc,pc_rect,(char *) str,0,18); + OffsetRect(&pc_rect,0,13); + sprintf((char *) str,"Health %d, Spell pts. %d", adven[i].max_health,adven[i].max_sp); + char_win_draw_string(main_dc,pc_rect,(char *) str,0,18); + break; + case MAIN_STATUS_DEAD: char_win_draw_string(main_dc,pc_rect,"Dead",0,18); break; + case MAIN_STATUS_DUST: char_win_draw_string(main_dc,pc_rect,"Dust",0,18); break; + case MAIN_STATUS_STONE: char_win_draw_string(main_dc,pc_rect,"Stone",0,18); break; + } + } + } + + SelectObject(main_dc,small_bold_font); + pc_rect = startup_from[0]; + OffsetRect(&pc_rect,5,5); + pc_rect.top = pc_rect.bottom - 28; + pc_rect.left = pc_rect.right - 255; + char_win_draw_string(main_dc,pc_rect,"That is not dead which can eternally lie...",0,18); + + SetTextColor(main_dc,colors[0]); + DeleteObject(hbrush); +} + +void draw_startup_anim() +{ + RECT anim_to = {1,4,276,44},anim_from; + RECT anim_size = {0,0,301,48}; + + anim_from = anim_to; + OffsetRect(&anim_from,-1,-4 + startup_anim_pos); + startup_anim_pos = (startup_anim_pos + 1) % 542; + rect_draw_some_item(startup_button_orig,anim_size,startup_button_g,anim_size,0,0); + rect_draw_some_item(anim_mess,anim_from,startup_button_g,anim_to,1,0); + rect_draw_some_item(startup_button_g,anim_size,startup_button_g,startup_button[5],0,1); +} + +void draw_start_button(short which_position,short which_button) +{ + RECT from_rect,to_rect; + char *button_labels[] = + { + "Load Game", + "Make New Party", + " < Unused > ", + "Start Scenario", + "Custom Scenario", + "Quit" + }; + COLORREF colors[5] = {RGB(0,0,0),RGB(255,0,0),RGB(255,255,255),RGB(0,255,255),RGB(0,0,255)}; + + from_rect = startup_from[3]; + OffsetRect(&from_rect, (which_button > 0) ? 40 : 0,0); + to_rect = startup_button[which_position]; + to_rect.left += 4; to_rect.top += 4; + to_rect.right = to_rect.left + 40; + to_rect.bottom = to_rect.top + 40; + from_rect.top += 4; to_rect.top += 4; + rect_draw_some_item(startup_gworld,from_rect,startup_gworld,to_rect,0,1); + + to_rect = startup_button[which_position]; + OffsetRect(&to_rect, 10, 0); + if (which_button == 5) + which_button = 4; + SetTextColor(main_dc,colors[2]); + + SelectObject(main_dc,fantasy_font); + if (which_position == 3) + OffsetRect(&to_rect,-7,0); + SetTextColor(main_dc,colors[0]); + + OffsetRect(&to_rect,0,1); + char_win_draw_string(main_dc,to_rect, + (char *) button_labels[which_position],1,18); + OffsetRect(&to_rect,0,-2); + char_win_draw_string(main_dc,to_rect, + (char *) button_labels[which_position],1,18); + OffsetRect(&to_rect,1,1); + char_win_draw_string(main_dc,to_rect, + (char *) button_labels[which_position],1,18); + OffsetRect(&to_rect,-2,0); + char_win_draw_string(main_dc,to_rect, + (char *) button_labels[which_position],1,18); + OffsetRect(&to_rect,1,0); + SetTextColor(main_dc,colors[2]); + char_win_draw_string(main_dc,to_rect, + (char *) button_labels[which_position],1,18); + SelectObject(main_dc,font); + SetTextColor(main_dc,colors[0]); +} + +void main_button_click(short, RECT button_rect) +{ + long dummy; + + ClipRect(&button_rect); + + draw_buttons(1); + if (play_sounds == TRUE) + play_sound(37); + else Delay(5,&dummy); + draw_buttons(0); + undo_clip(); +} + +void arrow_button_click(RECT button_rect) +{ + long dummy; + + ClipRect(&button_rect); + + refresh_stat_areas(1); + if (play_sounds == TRUE) + play_sound(37); + else Delay(5,&dummy); + refresh_stat_areas(0); + undo_clip(); +} + +void reload_startup()//// +{ + if (startup_loaded == TRUE) + return; + + DestroyWindow(modeless_dialogs[5]); + modeless_exists[5] = FALSE; + if (text_sbar != NULL) { + ShowScrollBar(text_sbar,SB_CTL,FALSE); + ShowScrollBar(item_sbar,SB_CTL,FALSE); + } + init_startup(); + + startup_loaded = TRUE; +} + +void end_startup() +{ + if (startup_loaded == FALSE) + return; + + DeleteObject(startup_gworld); + DeleteObject(startup_button_orig); + DeleteObject(startup_button_g); + DeleteObject(anim_mess); + + startup_loaded = FALSE; + load_main_screen(); +} + +// This loads the graphics at the top of the game. +void Set_up_win () +{ + RECT temp_rect = {0,0,280,0}; + RECT map_rect = {0,0,384,384}; + RECT pc_rect = {0,0,113,216}; + HBITMAP temp_gworld; + short i,j; + RECT r = {0,0,280,180}; /**/ + RECT bg_from[9] = {{0,168,8,176},{23,206,31,214},{32,168,40,176},{102,174,110,182}, + {173,191,181,199},{203,190,211,198},{273,183,281,191},{373,0,381,8}, + {380,17,388,25}}; + RECT map_from_orig = {372,0,380,8},map_from,brush_to = {0,0,8,8}; + WORD patbits[] = {0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55}; + + RECT pat_from = {96,168,160,232}, pat_to_orig = {0,0,64,64},pat_to; + + checker_bitmap = CreateBitmap(8,8,1,1,(LPSTR) patbits); + checker_brush = CreatePatternBrush(checker_bitmap); + bw_bitmap = CreateBitmap(72,72,1,1,NULL); + + temp_rect.bottom = (STORED_GRAPHICS / 10) * 36; + storage_gworld = CreateCompatibleBitmap(main_dc,temp_rect.right,temp_rect.bottom); + + temp_gworld = load_pict(800,main_dc); + rect_draw_some_item(temp_gworld,r,storage_gworld,r,0,0); + DeleteObject(temp_gworld); + + terrain_screen_gworld = load_pict(705,main_dc); + + party_template_gworld = CreateCompatibleBitmap(main_dc,pc_rect.right,pc_rect.bottom); + small_temp_gworld = CreateCompatibleBitmap(main_dc,28,36); + + items_gworld = load_pict(901,main_dc); + tiny_obj_gworld = load_pict(900,main_dc); + fields_gworld = load_pict(821,main_dc); + missiles_gworld = load_pict(880,main_dc); + dlogpics_gworld = load_pict(850,main_dc); + mixed_gworld = load_pict(903,main_dc); + + dialog_pattern_gworld = CreateCompatibleBitmap(main_dc,192,256); + pattern_gworld = CreateCompatibleBitmap(main_dc,192,256); + status_pattern_gworld = CreateCompatibleBitmap(main_dc,256,128); + for (i = 0; i < 4; i++) + for (j = 0; j < 2; j++) { + pat_to = pat_to_orig; + OffsetRect(&pat_to,64 * i, 64 * j); + rect_draw_some_item(mixed_gworld,pat_from,status_pattern_gworld, + pat_to,0,0); + } + + + dlg_buttons_gworld = load_pict(2000,main_dc); + + map_gworld = CreateCompatibleBitmap(main_dc,map_rect.right,map_rect.bottom); + + // Create and initialize map gworld + + for (i = 0; i < 9; i++) { + bg_bitmap[i] = CreateCompatibleBitmap(main_dc,8,8); + rect_draw_some_item(mixed_gworld,bg_from[i],bg_bitmap[i],brush_to,0,0); + bg[i] = CreatePatternBrush(bg_bitmap[i]); + } + + for (i = 0; i < 25; i++) { + map_from = map_from_orig; + OffsetRect(&map_from,8 * (i / 10),8 * (i % 10)); + map_bitmap[i] = CreateCompatibleBitmap(main_dc,8,8); + rect_draw_some_item(mixed_gworld,map_from,map_bitmap[i],brush_to,0,0); + map_brush[i] = CreatePatternBrush(map_bitmap[i]); + } +} + +void lose_graphics() +{ + short i,j; + + if (startup_loaded == TRUE) + { + DeleteObject(startup_gworld); + } + else + { + DeleteObject(pc_stats_gworld); + DeleteObject(item_stats_gworld); + DeleteObject(text_area_gworld); + DeleteObject(text_bar_gworld); + DeleteObject(orig_text_bar_gworld); + DeleteObject(buttons_gworld); + } + + DeleteObject(bw_bitmap); + DeleteObject(dialog_pattern_gworld); + DeleteObject(pattern_gworld); + DeleteObject(status_pattern_gworld); + + DeleteObject(checker_bitmap); + DeleteObject(checker_brush); + DeleteObject(storage_gworld); + DeleteObject(terrain_screen_gworld); + DeleteObject(party_template_gworld); + DeleteObject(items_gworld); + DeleteObject(tiny_obj_gworld); + DeleteObject(fields_gworld); + DeleteObject(missiles_gworld); + DeleteObject(dlogpics_gworld); + DeleteObject(mixed_gworld); + DeleteObject(dlg_buttons_gworld); + DeleteObject(map_gworld); + DeleteObject(small_temp_gworld); + DeleteDC(main_dc3); + DeleteDC(main_dc2); + DeleteObject(font); + DeleteObject(fantasy_font); + DeleteObject(underline_font); + DeleteObject(italic_font); + DeleteObject(bold_font); + for (i = 0; i < 9; i++) + { + DeleteObject(bg_bitmap[i]); + DeleteObject(bg[i]); + } + for (i = 0; i < 25; i++) + { + DeleteObject(map_bitmap[i]); + DeleteObject(map_brush[i]); + } + for (i = 0; i < 3; i++) + for (j = 0; j < 3; j++) + DeleteObject(arrow_curs[i][j]); + DeleteObject(talk_curs); + DeleteObject(sword_curs); + DeleteObject(key_curs); + DeleteObject(target_curs); + DeleteObject(look_curs); + DeleteObject(gbrush); + DeleteObject(gpen); + + kill_sound(); + } + + +void load_main_screen() +{ + HBITMAP temp_gworld; + RECT from_rect = {0,0,271,116},to_rect = {0,0,0,0}; + + // load in graphic with 3 right side status areas, and copy each of them into + // its own private HBITMAP + temp_gworld = load_pict(700,main_dc); + + pc_stats_gworld = CreateCompatibleBitmap(main_dc,271,116); + to_rect.right = 271; to_rect.bottom = 116; + rect_draw_some_item(temp_gworld,from_rect,pc_stats_gworld,to_rect,0,0); + + item_stats_gworld = CreateCompatibleBitmap(main_dc,271,144); + to_rect.bottom = 144; + from_rect.top = 116; from_rect.bottom = 260; + rect_draw_some_item(temp_gworld,from_rect,item_stats_gworld,to_rect,0,0); + + text_area_gworld = CreateCompatibleBitmap(main_dc,256,138); + to_rect.right = 256; to_rect.bottom = 138; + from_rect.top = 260; from_rect.bottom = 398; from_rect.right = 256; + rect_draw_some_item(temp_gworld,from_rect,text_area_gworld,to_rect,0,0); + + DeleteObject(temp_gworld); + + text_bar_gworld = load_pict(703,main_dc); + orig_text_bar_gworld = load_pict(703,main_dc); + buttons_gworld = load_pict(704,main_dc); +} + +void create_clip_region() +{ + short i; + RECT store_rect = {0,0,2000,2000}; + RECT scrollbar_rect; + HRGN temp_rgn; + + DeleteObject(clip_region); + GetWindowRect(GetDesktopWindow(),&store_rect); + + clip_region = CreateRectRgn(0,0,store_rect.right * 2,store_rect.bottom * 2); + + + for (i = 0; i < 6; i++) { + store_rect = win_to_rects[i]; + OffsetRect(&store_rect,ulx,uly); + if ((is_out()) || (is_town()) || (is_combat()) || + (i == 2) || (i == 3) || (i == 5)) { + temp_rgn = CreateRectRgn(store_rect.left,store_rect.top,store_rect.right,store_rect.bottom); + CombineRgn(clip_region,clip_region,temp_rgn,RGN_DIFF); + DeleteObject(temp_rgn); + } + } + if ((overall_mode == 20) || (overall_mode == 21) ){ + scrollbar_rect = talk_area_rect; + OffsetRect(&scrollbar_rect,ulx,uly); + temp_rgn = CreateRectRgn(scrollbar_rect.left,scrollbar_rect.top,scrollbar_rect.right,scrollbar_rect.bottom); + CombineRgn(clip_region,clip_region,temp_rgn,RGN_DIFF); + DeleteObject(temp_rgn); + } + scrollbar_rect = sbar_rect; + OffsetRect(&scrollbar_rect,ulx,uly); + temp_rgn = CreateRectRgn(scrollbar_rect.left,scrollbar_rect.top,scrollbar_rect.right,scrollbar_rect.bottom); + CombineRgn(clip_region,clip_region,temp_rgn,RGN_DIFF); + DeleteObject(temp_rgn); + scrollbar_rect = item_sbar_rect; + OffsetRect(&scrollbar_rect,ulx,uly); + temp_rgn = CreateRectRgn(scrollbar_rect.left,scrollbar_rect.top,scrollbar_rect.right,scrollbar_rect.bottom); + CombineRgn(clip_region,clip_region,temp_rgn,RGN_DIFF); + DeleteObject(temp_rgn); + +} + +// redraw_screen does the very first redraw, and any full redraw +void redraw_screen(short) +{ + if (text_sbar == NULL) { + text_sbar = CreateWindow("scrollbar",NULL, + WS_CHILD | WS_TABSTOP | SBS_VERT | WS_VISIBLE, sbar_rect.left,sbar_rect.top,sbar_rect.right,sbar_rect.bottom, + mainPtr,(HMENU) 1,store_hInstance,NULL); + SetScrollRange(text_sbar,SB_CTL,0,58,FALSE); + item_sbar = CreateWindow("scrollbar",NULL, + WS_CHILD | WS_TABSTOP | SBS_VERT | WS_VISIBLE, item_sbar_rect.left,item_sbar_rect.top,item_sbar_rect.right,item_sbar_rect.bottom, + mainPtr,(HMENU) 2,store_hInstance,NULL); + SetScrollRange(item_sbar,SB_CTL,0,16,FALSE); + ShowScrollBar(text_sbar,SB_CTL,TRUE); + ShowScrollBar(item_sbar,SB_CTL,TRUE); + MoveWindow(text_sbar,ulx + 547,uly + 283,15,138,TRUE); + MoveWindow(item_sbar,ulx + 547,uly + 147,15,107,TRUE); + } + else { + ShowScrollBar(text_sbar,SB_CTL,TRUE); + ShowScrollBar(item_sbar,SB_CTL,TRUE); + } + switch (overall_mode) { + case 20: case 21: + put_background(); + break; + default: + draw_terrain(0); + + draw_buttons(0); + draw_text_bar(1); + if ((overall_mode == 10) && (current_pc < 6)) + draw_pcs(pc_pos[current_pc],1); + if (overall_mode == 14) + draw_targets(center); + + break; + } + + put_pc_screen(); + + if (current_pc < 6) put_item_screen(current_pc,0); + + print_buf(); +} + +void refresh_screen(short) +{ + if (overall_mode == MODE_TALKING) { + put_background(); + refresh_talking(); + } + else if (overall_mode == MODE_SHOPPING) { + put_background(); + refresh_shopping(); + } + else { + draw_buttons(0); + redraw_terrain(); + if ((current_pc < 6) && (overall_mode == MODE_COMBAT)) + draw_pcs(pc_pos[current_pc],1); + if (overall_mode == 14) + draw_targets(center); + draw_text_bar(1); + } + + refresh_stat_areas(0); + draw_text_bar(0); +} + +void put_background() +{ + short wp; + RECT r; + + if (is_out()) { + if (party.outdoor_corner.x >= 7) + wp = 0; + else wp = 7; + } + else if (is_combat()) { + if (party.outdoor_corner.x >= 7) + wp = 9; + else wp = 6; + } + else { + if (party.outdoor_corner.x >= 7) + wp = 5; + else wp = 8; + } + + SelectClipRgn(main_dc,clip_region); + GetClientRect(mainPtr,&r); + paint_pattern((HBITMAP)mainPtr, 1,r,wp); + undo_clip(); +} + +void draw_buttons(short mode) +//mode; // 0 - regular 1 - button action +{ + RECT source_rect = {0,0,258,37}, dest_rec; /**/ + HBITMAP buttons_to_draw; + Boolean spec_draw = FALSE; + + if (mode == 1) { + spec_draw = TRUE; + mode -= 100; + } + + buttons_to_draw = buttons_gworld; + + source_rect = win_to_rects[1]; + OffsetRect(&source_rect,-1 * source_rect.left, -1 * source_rect.top); + if (is_combat()) { + source_rect.top += 37; + source_rect.bottom += 37; + } + if (is_town()) { + source_rect.top += 74; + source_rect.bottom += 74; + } + + dest_rec = win_to_rects[1]; + rect_draw_some_item(buttons_gworld,source_rect,buttons_gworld,dest_rec,(spec_draw == TRUE) ? 2 : 0,1); + + put_background(); + +} + +void reset_text_bar() +{ + remember_tiny_text = 300; +} + + +void draw_text_bar(short mode) +//short mode; // 0 - no redraw 1 - forced +{ + short i;//num_rect[3] = {12,10,4}; + location loc; + + loc = (is_out()) ? party.p_loc.toLocal() : c_town.p_loc; + + if (mode == 1) + remember_tiny_text = 500; + if ((PSD[305][0] > 0) || (PSD[305][1] > 0) ||(PSD[305][2] > 0) ||(PSD[305][3] > 0) ) + remember_tiny_text = 500; + if (is_out()) { + for (i = 0; i < 8; i++) + if (pt_in_rect(loc,outdoors[party.i_w_c.x][party.i_w_c.y].info_rect[i])) + if ((remember_tiny_text == i) && (mode == 0)) + return; + else { + put_text_bar(data_store4->outdoor_text[party.i_w_c.x][party.i_w_c.y].out_strs[i + 1]); + remember_tiny_text = i; + return; + } + if (remember_tiny_text != 50 + party.i_w_c.x + party.i_w_c.y) { + put_text_bar((char *) data_store4->outdoor_text[party.i_w_c.x][party.i_w_c.y].out_strs[0]); + remember_tiny_text = 50 + party.i_w_c.x + party.i_w_c.y; + } + } + if (is_town()) { + for (i = 0; i < 16; i++) + if (pt_in_rect(loc,t_d.room_rect[i])) + if ((remember_tiny_text == 200 + i) && (mode == 0)) + return; + else { + put_text_bar(data_store->town_strs[i + 1]); + remember_tiny_text = 200 + i; + return; + } + if (remember_tiny_text != 250) { + put_text_bar((char *) data_store->town_strs[0]); //// + remember_tiny_text = 250; + } + + } + if ((is_combat()) && (current_pc < 6) && (monsters_going == FALSE)) { + sprintf((char *) combat_string,"%s (ap: %d)", + adven[current_pc].name,pc_moves[current_pc]); + put_text_bar((char *) combat_string); + remember_tiny_text = 500; + } + if ((is_combat()) && (monsters_going == TRUE)) // Print bar for 1st monster with >0 ap - + // that is monster that is going + for (i = 0; i < T_M; i++) + if ((c_town.monst.dudes[i].active > 0) && (c_town.monst.dudes[i].m_d.ap > 0)) { + print_monster_going((char *) combat_string,c_town.monst.dudes[i].number,c_town.monst.dudes[i].m_d.ap); + put_text_bar((char *) combat_string); + remember_tiny_text = 500; + i = 400; + } +} + +void put_text_bar(char *str) +{ + char status_str[256]; + short xpos = 205; + HDC hdc; + HBITMAP store_bmp; + RECT text_rect = {5,3,279,21}; + COLORREF x = RGB(0,0,0),y = RGB(255,255,255); + + rect_draw_some_item (orig_text_bar_gworld, win_from_rects[4], text_bar_gworld, win_from_rects[4], 0, 0); + + hdc = CreateCompatibleDC(main_dc); + SetBkMode(hdc,TRANSPARENT); + SelectObject(hdc,small_bold_font); + store_bmp = (HBITMAP) SelectObject(hdc,text_bar_gworld); + sprintf(status_str,"%s",str); + SetTextColor(hdc,y); + win_draw_string(hdc,text_rect,status_str,2,9); + SetTextColor(hdc,x); + + if (monsters_going == FALSE) { + if (PSD[305][0] > 0) { + text_rect.left = xpos; + SetTextColor(hdc,RGB(255,255,255)); + sprintf((char *) status_str,"Stealth"); + win_draw_string(hdc,text_rect,status_str,2,9); + xpos -= 60; + } + if (PSD[305][1] > 0) { + text_rect.left = xpos; + SetTextColor(hdc,RGB(255,255,255)); + sprintf((char *) status_str,"Flying"); + win_draw_string(hdc,text_rect,status_str,2,9); + xpos -= 60; + } + if (PSD[305][2] > 0) { + text_rect.left = xpos; + SetTextColor(hdc,RGB(255,255,255)); + sprintf((char *) status_str,"Detect Life"); + win_draw_string(hdc,text_rect,status_str,2,9); + xpos -= 60; + } + if (PSD[305][3] > 0) { + text_rect.left = xpos; + SetTextColor(hdc,RGB(145+PSD[305][3]*10,40+PSD[305][3]*10,40)); + sprintf((char *) status_str,"Firewalk"); + win_draw_string(hdc,text_rect,status_str,2,9); + xpos -= 60; + } + } + + SelectObject(hdc,store_bmp); + if (!DeleteDC(hdc)) DebugQuit("Cannot release DC 23"); + rect_draw_some_item (text_bar_gworld, win_from_rects[4], text_bar_gworld, win_to_rects[4], 0, 1); +} + +// This is called when a new situation is entered. It figures out what graphics are needed, +// sets up which_g_stored, and loads them. +void load_area_graphics() +{ + short i; + + currently_loading_graphics = TRUE; + + // Set all graphics as loseable + for (i = 50; i < STORED_GRAPHICS; i++) + if (storage_status[i] == 1) + storage_status[i] = 2; + for (i = 0; i < STORED_GRAPHICS; i++) + wish_list[i] = 0; + + // Build wish list + if (is_out()) + load_outdoor_graphics(); + if ((is_town()) || (is_combat())) + load_town_graphics(); + + // Reserve all in wish list not taken + for (i = 0; i < STORED_GRAPHICS; i++) + if (wish_list[i] > 49) + if (reserve_graphic_num_in_array(wish_list[i]) == TRUE) + wish_list[i] = 0; + + // Place all graphics not found in array. + for (i = 0; i < STORED_GRAPHICS; i++) + if (wish_list[i] > 49) { + place_graphic_num_in_array(wish_list[i]); + wish_list[i] = 0; + } + + // Finally, load graphics. + put_graphics_in_template(); + + currently_loading_graphics = FALSE; +} + +void add_to_wish_list(short which_g) +{ + short i; + + if (which_g < 50) return; + + for (i = 0; i < STORED_GRAPHICS; i++) + { + if (wish_list[i] == which_g) return; + if (wish_list[i] == 0) + { + wish_list[i] = which_g; + return; + } + } + add_string_to_buf("No room for graphic 1."); +} + +// Used to set up array. If graphic there, sets it to be saved, otherwise leaves. +// Returns TRUE is already there +Boolean reserve_graphic_num_in_array(short which_g) +{ + short i; + + if (which_g < 50) + return TRUE; + for (i = 50; i < STORED_GRAPHICS; i++) + if (which_g_stored[i] == which_g) { + storage_status[i] = 1; + return TRUE; + } + return FALSE; +} + +// Otherwise, puts in array. Note ... if graphic is alreayd here and locked (i.e. +// storage status is 1, this will add a new copy. +void place_graphic_num_in_array(short which_g) +{ + short i; + + for (i = 50; i < STORED_GRAPHICS; i++) + if ((storage_status[i] == 2) || (storage_status[i] == 0)) { + which_g_stored[i] = which_g; + storage_status[i] = 3; + return; + } + // if we get here, couldn't find a space. Time to flush excess crap. + + if (currently_loading_graphics == FALSE) + load_area_graphics(); // calling this is nice and fast, because game won't try to reload + // graphics already there. It'll only purge the trash. + + // try again + for (i = 50; i < STORED_GRAPHICS; i++) + if ((storage_status[i] == 2) || (storage_status[i] == 0)) { + which_g_stored[i] = which_g; + storage_status[i] = 3; + return; + } + add_string_to_buf("No room for graphic 2."); + print_nums(0,0,which_g); +} + +void add_one_graphic(short which_g) +{ + short i; + for (i = 0; i < STORED_GRAPHICS; i++) + if (which_g_stored[i] == which_g) { + // Good. We got it. Now lock it and leave + storage_status[i] = 1; + return; + } + + // otherwise, load it in + place_graphic_num_in_array(which_g); + put_graphics_in_template(); +} + + +void add_terrain_to_wish_list(unsigned char ter) +{ + if (terrain_pic[ter] >= 1000) + return; + else if (terrain_pic[ter] >= 400) + { + add_to_wish_list(600 + terrain_pic[ter]); + add_to_wish_list(700 + terrain_pic[ter]); + add_to_wish_list(800 + terrain_pic[ter]); + add_to_wish_list(900 + terrain_pic[ter]); + } + else switch (terrain_pic[ter]) { + + case 143: + add_to_wish_list(230); + add_to_wish_list(143); + break; + case 213: case 214: + add_to_wish_list(213); + add_to_wish_list(214); + break; + + case 215: + add_to_wish_list(215); + add_to_wish_list(218); + add_to_wish_list(219); + add_to_wish_list(220); + add_to_wish_list(221); + break; + case 216: + add_to_wish_list(216); + add_to_wish_list(222); + add_to_wish_list(223); + add_to_wish_list(224); + add_to_wish_list(225); + break; + case 68: case 69: + add_to_wish_list(68); + add_to_wish_list(69); + break; + case 86: case 87: + add_to_wish_list(86); + add_to_wish_list(87); + break; + + default: + add_to_wish_list((short) terrain_pic[ter]); + break; + } +} + +void load_outdoor_graphics() +{ + short l,m,i,j; + short pict; + + for (i = 0; i < 96; i++) + for (j = 0; j < 96; j++) + add_terrain_to_wish_list(out[i][j]); + + for (l = 0; l < 2; l++) + for (m = 0; m < 2; m++) + for (i = 0; i < 4; i++) { + for (j = 0; j < 7; j++) + if (outdoors[l][m].wandering[i].monst[j] != 0) { + pict = get_monst_picnum(outdoors[l][m].wandering[i].monst[j]); + //add_monst_graphic(pict,0); + add_monst_graphic(outdoors[l][m].wandering[i].monst[j],0); + + j = 8; + } + for (j = 0; j < 7; j++) + if (outdoors[l][m].special_enc[i].monst[j] != 0) { + pict = get_monst_picnum(outdoors[l][m].special_enc[i].monst[j]); + //add_monst_graphic(pict,0); + add_monst_graphic(outdoors[l][m].special_enc[i].monst[j],0); + j = 8; + } + } + + for (i = 0; i < 10; i++) + if (party.out_c[i].exists == TRUE) + for (j = 0; j < 7; j++) + if (party.out_c[i].what_monst.monst[j] != 0) { + pict = get_monst_picnum(party.out_c[i].what_monst.monst[j]); + //add_monst_graphic(pict, 0); + add_monst_graphic(party.out_c[i].what_monst.monst[j], 0); + j = 8; + } +} + +void add_monst_graphic(unsigned char m,short mode) +// mode 0 - just put in list, 1 - actually add graphics +{ + short x,y,i,pict; + get_monst_dims(m,&x,&y); + for (i = 0; i < x * y; i++) { + pict = get_monst_picnum(m); + if (pict >= NUM_MONST_G) + return; + pict = m_pic_index[pict]; + if (mode == 0) { + add_to_wish_list(300 + pict + i); + add_to_wish_list(600 + pict + i); + add_to_wish_list(2300 + pict + i); + add_to_wish_list(2600 + pict + i); + } + else { + add_one_graphic(300 + pict + i); + add_one_graphic(600 + pict + i); + add_one_graphic(2300 + pict + i); + add_one_graphic(2600 + pict + i); + } + } +} + +void load_town_graphics() // Setting up town monsters takes some finess, due to the flexibility + // of the situation +// This can be used for town or beginning out outdoor combat +{ + short i,j; + + for (i = 0; i < town_size[town_type]; i++) + for (j = 0; j < town_size[town_type]; j++) + if (is_combat()) + add_terrain_to_wish_list(combat_terrain[i][j]); + else add_terrain_to_wish_list(t_d.terrain[i][j]); + + for (i = 0; i < T_M; i++) + if ((c_town.monst.dudes[i].number != 0) && (c_town.monst.dudes[i].active > 0)) + add_monst_graphic(c_town.monst.dudes[i].number,0); + if (is_town()) + for (i = 0; i < 4; i++) + for (j = 0; j < 4; j++) { + add_monst_graphic(c_town.town.wandering[i].monst[j],0); + } +} + +void update_pc_graphics() +{ + short i; + HBITMAP temp_gworld; + RECT template_rect = {0,0,28,36}; /**/ + RECT source_rect; + + if (party_in_memory == FALSE) + return; + + temp_gworld = load_pict(902,main_dc); + + for (i = 0; i < 6; i++) + if (adven[i].main_status > MAIN_STATUS_ABSENT) + if (adven[i].which_graphic != which_graphic_index[i]) { + template_rect.left = (i / 3) * 56; + template_rect.right = template_rect.left + 56; + template_rect.top = (i % 3) * 36; + template_rect.bottom = template_rect.top + 36; + + source_rect.left = (adven[i].which_graphic / 8) * 56; + source_rect.right = source_rect.left + 56; + source_rect.top = 36 * (adven[i].which_graphic % 8); + source_rect.bottom = 36 * (adven[i].which_graphic % 8) + 36; + + rect_draw_some_item(temp_gworld,source_rect,party_template_gworld,template_rect,0,0); + + OffsetRect(&source_rect,280,0); + OffsetRect(&template_rect,0,108); + rect_draw_some_item(temp_gworld,source_rect,party_template_gworld,template_rect,0,0); + + which_graphic_index[i] = adven[i].which_graphic; + } + DeleteObject (temp_gworld); + +} + + +// This one is complicated, but that's because it's optimized for efficiency. +// Goes through, and loads graphics for anything with storage_status of 3 +void put_graphics_in_template() +{ + HBITMAP temp_gworld; + short i,j,which_position,offset; + Boolean this_graphic_needed = FALSE; + RECT from_rect,to_rect; + + // First, load all terrains + for (j = 1; j < 6; j++) { + for (i = 50; i < STORED_GRAPHICS; i++) + if ((which_g_stored[i] >= j * 50) && (which_g_stored[i] < j * 50 + 50) && + (storage_status[i] == 3)) { + this_graphic_needed = TRUE; + } + if (this_graphic_needed == TRUE) { + temp_gworld = load_pict(800 + j,main_dc); + for (i = 50; i < STORED_GRAPHICS; i++) + if ((which_g_stored[i] >= j * 50) && (which_g_stored[i] < j * 50 + 50) && + (storage_status[i] == 3)) { + which_position = which_g_stored[i] - j * 50; + from_rect = calc_rect(which_position % 10,which_position / 10); + to_rect = calc_rect(i % 10,i / 10); + + rect_draw_some_item(temp_gworld,from_rect,storage_gworld,to_rect,0,0); + storage_status[i] = 1; + } + DeleteObject (temp_gworld); + } + this_graphic_needed = FALSE; + } + + // Now, load all monsters + for (j = 0; j < 10; j++) { + for (i = 50; i < STORED_GRAPHICS; i++) + if ((which_g_stored[i] >= 300 + j * 20) && (which_g_stored[i] < 300 + j * 20 + 20) && + (storage_status[i] == 3)) + this_graphic_needed = TRUE; + for (i = 50; i < STORED_GRAPHICS; i++) + if ((which_g_stored[i] >= 600 + j * 20) && (which_g_stored[i] < 600 + j * 20 + 20) && + (storage_status[i] == 3)) + this_graphic_needed = TRUE; + + if (this_graphic_needed == TRUE) { + temp_gworld = load_pict(1100 + j,main_dc); + for (i = 50; i < STORED_GRAPHICS; i++) + if ((which_g_stored[i] >= 300 + j * 20) && (which_g_stored[i] < 300 + j * 20 + 20) && + (storage_status[i] == 3)) { + which_position = which_g_stored[i] % 20; + from_rect = calc_rect((which_position / 10) * 2,which_position % 10); + to_rect = calc_rect(i % 10,i / 10); + + rect_draw_some_item(temp_gworld,from_rect,storage_gworld,to_rect,0,0); + + storage_status[i] = 1; + } + for (i = 50; i < STORED_GRAPHICS; i++) + if ((which_g_stored[i] >= 600 + j * 20) && (which_g_stored[i] < 600 + j * 20 + 20) && + (storage_status[i] == 3)) { + which_position = which_g_stored[i] % 20; + from_rect = calc_rect((which_position / 10) * 2 + 1,which_position % 10); + to_rect = calc_rect(i % 10,i / 10); + + rect_draw_some_item(temp_gworld,from_rect,storage_gworld,to_rect,0,0); + + storage_status[i] = 1; + } + DeleteObject (temp_gworld); + } + this_graphic_needed = FALSE; + } + + // Now, load all monster combat poses + for (j = 0; j < 10; j++) { + for (i = 50; i < STORED_GRAPHICS; i++) + if ((which_g_stored[i] >= 2300 + j * 20) && (which_g_stored[i] < 2300 + j * 20 + 20) && + (storage_status[i] == 3)) + this_graphic_needed = TRUE; + for (i = 50; i < STORED_GRAPHICS; i++) + if ((which_g_stored[i] >= 2600 + j * 20) && (which_g_stored[i] < 2600 + j * 20 + 20) && + (storage_status[i] == 3)) + this_graphic_needed = TRUE; + + if (this_graphic_needed == TRUE) { + temp_gworld = load_pict(1200 + j,main_dc); + for (i = 50; i < STORED_GRAPHICS; i++) + if ((which_g_stored[i] >= 2300 + j * 20) && (which_g_stored[i] < 2300 + j * 20 + 20) && + (storage_status[i] == 3)) { + which_position = which_g_stored[i] % 20; + from_rect = calc_rect((which_position / 10) * 2 + 4,which_position % 10); + to_rect = calc_rect(i % 10,i / 10); + + rect_draw_some_item(temp_gworld,from_rect,storage_gworld,to_rect,0,0); + + storage_status[i] = 1; + } + for (i = 50; i < STORED_GRAPHICS; i++) + if ((which_g_stored[i] >= 2600 + j * 20) && (which_g_stored[i] < 2600 + j * 20 + 20) && + (storage_status[i] == 3)) { + which_position = which_g_stored[i] % 20; + from_rect = calc_rect((which_position / 10) * 2 + 5,which_position % 10); + to_rect = calc_rect(i % 10,i / 10); + + rect_draw_some_item(temp_gworld,from_rect,storage_gworld,to_rect,0,0); + + storage_status[i] = 1; + } + DeleteObject (temp_gworld); + } + this_graphic_needed = FALSE; + } + + + // Now, anim terrains + for (i = 50; i < STORED_GRAPHICS; i++) + if ((which_g_stored[i] >= 1000) && (which_g_stored[i] < 1400) && + (storage_status[i] == 3)) + this_graphic_needed = TRUE; + if (this_graphic_needed == TRUE) { + temp_gworld = load_pict(820,main_dc); + for (i = 50; i < STORED_GRAPHICS; i++) + if ((which_g_stored[i] >= 1000) && (which_g_stored[i] < 1400) && + (storage_status[i] == 3)) { + which_position = which_g_stored[i] % 100; + offset = (which_g_stored[i] - 1000) / 100; + from_rect = calc_rect(4 * (which_position / 5) + offset,which_position % 5); + to_rect = calc_rect(i % 10,i / 10); + + rect_draw_some_item(temp_gworld,from_rect,storage_gworld,to_rect,0,0); + + storage_status[i] = 1; + } + DeleteObject(temp_gworld); + } +} + +// this is used for determinign whether to round off walkway corners +// right now, trying a restrictive rule (just cave floor and grass, mainly) +Boolean is_nature(char x, char y) +{ + short pic; + unsigned char ter_type; + + ter_type = coord_to_ter((short) x,(short) y); + pic = scenario.ter_types[ter_type].picture; + if ((pic >= 0) && (pic <= 45)) + return TRUE; + if ((pic >= 67) && (pic <= 73)) + return TRUE; + if ((pic >= 75) && (pic <= 87)) + return TRUE; + if ((pic >= 121) && (pic <= 122)) + return TRUE; + if ((pic >= 179) && (pic <= 208)) + return TRUE; + if ((pic >= 211) && (pic <= 212)) + return TRUE; + if ((pic >= 217) && (pic <= 246)) + return TRUE; + + return FALSE; +} + + + +void draw_terrain(short mode) +//mode ... if 1, don't place on screen after redoing +// if 2, only redraw over active monst +{ + short q,r; + location where_draw; + location sector_p_in,view_loc; + char can_draw; + unsigned char spec_terrain; + Boolean off_terrain = FALSE,draw_trim = TRUE; + short i,j,short_spec_terrain; + + if (mode == 2) { + if (current_working_monster < 0) return; + supressing_some_spaces = TRUE; + for (i = 0; i < 4; i++) ok_space[i].x = -1; + if (current_working_monster >= 100) { + for (i = 0; i < c_town.monst.dudes[current_working_monster - 100].m_d.x_width; i++) + for (j = 0; j < c_town.monst.dudes[current_working_monster - 100].m_d.y_width; j++) { + ok_space[i + 2 * j].x = c_town.monst.dudes[current_working_monster - 100].m_loc.x + i; + ok_space[i + 2 * j].y = c_town.monst.dudes[current_working_monster - 100].m_loc.y + j; + ok_space[i + 2 * j].x = ok_space[i + 2 * j].x - center.x + 4; + ok_space[i + 2 * j].y = ok_space[i + 2 * j].y - center.y + 4; + } + } + if (current_working_monster < 6) { + ok_space[0] = pc_pos[current_working_monster]; + ok_space[0].x = ok_space[0].x - center.x + 4; + ok_space[0].y = ok_space[0].y - center.y + 4; + } + mode = 0; + } + + for (i = 0; i < 13; i++) + for (j = 0; j < 13; j++) { + light_area[i][j] = 0; + unexplored_area[i][j] = 0; + } + + sector_p_in.x = party.outdoor_corner.x + party.i_w_c.x; + sector_p_in.y = party.outdoor_corner.y + party.i_w_c.y; + + anim_onscreen = FALSE; + + if (is_town()) + view_loc = c_town.p_loc; + if (is_combat()) + view_loc = pc_pos[(current_pc < 6) ? current_pc : first_active_pc()]; + + for (i = 0; i < 13; i++) + for (j = 0; j < 13; j++) { + where_draw = (is_out()) ? party.p_loc : center; + where_draw.x += i - 6; + where_draw.y += j - 6; + if (is_out() == FALSE) + light_area[i][j] = (is_town()) ? pt_in_light(view_loc,where_draw) : combat_pt_in_light(where_draw); + if ((is_out() == FALSE) && ((where_draw.x < 0) || (where_draw.x > town_size[town_type] - 1) + || (where_draw.y < 0) || (where_draw.y > town_size[town_type] - 1))) + unexplored_area[i][j] = 0; + else unexplored_area[i][j] = 1 - is_explored(where_draw.x,where_draw.y); + } + + + for (q = 0; q < 9; q++) { + for (r = 0; r < 9; r++) + { + where_draw = (is_out()) ? party.p_loc : center; + where_draw.x += q - 4; + where_draw.y += r - 4; + off_terrain = FALSE; + + draw_trim = TRUE; + if ((is_out() == FALSE) && ((where_draw.x < 0) || (where_draw.x > town_size[town_type] - 1) + || (where_draw.y < 0) || (where_draw.y > town_size[town_type] - 1))) { + draw_trim = FALSE; + // Warning - this section changes where_draw + if (where_draw.x < 0) + where_draw.x = -1; + if (where_draw.x > town_size[town_type] - 1) + where_draw.x = town_size[town_type]; + if (where_draw.y < 0) + where_draw.y = -1; + if (where_draw.y > town_size[town_type] - 1) + where_draw.y = town_size[town_type]; + if (can_see(view_loc,where_draw,0) < 5) + can_draw = 1; + else can_draw = 0; + spec_terrain = 0; + } + else if (is_out()) { + if ((where_draw.x < 0) || (where_draw.x > 95) + || (where_draw.y < 0) || (where_draw.y > 95)) + can_draw = 0; + else { + spec_terrain = out[where_draw.x][where_draw.y]; + can_draw = out_e[where_draw.x][where_draw.y]; + } + } + else if (is_combat()) { + + spec_terrain = combat_terrain[where_draw.x][where_draw.y]; + if (cartoon_happening == TRUE) + can_draw = TRUE; + else can_draw = (((is_explored(where_draw.x,where_draw.y)) || + (which_combat_type == 0) || (monsters_going == TRUE) || (overall_mode != 10)) + && (party_can_see(where_draw) < 6)) ? 1 : 0; + + } + else { + spec_terrain = t_d.terrain[where_draw.x][where_draw.y]; + can_draw = is_explored(where_draw.x,where_draw.y); + + if (can_draw > 0) { + if (pt_in_light(c_town.p_loc,where_draw) == FALSE) + can_draw = 0; + } + if ((overall_mode == 36) && (can_draw == 0)) + can_draw = (party_can_see(where_draw) < 6) ? 1 : 0; + } + spot_seen[q][r] = can_draw; + + + if ((can_draw != 0) && (overall_mode != 50)) { // if can see, not a pit, and not resting + if ((is_combat()) && (cartoon_happening == FALSE)) { + anim_ticks = 0; + } + + short_spec_terrain = spec_terrain; + + // Finally, draw this terrain spot + + switch (short_spec_terrain) { + case 82: // cave wway + if (loc_off_act_area(where_draw) == FALSE) { + if ((is_nature(where_draw.x - 1,where_draw.y)) && + (is_nature(where_draw.x,where_draw.y - 1) )) + short_spec_terrain = 10219; + if ((is_nature(where_draw.x + 1,where_draw.y) ) && + (is_nature(where_draw.x,where_draw.y - 1) )) + short_spec_terrain = 10220; + if ((is_nature(where_draw.x + 1,where_draw.y) ) && + (is_nature(where_draw.x,where_draw.y + 1) )) + short_spec_terrain = 10221; + if ((is_nature(where_draw.x - 1,where_draw.y) ) && + (is_nature(where_draw.x,where_draw.y + 1) )) + short_spec_terrain = 10218; + } + draw_one_terrain_spot(q,r,short_spec_terrain,0); + break; + case 83: // ground wway + if (loc_off_act_area(where_draw) == FALSE) { + if ((is_nature(where_draw.x - 1,where_draw.y)) && + (is_nature(where_draw.x,where_draw.y - 1)) ) + short_spec_terrain = 10223; + if ((is_nature(where_draw.x + 1,where_draw.y) ) && + (is_nature(where_draw.x,where_draw.y - 1) )) + short_spec_terrain = 10224; + if ((is_nature(where_draw.x + 1,where_draw.y) ) && + (is_nature(where_draw.x,where_draw.y + 1) )) + short_spec_terrain = 10225; + if ((is_nature(where_draw.x - 1,where_draw.y) ) && + (is_nature(where_draw.x,where_draw.y + 1) )) + short_spec_terrain = 10222; + } + draw_one_terrain_spot(q,r,short_spec_terrain,0); + break; + + case 79: case 80: case 81: + if ((short_spec_terrain == 81) + && ((out[where_draw.x][where_draw.y - 1] == 80) || (out[where_draw.x][where_draw.y - 1] == 79))) + short_spec_terrain = 42; + if ((short_spec_terrain == 81) + && ((out[where_draw.x][where_draw.y + 1] == 80) || (out[where_draw.x][where_draw.y + 1] == 79))) + short_spec_terrain = 38; + if ((short_spec_terrain == 81) + && ((out[where_draw.x - 1][where_draw.y] == 80) || (out[where_draw.x - 1][where_draw.y] == 79))) + short_spec_terrain = 44; + if ((short_spec_terrain == 81) + && ((out[where_draw.x + 1][where_draw.y ] == 80) || (out[where_draw.x + 1][where_draw.y] == 79))) + short_spec_terrain = 40; + draw_one_terrain_spot(q,r,short_spec_terrain,0); + place_road(q,r,where_draw); + break; + case 90: + draw_one_terrain_spot(q,r,-1,0); + break; + default: + if (short_spec_terrain < 2) + current_ground = 0; + if ((short_spec_terrain == 2) || ( + (short_spec_terrain >= 22) && (short_spec_terrain <= 49))) + current_ground = 2; + draw_one_terrain_spot(q,r,short_spec_terrain,0); + break; + } + + } + else { // Can't see. Place darkness. + draw_one_terrain_spot(q,r,-1,0); + } + + if ((can_draw != 0) && (overall_mode != 50) && (frills_on == TRUE) + && (draw_trim == TRUE) && (cartoon_happening == FALSE)) { // Place the trim + place_trim((short) q,(short) r,where_draw,spec_terrain); + } + } + } + + if ((overall_mode != 50) && (!is_out())) + draw_sfx(); + + // Now place items + if ((overall_mode > 0) && (overall_mode != 35) && (overall_mode != 50)) + draw_items(); + + // Now place fields + if ((overall_mode != 50) && (!is_out())) + { + if (crate == TRUE) draw_one_field(8,6,0); + if (barrel == TRUE) draw_one_field(16,7,0); + if (web == TRUE) draw_one_field(4,5,0); + if (quickfire == TRUE) draw_one_field(128,7,1); + if (fire_barrier == TRUE) draw_one_field(32,anim_ticks % 4,2); + if (force_barrier == TRUE) draw_one_field(64,anim_ticks % 4,2); + if (force_wall == TRUE) draw_one_spec_item(2,0,1); + if (fire_wall == TRUE) draw_one_spec_item(4,1,1); + if (antimagic == TRUE) draw_one_spec_item(8,2,1); + if (scloud == TRUE) draw_one_spec_item(16,3,1); + if (ice_wall == TRUE) draw_one_spec_item(32,4,1); + if (blade_wall == TRUE) draw_one_spec_item(64,5,1); + if (sleep_field == TRUE) draw_one_spec_item(128,6,1); + } + + // Not camping. Place misc. shit. + if (overall_mode != 50) { + if (is_out()) + draw_outd_boats(party.p_loc); + else if ((is_town()) || (which_combat_type == 1)) + draw_town_boat(center); + draw_monsters(); + } + + + if ((overall_mode < MODE_COMBAT) || (overall_mode == 35) || ((overall_mode == 36) && (point_onscreen(c_town.p_loc,center) == TRUE)) + || (overall_mode == 50)) + draw_party_symbol(center); + else if (overall_mode != 36) + draw_pcs(center,0); + + + apply_light_mask(); + apply_unseen_mask(); + // } + if (mode == 0) { + redraw_terrain(); + + if (cartoon_happening == FALSE) { + draw_text_bar(0); + if ((overall_mode > 9) && (overall_mode != 35) && (overall_mode != 36) && (overall_mode != 50)) + draw_pcs(center,1); + if (overall_mode == 14) + draw_targets(center); + + } + + } + + + supressing_some_spaces = FALSE; +} + +void place_trim(short q,short r,location where,unsigned char ter_type) +{ + Boolean at_top = FALSE,at_bot = FALSE,at_left = FALSE,at_right = FALSE; + unsigned char store,store2,store3,store1; + location targ; + + // FIrst quick check ... if a pit or barrier in outdoor combat, no trim + if ((is_combat()) && (which_combat_type == 0) && (ter_type == 90)) + return; + if (PSD[306][5] > 0) + return; + + targ.x = q; + targ.y = r; + if ((supressing_some_spaces == TRUE) && + (same_point(targ,ok_space[0]) == FALSE) && + (same_point(targ,ok_space[1]) == FALSE) && + (same_point(targ,ok_space[2]) == FALSE) && + (same_point(targ,ok_space[3]) == FALSE)) + return; + + + if (where.x == 0) + at_left = TRUE; + if (where.y == 0) + at_top = TRUE; + if ((overall_mode == MODE_OUTDOORS) || (overall_mode == 35)) { + if (where.x == 95) + at_right = TRUE; + if (where.y == 95) + at_bot = TRUE; + } + else { + if (where.x == town_size[town_type]) + at_right = TRUE; + if (where.y == town_size[town_type]) + at_bot = TRUE; + } + + // First, trim for fluids + if (((is_town()) || (is_combat())) && (town_trim[where.x][where.y] != 0)) { + + if (town_trim[where.x][where.y] & 1) + draw_trim(q,r,1,0); + if (town_trim[where.x][where.y] & 2) + draw_trim(q,r,2,5); + if (town_trim[where.x][where.y] & 4) + draw_trim(q,r,0,3); + if (town_trim[where.x][where.y] & 8) + draw_trim(q,r,2,6); + if (town_trim[where.x][where.y] & 16) + draw_trim(q,r,1,1); + if (town_trim[where.x][where.y] & 32) + draw_trim(q,r,2,7); + if (town_trim[where.x][where.y] & 64) + draw_trim(q,r,0,2); + if (town_trim[where.x][where.y] & 128) + draw_trim(q,r,2,4); + } + if ((is_out()) && (out_trim[where.x][where.y] != 0)) { + if (out_trim[where.x][where.y] & 1) draw_trim(q,r,1,0); + if (out_trim[where.x][where.y] & 2) draw_trim(q,r,2,5); + if (out_trim[where.x][where.y] & 4) draw_trim(q,r,0,3); + if (out_trim[where.x][where.y] & 8) draw_trim(q,r,2,6); + if (out_trim[where.x][where.y] & 16) draw_trim(q,r,1,1); + if (out_trim[where.x][where.y] & 32) draw_trim(q,r,2,7); + if (out_trim[where.x][where.y] & 64) draw_trim(q,r,0,2); + if (out_trim[where.x][where.y] & 128) draw_trim(q,r,2,4); + } + + + if (((ter_type >= 100) && (ter_type <= 137)) && (at_top == FALSE) && + (at_bot == FALSE) && (at_left == FALSE) && (at_right == FALSE)) { + store = get_t_t(where.x - 1,where.y); + store1 = get_t_t(where.x,where.y - 1); + store2 = get_t_t(where.x + 1,where.y); + store3 = get_t_t(where.x,where.y + 1); + if ((is_wall(store) == TRUE) + && (is_wall(store1) == TRUE) && + (is_ground(store2) == TRUE) + && (is_ground(store3) == TRUE)) + draw_trim(q,r,3,6); + + if ((is_wall(store) == TRUE) + && (is_wall(store3) == TRUE) && + (is_ground(store2) == TRUE) + && (is_ground(store1) == TRUE)) + draw_trim(q,r,3,5); + + if ((is_wall(store2) == TRUE) + && (is_wall(store1) == TRUE) && + (is_ground(store) == TRUE) + && (is_ground(store3) == TRUE)) + draw_trim(q,r,3,7); + + if ((is_wall(store2) == TRUE) + && (is_wall(store3) == TRUE) && + (is_ground(store) == TRUE) + && (is_ground(store1) == TRUE)) + draw_trim(q,r,3,4); + + + if ((is_ground(store) == TRUE) + && (is_ground(store1) == TRUE) && + (is_ground(store2) == TRUE) + && (is_wall(store3) == TRUE)) { + draw_trim(q,r,3,4); + draw_trim(q,r,3,5); + } + + if ((is_wall(store) == TRUE) + && (is_ground(store3) == TRUE) && + (is_ground(store2) == TRUE) + && (is_ground(store1) == TRUE)) { + draw_trim(q,r,3,5); + draw_trim(q,r,3,6); + } + + if ((is_ground(store2) == TRUE) + && (is_wall(store1) == TRUE) && + (is_ground(store) == TRUE) + && (is_ground(store3) == TRUE)) { + draw_trim(q,r,3,6); + draw_trim(q,r,3,7); + } + + if ((is_wall(store2) == TRUE) + && (is_ground(store3) == TRUE) && + (is_ground(store) == TRUE) + && (is_ground(store1) == TRUE)) { + draw_trim(q,r,3,4); + draw_trim(q,r,3,7); + } + } +} + +void draw_trim(short q,short r,short which_trim,short which_mode) +//which_trim is 3 -> drawing wall trim -> might shift down if ground is grass +//short which_mode; // 0 top 1 bottom 2 left 3 right 4 up left 5 up right 6 down right 7 down left +{ + HBITMAP from_file; + RECT from_rect = {0,0,28,36},to_rect; + + from_file = load_pict(4000,main_dc); + + if (frills_on == FALSE) + return; + if (current_ground == 2 && PSD[309][3] == 0) + return; + + terrain_there[q][r] = -1; + + from_rect.left = 28 * which_trim + trim_rects[which_mode].left; + from_rect.right = 28 * which_trim + trim_rects[which_mode].right; + from_rect.top = trim_rects[which_mode].top; + from_rect.bottom = trim_rects[which_mode].bottom; + + if (current_ground == 2) // trim with grass instead of cave floor + OffsetRect(&from_rect,0,36); + to_rect = coord_to_rect(q,r); + to_rect.right = to_rect.left + trim_rects[which_mode].right; + to_rect.left = to_rect.left + trim_rects[which_mode].left; + to_rect.bottom = to_rect.top + trim_rects[which_mode].bottom; + to_rect.top = to_rect.top + trim_rects[which_mode].top; + + rect_draw_some_item(from_file,from_rect,terrain_screen_gworld,to_rect,1,0); + + DeleteObject(from_file); +} + + +Boolean extend_road_terrain(unsigned char ter) +{ + short i; + short extend_pics[39] = {61,62,63,64,65, 66,401,402,406,202, + 203,204,215,216,90, 91,92,93,102,103, + 104,105,112,113,114, 115,187,188,189,190, + 192,193,194,195,196, 197,191,200,201}; + + for (i = 0; i < 39; i++) + if (scenario.ter_types[ter].picture == extend_pics[i]) + return TRUE; + return FALSE; +} + +void place_road(short q,short r,location where) +{ + location draw_loc; + unsigned char ter; + RECT to_rect; + RECT road_rects[2] = {{112,76,125,80},{144,72,148,90}}; // 0 - rl partial 1 - ud partial + RECT road_dest_rects[4] = {{12,0,16,18},{15,16,28,20},{12,18,16,36},{0,16,13,20}}; // top right bottom left + /**/ + + draw_loc.x = q; draw_loc.y = r; + + terrain_there[q][r] = -1; + + if (where.y > 0) + ter = coord_to_ter(where.x,where.y - 1); + if ((where.y == 0) || (extend_road_terrain(ter) == TRUE)) { + to_rect = road_dest_rects[0]; + OffsetRect(&to_rect,13 + q * 28,13 + r * 36); + rect_draw_some_item (fields_gworld, road_rects[1], terrain_screen_gworld, to_rect, 0, 0); + } + + if (((is_out()) && (where.x < 96)) || (!(is_out()) && (where.x < town_size[town_type] - 1))) + ter = coord_to_ter(where.x + 1,where.y); + if (((is_out()) && (where.x == 96)) || (!(is_out()) && (where.x == town_size[town_type] - 1)) + || (extend_road_terrain(ter) == TRUE)) { + to_rect = road_dest_rects[1]; + OffsetRect(&to_rect,13 + q * 28,13 + r * 36); + rect_draw_some_item (fields_gworld, road_rects[0], terrain_screen_gworld, to_rect, 0, 0); + } + + if (((is_out()) && (where.y < 96)) || (!(is_out()) && (where.y < town_size[town_type] - 1))) + ter = coord_to_ter(where.x,where.y + 1); + if (((is_out()) && (where.y == 96)) || (!(is_out()) && (where.y == town_size[town_type] - 1)) + || (extend_road_terrain(ter) == TRUE)) { + to_rect = road_dest_rects[2]; + OffsetRect(&to_rect,13 + q * 28,13 + r * 36); + rect_draw_some_item (fields_gworld, road_rects[1], terrain_screen_gworld, to_rect, 0, 0); + } + + if (where.x > 0) + ter = coord_to_ter(where.x - 1,where.y); + if ((where.x == 0) || (extend_road_terrain(ter) == TRUE)) { + to_rect = road_dest_rects[3]; + OffsetRect(&to_rect,13 + q * 28,13 + r * 36); + rect_draw_some_item (fields_gworld, road_rects[0], terrain_screen_gworld, to_rect, 0, 0); + } + +} + +void draw_rest_screen() +{ + short store_mode; + + store_mode = overall_mode; + overall_mode = 50; + draw_terrain(0); + overall_mode = store_mode ; +} + +void pre_boom_space(location where,short mode,short type,short damage,short sound) +// if mode is 100, force +//short type; // 0 - flame 1 - magic 2 - poison 3 - blood 4 - cold + // 10s digit indicates sound 0 - normal ouch 1 - small sword 2 - loud sword + // 3 - pole 4 - club 5 - fireball hit 6 - squish 7 - cold + // 8 - acid 9 - claw 10 - bite 11 - slime 12 - zap 13 - missile hit +{ + short sound_key; + short sound_to_play[20] = {97,69,70,71,72, 73,55,75,42,86, + 87,88,89,98,0, 0,0,0,0,0}; + + sound_key = type / 10; + type = type % 10; + + if ((cartoon_happening == FALSE) && ((mode != 100) && (party_can_see(where) == 6))) + return; + if ((type < 0) || (type > 4)) return; + if ((boom_anim_active == TRUE) && (type != 3)) return; + if ((cartoon_happening == FALSE) && (PSD[306][2] > 0) && (fast_bang == TRUE)) return; + if (is_out()) return; + + // Redraw terrain in proper position + if ((((point_onscreen(center,where) == FALSE) && (overall_mode >= MODE_COMBAT)) || (overall_mode == MODE_OUTDOORS)) + ) { + play_sound(sound_to_play[sound]); + + return; + } + else if (is_combat()) { + if (which_combat_type == 1) + draw_terrain(0); + else draw_terrain(0); + } + else if (fast_bang < 2) { + draw_terrain(0); + if (fast_bang == 1) + fast_bang = 2; + } + + boom_space(where,mode,type,damage,sound); + } + + void boom_space(location where, short, short type,short damage,short sound) +// if mode is 100, force +//short type; // 0 - flame 1 - magic 2 - poison 3 - blood 4 - cold + // 10s digit indicates sound 0 - normal ouch 1 - small sword 2 - loud sword + // 3 - pole 4 - club 5 - fireball hit 6 - squish 7 - cold + // 8 - acid 9 - claw 10 - bite 11 - slime 12 - zap 13 - missile hit +{ + location where_draw = location(4,4); + RECT source_rect = {0,0,28,36},text_rect,dest_rect = {13,13,41,49},big_to = {13,13,265,337},store_rect; + /**/ + RECT terrain_from; + long dummy; + short del_len,sound_key; + char dam_str[20]; + short x_adj = 0,y_adj = 0,which_m; +// RECT mixed_square = {353,169,381,205}; +// RECT mixed_square = {353,193,381,230}; + short sound_to_play[20] = {97,69,70,71,72, 73,55,75,42,86, + 87,88,89,98,0, 0,0,0,0,0}; + + sound_key = type / 10; + type = type % 10; + + where_draw.x = where.x - center.x + 4; + where_draw.y = where.y - center.y + 4; + + // adjust for possible big monster + which_m = monst_there(where); + if (which_m < 90) { + x_adj += 14 * (c_town.monst.dudes[which_m].m_d.x_width - 1); + y_adj += 18 * (c_town.monst.dudes[which_m].m_d.y_width - 1); + } + OffsetRect(&dest_rect,where_draw.x * 28,where_draw.y * 36); + terrain_from = dest_rect; + source_rect = store_rect = dest_rect; + OffsetRect(&dest_rect,x_adj,y_adj); + //SectRect(&dest_rect,&big_to,&dest_rect); + IntersectRect(&dest_rect,&dest_rect,&big_to); + + if (cartoon_happening == FALSE) + OffsetRect(&dest_rect,win_to_rects[0].left,win_to_rects[0].top); + else if (store_anim_type == 0) + OffsetRect(&dest_rect,306,5); + else OffsetRect(&dest_rect,store_anim_ul.x,store_anim_ul.y); + + OffsetRect(&source_rect,-1 * store_rect.left + 28 * type,-1 * store_rect.top); + + OffsetRect(&terrain_from,x_adj,y_adj); +// rect_draw_some_item(terrain_screen_gworld,terrain_from,mixed_gworld,mixed_square,0,0); +// rect_draw_some_item(fields_gworld,source_rect,mixed_gworld,mixed_square,1,0); + rect_draw_some_item(fields_gworld,source_rect,mixed_gworld,dest_rect,1,1); + + if ((cartoon_happening == FALSE) && (dest_rect.right - dest_rect.left >= 28) + && (dest_rect.bottom - dest_rect.top >= 36)) { + sprintf((char *) dam_str,"%d",damage); + text_rect = dest_rect; + text_rect.top += 10; + if ((damage < 10) && (dest_rect.right - dest_rect.left > 19)) + text_rect.left += 2; + OffsetRect(&text_rect,-4,-5); + + if ((type == 1) || (type == 4)) + WinBlackDrawString(dam_str,text_rect.left + 12,text_rect.top + 6); + else WinDrawString(dam_str,text_rect.left + 12,text_rect.top + 6); + } + + if(party.stuff_done[305][7] > 0) //{del_len = PSD[306][6] * 3 + 4;Delay(del_len,&dummy);} + play_sound(-sound_to_play[sound]); + else{ + play_sound(sound_to_play[sound]); + + if ((sound == 6) && (fast_bang == 0)) + Delay(12, &dummy); + + Delay(10,&dummy); + if (fast_bang == 0) { + del_len = PSD[306][6] * 3 + 4; + if (play_sounds == FALSE) + Delay(del_len, &dummy); + } + } + + redraw_terrain(); + if ((cartoon_happening == FALSE) && (overall_mode > 9) && (overall_mode != 35) && (overall_mode != 36) && (overall_mode != 50)) + draw_pcs(center,1); +} + + +void draw_pointing_arrows() +{ + RECT sources[4] = {{65,46,73,54},{56,46,64,54},{56,37,64,45},{65,37,73,45}}; + RECT dests[8] = {{7,100,15,108},{7,170,15,178},{140,7,148,15},{212,7,220,15}, + {346,100,354,108},{346,170,354,178},{140,274,148,282},{212,274,220,282}}; + // rects modified below + short i; + + for (i = 0; i < 4; i++) alter_rect(&sources[i]); + for (i = 0; i < 8; i++) alter_rect(&dests[i]); + + if ((monsters_going == TRUE) || (overall_mode <= MODE_TOWN) || (overall_mode <= MODE_COMBAT) + || (overall_mode == 35)) + return; + for (i = 0; i < 4; i++) { + rect_draw_some_item (mixed_gworld,sources[i],mixed_gworld,dests[i * 2],1,1); + rect_draw_some_item (mixed_gworld,sources[i],mixed_gworld,dests[i * 2 + 1],1,1); + } +} + +void redraw_terrain() +{ + RECT to_rect; + RECT ter_scrn_rect = {0,0,279,351}; + + if (cartoon_happening == FALSE) + to_rect = win_to_rects[0]; + else { + to_rect = ter_scrn_rect; + if (store_anim_type == 0) + OffsetRect(&to_rect,306,5); + else OffsetRect(&to_rect,store_anim_ul.x,store_anim_ul.y); + } + rect_draw_some_item (terrain_screen_gworld, win_from_rects[0], terrain_screen_gworld, to_rect, 0, 1); + + // Now place arrows + draw_pointing_arrows(); +} + +void draw_targets(location center) +{ + RECT source_rect = {36,74,47,85},dest_rect; /**/ + short i = 0; + + if (party_toast() == TRUE) + return; + + for (i = 0; i < 8; i++) + if ((spell_targets[i].x != 120) && (point_onscreen(center,spell_targets[i]) == TRUE)) { + dest_rect = coord_to_rect(spell_targets[i].x - center.x + 4,spell_targets[i].y - center.y + 4); + OffsetRect(&dest_rect,5,5); + InflateRect(&dest_rect,-8,-12); + rect_draw_some_item (mixed_gworld,source_rect,mixed_gworld,dest_rect,1,1); + } +} + +void draw_targeting_line(POINT where_curs) +{ + location which_space,store_loc; + short i,j,k,l; + long dummy; + RECT redraw_rect,redraw_rect2,terrain_rect = {0,0,279,351},target_rect; + location from_loc; + RECT on_screen_terrain_area = {18, 18, 269,341}; + char dam_str[20]; + HPEN white_pen,store_pen; + static LOGPEN white_pen_data = {PS_SOLID,2,2,RGB(255,255,255)}; + COLORREF colors[2] = {RGB(0,0,0),RGB(255,255,255)},storec; + + if (party.stuff_done[305][6] > 0) + return; + + if (overall_mode >= MODE_COMBAT) + from_loc = pc_pos[current_pc]; + else from_loc = c_town.p_loc; + if ((overall_mode == 11) || (overall_mode == 12) || (overall_mode == 13) || (overall_mode == 14) + || ((overall_mode == 3) && (current_pat.pattern[4][4] != 0))) { + + OffsetRect(&on_screen_terrain_area,ulx,uly); + OffsetRect(&terrain_rect,18,18); + if (PtInRect (&on_screen_terrain_area,where_curs) == TRUE) { + i = (where_curs.x - 18 - ulx) / 28; + j = (where_curs.y - 18 - uly) / 36; + which_space.x = center.x + (short) i - 4; + which_space.y = center.y + (short) j - 4; + + k = (short) (from_loc.x - center.x + 4); + l = (short) (from_loc.y - center.y + 4); + k = (k * 28) + 32 ;//+ ulx; + l = (l * 36) + 36 ; + + if ((loc_off_act_area(which_space) == FALSE) && + (can_see(from_loc,which_space,0) < 5) + && (dist(from_loc,which_space) <= current_spell_range)) { + SetViewportOrgEx(main_dc,ulx,uly,NULL); + white_pen = CreatePenIndirect(&white_pen_data); + store_pen = (HPEN) SelectObject(main_dc,white_pen); + + OffsetRect(&on_screen_terrain_area,-1 * ulx,-1 * uly); + ClipRect(&on_screen_terrain_area); + MoveToEx(main_dc,where_curs.x - ulx,where_curs.y - uly, NULL); + LineTo(main_dc,k,l); + + redraw_rect.left = min(where_curs.x,k) - 4; + redraw_rect.right = max(where_curs.x,k) + 4; + redraw_rect.top = min(where_curs.y,l) - 4; + redraw_rect.bottom = max(where_curs.y,l) + 4; + + IntersectRect(&redraw_rect2,&redraw_rect,&on_screen_terrain_area); + + // Now place targeting pattern + for (i = 0; i < 9; i++) + for (j = 0; j < 9; j++) { + store_loc.x = center.x + i - 4; + store_loc.y = center.y + j - 4; + if ((ex_abs(store_loc.x - which_space.x) <= 4) && + (ex_abs(store_loc.y - which_space.y) <= 4) && + (current_pat.pattern[store_loc.x - which_space.x + 4][store_loc.y - which_space.y + 4] != 0)) { + target_rect.left = 13 + BITMAP_WIDTH * i + 5;// + ulx; + target_rect.right = target_rect.left + BITMAP_WIDTH; + target_rect.top = 13 + BITMAP_HEIGHT * j + 5;// + uly; + target_rect.bottom = target_rect.top + BITMAP_HEIGHT; + + MoveToEx(main_dc,target_rect.left,target_rect.top, NULL); + LineTo(main_dc,target_rect.right,target_rect.top); + LineTo(main_dc,target_rect.right,target_rect.bottom); + LineTo(main_dc,target_rect.left,target_rect.bottom); + LineTo(main_dc,target_rect.left,target_rect.top); + + InflateRect(&target_rect,5,5); + UnionRect(&redraw_rect2,&target_rect,&redraw_rect2); + + // Now place number of shots left, if drawing center of target + if ((overall_mode == 14) && (store_loc.x - which_space.x + 4 == 4) + && (store_loc.y - which_space.y + 4 == 4)) { + storec = GetTextColor(main_dc); + SetTextColor(main_dc,colors[1]); + sprintf((char *) dam_str,"%d ",num_targets_left); + DrawText(main_dc,dam_str,-1,&target_rect,DT_SINGLELINE | DT_VCENTER | DT_CENTER); + SetTextColor(main_dc,storec); + } + + } + } + SelectObject(main_dc,store_pen); + DeleteObject(white_pen); + + Delay(4,&dummy); + + InflateRect(&redraw_rect2,5,5); + redraw_partial_terrain(redraw_rect2); + undo_clip(); + if (is_combat()) + draw_pcs(center,1); + else draw_party_symbol(center); + if (overall_mode == 14) + draw_targets(center); + } + } + } +} + + +Boolean party_toast() +{ + for (int i = 0; i < 6; i++) + if (adven[i].isAlive()) return FALSE; + return TRUE; +} + +void redraw_partial_terrain(RECT redraw_rect) +{ + RECT from_rect = redraw_rect; + + OffsetRect(&redraw_rect,5, 5); + + rect_draw_some_item(terrain_screen_gworld,from_rect,terrain_screen_gworld,redraw_rect,0,1); +} + +// This tells the dialog engine to kill the dialog, and refreshes the screen +// will probably need to be modified for windows +void final_process_dialog(short which_dlog) +{ + cd_kill_dialog(which_dlog,0); + + if (in_startup_mode == FALSE) + refresh_screen(0); + else draw_startup(0); +} diff --git a/Win32/Blades of Exile/GRAPHICS.H b/Win32/Blades of Exile/GRAPHICS.H new file mode 100644 index 00000000..a169052a --- /dev/null +++ b/Win32/Blades of Exile/GRAPHICS.H @@ -0,0 +1,66 @@ +#ifndef _GRAPHICS_H + #define _GRAPHICS_H + +void draw_startup_anim(); +void draw_startup_stats(); +void adjust_window_mode(); +void plop_fancy_startup(); +void fancy_startup_delay(); +void init_startup(); +void init_animation(); +void next_animation_step() ; +void draw_startup(short but_type); +void reload_startup(); +void draw_anim(); +void place_anim(); +void draw_start_button(short which_position,short which_button); +void main_button_click(short mode,RECT button_rect); +void arrow_button_click(RECT button_rect); +void end_startup(); +void Set_up_win (); +void load_main_screen(); +void create_clip_region(); +void set_gworld_fonts(short font_num); +void redraw_screen(short mode); +void put_background(); +void refresh_screen(short mode); +void draw_buttons(short mode); +void draw_text_area(short mode); +void reset_text_bar(); +void draw_text_bar(short mode); +void put_text_bar(char *str); +void load_area_graphics(); +void add_to_wish_list(short which_g); +Boolean reserve_graphic_num_in_array(short which_g); +void place_graphic_num_in_array(short which_g); + +void add_one_graphic(short which_g); +void add_terrain_to_wish_list(unsigned char ter); +void load_outdoor_graphics(); +void add_monst_graphic(unsigned char m,short mode); +void load_town_graphics(); +void update_pc_graphics(); +void put_graphics_in_template(); +void draw_terrain(short mode); +void place_trim(short q,short r,location where,unsigned char ter_type); +void draw_trim(short q,short r,short which_trim,short which_mode); +Boolean extend_road_terrain(unsigned char ter); +void place_road(short q,short r,location where); +void draw_rest_screen(); +void boom_space(location where,short mode,short type,short damage,short sound); +void draw_pointing_arrows() ; +void redraw_terrain(); +void draw_targets(location center); +void erase_spot(short i,short j); +void draw_targeting_line(POINT where_curs); +Boolean party_toast(); +void redraw_partial_terrain(RECT redraw_rect); +void dump_gworld(); +void final_process_dialog(short which_dlog); +Boolean is_nature(char i, char j); +void put_dialog_graphic(short graphic_num,short spec_g,RECT draw_rect); +void lose_graphics(); +void put_anim_str(); +void pre_boom_space(location where,short mode,short type,short damage,short sound); + +#endif diff --git a/Win32/Blades of Exile/GRAPHUTL.CPP b/Win32/Blades of Exile/GRAPHUTL.CPP new file mode 100644 index 00000000..87785e94 --- /dev/null +++ b/Win32/Blades of Exile/GRAPHUTL.CPP @@ -0,0 +1,358 @@ +#define xmin(a,b) ((a) < (b) ? (a) : (b)) + +#include +#include +#include +#include +#include +#include "global.h" +#include "text.h" +#include "string.h" +#include "exlsound.h" + +#include "graphutl.h" +#include "globvar.h" + +void rect_draw_some_item(HBITMAP src, RECT16 src_rect,HBITMAP dest, RECT16 dest_rect, + short trans, short main_win) +{ + HDC hdcMem,hdcMem2,hdcMem3,destDC; + HBITMAP transbmp; + COLORREF white = RGB(255,255,255),oldcolor; + HBRUSH hbrush,old_brush; + COLORREF x = RGB(17,17,17); + HBITMAP store,store2; + Boolean dlog_draw = FALSE; + + if (main_win == 2) + { + destDC = (HDC) dest; + main_win = 1; + dlog_draw = TRUE; + hdcMem = CreateCompatibleDC(destDC); + SelectObject(hdcMem, src); + SetMapMode(hdcMem,GetMapMode((HDC) mainPtr)); + } + else + { + destDC = main_dc; + hdcMem = main_dc2; + store = (HBITMAP) SelectObject(hdcMem,src); + } + + if (trans != 1) + { + if (main_win == 0) + { // Not transparent, into bitmap + hdcMem2 = main_dc3; + store2 = (HBITMAP) SelectObject(hdcMem2, dest); + StretchBlt(hdcMem2,dest_rect.left,dest_rect.top,dest_rect.right - dest_rect.left, + dest_rect.bottom - dest_rect.top, + hdcMem,src_rect.left,src_rect.top,src_rect.right - src_rect.left, + src_rect.bottom - src_rect.top,(trans >= 0) ? SRCCOPY : SRCAND); + SelectObject(hdcMem2,store2); + } + else + { // Not transparent, onto screen + + if (trans == 2) + { + hbrush = CreateSolidBrush(x); + old_brush = (HBRUSH) SelectObject(destDC,hbrush); + } + + if (dlog_draw == FALSE) SetViewportOrgEx(destDC,ulx,uly,NULL); + + StretchBlt(destDC,dest_rect.left,dest_rect.top,dest_rect.right - dest_rect.left, + dest_rect.bottom - dest_rect.top, + hdcMem,src_rect.left,src_rect.top,src_rect.right - src_rect.left, + src_rect.bottom - src_rect.top,(trans == 0) ? SRCCOPY : MERGECOPY); + if (trans == 2) + { + SelectObject(destDC,old_brush); + if (DeleteObject(hbrush) == 0) play_sound(1); + } + + if (dlog_draw == FALSE) SetViewportOrgEx(destDC,0,0,NULL); + } + + } // end of non-transparent draws + else + { + if (main_win == 0) + { + hdcMem3 = CreateCompatibleDC(hdcMem); + SelectObject(hdcMem3, dest); + SetMapMode(hdcMem3,GetMapMode((HDC) mainPtr)); + if ((src_rect.right - src_rect.left < 72) && + (src_rect.bottom - src_rect.top < 72)) + transbmp = bw_bitmap; + else transbmp = CreateBitmap(src_rect.right - src_rect.left, + src_rect.bottom - src_rect.top,1,1,NULL); + + hdcMem2 = CreateCompatibleDC(destDC); + SelectObject(hdcMem2, transbmp); + oldcolor = SetBkColor(hdcMem, white); + StretchBlt(hdcMem2,0,0,dest_rect.right - dest_rect.left, + dest_rect.bottom - dest_rect.top, + hdcMem,src_rect.left,src_rect.top,src_rect.right - src_rect.left, + src_rect.bottom - src_rect.top,SRCCOPY); + SetBkColor(hdcMem, oldcolor); + + StretchBlt(hdcMem3,dest_rect.left,dest_rect.top,dest_rect.right - dest_rect.left, + dest_rect.bottom - dest_rect.top, + hdcMem,src_rect.left,src_rect.top,src_rect.right - src_rect.left, + src_rect.bottom - src_rect.top,SRCINVERT); + StretchBlt(hdcMem3,dest_rect.left,dest_rect.top,dest_rect.right - dest_rect.left, + dest_rect.bottom - dest_rect.top, + hdcMem2,0,0,dest_rect.right - dest_rect.left, + dest_rect.bottom - dest_rect.top,SRCAND); + StretchBlt(hdcMem3,dest_rect.left,dest_rect.top,dest_rect.right - dest_rect.left, + dest_rect.bottom - dest_rect.top, + hdcMem,src_rect.left,src_rect.top,src_rect.right - src_rect.left, + src_rect.bottom - src_rect.top,SRCINVERT); + DeleteDC(hdcMem3); + DeleteDC(hdcMem2); + if (transbmp != bw_bitmap) DeleteObject(transbmp); + } + else + { + if (dlog_draw == FALSE) SetViewportOrgEx(destDC,ulx,uly,NULL); + if ((src_rect.right - src_rect.left < 72) && + (src_rect.bottom - src_rect.top < 72)) + transbmp = bw_bitmap; + else transbmp = CreateBitmap(src_rect.right - src_rect.left, + src_rect.bottom - src_rect.top,1,1,NULL); + + hdcMem2 = CreateCompatibleDC(destDC); + + SelectObject(hdcMem2, transbmp); + + oldcolor = SetBkColor(hdcMem, white); + + StretchBlt(hdcMem2,0,0,dest_rect.right - dest_rect.left, + dest_rect.bottom - dest_rect.top, + hdcMem,src_rect.left,src_rect.top,src_rect.right - src_rect.left, + src_rect.bottom - src_rect.top,SRCCOPY); + + SetBkColor(hdcMem, oldcolor); + + StretchBlt(destDC,dest_rect.left,dest_rect.top,dest_rect.right - dest_rect.left, + dest_rect.bottom - dest_rect.top, + hdcMem,src_rect.left,src_rect.top,src_rect.right - src_rect.left, + src_rect.bottom - src_rect.top,SRCINVERT); + + StretchBlt(destDC,dest_rect.left,dest_rect.top,dest_rect.right - dest_rect.left, + dest_rect.bottom - dest_rect.top, + hdcMem2,0,0,dest_rect.right - dest_rect.left, + dest_rect.bottom - dest_rect.top,SRCAND); + + StretchBlt(destDC,dest_rect.left,dest_rect.top,dest_rect.right - dest_rect.left, + dest_rect.bottom - dest_rect.top, + hdcMem,src_rect.left,src_rect.top,src_rect.right - src_rect.left, + src_rect.bottom - src_rect.top,SRCINVERT); + + if (dlog_draw == FALSE) SetViewportOrgEx(destDC,0,0,NULL); + + DeleteDC(hdcMem2); + + if (transbmp != bw_bitmap) DeleteObject(transbmp); + } + } + if (dlog_draw == TRUE) DeleteDC(hdcMem); + else SelectObject(hdcMem,store); +} + +void fry_dc(HWND hwnd,HDC dc) +{ + if (ReleaseDC(hwnd,dc) == 0) + DebugQuit("Cannot release DC in fry_dc"); +} + +// which_mode is 0 ... dest is a bitmap +// is 1 ... ignore dest ... paint on mainPtr +// is 2 ... dest is a dialog, use the dialog pattern +// both pattern gworlds are 192 x 256 +void paint_pattern(HBITMAP dest,short which_mode,RECT dest_rect,short which_pattern) +{ + HBITMAP source_pat; + RECT pattern_source = {32,168,96,232}, pat_dest_orig = {0,0,64,64},pat_dest; + short i,j; + + RECT draw_from_orig = {0,0,192,256},draw_from,draw_to; + short store_ulx,store_uly; + + if (which_mode == 2) { + source_pat = dialog_pattern_gworld; + if (dlog_pat_placed == 0) { + dlog_pat_placed = 1; + OffsetRect(&pattern_source, 64 * 2,0); + for (i = 0; i < 3; i++) + for (j = 0; j < 4; j++) { + pat_dest = pat_dest_orig; + OffsetRect(&pat_dest,64 * i, 64 * j); + rect_draw_some_item(mixed_gworld,pattern_source, + dialog_pattern_gworld,pat_dest,0,0); + } + } + } + else { + source_pat = pattern_gworld; + if (current_pattern != which_pattern) { + current_pattern = which_pattern; + OffsetRect(&pattern_source, 64 * (which_pattern % 5), + 64 * (which_pattern / 5)); + for (i = 0; i < 3; i++) + for (j = 0; j < 4; j++) { + pat_dest = pat_dest_orig; + OffsetRect(&pat_dest,64 * i, 64 * j); + rect_draw_some_item(mixed_gworld,pattern_source, + pattern_gworld,pat_dest,0,0); + } + } + } + + // now patterns are loaded, so have fun + // first nullify ul shifting + store_ulx = ulx; + store_uly = uly; + ulx = uly = 0; + for (i = 0; i < (dest_rect.right / 192) + 1; i++) + for (j = 0; j < (dest_rect.bottom / 256) + 1; j++) { + draw_to = draw_from_orig; + OffsetRect(&draw_to,192 * i, 256 * j); + IntersectRect(&draw_to,&draw_to,&dest_rect); + if (draw_to.right != 0) { + draw_from = draw_to; + OffsetRect(&draw_from, -192 * i, -256 * j); + switch (which_mode) { + case 0: + rect_draw_some_item(source_pat,draw_from, + dest,draw_to,0,0); break; + case 1: + rect_draw_some_item(source_pat,draw_from, + source_pat,draw_to,0,1); break; + case 2: + rect_draw_some_item(source_pat,draw_from, + dest,draw_to,0,2); break; + } + } + } + ulx = store_ulx; + uly = store_uly; +} + +HBITMAP load_pict(short pict_num,HDC) +{ + HBITMAP got_bitmap; + + switch(pict_num) { + case 700: + case 701: + case 702: got_bitmap = ReadBMP("images/STATAREA.BMP"); break; + case 703: got_bitmap = ReadBMP("images/TEXTBAR.BMP"); break; + case 704: got_bitmap = ReadBMP("images/BUTTONS.BMP"); break; + case 705: got_bitmap = ReadBMP("images/TERSCRN.BMP"); break; + case 800: if(party.stuff_done[307][0] == 0) + got_bitmap = ReadBMP("images/TER1.BMP"); + else + got_bitmap = ReadBMP("images/TER1_D.BMP"); + break; + case 801: if(party.stuff_done[307][0] == 0) + got_bitmap = ReadBMP("images/TER2.BMP"); + else + got_bitmap = ReadBMP("images/TER2_D.BMP"); + break; + case 802: if(party.stuff_done[307][0] == 0) + got_bitmap = ReadBMP("images/TER3.BMP"); + else + got_bitmap = ReadBMP("images/TER3_D.BMP"); + break; + case 803: if(party.stuff_done[307][0] == 0) + got_bitmap = ReadBMP("images/TER4.BMP"); + else + got_bitmap = ReadBMP("images/TER4_D.BMP"); + break; + case 804: if(party.stuff_done[307][0] == 0) + got_bitmap = ReadBMP("images/TER5.BMP"); + else + got_bitmap = ReadBMP("images/TER5_D.BMP"); + break; + case 805: if(party.stuff_done[307][0] == 0) + got_bitmap = ReadBMP("images/TER6.BMP"); + else + got_bitmap = ReadBMP("images/TER6_D.BMP"); + break; + case 820: if(party.stuff_done[307][0] == 0) + got_bitmap = ReadBMP("images/TERANIM.BMP"); + else + got_bitmap = ReadBMP("images/TERANIM_D.BMP"); + break; + case 821: if(party.stuff_done[307][0] == 0) + got_bitmap = ReadBMP("images/FIELDS.BMP"); + else + got_bitmap = ReadBMP("images/FIELDS_D.BMP"); + break; + case 830: got_bitmap = ReadBMP("images/STARTUP.BMP"); break; + case 831: got_bitmap = ReadBMP("images/STANIM.BMP"); break; + case 832: got_bitmap = ReadBMP("images/STARTBUT.BMP"); break; + case 850: got_bitmap = ReadBMP("images/DLOGPICS.BMP"); break; + case 851: got_bitmap = ReadBMP("images/SCENPICS.BMP"); break; + case 860: got_bitmap = ReadBMP("images/TALKPORT.BMP"); break; + case 875: got_bitmap = ReadBMP("images/DLOGMAPS.BMP"); break; + case 880: got_bitmap = ReadBMP("images/MISSILES.BMP"); break; + case 900: got_bitmap = ReadBMP("images/TINYOBJ.BMP"); break; + case 901: got_bitmap = ReadBMP("images/OBJECTS.BMP"); break; + case 902: got_bitmap = ReadBMP("images/PCS.BMP"); break; + case 905: got_bitmap = ReadBMP("images/PCS.BMP"); break; + case 903: + case 904: if(party.stuff_done[307][0] == 0) + got_bitmap = ReadBMP("images/MIXED.BMP"); + else + got_bitmap = ReadBMP("images/MIXED_D.BMP"); + break; + case 910: + case 911: + case 912: got_bitmap = ReadBMP("images/BIGSCEN.BMP"); break; + case 1100: case 1200: got_bitmap = ReadBMP("images/MONST1.BMP"); break; + case 1101: case 1201: got_bitmap = ReadBMP("images/MONST2.BMP"); break; + case 1102: case 1202: got_bitmap = ReadBMP("images/MONST3.BMP"); break; + case 1103: case 1203: got_bitmap = ReadBMP("images/MONST4.BMP"); break; + case 1104: case 1204: got_bitmap = ReadBMP("images/MONST5.BMP"); break; + case 1105: case 1205: got_bitmap = ReadBMP("images/MONST6.BMP"); break; + case 1106: case 1206: got_bitmap = ReadBMP("images/MONST7.BMP"); break; + case 1107: case 1207: got_bitmap = ReadBMP("images/MONST8.BMP"); break; + case 1108: case 1208: got_bitmap = ReadBMP("images/MONST9.BMP"); break; + case 1109: case 1209: got_bitmap = ReadBMP("images/MONST10.BMP"); break; + case 1400: got_bitmap = ReadBMP("images/STSCICON.BMP"); break; + case 1401: got_bitmap = ReadBMP("images/HELPPICS.BMP"); break; + case 1402: got_bitmap = ReadBMP("images/APPIC.BMP"); break; + case 1500: + case 1501: + case 1502: + case 1503: + case 1504: + case 1505: + case 1506: + case 1507: + got_bitmap = ReadBMP("images/BIGMAPS.BMP"); break; + case 2000: got_bitmap = ReadBMP("images/DLOGBTNS.BMP"); break; + case 3000: got_bitmap = ReadBMP("images/START.BMP"); break; + case 3001: got_bitmap = ReadBMP("images/SPIDLOGO.BMP"); break; + case 4000: if(party.stuff_done[307][0] == 0) + got_bitmap = ReadBMP("images/TRIMS.BMP"); + else + got_bitmap = ReadBMP("images/TRIMS_D.BMP"); + break; + + default: got_bitmap = NULL; + } + return got_bitmap; +} + +/* GK */ + +HBITMAP ReadBMP(char * fileName) +{ + return (HBITMAP) LoadImage(0, fileName, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE); +} diff --git a/Win32/Blades of Exile/GRAPHUTL.H b/Win32/Blades of Exile/GRAPHUTL.H new file mode 100644 index 00000000..a8f1e8ef --- /dev/null +++ b/Win32/Blades of Exile/GRAPHUTL.H @@ -0,0 +1,15 @@ +#ifndef _GRAPHUTIL_H + #define _GRAPHUTIL_H + +void rect_draw_some_item(HBITMAP src, RECT16 src_rect, HBITMAP dest, RECT16 dest_rect, + short trans, short main_win); +void fry_dc(HWND hwnd,HDC dc); + +void DisposeGWorld(HBITMAP bitmap); +HBITMAP load_pict(short pict_num,HDC); +void paint_pattern(HBITMAP dest,short which_mode,RECT dest_rect,short which_pattern); + +/* GK */ +extern HBITMAP ReadBMP(char * fileName); + +#endif diff --git a/Win32/Blades of Exile/GUTILS.CPP b/Win32/Blades of Exile/GUTILS.CPP new file mode 100644 index 00000000..93c2eaf9 --- /dev/null +++ b/Win32/Blades of Exile/GUTILS.CPP @@ -0,0 +1,828 @@ + +#include + +#include "global.h" +#include "gutils.h" +#include "text.h" +#include "fields.h" +#include "locutils.h" +#include "graphics.h" +#include "infodlgs.h" +#include "monster.h" +#include "dlogtool.h" +#include "exlsound.h" +#include "graphutl.h" +#include "stdio.h" + +#include "globvar.h" + +void draw_one_terrain_spot (short i,short j,short terrain_to_draw,short dest) +//short dest; // 0 - terrain gworld 1 - screen +// if terrain_to_draw is -1, do black +// if terrain_to_draw >= 1000, force to draw graphic which is terrain_to_draw - 1000 +{ + RECT where_draw; + RECT source_rect; + + HBITMAP source_gworld; + short anim_type = 0; + location l; + HDC hdc; + HBITMAP store_bmp; + + source_gworld = storage_gworld; + + l.x = i; l.y = j; + if ((supressing_some_spaces == TRUE) && + (same_point(l,ok_space[0]) == FALSE) && + (same_point(l,ok_space[1]) == FALSE) && + (same_point(l,ok_space[2]) == FALSE) && + (same_point(l,ok_space[3]) == FALSE)) + return; + + where_draw = calc_rect(i,j); + OffsetRect(&where_draw,13,13); + if (terrain_to_draw == -1) { + if ((cartoon_happening == FALSE) && (terrain_there[i][j] == 300)) { + return; + } + terrain_there[i][j] = 300; + hdc = CreateCompatibleDC(main_dc); + store_bmp = (HBITMAP) SelectObject(hdc,terrain_screen_gworld); + SelectObject(hdc,GetStockObject(BLACK_BRUSH)); + Rectangle(hdc,where_draw.left,where_draw.top,where_draw.right,where_draw.bottom); + SelectObject(hdc,store_bmp); + if (!DeleteDC(hdc)) DebugQuit("Cannot release DC 24"); + return; + } + if (terrain_to_draw >= 10000) { // force using a specific graphic + if (terrain_there[i][j] == terrain_to_draw - 10000) + return; + terrain_there[i][j] = terrain_to_draw - 10000; + source_rect = return_item_rect(terrain_to_draw - 10000); + anim_type = -1; + } + else if (terrain_pic[terrain_to_draw] >= 2000) { // custom + source_gworld = spec_scen_g; + source_rect = get_custom_rect(terrain_pic[terrain_to_draw] - 2000 + (anim_ticks % 4)); + anim_type = 0; + terrain_there[i][j] = -1; + } + else if (terrain_pic[terrain_to_draw] >= 1000) { // custom + source_gworld = spec_scen_g; + source_rect = get_custom_rect(terrain_pic[terrain_to_draw] - 1000); + terrain_there[i][j] = -1; + } + else if (terrain_pic[terrain_to_draw] >= 400) { // animated + source_rect = return_item_rect(terrain_pic[terrain_to_draw] + 600 + 100 * (anim_ticks % 4)); + terrain_there[i][j] = -1; + anim_type = 0; + } + else { + if (cartoon_happening == FALSE) { + if (terrain_there[i][j] == terrain_pic[terrain_to_draw]) { + return; + } + terrain_there[i][j] = terrain_pic[terrain_to_draw]; + } + source_rect = return_item_rect(terrain_pic[terrain_to_draw]); + anim_type = -1; + } + + if (anim_type >= 0) + { + if ((is_town()) || (is_out())) + anim_onscreen = TRUE; + } + + if (dest == 0) + rect_draw_some_item(source_gworld, source_rect, terrain_screen_gworld, where_draw, (unsigned char) 0, 0); + else rect_draw_some_item(source_gworld, source_rect, terrain_screen_gworld, where_draw, (unsigned char) 0, 1); +} + +void draw_monsters() +{ + short i,j = 0,k; + short width,height; + RECT source_rect,to_rect; + location where_draw,store_loc; + + short picture_wanted; + unsigned char ter; + RECT monst_rects[4][4] = {{{0,0,28,36},{0,0,0,0},{0,0,0,0},{0,0,0,0}}, + {{7,0,21,18},{7,18,21,36},{0,0,0,0},{0,0,0,0}}, + {{0,9,14,27},{14,9,28,27},{0,0,0,0},{0,0,0,0}}, + {{0,0,14,18},{14,0,28,18},{0,18,14,36},{14,18,28,36}}}; + + if (is_out()) + for (i = 0; i < 10; i++) + if (party.out_c[i].exists == TRUE) { + if ((point_onscreen(party.p_loc, party.out_c[i].m_loc) == TRUE) && + (can_see(party.p_loc, party.out_c[i].m_loc,0) < 5)) { + where_draw.x = party.out_c[i].m_loc.x - party.p_loc.x + 4; + where_draw.y = party.out_c[i].m_loc.y - party.p_loc.y + 4; + terrain_there[where_draw.x][where_draw.y] = -1; + + j = 0; + while ((party.out_c[i].what_monst.monst[j] == 0) && (j < 7)) + j++; + + if (j == 7) party.out_c[i].exists = FALSE; // begin watch out + else picture_wanted = get_monst_picnum(party.out_c[i].what_monst.monst[j]); + // end watch out + + if (party.out_c[i].exists == TRUE) { + get_monst_dims(party.out_c[i].what_monst.monst[j],&width,&height); + if (picture_wanted >= 1000) { + for (k = 0; k < width * height; k++) { + source_rect = get_custom_rect(picture_wanted % 1000 + + ((party.out_c[i].direction < 4) ? 0 : (width * height)) + k); + to_rect = monst_rects[(width - 1) * 2 + height - 1][k]; + rect_draw_some_item(spec_scen_g, source_rect, small_temp_gworld,to_rect, 0, 0); + source_rect = to_rect; + OffsetRect(&to_rect,13 + 28 * where_draw.x,13 + 36 * where_draw.y); + rect_draw_some_item(small_temp_gworld, source_rect, terrain_screen_gworld,to_rect, 1, 0); + } + } + if (picture_wanted < 1000) { + for (k = 0; k < width * height; k++) { + source_rect = get_monster_template_rect(party.out_c[i].what_monst.monst[j], + (party.out_c[i].direction < 4) ? 0 : 1,k); + to_rect = monst_rects[(width - 1) * 2 + height - 1][k]; + rect_draw_some_item(storage_gworld, source_rect, small_temp_gworld,to_rect, 0, 0); + source_rect = to_rect; + OffsetRect(&to_rect,13 + 28 * where_draw.x,13 + 36 * where_draw.y); + rect_draw_some_item(small_temp_gworld, source_rect, terrain_screen_gworld,to_rect, 1, 0); + } + } + } + } + } + if (is_town()) + for (i = 0; i < T_M; i++) + if ((c_town.monst.dudes[i].active != 0) && (c_town.monst.dudes[i].m_d.spec_skill != 11)) + if (party_can_see_monst(i)) { + where_draw.x = c_town.monst.dudes[i].m_loc.x - center.x + 4; + where_draw.y = c_town.monst.dudes[i].m_loc.y - center.y + 4; + get_monst_dims(c_town.monst.dudes[i].number,&width,&height); + + for (k = 0; k < width * height; k++) { + store_loc = where_draw; + store_loc.x += k % width; + store_loc.y += k / width; + // customize? + if (c_town.monst.dudes[i].m_d.picture_num >= 1000) { + source_rect = get_custom_rect((c_town.monst.dudes[i].m_d.picture_num % 1000) + + k + ((c_town.monst.dudes[i].m_d.direction < 4) ? 0 : width * height) + + ((combat_posing_monster == i + 100) ? (2 * width * height) : 0)); + Draw_Some_Item(spec_scen_g, source_rect, terrain_screen_gworld, store_loc, 1, 0); + } + if (c_town.monst.dudes[i].m_d.picture_num < 1000) { + source_rect = get_monster_template_rect(c_town.monst.dudes[i].number, + ((c_town.monst.dudes[i].m_d.direction < 4) ? 0 : 1) + ((combat_posing_monster == i + 100) ? 10 : 0),k); + ter = t_d.terrain[c_town.monst.dudes[i].m_loc.x][c_town.monst.dudes[i].m_loc.y]; + // in bed? + if ((store_loc.x >= 0) && (store_loc.x < 9) && (store_loc.y >= 0) && (store_loc.y < 9) && + (scenario.ter_types[ter].picture == 143) && + ((c_town.monst.dudes[i].m_d.m_type < 7) + && (c_town.monst.dudes[i].m_d.m_type != 1) && (c_town.monst.dudes[i].m_d.m_type != 2)) + && ((c_town.monst.dudes[i].active == 1) || (monst_target[i] == 6)) && + (width == 1) && (height == 1)) //// + draw_one_terrain_spot((short) where_draw.x,(short) where_draw.y,10230,0); + else Draw_Some_Item(storage_gworld, source_rect, terrain_screen_gworld, store_loc, 1, 0); + } + } + } + if (is_combat()) { + for (i = 0; i < T_M; i++) + if ((c_town.monst.dudes[i].active != 0) && (c_town.monst.dudes[i].m_d.spec_skill != 11)) + if (((point_onscreen(center,c_town.monst.dudes[i].m_loc) == TRUE) && (cartoon_happening == TRUE)) + || (party_can_see_monst(i) == TRUE)) { + where_draw.x = c_town.monst.dudes[i].m_loc.x - center.x + 4; + where_draw.y = c_town.monst.dudes[i].m_loc.y - center.y + 4; + get_monst_dims(c_town.monst.dudes[i].number,&width,&height); + + for (k = 0; k < width * height; k++) { + store_loc = where_draw; + store_loc.x += k % width; + store_loc.y += k / width; + // customize? + if (c_town.monst.dudes[i].m_d.picture_num >= 1000) { + source_rect = get_custom_rect((c_town.monst.dudes[i].m_d.picture_num % 1000) + + k + ((c_town.monst.dudes[i].m_d.direction < 4) ? 0 : width * height) + + ((combat_posing_monster == i + 100) ? (2 * width * height) : 0)); + Draw_Some_Item(spec_scen_g, source_rect, terrain_screen_gworld, store_loc, 1, 0); + } + if (c_town.monst.dudes[i].m_d.picture_num < 1000) { + source_rect = get_monster_template_rect(c_town.monst.dudes[i].number, + ((c_town.monst.dudes[i].m_d.direction < 4) ? 0 : 1) + ((combat_posing_monster == i + 100) ? 10 : 0) + ,k); + ter = t_d.terrain[c_town.monst.dudes[i].m_loc.x][c_town.monst.dudes[i].m_loc.y]; + if ((store_loc.x >= 0) && (store_loc.x < 9) && (store_loc.y >= 0) && (store_loc.y < 9) && + (scenario.ter_types[ter].picture == 143) && + ((c_town.monst.dudes[i].m_d.m_type < 7) + && (c_town.monst.dudes[i].m_d.m_type != 1) && (c_town.monst.dudes[i].m_d.m_type != 2)) + && ((c_town.monst.dudes[i].active == 1) || (monst_target[i] == 6)) && + (width == 1) && (height == 1)) + draw_one_terrain_spot((short) where_draw.x,(short) where_draw.y,10230,0); //// + else Draw_Some_Item(storage_gworld, source_rect, terrain_screen_gworld, store_loc, 1, 0); + } + } + } + } +} + + +void draw_pcs(location center,short mode) +//short mode; // 0 - put pcs in gworld 1 - only rectangle around active pc +{ + short i; + RECT source_rect; + location where_draw; + + if (party_toast() == TRUE) return; // is party dead + if (can_draw_pcs == FALSE) return; + + if ((mode == 1) && (cartoon_happening == TRUE)) return; + + for (i = 0; i < NUM_OF_PCS; i++) + if (adven[i].isAlive()) + if (((point_onscreen(center, pc_pos[i])) == TRUE) && + ((cartoon_happening == TRUE) || (party_can_see(pc_pos[i]) < 6))){ + where_draw.x = pc_pos[i].x - center.x + 4; + where_draw.y = pc_pos[i].y - center.y + 4; + source_rect = get_party_template_rect(i,(pc_dir[i] < 4) ? 0 : 1); + if (combat_posing_monster == i) + OffsetRect(&source_rect,0,108); + + if (mode == 0) + Draw_Some_Item(party_template_gworld, source_rect, terrain_screen_gworld, where_draw, 1, 0); + + if ((current_pc == i) && (mode == 1) && (monsters_going == FALSE)) + frame_space(pc_pos[current_pc],1,1,1); + } + + if (current_pc == INVALID_PC) return; + + // Draw current pc on top + if ((current_pc < 6) && ((point_onscreen(center, pc_pos[current_pc])) == TRUE) && (adven[current_pc].isAlive())) { + where_draw.x = pc_pos[current_pc].x - center.x + 4; + where_draw.y = pc_pos[current_pc].y - center.y + 4; + source_rect = get_party_template_rect(current_pc,(pc_dir[current_pc] < 4) ? 0 : 1); + if (combat_posing_monster == current_pc) + OffsetRect(&source_rect,0,108); + + if (mode == 0) + Draw_Some_Item(party_template_gworld, source_rect, terrain_screen_gworld, where_draw, 1, 0); + } +} + +void draw_items() +{ + short i; + RECT source_rect,dest_rect; + location where_draw; + + for (i = 0; i < NUM_TOWN_ITEMS; i++) { + if (t_i.items[i].variety != 0) { + where_draw.x = t_i.items[i].item_loc.x - center.x + 4; + where_draw.y = t_i.items[i].item_loc.y - center.y + 4; + + if ((supressing_some_spaces == TRUE) && + (same_point(where_draw,ok_space[0]) == FALSE) && + (same_point(where_draw,ok_space[1]) == FALSE) && + (same_point(where_draw,ok_space[2]) == FALSE) && + (same_point(where_draw,ok_space[3]) == FALSE)) + ; + else if ((point_onscreen(center, t_i.items[i].item_loc) == TRUE) && + (t_i.items[i].isContained() == false) && + ((cartoon_happening == TRUE) || (party_can_see(t_i.items[i].item_loc) < 6))) { + if (t_i.items[i].graphic_num >= 150) { + source_rect = get_custom_rect(t_i.items[i].graphic_num - 150); + dest_rect = coord_to_rect(where_draw.x,where_draw.y); + terrain_there[where_draw.x][where_draw.y] = -1; + + rect_draw_some_item(spec_scen_g, + source_rect, terrain_screen_gworld, dest_rect, 1, 0); + } + else { + source_rect = get_item_template_rect(t_i.items[i].graphic_num); + dest_rect = coord_to_rect(where_draw.x,where_draw.y); + terrain_there[where_draw.x][where_draw.y] = -1; + if (t_i.items[i].graphic_num >= 45) { + dest_rect.top += 9; + dest_rect.bottom -= 9; + dest_rect.left += 5; + dest_rect.right -= 5; + } + rect_draw_some_item((t_i.items[i].graphic_num < 45) ? items_gworld : tiny_obj_gworld, + source_rect, terrain_screen_gworld, dest_rect, 1, 0); + } + } + } + } +} + +void draw_outd_boats(location center) +{ + location where_draw; + RECT source_rect; + short i; + + for (i = 0; i < 30; i++) + if ((point_onscreen(center, party.boats[i].boat_loc) == TRUE) && (party.boats[i].exists == TRUE) && + (party.boats[i].which_town == INVALID_TOWN) && + (can_see(center, party.boats[i].boat_loc,0) < 5) && (party.in_boat != i)) { + where_draw.x = party.boats[i].boat_loc.x - center.x + 4; + where_draw.y = party.boats[i].boat_loc.y - center.y + 4; + source_rect = boat_rects[0]; + OffsetRect(&source_rect,61,0); + Draw_Some_Item(mixed_gworld, source_rect, terrain_screen_gworld, where_draw, 1, 0); + } + for (i = 0; i < 30; i++) + if ((point_onscreen(center, party.horses[i].horse_loc) == TRUE) && (party.horses[i].exists == TRUE) && + (party.horses[i].which_town == INVALID_TOWN) && + (can_see(center, party.horses[i].horse_loc,0) < 5) && (party.in_horse != i)) { + where_draw.x = party.horses[i].horse_loc.x - center.x + 4; + where_draw.y = party.horses[i].horse_loc.y - center.y + 4; + source_rect = boat_rects[0]; + OffsetRect(&source_rect,61,0); + OffsetRect(&source_rect,0,74); + OffsetRect(&source_rect,56,36); + Draw_Some_Item(mixed_gworld, source_rect, terrain_screen_gworld, where_draw, 1, 0); + } +} + +void draw_town_boat(location center) +{ + location where_draw; + RECT source_rect; + short i; + + for (i = 0; i < 30; i++) + if ((party.boats[i].which_town == c_town.town_num) && + ((point_onscreen(center, party.boats[i].boat_loc) == TRUE) && + (can_see(center, party.boats[i].boat_loc,0) < 5) && (party.in_boat != i) + && (pt_in_light(center,party.boats[i].boat_loc) == TRUE))) { + where_draw.x = party.boats[i].boat_loc.x - center.x + 4; + where_draw.y = party.boats[i].boat_loc.y - center.y + 4; + source_rect = boat_rects[0]; + OffsetRect(&source_rect,61,0); + Draw_Some_Item(mixed_gworld, source_rect, terrain_screen_gworld, where_draw, 1, 0); + } + for (i = 0; i < 30; i++) + if ((party.horses[i].which_town == c_town.town_num) && + ((point_onscreen(center, party.horses[i].horse_loc) == TRUE) && + (can_see(center, party.horses[i].horse_loc,0) < 5) && (party.in_horse != i) + && (pt_in_light(center,party.horses[i].horse_loc) == TRUE))) { + where_draw.x = party.horses[i].horse_loc.x - center.x + 4; + where_draw.y = party.horses[i].horse_loc.y - center.y + 4; + + source_rect = boat_rects[0]; + OffsetRect(&source_rect,61,0); + OffsetRect(&source_rect,0,74); + OffsetRect(&source_rect,56,36); + Draw_Some_Item(mixed_gworld, source_rect, terrain_screen_gworld, where_draw, 1, 0); + } +} + +void draw_sfx() +{ + short q,r,i,flag; + location where_draw,loc; + RECT orig_rect = {0,0,28,36},source_rect; + + if (PSD[306][2] > 0) + return; + + for (q = 0; q < 9; q++) + for (r = 0; r < 9; r++) + { + where_draw = center;where_draw.x += q - 4;where_draw.y += r - 4; + + if ((where_draw.x < 0) || (where_draw.x > town_size[town_type] - 1) + || (where_draw.y < 0) || (where_draw.y > town_size[town_type] - 1)) + ; + else if (sfx[where_draw.x][where_draw.y] != 0) { + for (i = 0; i < 8; i++) { + flag = s_pow(2,i); + if (sfx[where_draw.x][where_draw.y] & flag) + if (spot_seen[q][r] > 0) { + loc.x = q; loc.y = r; + source_rect = orig_rect; + OffsetRect(&source_rect,28 * i,36 * 3); + Draw_Some_Item(fields_gworld,source_rect,terrain_screen_gworld,loc, + 1,0); + } + } + } + } +} + + +void draw_one_field(unsigned char flag,short source_x,short source_y) +{ + short q,r; + location where_draw,loc; + RECT orig_rect = {0,0,28,36},source_rect; + + for (q = 0; q < 9; q++) + for (r = 0; r < 9; r++) + { + where_draw = center;where_draw.x += q - 4;where_draw.y += r - 4; + + if ((where_draw.x < 0) || (where_draw.x > town_size[town_type] - 1) + || (where_draw.y < 0) || (where_draw.y > town_size[town_type] - 1)) + ; + else { + if (misc_i[where_draw.x][where_draw.y] & flag) + if (spot_seen[q][r] > 0) { + loc.x = q; loc.y = r; + source_rect = orig_rect; + OffsetRect(&source_rect,28 * source_x,36 * source_y); + Draw_Some_Item(fields_gworld,source_rect,terrain_screen_gworld,loc, + 1,0); + if ((is_town()) && ((flag == 32) || (flag == 64))) + anim_onscreen = TRUE; + } + } + } +} + +void draw_one_spec_item(unsigned char flag,short source_x,short source_y) +{ + short q,r; + location where_draw,loc; + RECT orig_rect = {0,0,28,36},source_rect; + + for (q = 0; q < 9; q++) + for (r = 0; r < 9; r++) + { + where_draw = center;where_draw.x += q - 4;where_draw.y += r - 4; + + if ((where_draw.x < 0) || (where_draw.x > town_size[town_type] - 1) + || (where_draw.y < 0) || (where_draw.y > town_size[town_type] - 1)) + ; + else { + if (c_town.explored[where_draw.x][where_draw.y] & flag) + if (spot_seen[q][r] > 0) { + loc.x = q; loc.y = r; + source_rect = orig_rect; + OffsetRect(&source_rect,28 * source_x,36 * source_y); + Draw_Some_Item(fields_gworld,source_rect,terrain_screen_gworld,loc, + 1,0); + } + } + } +} + + + +void draw_party_symbol(location center) +{ + RECT source_rect; + location target = location(4,4); + short i = 0; + short dir_array[8] = {0,3,3,3,2,1,1,1}; + + if (can_draw_pcs == FALSE) return; + if (party_toast() == TRUE) return; + if ((is_town()) && (c_town.p_loc.x > 70)) return; + if (overall_mode == 36) + { + target.x += c_town.p_loc.x - center.x; + target.y += c_town.p_loc.y - center.y; + } + + if ((party.in_boat < 0) && (party.in_horse < 0)) { + i = first_active_pc(); + source_rect = get_party_template_rect(i,(party.direction < 4) ? 0 : 1); + + // now wedge in bed graphic + if ((is_town()) && (scenario.ter_types[t_d.terrain[c_town.p_loc.x][c_town.p_loc.y]].picture == 143)) + draw_one_terrain_spot((short) target.x,(short) target.y,10230,0); + else Draw_Some_Item(party_template_gworld, source_rect, terrain_screen_gworld, target, 1, 0); + } + else if (party.in_boat >= 0) { + source_rect = boat_rects[dir_array[party.direction]]; + OffsetRect(&source_rect,61,0); + Draw_Some_Item(mixed_gworld, source_rect, terrain_screen_gworld, target, 1, 0); + } + else { + source_rect = boat_rects[(party.direction < 4) ? 0 : 1]; + OffsetRect(&source_rect,61,0); + OffsetRect(&source_rect,0,74); + Draw_Some_Item(mixed_gworld, source_rect, terrain_screen_gworld, target, 1, 0); + } +} + +RECT return_item_rect(short wanted) +{ + RECT orig_rect = {0,0,28,36}; + short i; + if (wanted < 50) { + OffsetRect(&orig_rect,28 * (wanted % 10),36 * (wanted / 10)); + return orig_rect; + } + for (i = 50; i < STORED_GRAPHICS; i++) + if (which_g_stored[i] == wanted) { + OffsetRect(&orig_rect,28 * (i % 10),36 * (i / 10)); + return orig_rect; + } + // oops it's not here. better try to add it. + add_one_graphic(wanted); + for (i = 50; i < STORED_GRAPHICS; i++) + if (which_g_stored[i] == wanted) { + OffsetRect(&orig_rect,28 * (i % 10),36 * (i / 10)); + return orig_rect; + } + // oh well. + if (gave_no_g_error == FALSE) { + 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); + gave_no_g_error = TRUE; + } + return orig_rect; +} + +// Give the position of the monster graphic in the template in memory +RECT get_monster_template_rect (unsigned char type_wanted,short mode,short which_part) +//mode; // 0 - left 1 - right +10 - combat mode +{ + RECT store_rect = {0,0,28,36}; + + short picture_wanted; + short adj = 0; + + if (mode >= 10) {adj = 2000; mode -= 10;} + picture_wanted = get_monst_picnum(type_wanted); + if (picture_wanted >= 1000) + return store_rect; + picture_wanted = m_pic_index[picture_wanted] + which_part; + return return_item_rect(300 + picture_wanted + (300 * mode) + adj); +} + + +// Returns rect for drawing an item, if num < 25, rect is in big item template, +// otherwise in small item template +RECT get_item_template_rect (short type_wanted) +{ + RECT store_rect; + + if (type_wanted < 45) { + store_rect.top = (type_wanted / 5) * BITMAP_HEIGHT; + store_rect.bottom = store_rect.top + BITMAP_HEIGHT; + store_rect.left = (type_wanted % 5) * BITMAP_WIDTH; + store_rect.right = store_rect.left + BITMAP_WIDTH; + } + else { + store_rect.top = (type_wanted / 10) * 18; + store_rect.bottom = store_rect.top + 18; + store_rect.left = (type_wanted % 10) * 18; + store_rect.right = store_rect.left + 18; + } + + return store_rect; +} + + +unsigned char get_t_t(int x, int y) // returns terrain type at where +{ + if (is_out()) + return out[x][y]; + else if (is_town()) + return t_d.terrain[x][y]; + else return combat_terrain[x][y]; +} + +// Is this is subterranean fluid that gets shore plopped down on it? +Boolean is_fluid(unsigned char ter_type)//// +{ + if (((ter_type >= 71) && (ter_type <= 76)) || (ter_type == 90)) + return TRUE; + return FALSE; +} + +// Is this is subterranean beach that gets shore plopped down next to it? +Boolean is_shore(unsigned char ter_type)//// +{ + if (is_fluid(ter_type) == TRUE) return FALSE; + if (ter_type == 77) return FALSE; + if (ter_type == 90) return FALSE; + return TRUE; +} + +// These two functions used to determine wall round-cornering +Boolean is_wall(unsigned char ter_type)//// +{ + short pic = scenario.ter_types[ter_type].picture; + + if ((pic >= 88) && (pic <= 120)) + return TRUE; + + return FALSE; +} +Boolean is_ground(unsigned char ter_type) +{ + short pic = scenario.ter_types[ter_type].picture; + + if ((pic >= 0) && (pic <= 87)) return TRUE; + if ((pic >= 121) && (pic <= 122)) return TRUE; + if ((pic >= 179) && (pic <= 208)) return TRUE; + if ((pic >= 211) && (pic <= 212)) return TRUE; + if ((pic >= 215) && (pic <= 246)) return TRUE; + + return FALSE; +} + +void make_town_trim(short mode) +//mode; // 0 - town 1 - outdoor combat +{ + short store_mode; + + store_mode = overall_mode; + overall_mode = (mode == MODE_OUTDOORS) ? 1 : 10; + for (int x = 0; x < town_size[town_type]; x++) + for (int y = 0; y < town_size[town_type]; y++) + town_trim[x][y] = add_trim_to_array(x, y, + (mode == 0) ? t_d.terrain[x][y] : combat_terrain[x][y]); + + for (int x = 0; x < town_size[town_type]; x++) + for (int y = 0; y < town_size[town_type]; y++) + { + if (town_trim[x][y] & 1) town_trim[x][y] &= 125; + if (town_trim[x][y] & 4) town_trim[x][y] &= 245; + if (town_trim[x][y] & 10) town_trim[x][y] &= 215; + if (town_trim[x][y] & 64) town_trim[x][y] &= 95; + } + overall_mode = store_mode; +} + +void make_out_trim() +{ + short store_mode; + + store_mode = overall_mode; + overall_mode = MODE_OUTDOORS; + + for (int x = 0; x < 96; x++) + for (int y = 0; y < 96; y++) + out_trim[x][y] = add_trim_to_array(x, y, out[x][y]); + + for (int x = 0; x < 96; x++) + for (int y = 0; y < 96; y++) + { + if (out_trim[x][y] & 1) out_trim[x][y] &= 125; + if (out_trim[x][y] & 4) out_trim[x][y] &= 245; + if (out_trim[x][y] & 10) out_trim[x][y] &= 215; + if (out_trim[x][y] & 64) out_trim[x][y] &= 95; + } + overall_mode = store_mode; + +} + +/* fixup */ +char add_trim_to_array(location where,unsigned char ter_type) +{ + return add_trim_to_array(where.x, where.y, ter_type); +} + +char add_trim_to_array(int x, int y, unsigned char ter_type) +{ + Boolean at_top = FALSE,at_bot = FALSE,at_left = FALSE,at_right = FALSE; + unsigned char store; + char to_return = 0; + + if (x == 0) at_left = TRUE; + if (y == 0) at_top = TRUE; + if ((overall_mode == MODE_OUTDOORS) || (overall_mode == 35)) + { + if (x == 95) at_right = TRUE; + if (y == 95) at_bot = TRUE; + } + else + { + if (x == town_size[town_type] - 1) at_right = TRUE; + if (y == town_size[town_type] - 1) at_bot = TRUE; + } + + // Set up trim for fluids + if (is_fluid(ter_type) == TRUE) { + if (at_left == FALSE) { + store = get_t_t(x - 1,y); + if (is_shore(store) == TRUE) to_return |= 64; + } + if (at_right == FALSE) { + store = get_t_t(x + 1,y); + if (is_shore(store) == TRUE) to_return |= 4; + } + if (at_top == FALSE) { + store = get_t_t(x,y - 1); + if (is_shore(store) == TRUE) to_return |= 1; + } + if (at_bot == FALSE) { + store = get_t_t(x,y + 1); + if (is_shore(store) == TRUE) to_return |= 16; + } + if ((at_left == FALSE) && (at_top == FALSE)) { + store = get_t_t(x - 1,y - 1); + if (is_shore(store) == TRUE) to_return |= 128; + } + if ((at_right == FALSE) && (at_top == FALSE)) { + store = get_t_t(x + 1,y + 1); + if (is_shore(store) == TRUE) to_return |= 8; + } + if ((at_right == FALSE) && (at_bot == FALSE)) { + store = get_t_t(x + 1,y - 1); + if (is_shore(store) == TRUE) to_return |= 2; + } + if ((at_left == FALSE) && (at_bot == FALSE)) { + store = get_t_t(x - 1,y + 1); + if (is_shore(store) == TRUE) to_return |= 32; + } + } + + return to_return; +} + +/* this is NOT the same as PtInRect() function */ +Boolean pt_in_rect(location loc, RECT16 rect) +{ + if ((loc.x >= rect.left) && (loc.x <= rect.right) && (loc.y >= rect.top) && (loc.y <= rect.bottom)) + return TRUE; + return FALSE; +} + +// Time for some chicanery +// The how to item for monsters will be 599 +// item 600 + i will mean monster i. +void adjust_monst_menu() +{ + short i,monst_pos = 0; + char monst_name[256]; + HMENU menu,big_menu; + short total_added = 0; + + if (in_startup_mode == TRUE) + return; + + big_menu = GetMenu(mainPtr); + menu = GetSubMenu(big_menu,5); + if (menu == NULL) + return; + for (i = 0; i < 256; i++) + on_monst_menu[i] = -1; + + for (i = 1; i < 256; i++) + if ((i == 1) || (party.m_seen[i] > 0)) { + on_monst_menu[monst_pos] = i; + monst_pos++; + } + + for (i = 0; i < 256; i++) + DeleteMenu(menu,600 + i,MF_BYCOMMAND); + + for (i = 0; i < 256; i++) + if (on_monst_menu[i] >= 0) { + //GetIndString(monst_name, 2,on_monst_menu[i]); + sprintf((char *) monst_name,"%s",data_store2->scen_item_list.monst_names[on_monst_menu[i]]); if ((total_added % 24 == 0) && (total_added > 0)) + InsertMenu(menu,599,MF_MENUBREAK | MF_BYCOMMAND | MF_ENABLED | MF_STRING, 600 + i, monst_name); + else InsertMenu(menu,599,MF_BYCOMMAND | MF_ENABLED | MF_STRING, 600 + i, monst_name); + total_added++; + } +} + +void frame_space(location where,short mode,short width,short height) +//mode; // 0 - red 1 - green +{ + location where_put; + RECT to_frame; + HDC hdc; + HPEN hpen,old_pen; + COLORREF x[3] = {RGB(200,0,0),RGB(102,255,0),RGB(200,0,200)};//RGB(204,204,204); + + if (point_onscreen(center,where) == FALSE) + return; + + where_put.x = 4 + where.x - center.x; + where_put.y = 4 + where.y - center.y; + + to_frame.top = 18 + where_put.y * 36; + to_frame.left = 18 + where_put.x * 28; + to_frame.bottom = 54 + where_put.y * 36 + 36 * (height - 1); + to_frame.right = 46 + where_put.x * 28 + 28 * (width - 1); + + hdc = GetDC(mainPtr); + SetViewportOrgEx(hdc,ulx,uly,NULL); + hpen = CreatePen(PS_SOLID,1,x[mode]); + old_pen = (HPEN) SelectObject(hdc,hpen); + MoveToEx(hdc,to_frame.left,to_frame.top, NULL); + + LineTo(hdc,to_frame.right,to_frame.top); + LineTo(hdc,to_frame.right,to_frame.bottom); + LineTo(hdc,to_frame.left,to_frame.bottom); + LineTo(hdc,to_frame.left,to_frame.top); + + SelectObject(hdc,old_pen); + ReleaseDC(mainPtr,hdc); + DeleteObject(hpen); +} diff --git a/Win32/Blades of Exile/GUTILS.H b/Win32/Blades of Exile/GUTILS.H new file mode 100644 index 00000000..77bd692e --- /dev/null +++ b/Win32/Blades of Exile/GUTILS.H @@ -0,0 +1,34 @@ +#ifndef _GUTILS_H + #define _GUTILS_H + +void draw_one_terrain_spot (short i,short j,short terrain_to_draw,short dest); +void draw_monsters(); +void play_see_monster_str(unsigned char m); +void draw_pcs(location center,short mode); +void draw_items(); +void draw_outd_boats(location center); +void draw_town_boat(location center) ; +void draw_fields(); +void draw_spec_items(); +void draw_sfx(); +void draw_one_field(unsigned char flag,short source_x,short short_y); +void draw_one_spec_item(unsigned char flag,short source_x,short short_y); +void draw_party_symbol(location center); +RECT return_item_rect(short wanted); +RECT get_monster_template_rect (unsigned char type_wanted,short mode,short which_part) ; +RECT get_item_template_rect (short type_wanted); +unsigned char get_t_t(int x, int y); // returns terrain type at where +Boolean is_fluid(unsigned char ter_type); +Boolean is_shore(unsigned char ter_type); +Boolean is_wall(unsigned char ter_type); +Boolean is_ground(unsigned char ter_type); +void make_town_trim(short mode); +void make_out_trim(); +Boolean pt_in_rect(location loc, RECT16 rect); +void adjust_monst_menu(); +void frame_space(location where,short mode,short width,short height); + +char add_trim_to_array(int x, int y, unsigned char ter_type); +char add_trim_to_array(location where,unsigned char ter_type); + +#endif diff --git a/Win32/Blades of Exile/INFODLGS.CPP b/Win32/Blades of Exile/INFODLGS.CPP new file mode 100644 index 00000000..938b9638 --- /dev/null +++ b/Win32/Blades of Exile/INFODLGS.CPP @@ -0,0 +1,1259 @@ +#include +#include "stdio.h" + +#include "global.h" + +#include "graphics.h" +#include "newgraph.h" +#include "items.h" +#include "string.h" +#include "monster.h" +#include "dlogtool.h" +#include "party.h" +#include "fields.h" +#include "locutils.h" +#include "text.h" +#include "exlsound.h" +#include "infodlgs.h" +#include "fileio.h" + +#include "globvar.h" + +void put_spell_info() +{ + char store_text[256]; + short pos,res,ran; + + pos = (store_display_mode == 0) ? mage_spell_pos : priest_spell_pos; + res = (store_display_mode == 0) ? 7 : 8; + ran = (store_display_mode == 0) ? mage_range[pos] : priest_range[pos]; + + GetIndString(store_text, res, pos * 2 + 1); + cd_set_item_text(1096,4,(char *) store_text); + + if (spell_cost[store_display_mode][pos] > 0) + sprintf((char *) store_text, "%d/%d",spell_level[pos],spell_cost[store_display_mode][pos]); + else sprintf((char *) store_text, "%d/?",spell_level[pos]); + cd_set_item_text(1096,5,(char *) store_text); + + if (ran == 0) { + cd_set_item_text(1096,6,""); + } + else cd_set_item_num(1096,6,ran); + GetIndString(store_text, res, pos * 2 + 2); + + cd_set_item_text(1096,7,(char *) store_text); + GetIndString(store_text, 11, 1 + spell_w_cast[store_display_mode][pos]); + cd_set_item_text(1096,11,(char *) store_text); +} + +Boolean display_spells_event_filter (short item_hit) +{ + short store; + switch (item_hit) { + case 1: case 8: + dialog_not_toast = FALSE; + break; + + case 9: case 10: + store = (store_display_mode == 0) ? mage_spell_pos : priest_spell_pos; + if (item_hit == 9) { + store = (store == 0) ? 61 : store - 1; + } + else { + store = (store + 1) % 62; + } + if (store_display_mode == 0) + mage_spell_pos = store; + else priest_spell_pos = store; + put_spell_info(); + break; + } + + return FALSE; +} +void display_spells(short mode,short force_spell,short parent_num) +//short mode; // 0 - mage 1 - priest +//short force_spell; // if 100, ignore +{ + store_display_mode = mode; + if (force_spell < 100) { + if (mode == 0) + mage_spell_pos = force_spell; + else priest_spell_pos = force_spell; + } + + SetCursor(sword_curs); + + cd_create_dialog_parent_num(1096,parent_num); + + cd_set_pict(1096,18,714 + mode); + put_spell_info(); + if (mode == 0) + csit(1096,3,"Mage Spells"); + else csit(1096,3,"Priest Spells"); + while (dialog_not_toast) + ModalDialog(); + + cd_kill_dialog(1096,0); + +} + +void put_skill_info() +{ + char store_text[256]; + short pos; + + pos = skill_pos; + + GetIndString(store_text,9,pos * 2 + 1); + cd_set_item_text(1097,3,(char *) store_text); + cd_set_item_num(1097,4,skill_cost[pos]); + cd_set_item_num(1097,5,skill_g_cost[pos]); + cd_set_item_num(1097,6,skill_max[pos]); + + GetIndString(store_text, 9, pos * 2 + 2); + cd_set_item_text(1097,7,(char *) store_text); + GetIndString(store_text, 12, 1 + pos); + cd_set_item_text(1097,8,(char *) store_text); +} + + +Boolean display_skills_event_filter (short item_hit) +{ + switch (item_hit) { + case 1: case 11: + dialog_not_toast = FALSE; + break; + + case 10: case 9: + if (item_hit == 9) { + skill_pos = (skill_pos == 0) ? 18 : skill_pos - 1; + } + else { + skill_pos = (skill_pos + 1) % 19; + } + put_skill_info(); + break; + } + return FALSE; +} + +void display_skills(short force_skill,short parent) +{ + if (force_skill < 100) skill_pos = force_skill; + if (skill_pos < 0) skill_pos = 0; + + SetCursor(sword_curs); + + cd_create_dialog_parent_num(1097,parent); + + put_skill_info(); + while (dialog_not_toast) + ModalDialog(); + + cd_kill_dialog(1097,0); + +} + +void put_pc_graphics() +{ + short i; + + for (i = 3; i < 65; i++) { + if (((store_trait_mode == 0) && (adven[which_pc_displayed].mage_spells[i - 3] == TRUE)) || + ((store_trait_mode == 1) && (adven[which_pc_displayed].priest_spells[i - 3] == TRUE))) + cd_set_led(991,i,2); + else cd_set_led(991,i,0); + } + + cd_set_item_text(991,69,adven[which_pc_displayed].name); +} +Boolean display_pc_event_filter (short item_hit) +{ + short pc_num; + + pc_num = which_pc_displayed; + switch (item_hit) { + case 1: case 65: + dialog_not_toast = FALSE; + break; + + case 66: + do { + pc_num = (pc_num == 0) ? 5 : pc_num - 1; + } while (adven[pc_num].main_status == MAIN_STATUS_ABSENT); + which_pc_displayed = pc_num; + put_pc_graphics(); + break; + case 67: + do { + pc_num = (pc_num == 5) ? 0 : pc_num + 1; + } while (adven[pc_num].main_status == MAIN_STATUS_ABSENT); + which_pc_displayed = pc_num; + put_pc_graphics(); + break; + + case 100: + break; + + } + return FALSE; +} + +void display_pc(short pc_num,short mode,short parent) +{ + short i; + char label_str[256]; + + if (adven[pc_num].main_status == MAIN_STATUS_ABSENT) { + for (pc_num = 0; pc_num < 6; pc_num++) + if (adven[pc_num].isAlive()) + break; + } + which_pc_displayed = pc_num; + store_trait_mode = mode; + + SetCursor(sword_curs); + + cd_create_dialog_parent_num(991,parent); + + for (i = 3; i < 65; i++) { + GetIndString(label_str,(mode == 0) ? 7 : 8,(i - 3) * 2 + 1); + cd_add_label(991,i,(char *)label_str,46); + } + put_pc_graphics(); + + cd_set_pict(991,2,714 + mode); + while (dialog_not_toast) + ModalDialog(); cd_kill_dialog(991,0); +} + +void put_item_info() +{ + char store_text[256]; + char desc_str[256]; + short i; + item_record_type s_i; + char *item_types[] = {"","1-Handed weapon","2-Handed weapon","","Bow","Arrows","Thrown missile", + "Potion/Magic Item","Scroll/Magic Item","Wand","Tool","","Shield","Armor","Helm", + "Gloves","Shield","Boots","Ring","Necklace", + "Weapon Poison","Gem, Stone, Etc.","Pants","Crossbow","Bolts","Missile Weapon"}; + + + s_i = store_i; + + csp(998,1,950); + if (s_i.graphic_num >= 150) + csp(998,1,s_i.graphic_num - 150 + 2000); + else csp(998,1,1800 + s_i.graphic_num); + + // id? magic? + if (store_i.isMagic() && store_i.isIdent()) + cd_set_led(998,17,1); + else cd_set_led(998,17,0); + if (store_i.isIdent()) + cd_set_led(998,16,1); + else cd_set_led(998,16,0); + cd_set_item_text(998,4, item_types[s_i.variety]); + + // Clear fields + for (i = 5; i < 13; i++) cd_set_item_text(998,i, ""); + + if (s_i.isIdent() == false) { + cd_set_item_text(998,3, s_i.name); + cd_set_item_text(998,12, "???"); // cosmetic change, display ??? in ability when the item isn't identified + return; + } + + cd_set_item_text(998,3, s_i.full_name); + i = item_weight(s_i); + cd_set_item_num(998,20,i); + + cd_set_item_num(998,5,(s_i.charges > 0) ? s_i.value * s_i.charges : s_i.value); + +// if (s_i.ability > 0) {//// +// GetIndString(desc_str,23,s_i.ability + 1); +// cd_set_item_text(998,12,(char *) desc_str); +// } +if (s_i.isConcealed()){cd_set_item_text(998,12,"???");} //check if the item ability is to be concealed and print "???" in ability if so + else{ + GetIndString(desc_str,23,s_i.ability + 1); //else it display the item ability as usual + cd_set_item_text(998,12,(char *) desc_str); //note : common items weren't displaying the "No ability" string. It is restored here. + } + if (s_i.charges > 0) + cd_set_item_num(998,10,s_i.charges); + if (s_i.protection > 0) + cd_set_item_num(998,8,s_i.protection); + + switch (s_i.variety) { + case 1: case 2: + cd_set_item_num(998,6,s_i.item_level); + cd_set_item_num(998,7,s_i.bonus); + + switch (s_i.type) { + case 1:sprintf((char *) store_text, "Edged weapon"); + break; + case 2:sprintf((char *) store_text, "Bashing weapon"); + break; + case 3:sprintf((char *) store_text, "Pole weapon"); + break; + } + if (s_i.ability == 0) + cd_set_item_text(998,12,store_text); + break; + case 4: case 23: + cd_set_item_num(998,6,s_i.item_level); + cd_set_item_num(998,7,s_i.bonus); + break; + case 5: case 6: case 24: case 25: + cd_set_item_num(998,6,s_i.item_level); + cd_set_item_num(998,7,s_i.bonus); + break; + case 7: case 18: + cd_set_item_num(998,11,s_i.item_level); + break; + case 12: case 13: case 14: case 15: case 16: case 17: + cd_set_item_num(998,7,s_i.bonus + s_i.protection); + cd_set_item_num(998,8,s_i.item_level); + cd_set_item_num(998,9,s_i.awkward); + break; + case 20: + cd_set_item_num(998,11,s_i.item_level); + break; + } + +} + +Boolean display_pc_item_event_filter (short item_hit) +{ + short item,pc_num; + + item = store_displayed_item; + pc_num = store_item_pc; + + switch (item_hit) { + case 1: case 13: + dialog_not_toast = FALSE; + break; + + case 14: + do { + item = (item == 0) ? 23 : item - 1; + } while (adven[pc_num].items[item].variety == 0); + store_displayed_item = item; + store_i = adven[pc_num].items[item]; + put_item_info(); + break; + case 15: + do { + item = (item == 23) ? 0 : item + 1; + } while (adven[pc_num].items[item].variety == 0); + store_displayed_item = item; + store_i = adven[pc_num].items[item]; + put_item_info(); + break; + + case 100: + break; + + } + return FALSE; +} + +void display_pc_item(short pc_num,short item,item_record_type si,short parent) +{ + store_item_pc = pc_num; + if (pc_num == 6) + store_i = si; + else store_i = adven[pc_num].items[item]; + store_displayed_item = item; + SetCursor(sword_curs); + + if (cd_create_dialog_parent_num(998,parent) < 0) + return; + + if (store_item_pc >= 6) { + cd_activate_item(998,14,0); + cd_activate_item(998,15,0); + } + cd_add_label(998,3,"Name:",1026); + cd_add_label(998,4,"Type:",1026); + cd_add_label(998,5,"Value:",1020); + cd_add_label(998,6,"Damage:",1026); + cd_add_label(998,7,"Bonus:",1024); + cd_add_label(998,8,"Defend:",1025); + cd_add_label(998,9,"Encumb.:",1029); + cd_add_label(998,10,"Uses:",1019); + cd_add_label(998,11,"Item Level:",1037); + cd_add_label(998,12,"Ability:",1026); + cd_add_label(998,16,"ID?",1013); + cd_add_label(998,17,"Magic?",1022); + cd_add_label(998,20 ,"Weight",1022); + + put_item_info(); + while (dialog_not_toast) + ModalDialog(); cd_kill_dialog(998,0); + +} + + +void put_monst_info() +{ + char store_text[256]; + char str[256]; + short abil,i; + + if ( store_m->m_d.spec_skill == 11) + cd_set_pict(999,4,400); + else if (store_m->m_d.picture_num < 1000) + cd_set_pict(999,4,400 + store_m->m_d.picture_num); + else cd_set_pict(999,4,2000 + (store_m->m_d.picture_num % 1000)); + + get_m_name((char *) store_text,store_m->number); + cd_set_item_text(999,5,store_text); + // Clear fields + for (i = 6; i < 20; i++) { + cd_set_item_text(999,i,""); + } + + abil = store_m->m_d.spec_skill; + GetIndString(str,20,abil + 1); + cd_set_item_text(999,19,(char *) str); + GetIndString(str,20,store_m->m_d.radiate_1 + 50); + cd_set_item_text(999,31,(char *) str); + + for (i = 0; i < 3; i++) + if (store_m->m_d.a[i] > 0) { + sprintf((char *) store_text," %dd%d ", + store_m->m_d.a[i] / 100 + 1, store_m->m_d.a[i] % 100); + + cd_set_item_text(999,13 + i,store_text); + } + cd_set_item_num(999,6,store_m->m_d.level); + cd_set_item_num(999,7,store_m->m_d.health); + cd_set_item_num(999,8,store_m->m_d.mp); + cd_set_item_num(999,9,store_m->m_d.armor); + cd_set_item_num(999,10,store_m->m_d.skill); + cd_set_item_num(999,11,store_m->m_d.morale); + cd_set_item_num(999,12,store_m->m_d.speed); + cd_set_item_num(999,16,store_m->m_d.mu); + cd_set_item_num(999,17,store_m->m_d.cl); + cd_set_item_num(999,18,store_m->m_d.poison); + // 2140 - lit 2141 - dark + // immunities + for (i = 0; i < 8; i++) + if (store_m->m_d.immunities & (char)(s_pow(2,i))) + cd_set_led(999,20 + i,1); + else cd_set_led(999,20 + i,0); + + + } + + +Boolean display_monst_event_filter (short item_hit) +{ + short i,dummy = 0; + + switch (item_hit) { + case 1: case 3: + dialog_not_toast = FALSE; + break; + + case 28: + if (position == 0) { + for (i = 255; on_monst_menu[i] < 0 && i > 0; i--) + dummy++; + position = i; + } + else position--; + + if (on_monst_menu[position] < 0) + position = 0; + store_m->number = (unsigned char)on_monst_menu[position]; + store_m->m_d = return_monster_template((unsigned char)on_monst_menu[position]); + put_monst_info(); + break; + case 29: + position++; + if (on_monst_menu[position] < 0) + position = 0; + store_m->number = (unsigned char)on_monst_menu[position]; + store_m->m_d = return_monster_template((unsigned char)on_monst_menu[position]); + put_monst_info(); + break; + + case 100: + break; + + } + + return FALSE; +} + +void display_monst(short array_pos,creature_data_type *which_m,short mode) +//creature_data_type *which_m; // if NULL, show full roster +//short mode; // if 1, full roster, else use monster from storwhich_me_m +{ + position = array_pos; + full_roster = FALSE; + if (mode == 1) { + full_roster = TRUE; + store_m = &hold_m; + store_m->number = on_monst_menu[array_pos]; + store_m->m_d = return_monster_template((unsigned char)on_monst_menu[array_pos]); + } + else { + hold_m = *which_m; + store_m = which_m; + } + + SetCursor(sword_curs); + + cd_create_dialog(999,mainPtr); + + if (full_roster == FALSE) { + cd_activate_item(999,28,0); + cd_activate_item(999,29,0); + } + cd_add_label(999,5,"Name",1026); + cd_add_label(999,6,"Level",1021); + cd_add_label(999,7,"Health",1024); + cd_add_label(999,8,"Magic Pts.",1032); + cd_add_label(999,9,"Armor",1023); + cd_add_label(999,10,"Skill",1018); + cd_add_label(999,11,"Morale",1023); + cd_add_label(999,12,"Speed",1019); + cd_add_label(999,13,"Att #1",1026); + cd_add_label(999,14,"Att #2",1023); + cd_add_label(999,15,"Att #3",1022); + cd_add_label(999,16,"Mage L.",1034); + cd_add_label(999,17,"Priest L.",1030); + cd_add_label(999,18,"Poison",1023); + cd_add_label(999,19,"Ability 1",1029); + cd_add_label(999,31,"Ability 2",1029); + cd_add_label(999,20,"Magic Resistant",45); + cd_add_label(999,21,"Immune To Magic",45); + cd_add_label(999,22,"Fire Resistant",45); + cd_add_label(999,23,"Immune To Fire",45); + cd_add_label(999,24,"Cold Resistant",45); + cd_add_label(999,25,"Immune To Cold",45); + cd_add_label(999,26,"Poison Resistant",45); + cd_add_label(999,27,"Immune To Poison",45); + put_monst_info(); + while (dialog_not_toast) + ModalDialog(); cd_kill_dialog(999,0); +} + + +Boolean display_help_event_filter (short item_hit) +{ + char get_text[256]; + + switch (item_hit) { + case 1: case 3: + dialog_not_toast = FALSE; + break; + + case 4: case 5: + if (item_hit == 4) + cur_entry = (cur_entry == 3) ? num_entries + 2 : cur_entry - 1; + else cur_entry = (cur_entry == num_entries + 2) ? 3 : cur_entry + 1; + GetIndString(get_text, 25 + store_help_mode, cur_entry); + cd_set_item_text(997,7,(char *) get_text); + break; + } + + return FALSE; +} + +void display_help(short mode,short parent) +{ + char get_text[256]; + long get_val; + + store_help_mode = mode; + cur_entry = 3; + + SetCursor(sword_curs); + + cd_create_dialog_parent_num(997,parent); + + GetIndString(get_text, 25 + mode, 1); + csit( 997,6,(char *) get_text); + GetIndString (get_text, 25 + mode, 2); + //StringToNum(get_text,&get_val); + get_val = atol(get_text); + num_entries = (short) get_val; + GetIndString(get_text, 25 + mode, cur_entry); + csit( 997,7,(char *) get_text); + + while (dialog_not_toast) + ModalDialog(); cd_kill_dialog(997,0); + +} + + + +Boolean display_alchemy_event_filter (short item_hit) +{ + switch (item_hit) { + case 1: case 3: + dialog_not_toast = FALSE; + break; + + } + return FALSE; +} + +void display_alchemy() +{ + short i; + char *alch_names[] = + { + "Weak Curing Potion (1)", + "Weak Healing Potion (1)", + "Weak Poison (1)", + "Weak Speed Potion (3)", + "Medium Poison (3)", + "Medium Heal Potion (4)", + "Strong Curing (5)", + "Medium Speed Potion (5)", + "Graymold Salve (7)", + "Weak Energy Potion (9)", + "Potion of Clarity (9)", + "Strong Poison (10)", + "Strong Heal Potion (12)", + "Killer Poison (12)", + "Resurrection Balm (9)", + "Medium Energy Ptn. (14)", + "Knowledge Brew (19)", + "Strong Strength (10)", + "Bliss (16)", + "Strong Power (20)" + }; + + SetCursor(sword_curs); + + cd_create_dialog_parent_num(996,1019); + + for (i = 0; i < 20; i++) { + cd_add_label(996,i + 4,alch_names[i],1083); + if (party.alchemy[i] > 0) + cd_set_led(996,i + 4,1); + else cd_set_led(996,i + 4,0); + } + + while (dialog_not_toast) + ModalDialog(); cd_kill_dialog(996,0); + dialog_not_toast = TRUE; + +} + + +void display_traits_graphics() +{ + short i,store; + + for (i = 0; i < 3; i++) { + cd_set_led(1013,4 + i,(store_pc->race == i) ? 1 : 0); + } + for (i = 0; i < 10; i++) { + cd_set_led(1013,7 + i,(store_pc->traits[i] > 0) ? 1 : 0); + } + for (i = 0; i < 5; i++) { + cd_set_led(1013,36 + i,(store_pc->traits[10 + i] > 0) ? 1 : 0); + } + + store = get_tnl(store_pc); + cdsin(1013,18,store); +} + +void pick_race_abil_event_filter(short item_hit) +{ + char abil_str[256]; + pc_record_type *pc; + + pc = store_pc; + switch (item_hit) { + case 3: + dialog_not_toast = FALSE; + break; + case 4: case 5: case 6: + if (store_trait_mode == 0) + pc->race = item_hit - 4; + display_traits_graphics(); + GetIndString(abil_str,5,12 + item_hit); + csit(1013,19,(char *) abil_str); + break; + case 36: case 37: case 38: case 39: case 40: + if (store_trait_mode != 1) + pc->traits[item_hit - 26] = (pc->traits[item_hit - 26] == TRUE) ? FALSE : TRUE; + display_traits_graphics(); + GetIndString(abil_str,5,item_hit - 25); + csit(1013,19,(char *) abil_str); + break; + default: + if (item_hit >= 100) + return; + if (store_trait_mode != 1) + pc->traits[item_hit - 7] = (pc->traits[item_hit - 7] == TRUE) ? FALSE : TRUE; + display_traits_graphics(); + GetIndString(abil_str,5,item_hit - 6); + csit(1013,19,(char *) abil_str); + break; + } + +} + +void pick_race_abil(pc_record_type *pc,short mode,short parent_num) +//mode; // 0 - edit 1 - just display 2 - can't change race +{ + char *start_str1 = "Click on button by name for description."; + char *start_str2 = "Click on advantage button to add/remove."; + + store_trait_mode = mode; + store_pc = pc; + SetCursor(sword_curs); + + cd_create_dialog_parent_num(1013,parent_num); + + display_traits_graphics(); + if (mode == 1) + csit(1013,19,start_str1); + else csit(1013,19,start_str2); + + while (dialog_not_toast) + ModalDialog(); cd_kill_dialog(1013,0); + dialog_not_toast = TRUE; +} + +void display_pc_info() +{ + short i,store; + char str[256]; + short pc; + char to_draw[60]; + + short weap1 = 24,weap2 = 24,hit_adj = 0, dam_adj = 0,skill_item; + + pc = store_pc_num; + + store = adven[pc].amountCarried(); + i = adven[pc].amountCanCarry(); + sprintf ((char *) to_draw, "%s is carrying %d stones out of %d.",adven[pc].name,store,i); + csit(1019,69,(char *) to_draw); + + sprintf((char *) str,"%d out of %d.", + adven[pc].cur_health,adven[pc].max_health); + csit(1019,65,(char *) str); + sprintf((char *) str,"%d out of %d.", + adven[pc].cur_sp,adven[pc].max_sp); + csit(1019,67,(char *) str); + + for (i = 0; i < 19; i++) { + cdsin(1019,18 + i * 2,adven[pc].skills[i]); + } + store = total_encumberance(pc); + cdsin(1019,62,store); + csit(1019,9,adven[pc].name); + cdsin(1019,11,adven[pc].level); + cdsin(1019,13,adven[pc].experience); + cdsin(1019,71,adven[pc].skill_pts); + store = adven[pc].level * get_tnl(&adven[pc]); + cdsin(1019,15,store); + csp(1019,7,800 + adven[pc].which_graphic); + + // Fight bonuses + for (i = 0; i < 24; i++) + if (((adven[pc].items[i].variety == 1) || (adven[pc].items[i].variety == 2)) && + (adven[pc].equip[i] == TRUE)) { + if (weap1 == 24) + weap1 = i; + else weap2 = i; + } + + hit_adj = adven[pc].statAdj(1) * 5 - (total_encumberance(pc)) * 5 + + (5 * minmax(-8,8,(int)adven[pc].status[1])); + if ((adven[pc].traits[TRAIT_AMBIDEXTROUS] == FALSE) && (weap2 < 24)) + hit_adj -= 25; + + dam_adj = adven[pc].statAdj(0) + minmax(-8,8,(int)adven[pc].status[1]); + if ((skill_item = text_pc_has_abil_equip(pc,101)) < 24) { + hit_adj += 5 * (adven[pc].items[skill_item].item_level + 1); + dam_adj += adven[pc].items[skill_item].item_level; + } + if ((skill_item = text_pc_has_abil_equip(pc,96)) < 24) { + dam_adj += 2; + hit_adj += 1; + } + if ((skill_item = text_pc_has_abil_equip(pc,97)) < 24) { + hit_adj += 5; + dam_adj += 3; + } + + csit(1019,56,"No weapon."); + csit(1019,57,""); + csit(1019,59,"No weapon."); + csit(1019,60,""); + if (weap1 < 24) { + if (adven[pc].items[weap1].isIdent() == false) + csit(1019,56,"Not identified."); + else { + if (hit_adj + 5 * adven[pc].items[weap1].bonus < 0) + sprintf(to_draw,"Penalty to hit: %%%d",hit_adj + 5 * adven[pc].items[weap1].bonus); + else sprintf(to_draw,"Bonus to hit: +%%%d",hit_adj + 5 * adven[pc].items[weap1].bonus); + csit(1019,56,to_draw); + sprintf(to_draw,"Damage: (1-%d) + %d",adven[pc].items[weap1].item_level + ,dam_adj + adven[pc].items[weap1].bonus); + csit(1019,57,to_draw); + + } + } + if (weap2 < 24) { + if (adven[pc].items[weap2].isIdent() == false) + csit(1019,59,"Not identified."); + else { + if (hit_adj + 5 * adven[pc].items[weap2].bonus < 0) + sprintf(to_draw,"Penalty to hit: %%%d",hit_adj + 5 * adven[pc].items[weap2].bonus); + else sprintf(to_draw,"Bonus to hit: +%%%d",hit_adj + 5 * adven[pc].items[weap2].bonus); + csit(1019,59,to_draw); + sprintf(to_draw,"Damage: (1-%d) + %d",adven[pc].items[weap2].item_level + ,dam_adj + adven[pc].items[weap2].bonus); + csit(1019,60,to_draw); + + } + } + +} + +void give_pc_info_event_filter(short item_hit) +{ + short pc; + + pc = store_pc_num; + switch (item_hit) { + case 1: + dialog_not_toast = FALSE; + break; + case 2: + do + store_pc_num = (store_pc_num == 0) ? 5 : store_pc_num - 1; + while (adven[store_pc_num].isAlive() == false); + display_pc_info(); + break; + case 3: + do + store_pc_num = (store_pc_num + 1) % 6; + while (adven[store_pc_num].isAlive() == false); + display_pc_info(); + break; + case 4: + display_pc(pc,0,1019); + break; + case 5: + display_pc(pc,1,1019); + break; + case 6: + pick_race_abil(&adven[pc],1,1019); + break; + case 68: + display_alchemy(); + break; + } + +} + +void give_pc_info(short pc_num) +{ + short i; + char str[256]; + + store_pc_num = pc_num; + SetCursor(sword_curs); + + cd_create_dialog_parent_num(1019,0); + + for (i = 0; i < 19; i++) { + GetIndString(str,9,1 + i * 2); + csit(1019,17 + i * 2,(char *) str); + } + display_pc_info(); + while (dialog_not_toast) + ModalDialog(); cd_kill_dialog(1019,0); +} + +void adventure_notes_event_filter (short item_hit) +{ + short i; + char place_str[256]; + + switch (item_hit) { + case 1: + dialog_not_toast = FALSE; + break; + + case 7: case 8: + if (item_hit == 7) { + if (store_page_on == 0) + store_page_on = (store_num_i - 1) / 3; + else store_page_on--; + } + else { + if (store_page_on == (store_num_i - 1) / 3) + store_page_on = 0; + else store_page_on++; + } + + break; + case 10: case 9: case 11: + party.special_notes_str[(store_page_on * 3) + item_hit - 9][0] = -1; + break; + } + for (i = 0; i < 3; i++) { + if (party.special_notes_str[i][0] > 0) { + switch (party.special_notes_str[i][0] / 1000) { + case 0: if (party.special_notes_str[i][0] % 1000 < 160) + strcpy((char *) place_str,data_store5->scen_strs[party.special_notes_str[i][0] % 1000]); + else strcpy((char *) place_str,scen_strs2[(party.special_notes_str[i][0] % 1000) - 160]); + break; + case 1: + load_outdoors(party.special_notes_str[i][1] % scenario.out_width, + party.special_notes_str[i][1] / scenario.out_width, + 0,0,1,party.special_notes_str[i][0] % 1000,(char *)place_str); + break; + case 2: load_town(party.special_notes_str[i][1],2,party.special_notes_str[i][0],(char *)place_str); break; + } + + GetIndString(place_str,party.special_notes_str[i][0],party.special_notes_str[i][1]); + csit(961,3 + i,(char *) place_str); + cd_activate_item(961,9 + i,1); + } + else cd_activate_item(961,9 + i,0); + } + for (i = store_page_on * 3; i < (store_page_on * 3) + 3; i++) { + if (party.special_notes_str[i][0] > 0) { + switch (party.special_notes_str[i][0] / 1000) { + case 0: if (party.special_notes_str[i][0] % 1000 < 160) + strcpy((char *) place_str,data_store5->scen_strs[party.special_notes_str[i][0] % 1000]); + else strcpy((char *) place_str,scen_strs2[(party.special_notes_str[i][0] % 1000) - 160]); + break; + case 1: + load_outdoors(party.special_notes_str[i][1] % scenario.out_width, + party.special_notes_str[i][1] / scenario.out_width, + 0,0,1,party.special_notes_str[i][0] % 1000,(char *)place_str); + break; + case 2: load_town(party.special_notes_str[i][1],2,party.special_notes_str[i][0] % 1000,(char *)place_str); break; + } + + + csit(961,3 + (i - store_page_on * 3),(char *) place_str); + cd_activate_item(961,9 + (i - store_page_on * 3),1); + } + else { + csit(961,3 + (i - store_page_on * 3),""); + cd_activate_item(961,9 + (i - store_page_on * 3),0); + } + } +} + +void adventure_notes() +{ + short i; + char place_str[256]; + + store_num_i = 0; + for (i = 0; i < 140; i++) + if (party.special_notes_str[i][0] > 0) + store_num_i = i + 1; + store_page_on = 0; + if (store_num_i == 0) { + ASB("Nothing in your journal."); + print_buf(); + return; + } + + SetCursor(sword_curs); + + cd_create_dialog_parent_num(961,0); + + for (i = 0; i < 3; i++) { + if (party.special_notes_str[i][0] > 0) { + switch (party.special_notes_str[i][0] / 1000) { + case 0: + if (party.special_notes_str[i][0] % 1000 < 160) + strcpy((char *) place_str,data_store5->scen_strs[party.special_notes_str[i][0] % 1000]); + else strcpy((char *) place_str,scen_strs2[(party.special_notes_str[i][0] % 1000) - 160]); + break; + case 1: + load_outdoors(party.special_notes_str[i][1] % scenario.out_width, + party.special_notes_str[i][1] / scenario.out_width, + 0,0,1,party.special_notes_str[i][0] % 1000,(char *)place_str); + break; + case 2: load_town(party.special_notes_str[i][1],2,party.special_notes_str[i][0] % 1000,(char *)place_str); break; + } + + csit(961,3 + i,(char *) place_str); + cd_activate_item(961,9 + i,1); + } + else cd_activate_item(961,9 + i,0); + } + + if (store_num_i <= 3) { + cd_activate_item(961,7,0); + cd_activate_item(961,8,0); + } + + while (dialog_not_toast) + ModalDialog(); + + cd_kill_dialog(961,0); + +} + +void put_talk() +{ + short personality; + char place_str[256]; + + csit(960,3,""); + csit(960,5,""); + csit(960,7,""); + csit(960,9,""); + if ((personality = party.talk_save[store_page_on].personality) >= 0) { + if (personality / 10 != cur_town_talk_loaded) + load_town(personality / 10,1,0,NULL); + + load_town(party.talk_save[store_page_on].town_num,2,0,(char *) place_str); + csit(960,9,(char *) place_str); + + //GetIndString(place_str,120 + ((personality - 1) / 10),((personality - 1) % 10) + 1); + csit(960,7,data_store3->talk_strs[personality % 10]); + + if (party.talk_save[store_page_on].str1 >= 1000) { + if (party.talk_save[store_page_on].str1 >= 3000) { + if (party.talk_save[store_page_on].str1 - 3000 < 160) + csit(960,3,data_store5->scen_strs[party.talk_save[store_page_on].str1 - 3000 ]); + else csit(960,3,scen_strs2[party.talk_save[store_page_on].str1 - 3000 - 160]); + + } + else { + load_town(party.talk_save[store_page_on].town_num,2, + party.talk_save[store_page_on].str1 - 2000 ,(char *) place_str); + csit(960,3,(char *) place_str); + } + } + else if ((party.talk_save[store_page_on].str1 > 0) && + (party.talk_save[store_page_on].str1 < 170)) + csit(960,3,data_store3->talk_strs[party.talk_save[store_page_on].str1]); + + if (party.talk_save[store_page_on].str2 >= 1000) { + if (party.talk_save[store_page_on].str2 >= 3000) { + if (party.talk_save[store_page_on].str2 - 3000 < 160) + csit(960,5,data_store5->scen_strs[party.talk_save[store_page_on].str2 - 3000 ]); + else csit(960,5,scen_strs2[party.talk_save[store_page_on].str2 - 3000 - 160]); + + } + else { + load_town(party.talk_save[store_page_on].town_num,2, + party.talk_save[store_page_on].str2 - 2000,(char *) place_str); + csit(960,5,(char *) place_str); + } + } + else if ((party.talk_save[store_page_on].str2 > 0) && + (party.talk_save[store_page_on].str2 < 170)) + csit(960,5,data_store3->talk_strs[party.talk_save[store_page_on].str2]); + } +} + +void talk_notes_event_filter (short item_hit) +{ + switch (item_hit) { + case 1: + dialog_not_toast = FALSE; + break; + + case 10: case 11: + if (item_hit == 10) { + if (store_page_on == 0) + store_page_on = store_num_i - 1; + else store_page_on--; + } + else { + if (store_page_on == store_num_i - 1) + store_page_on = 0; + else store_page_on++; + } + + break; + case 12: + party.talk_save[store_page_on].personality = -1; + break; + } + put_talk(); +} + +void talk_notes() +{ + short i; + + store_num_i = 0; + for (i = 0; i < 120; i++) + if (party.talk_save[i].personality != -1) + store_num_i = i + 1; + store_page_on = 0; + if (store_num_i == 0) { + ASB("Nothing in your talk journal."); + print_buf(); + return; + } + + SetCursor(sword_curs); + + cd_create_dialog_parent_num(960,0); + + put_talk(); + if (store_num_i == 1) { + cd_activate_item(960,10,0); + cd_activate_item(960,11,0); + } + + while (dialog_not_toast) + ModalDialog(); + cd_kill_dialog(960,0); + +} + +// Call this anywhere, but don't forget parent!!! +void give_help(short help1,short help2,short parent_num) +{ + Boolean help_forced = FALSE; + char str1[256],str2[256]; + + if (help1 >= 200) { + help_forced = TRUE; + help1 -= 200; + } + if ((PSD[306][4] > 0) && (help_forced == FALSE)) + return; + if (party.help_received[help1] > 0) + return; + party.help_received[help1] = 1; + GetIndString(str1,10,help1); + if (help2 > 0) + GetIndString(str2,10,help2); + if (help2 == 0) + display_strings((char *)str1, "",-1,-1,-1,-1,"Instant Help",57,724, parent_num); + else display_strings((char *)str1,(char *)str2,-1,-1,-1,-1,"Instant Help",57,724, parent_num); + +} + +void put_spec_item_info (short which_i) +{ + display_strings(data_store5->scen_strs[60 + 1 + which_i * 2],"", + -1,-1,-1,-1, + data_store5->scen_strs[60 + which_i * 2],57,1600 + scenario.intro_pic,0); +} + +void display_strings_event_filter (short item_hit) +{ + short i; + Boolean had1 = FALSE, had2 = FALSE; + + switch (item_hit) { + case 1: + dialog_not_toast = FALSE; + break; + case 2: + play_sound(0); + for (i = 0; i < 140; i++) + if ((store_str_label_1 == party.special_notes_str[i][0]) && + (store_str_label_1b == party.special_notes_str[i][1])) + had1 = TRUE; + if (had1 == FALSE) { + //give_help(58,0,store_which_string_dlog); + for (i = 0; i < 140; i++) + if (party.special_notes_str[i][0] <= 0) { + party.special_notes_str[i][0] = store_str_label_1; + party.special_notes_str[i][1] = store_str_label_1b; + //party.special_notes_str[i][1] = store_str1b; + ASB("Info added to Encounter Notes."); + i = 140; + } + + } + for (i = 0; i < 140; i++) + if ((store_str_label_2 == party.special_notes_str[i][0]) && + (store_str_label_2b == party.special_notes_str[i][1])) + had2 = TRUE; + if (had2 == FALSE) { + for (i = 0; i < 140; i++) + if (party.special_notes_str[i][0] <= 0) { + party.special_notes_str[i][0] = store_str_label_2; + party.special_notes_str[i][1] = store_str_label_2b; + //party.special_notes_str[i][1] = store_str2b; + i = 140; + } + + } + break; + } +} + +// str_label_1 & str_label_2 uysed for saving button for journal +// 1000 + x scen 2000 + x out 3000 + x town +void display_strings(char *text1, char *text2,short str_label_1,short str_label_2,short str_label_1b, + short str_label_2b, + char *title,short sound_num,short graphic_num,short parent_num) +{ + + SetCursor(sword_curs); + + store_str_label_1 = str_label_1; + store_str_label_2 = str_label_2; + store_str_label_1b = str_label_1b; + store_str_label_2b = str_label_2b; + + store_which_string_dlog = 970; + if (strlen(title) > 0) + store_which_string_dlog += 2; + if ((text2 != NULL) && (text2[0] != 0)) + store_which_string_dlog++; + cd_create_dialog_parent_num(store_which_string_dlog,parent_num); + + csp(store_which_string_dlog,store_which_string_dlog,graphic_num); + + csit(store_which_string_dlog,4,(char *) text1); + if (text2 != NULL) { + csit(store_which_string_dlog,5,(char *) text2); + } + if (strlen(title) > 0) + csit(store_which_string_dlog,6,title); + csp(store_which_string_dlog,3,graphic_num); + if (sound_num >= 0) + play_sound(sound_num); + + if ((str_label_1 < 0) && (str_label_2 < 0)) + cd_activate_item(store_which_string_dlog,2,0); + while (dialog_not_toast) + ModalDialog(); //cd_kill_dialog(store_which_string_dlog,0); + final_process_dialog(store_which_string_dlog); +} + +void give_error(char *text1, char *text2,short parent_num) +{ + display_strings(text1,text2,-1,-1,-1,-1,"Error!",57,716,parent_num); +} + +void display_strings_with_nums(short a1,short a2, short b1, short b2, + char *title,short sound_num,short graphic_num,short parent_num) +{ + char str1[256] = "", str2[256] = ""; + + if ((a1 > 0) && (a2 > 0)) + GetIndString(str1,a1,a2); + if ((b1 > 0) && (b2 > 0)) + GetIndString(str2,b1,b2); + display_strings((char *) str1,(char *) str2,-1,-1,-1,-1, + title, sound_num, graphic_num, parent_num); +} diff --git a/Win32/Blades of Exile/INFODLGS.H b/Win32/Blades of Exile/INFODLGS.H new file mode 100644 index 00000000..dfb8a2af --- /dev/null +++ b/Win32/Blades of Exile/INFODLGS.H @@ -0,0 +1,48 @@ +#ifndef _INFODLGS_H + #define _INFODLGS_H + +void put_spell_info(); +Boolean display_spells_event_filter (short item_hit); +void display_spells(short mode,short force_spell,short parent_num); +void put_skill_info(); +Boolean display_skills_event_filter (short item_hit); +void display_skills(short force_skill,short parent); +void put_pc_graphics(); +Boolean display_pc_event_filter (short item_hit); +void display_pc(short pc_num,short mode,short parent_num); +void put_item_info(); +Boolean display_pc_item_event_filter (short item_hit); +void display_pc_item(short pc_num,short item,item_record_type si,short parent); +void put_monst_info(); +Boolean display_monst_event_filter (short item_hit); +void display_monst(short array_pos,creature_data_type *which_m,short mode); +Boolean display_help_event_filter (short item_hit); +void display_help(short mode,short parent); +Boolean display_alchemy_event_filter (short item_hit); +void display_alchemy(); +void pick_race_abil(pc_record_type *pc,short mode,short parent_num); +void pick_race_abil_event_filter(short item_hit); +void display_traits_graphics(); +void give_pc_info(short pc_num); +void give_pc_info_event_filter(short item_hit); +void display_pc_info(); +void adventure_notes_event_filter (short item_hit); +void adventure_notes(); +void put_talk(); +void talk_notes_event_filter (short item_hit); +void talk_notes(); +void journal(); +void journal_event_filter (short item_hit); +void add_to_journal(short event); +void anax_string(short val1,short val2); +void give_help(short help1,short help2,short parent_num); +void put_spec_item_info (short which_i); +void display_strings_event_filter (short item_hit); +void display_strings(char *text1, char *text2,short str_label_1,short str_label_2,short str_label_1b, + short str_label_2b, + char *title,short sound_num,short graphic_num,short parent_num); +void give_error(char *text1, char *text2,short parent_num); +void display_strings_with_nums(short a1,short a2, short b1, short b2, + char *title,short sound_num,short graphic_num,short parent_num); + +#endif diff --git a/Win32/Blades of Exile/ITEM.CPP b/Win32/Blades of Exile/ITEM.CPP new file mode 100644 index 00000000..05ec75a4 --- /dev/null +++ b/Win32/Blades of Exile/ITEM.CPP @@ -0,0 +1,37 @@ +#include "item.h" + +bool item_record_type::isIdent() const +{ + if (item_properties & ITEM_PROP_IDENTIFIED) return true; + else return false; +} + +bool item_record_type::isMagic() const +{ + if (item_properties & ITEM_PROP_MAGIC) return true; + else return false; +} + +bool item_record_type::isContained() const +{ + if (item_properties & ITEM_PROP_CONTAINED) return true; + else return false; +} + +bool item_record_type::isCursed() const +{ + if (item_properties & ITEM_PROP_CURSED) return true; + else return false; +} + +bool item_record_type::isProperty() const +{ + if (item_properties & ITEM_PROP_PROPERTY) return true; + else return false; +} + +bool item_record_type::isConcealed() const +{ + if (item_properties & ITEM_PROP_CONCEALED) return true; + else return false; +} diff --git a/Win32/Blades of Exile/ITEM.H b/Win32/Blades of Exile/ITEM.H new file mode 100644 index 00000000..8619890d --- /dev/null +++ b/Win32/Blades of Exile/ITEM.H @@ -0,0 +1,44 @@ +#ifndef _ITEM_H + #define _ITEM_H + +#include "location.h" + +/* item_properties: */ +/* + 0000 0001 identified + 0000 0010 someone's property + 0000 0100 magic + 0000 1000 contained in sth + 0001 0000 cursed + 0010 0000 concealed + 0100 0000 + 1000 0000 +*/ + +#define ITEM_PROP_IDENTIFIED 1 +#define ITEM_PROP_PROPERTY 2 +#define ITEM_PROP_MAGIC 4 +#define ITEM_PROP_CONTAINED 8 +#define ITEM_PROP_CURSED 16 +#define ITEM_PROP_CONCEALED 32 + +struct item_record_type { + short variety, item_level; + char awkward, bonus, protection, charges, type, magic_use_type; + unsigned char graphic_num,ability, ability_strength, type_flag, is_special,a; + short value; + unsigned char weight, special_class; + location item_loc; + char full_name[25], name[15]; + unsigned char treas_class, item_properties, reserved1, reserved2; + + /* functions */ + bool isIdent() const; /* is identified ? */ + bool isMagic() const; /* is magic ? */ + bool isContained() const; /* is contained in sth ? */ + bool isCursed() const; /* is cursed ? */ + bool isProperty() const; /* is someones property? */ + bool isConcealed() const; /* is the item ability concealed ? */ +}; + +#endif diff --git a/Win32/Blades of Exile/ITEMDATA.CPP b/Win32/Blades of Exile/ITEMDATA.CPP new file mode 100644 index 00000000..f0991481 --- /dev/null +++ b/Win32/Blades of Exile/ITEMDATA.CPP @@ -0,0 +1,166 @@ + +#include + +#include "global.h" +#include "itemdata.h" +#include "stdio.h" +#include "string.h" + +#include "globvar.h" + +short loot_min[5] = {0,0,5,50,400}; +short loot_max[5] = {3,8,40,800,4000}; +//// whole file + +item_record_type return_dummy_item() +{ + item_record_type dummy_item = {0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0, 0,0, location(),"", "",0,0,0,0}; + + return dummy_item; +} + +item_record_type get_stored_item(short which) +{ + item_record_type s_item; + + if ((which >= 400) || (which < 0)) { + s_item = return_dummy_item(); + return s_item; + } + + s_item = data_store2->scen_item_list.scen_items[which]; + return s_item; +} + +item_record_type get_food() +{ + item_record_type food = + {11,0, 0,0,0,0,0,0, 62,0,0,0,0,0, 0, 0,0, location(),"Food", "Food",0,0,0,0}; + food.graphic_num += get_ran(1,0,2); + food.item_level = get_ran(1,5,10); + if (get_ran(1,0,9) == 5) + food.graphic_num = 113; + if (get_ran(1,0,9) == 5) + food.graphic_num = 114; + // food doesn't always appear + if (get_ran(1,0,2) != 1) + food.variety = 0; + + return food; +} + + +item_record_type pull_item_of_type(short loot_max,short min_val,short max_val,short t1, short t2, short t3) +{ + short i,j,val; + item_record_type temp_i; + + // occasionally get nice item + if (get_ran(1,0,160) == 80) { + loot_max += 2; + max_val += 2000; + } + for (i = 0; i < 80; i++) { + j = get_ran(1,0,399); + temp_i = get_stored_item(j); + if ((temp_i.variety == t1) || (temp_i.variety == t2) || (temp_i.variety == t3)) { + val = (temp_i.charges > 0) ? temp_i.charges * temp_i.value : temp_i.value; + if ((val >= min_val) && (val <= max_val) && (temp_i.treas_class != 0) && + (temp_i.treas_class <= loot_max)) + return temp_i; + } + } + temp_i = return_dummy_item(); + return temp_i; +} + +item_record_type get_weapon(short loot) +{ + item_record_type weapon; + + if (loot == 0) + return return_dummy_item(); + weapon = pull_item_of_type(loot,loot_min[loot],loot_max[loot],1,2,-1); + + return weapon; + +} + +item_record_type get_armor(short loot) +{ + short r1; + item_record_type armor; + + if (loot == 0) + return return_dummy_item(); + r1 = get_ran(1,(loot - 1) * 5 + 124,142); + + armor = pull_item_of_type(loot,loot_min[loot],loot_max[loot],13,-1,-1); + + return armor; +} + +item_record_type get_helm(short loot) +{ + return pull_item_of_type(loot,loot_min[loot],loot_max[loot],14,-1,-1); +} + +item_record_type get_gloves(short loot) +{ + return pull_item_of_type(loot,loot_min[loot],loot_max[loot],15,-1,-1); +} + + + +item_record_type get_boots(short loot) +{ + return pull_item_of_type(loot,loot_min[loot],loot_max[loot],17,-1,-1); +} + +item_record_type get_shield(short loot) +{ + return pull_item_of_type(loot,loot_min[loot],loot_max[loot],12,-1,-1); +} + +item_record_type get_potion(short loot) +{ + item_record_type p; + + if (get_ran(1,0,80) < 20 * (4 - loot)) + p = pull_item_of_type(loot,loot_min[loot],loot_max[loot] / 2,7,-1,-1); + else p = pull_item_of_type(loot,loot_min[loot],loot_max[loot],7,-1,-1); + + return p; +} + +item_record_type get_scroll(short loot) +{ + return pull_item_of_type(loot,loot_min[loot],loot_max[loot],8,-1,-1); +} + +item_record_type get_missile(short loot) +{ + if (get_ran(1,0,2) < 2) + return pull_item_of_type(loot,loot_min[loot],loot_max[loot],5,6,4); + return pull_item_of_type(loot,loot_min[loot],loot_max[loot],23,24,25); +} + +item_record_type get_poison(short loot) +{ + return pull_item_of_type(loot,loot_min[loot],loot_max[loot],20,-1,-1); +} + +item_record_type get_wand(short loot) +{ + return pull_item_of_type(loot,loot_min[loot],loot_max[loot],9,-1,-1); +} + +item_record_type get_ring(short loot) +{ + return pull_item_of_type(loot,loot_min[loot],loot_max[loot],18,-1,-1); +} + +item_record_type get_necklace(short loot) +{ + return pull_item_of_type(loot,loot_min[loot],loot_max[loot],19,-1,-1); +} diff --git a/Win32/Blades of Exile/ITEMDATA.H b/Win32/Blades of Exile/ITEMDATA.H new file mode 100644 index 00000000..d12fc719 --- /dev/null +++ b/Win32/Blades of Exile/ITEMDATA.H @@ -0,0 +1,22 @@ +#ifndef _ITEMDATA_H + #define _ITEMDATA_H + +item_record_type return_dummy_item(); +item_record_type get_stored_item(short which); +item_record_type get_food(); +item_record_type get_weapon(short loot); +item_record_type get_armor(short loot); +item_record_type get_helm(short loot); +item_record_type get_gloves(short loot); +item_record_type get_boots(short loot); +item_record_type get_shield(short loot); +item_record_type get_potion(short loot); +item_record_type get_scroll(short loot); +item_record_type get_missile(short loot); +item_record_type get_poison(short loot); +item_record_type get_wand(short loot); +item_record_type get_ring(short loot); +item_record_type get_necklace(short loot); +item_record_type pull_item_of_type(short loot_max,short min_val,short max_val,short t1, short t2, short t3); + +#endif diff --git a/Win32/Blades of Exile/ITEMS.CPP b/Win32/Blades of Exile/ITEMS.CPP new file mode 100644 index 00000000..4ba3f37b --- /dev/null +++ b/Win32/Blades of Exile/ITEMS.CPP @@ -0,0 +1,928 @@ +#include + +#include "global.h" + +#include "graphics.h" +#include "text.h" +#include "dlogtool.h" +#include "items.h" +#include "party.h" +#include "fields.h" +#include "locutils.h" +#include "newgraph.h" +#include "dlogtool.h" +#include "itemdata.h" +#include "infodlgs.h" +#include "exlsound.h" +#include "stdio.h" +#include "string.h" +#include "graphutl.h" +#include "monster.h" + +#include "globvar.h" + +Boolean give_to_party(item_record_type item,short print_result) +{ + short i = 0; + + while (i < 6) { + if (adven[i].giveToPC(item,print_result) == true) + return TRUE; + i++; + } + return FALSE; +} + +Boolean forced_give(short item_num,short abil) +// if abil > 0, force abil, else ignore +{ + short i,j; + item_record_type item; + char announce_string[60]; + + if ((item_num < 0) || (item_num > 399)) + return TRUE; + item = get_stored_item(item_num); + if (abil > 0) + item.ability = abil; + for (i = 0; i < 6; i++) + for (j = 0; j < 24; j++) + if ((adven[i].isAlive()) && (adven[i].items[j].variety == 0)) { + adven[i].items[j] = item; + + if (item.isIdent() == false) + sprintf((char *) announce_string," %s gets %s.",adven[i].name,item.name); + else sprintf((char *) announce_string," %s gets %s.",adven[i].name,item.full_name); + add_string_to_buf((char *)announce_string); + adven[i].combineThings(); + adven[i].sortItems(); + return TRUE; + } + return FALSE; +} + +void party_record_type::giveGold(short amount, bool print_result) +{ + if (amount < 0) return; + + gold += amount; + if (print_result) put_pc_screen(); +} + +bool party_record_type::takeGold(short amount, bool print_result) +{ + if (gold < amount) return false; + + gold -= amount; + + if (print_result) put_pc_screen(); + + return true; +} + + + +bool pc_array::hasAbil(short abil) +{ + short i; + + for (i = 0; i < NUM_OF_PCS; i++) + if (pc[i].isAlive()) + if (pc[i].hasAbil(abil) < 24) + return true; + return false; +} + +short item_weight(item_record_type item) +{ + if (item.variety == 0) + return 0; + if ((item.variety == 5) || (item.variety == 6) || (item.variety == 24) || (item.variety == 7) + || ((item.variety == 21) && (item.charges > 0))) + return (short) (item.charges) * (short) (item.weight); + return (short) (item.weight); +} + +void party_record_type::giveFood(short amount, bool print_result) +{ + if (amount < 0) return; + + food += amount; + + if (print_result) put_pc_screen(); +} + +short party_record_type::takeFood(short amount, bool print_result) +{ + short diff; + + diff = amount - food; + + if (diff > 0) + { + food = 0; + if (print_result) put_pc_screen(); + return diff; + } + + food -= amount; + if (print_result) put_pc_screen(); + return 0; +} + + + +Boolean place_item(item_record_type item,location where,Boolean forced) +{ + short i; + + for (i = 0; i < NUM_TOWN_ITEMS; i++) + if (t_i.items[i].variety == 0) { + t_i.items[i] = item; + t_i.items[i].item_loc = where; + reset_item_max(); + return TRUE; + } + if (forced == FALSE) + return FALSE; + destroy_an_item(); + for (i = 0; i < NUM_TOWN_ITEMS; i++) + if (t_i.items[i].variety == 0) { + t_i.items[i] = item; + t_i.items[i].item_loc = where; + reset_item_max(); + return TRUE; + } + + return TRUE; +} + +void destroy_an_item() +{ +//// + short i; + ASB("Too many items. Some item destroyed."); + for (i = 0; i < NUM_TOWN_ITEMS; i++) + if (t_i.items[i].type_flag == 15) { + t_i.items[i].variety = 0; + return; + } + for (i = 0; i < NUM_TOWN_ITEMS; i++) + if (t_i.items[i].value < 3) { + t_i.items[i].variety = 0; + return; + } + for (i = 0; i < NUM_TOWN_ITEMS; i++) + if (t_i.items[i].value < 30) { + t_i.items[i].variety = 0; + return; + } + for (i = 0; i < NUM_TOWN_ITEMS; i++) + if (t_i.items[i].isMagic() == false) { + t_i.items[i].variety = 0; + return; + } + i = get_ran(1,0,NUM_TOWN_ITEMS); + t_i.items[i].variety = 0; + +} + +void set_item_flag(item_record_type *item) +{ + if ((item->is_special > 0) && (item->is_special < 65)) { + item->is_special--; + party.item_taken[c_town.town_num][item->is_special / 8] = + party.item_taken[c_town.town_num][item->is_special / 8] | s_pow(2,item->is_special % 8); + item->is_special = 0; + } +} + +short get_item(location place,short pc_num,Boolean check_container) +//short pc_num; // if 6, any +{ + short i,taken = 0; + + Boolean item_near = FALSE; + short mass_get = 1; + + for (i = 0; i < T_M; i++) + if ((c_town.monst.dudes[i].active > 0) && (c_town.monst.dudes[i].attitude == 1) + && (can_see(place,c_town.monst.dudes[i].m_loc,0) < 5)) + mass_get = 0; + + for (i = 0; i < NUM_TOWN_ITEMS; i++) + if (t_i.items[i].variety != 0) + if (((adjacent(place,t_i.items[i].item_loc) == TRUE) || + ((mass_get == 1) && (check_container == FALSE) && + ((dist(place,t_i.items[i].item_loc) <= 4) || ((is_combat()) && (which_combat_type == 0))) + && (can_see(place,t_i.items[i].item_loc,0) < 5))) + && ((t_i.items[i].isContained() == false) || (check_container == TRUE))) { + taken = 1; + + if (t_i.items[i].value < 2) + t_i.items[i].item_properties = t_i.items[i].item_properties | 1; + item_near = TRUE; + } + if (item_near == TRUE) + if (display_item(place,pc_num,mass_get,(bool) check_container) > 0) { // if true, there was a theft + for (i = 0; i < T_M; i++) + if ((c_town.monst.dudes[i].active > 0) && (c_town.monst.dudes[i].attitude % 2 != 1) + && (can_see(place,c_town.monst.dudes[i].m_loc,0) < 5)) { + make_town_hostile(); + i = T_M; + add_string_to_buf("Your crime was seen!"); + } + } + + if (pc_num != 10) { + if (taken == 0) + add_string_to_buf("Get: nothing here"); + else add_string_to_buf("Get: OK"); + } + + reset_item_max(); + + return taken; +} + +void make_town_hostile() +{ + short i,num; + Boolean fry_party = FALSE; + + if (which_combat_type == 0) + return; + give_help(53,0,0); + c_town.monst.friendly = 1; + //// + for (i = 0; i < T_M; i++) + if ((c_town.monst.dudes[i].active > 0) && (c_town.monst.dudes[i].summoned == 0)){ + c_town.monst.dudes[i].attitude = 1; + num = c_town.monst.dudes[i].number; + c_town.monst.dudes[i].mobile = TRUE; + if (scenario.scen_monsters[num].spec_skill == 37) { + c_town.monst.dudes[i].active = 2; + + // If a town, give power boost + c_town.monst.dudes[i].m_d.health *= 3; + c_town.monst.dudes[i].m_d.status[3] = 8; + c_town.monst.dudes[i].m_d.status[1] = 8; + } + } + +// In some towns, doin' this'll getcha' killed. +// wedge in special + + if (fry_party == TRUE) { + for (i = 0; i < 6; i++) + if (adven[i].main_status > MAIN_STATUS_ABSENT) + adven[i].main_status = MAIN_STATUS_ABSENT; + stat_window = 6; + boom_anim_active = FALSE; + } +} + + +void put_item_graphics() +{ + short i,storage; + + item_record_type item; + char message[256]; + + // First make sure all arrays for who can get stuff are in order. + if ((current_getting_pc < 6) && ((adven[current_getting_pc].isAlive() == false) + || (adven[current_getting_pc].hasSpace() == 24))) + { + current_getting_pc = 6; + } + for (i = 0; i < 6; i++) + if ((adven[i].isAlive()) && (adven[i].hasSpace() < 24) + && ((!is_combat()) || (current_pc == i))) { + if (current_getting_pc == 6) + current_getting_pc = i; + cd_activate_item(987,3 + i,1); + } + else { + cd_activate_item(987,3 + i,0); + cd_activate_item(987,11 + i,0); + } + for (i = 0; i < NUM_OF_PCS; i++) + if (current_getting_pc == i) + cd_add_label(987,3 + i,"* ",1007); + else cd_add_label(987,3 + i," ",1007); + + // darken arrows, as appropriate + if (first_item_shown == 0) + cd_activate_item(987,9,0); + else cd_activate_item(987,9,1); + if ((first_item_shown > total_items_gettable - 7) || + (total_items_gettable <= 8) ) + cd_activate_item(987,10,0); + else cd_activate_item(987,10,1); + + for (i = 0; i < 8; i++) { + // first, clear whatever item graphic is there + csp(987,20 + i * 4,950); + + if (item_array[i + first_item_shown] != 200) { // display an item in window + item = t_i.items[item_array[i + first_item_shown]]; + + sprintf ((char *) message, "%s", + (item.isIdent()) ? (char *) item.full_name : (char *) item.name); + csit(987,21 + i * 4,(char *) message); + if (item.graphic_num >= 150) + csp(987,20 + i * 4,3000 + 2000 + item.graphic_num - 150); + else csp(987,20 + i * 4,4800 + item.graphic_num);//// + get_item_interesting_string(item,(char *) message); + csit(987,22 + i * 4,(char *) message); + storage = item_weight(item); + sprintf ((char *) message, "Weight: %d",storage); + csit(987,53 + i,(char *) message); + + } + else { // erase the spot + sprintf ((char *) message, ""); + csit(987,21 + i * 4,(char *) message); + csit(987,22 + i * 4,(char *) message); + csit(987,53 + i,(char *) message); + } + } + + if (current_getting_pc < 6) { + i = adven[current_getting_pc].amountCanCarry(); + storage = adven[current_getting_pc].amountCarried(); + sprintf ((char *) message, "%s is carrying %d out of %d.", adven[current_getting_pc].name,storage,i); + csit(987,52,(char *) message); + } + + for (i = 0; i < 6; i++) + if (adven[i].isAlive()) { + csp(987,11 + i,800 + adven[i].which_graphic); + } +} + + +void display_item_event_filter (short item_hit) +{ + item_record_type item; + short i; + + switch (item_hit) { + case 1: + dialog_not_toast = FALSE; + break; + case 9: + if (first_item_shown > 0) + first_item_shown -= 8; + put_item_graphics(); + break; + case 10: + if (first_item_shown < 116) + first_item_shown += 8; + put_item_graphics(); + break; + case 3: case 4: case 5: case 6:case 7: case 8: + current_getting_pc = item_hit - 3; + put_item_graphics(); + break; + default: + if (current_getting_pc == 6) { + break; + } + item_hit = (item_hit - 19) / 4; + item_hit += first_item_shown; + if (item_array[item_hit] >= NUM_TOWN_ITEMS) + break; + item = t_i.items[item_array[item_hit]]; + if (item.isProperty()) + { + i = (dialog_answer == 0) ? fancy_choice_dialog(1011,987) : 2; + if (i == 1) + break; + else { + dialog_answer = 1; + item.item_properties = item.item_properties & 253; + } + } + + + if (t_i.items[item_array[item_hit]].variety == 3) { + if (t_i.items[item_array[item_hit]].item_level > 3000) + t_i.items[item_array[item_hit]].item_level = 3000; + set_item_flag(&item); + party.giveGold(t_i.items[item_array[item_hit]].item_level, false); + force_play_sound(39); + } + else if (t_i.items[item_array[item_hit]].variety == 11) { + party.giveFood(t_i.items[item_array[item_hit]].item_level, false); + set_item_flag(&item); + set_item_flag(&t_i.items[item_array[item_hit]]); + force_play_sound(62); + } + else { + if (item_weight(item) > + adven[current_getting_pc].amountCanCarry() - adven[current_getting_pc].amountCarried()) { + MessageBeep(MB_OK); + csit(987,52,"It's too heavy to carry."); + give_help(38,0,987); + break; + } + + set_item_flag(&item); + force_play_sound(0); + adven[current_getting_pc].giveToPC(item, 0); + } + t_i.items[item_array[item_hit]] = return_dummy_item(); + for (i = item_hit; i < 125; i++) + item_array[i] = item_array[i + 1]; + total_items_gettable--; + put_item_graphics(); + break; + } + +} + + +// Returns TRUE is a theft committed +short display_item(location from_loc,short pc_num, short mode, bool check_container) +//pc_num; // < 6 - this pc only 6 - any pc +//short mode; // 0 - adjacent 1 - all in sight +{ + short i,array_position = 0; + SetCursor(sword_curs); + + first_item_shown = 0; + store_get_mode = mode; + current_getting_pc = current_pc; + store_pcnum = pc_num; + dialog_answer = 0; + + for (i = 0; i < 130; i++) + item_array[i] = 200; + + total_items_gettable = 0; + for (i = 0; i < NUM_TOWN_ITEMS; i++) + if (t_i.items[i].variety != 0) { + if (((adjacent(from_loc,t_i.items[i].item_loc) == TRUE) || + ((mode == 1) && (check_container == false) && + ((dist(from_loc,t_i.items[i].item_loc) <= 4) || ((is_combat()) && (which_combat_type == 0))) + && (can_see(from_loc,t_i.items[i].item_loc,0) < 5))) && + (t_i.items[i].isContained() == check_container) && + ((check_container == false) || (same_point(t_i.items[i].item_loc,from_loc) == TRUE))) { + item_array[array_position] = i; + array_position++; + total_items_gettable++; + } + } + if (pcs_gworld == NULL) + pcs_gworld = load_pict(902,main_dc); + cd_create_dialog(987,mainPtr); + + if (check_container == true) + csit(987,17,"Looking in container:"); + else if (mode == 0) + csit(987,17,"Getting all adjacent items:"); + else csit(987,17,"Getting all nearby items:"); + cd_set_flag(987,18,1); + cd_set_flag(987,51,0); + cd_set_flag(987,52,0); + for (i = 0; i < 8; i++) + cd_attach_key(987,19 + 4 * i,(char) (97 + i)); + put_item_graphics(); + + if (party.help_received[36] == 0) { + cd_initial_draw(987); + give_help(36,37,987); + } + + while (dialog_not_toast) + ModalDialog(); + + cd_kill_dialog(987,0); + + DeleteObject(pcs_gworld); + pcs_gworld = NULL; + + put_item_screen(stat_window,0); + put_pc_screen(); + + return dialog_answer; +} + +short custom_choice_dialog(char *strs,short pic_num,short buttons[3]) //// +{ + + short i,store_dialog_answer; + + + store_dialog_answer = dialog_answer; + SetCursor(sword_curs); + + cd_create_custom_dialog(mainPtr,strs,pic_num, buttons); + + while (dialog_not_toast) + ModalDialog(); + + cd_kill_dialog(900,0); + + if (in_startup_mode == FALSE) + refresh_screen(0); + else draw_startup(0); + i = dialog_answer; + dialog_answer = store_dialog_answer; + + return i; + + } + +void fancy_choice_dialog_event_filter (short item_hit) +{ + dialog_not_toast = FALSE; + dialog_answer = item_hit; +} + +short fancy_choice_dialog(short which_dlog,short parent) +// ignore parent in Mac version +{ + short i,store_dialog_answer; + char temp_str[256]; + + store_dialog_answer = dialog_answer; + SetCursor(sword_curs); + + cd_create_dialog_parent_num(which_dlog,parent); + + if (which_dlog == 1062) { + i = get_ran(1,0,12); + GetIndString(temp_str,11,10 + i); + csit(1062,10,(char *) temp_str); + } + while (dialog_not_toast) + ModalDialog(); + + cd_kill_dialog(which_dlog,0); + + if (parent < 2) { + if (in_startup_mode == FALSE) + refresh_screen(0); + else draw_startup(0); + } + i = dialog_answer; + dialog_answer = store_dialog_answer; + + return i; +} + +void select_pc_event_filter (short item_hit) +{ + dialog_not_toast = FALSE; + if (item_hit == 16) + dialog_answer = 6; + else dialog_answer = item_hit - 3; +} + +short char_select_pc(short active_only,short free_inv_only,char *title) +//active_only; // 0 - no 1 - yes 2 - disarm trap +{ + short i; + + SetCursor(sword_curs); + + cd_create_dialog(1018,mainPtr); + + if (active_only == 2) + csit(1018,15,"Select PC to disarm trap:"); + else csit( 1018,15,title); + + for (i = 0; i < 6; i++) { + if ((adven[i].main_status == MAIN_STATUS_ABSENT) || + ((active_only == TRUE) && (adven[i].main_status > MAIN_STATUS_ALIVE)) || + ((free_inv_only == 1) && (adven[i].hasSpace() == 24)) || + (adven[i].main_status == MAIN_STATUS_FLED)) { + cd_activate_item(1018, 3 + i, 0); + } + if (adven[i].main_status != MAIN_STATUS_ABSENT) { + csit(1018,9 + i,adven[i].name); + } + else cd_activate_item(1018, 9 + i, 0); + } + + while (dialog_not_toast) + ModalDialog(); + cd_kill_dialog(1018,0); + + if (in_startup_mode == FALSE) + refresh_screen(0); + else draw_startup(0); + + return dialog_answer; +} + +short select_pc(short active_only,short free_inv_only) +//active_only; // 0 - no 1 - yes 2 - disarm trap +{ + if (active_only == 2) + return char_select_pc(active_only,free_inv_only,"Trap! Who will disarm?"); + else return char_select_pc(active_only,free_inv_only,"Select a character:"); +} + +void get_num_of_items_event_filter (short) +{ + char get_text[256]; + + cd_get_text_edit_str(1012,(char *) get_text); + dialog_answer = 0; + sscanf((char *) get_text,"%d",&dialog_answer); + dialog_not_toast = FALSE; +} + +short get_num_of_items(short max_num) +//town_num; // Will be 0 - 200 for town, 200 - 290 for outdoors +//short sign_type; // terrain type +{ + char sign_text[256]; + + SetCursor(sword_curs); + + cd_create_dialog(1012,mainPtr); + + sprintf((char *) sign_text,"How many? (0-%d) ",max_num); + csit(1012,4,(char *)sign_text); + sprintf((char *) sign_text,"%d",max_num); + cd_set_text_edit_str(1012,(char *) sign_text); + cd_set_edit_focus(); + + while (dialog_not_toast) + ModalDialog(); + cd_kill_dialog(1012,0); + + dialog_answer = minmax(0,(int)max_num,dialog_answer); + + return dialog_answer; +} + +void make_cursor_watch() +{ + SetCursor(LoadCursor(NULL,IDC_WAIT)); + ShowCursor(TRUE); +} + +void place_glands(location where,unsigned char m_type) +{ + item_record_type store_i; + monster_record_type monst; + + monst = return_monster_template(m_type); + + if ((monst.corpse_item >= 0) && (monst.corpse_item < 400) && (get_ran(1,1,100) <= monst.corpse_item_chance)) { + store_i = get_stored_item(monst.corpse_item); + place_item(store_i,where,FALSE); + } +} + +short pc_array::getTotalLevel() +{ + short i, j = 0; + + for (i = 0; i < NUM_OF_PCS; i++) + if (pc[i].isAlive()) + j += pc[i].level; + return j; +} + +void reset_item_max() +{ + short i; + + for (i = 0; i < NUM_TOWN_ITEMS; i++) + if (t_i.items[i].variety != 0) + item_max = i + 1; +} + +short item_val(item_record_type item) +{ + if (item.charges == 0) + return item.value; + return item.charges * item.value; +} + +void place_treasure(location where,short level,short loot,short mode) +//short mode; // 0 - normal, 1 - force +{ + + item_record_type new_item; + short amt,r1,i,j; + short treas_chart[5][6] = {{0,-1,-1,-1,-1,-1}, + {1,-1,-1,-1,-1,-1}, + {2,1,1,-1,-1,-1}, + {3,2,1,1,-1,-1}, + {4,3,2,2,1,1}}; + short treas_odds[5][6] = {{10,0,0,0,0,0}, + {50,0,0,0,0,0}, + {60,50,40,0,0,0}, + {100,90,80,70,0,0}, + {100,80,80,75,75,75}}; + short id_odds[21] = {0,10,15,20,25,30,35,39,43,47, + 51,55,59,63,67,71,73,75,77,79,81}; + short max_mult[5][10] = {{0,0,0,0,0,0,0,0,0,1}, + {0,0,1,1,1,1,2,3,5,20}, + {0,0,1,1,2,2,4,6,10,25}, + {5,10,10,10,15,20,40,80,100,100}, + {25,25,50,50,50,100,100,100,100,100}}; + short min_chart[5][10] = {{0,0,0,0,0,0,0,0,0,1}, + {0,0,0,0,0,0,0,0,5,20}, + {0,0,0,0,1,1,5,10,15,40}, + {10,10,15,20,20,30,40,50,75,100}, + {50,100,100,100,100,200,200,200,200,200}}; + short max,min; + + if (loot == 1) + amt = get_ran(2,1,7) + 1; + else amt = loot * (get_ran(1,0,10 + (loot * 6) + (level * 2)) + 5); + + if (adven.getTotalLevel() <= 12) + amt += 1; + if ((adven.getTotalLevel() <= 60) && (amt > 2)) + amt += 2; + + if (amt > 3) { + new_item = get_stored_item(0); + new_item.item_level = amt; + r1 = get_ran(1,1,9); + if (((loot > 1) && (r1 < 7)) || ((loot == 1) && (r1 < 5)) || (mode == 1) + || ((r1 < 6) && (adven.getTotalLevel() < 30)) || (loot > 2) ) + place_item(new_item,where,FALSE); + } + for (j = 0; j < 5; j++) { + r1 = get_ran(1,0,100); + if ((treas_chart[loot][j] >= 0) && (r1 <= treas_odds[loot][j] + adven.getTotalLuck())) { + r1 = get_ran(1,0,9); + min = min_chart[treas_chart[loot][j]][r1]; + r1 = get_ran(1,0,9); + max = (min + level + (2 * (loot - 1)) + (adven.getTotalLuck() / 3)) * max_mult[treas_chart[loot][j]][r1]; + if (get_ran(1,0,1000) == 500) { + max = 10000; + min = 100; + } + + // reality check + if ((loot == 1) && (max > 100) && (get_ran(1,0,8) < 7)) + max = 100; + if ((loot == 2) && (max > 200) && (get_ran(1,0,8) < 6)) + max = 200; + + + new_item = return_treasure(treas_chart[loot][j],level,mode); + if ((item_val(new_item) < min) || (item_val(new_item) > max)) { + new_item = return_treasure(treas_chart[loot][j],level,mode); + if ((item_val(new_item) < min) || (item_val(new_item) > max)) { + new_item = return_treasure(treas_chart[loot][j],level,mode); + if (item_val(new_item) > max) + new_item.variety = 0; + } + } + + // not many magic items + if (mode == 0) { + if (new_item.isMagic() && (level < 2) && (get_ran(1,0,5) < 3)) + new_item.variety = 0; + if (new_item.isMagic() && (level == 2) && (get_ran(1,0,5) < 2)) + new_item.variety = 0; + if (new_item.isCursed() && (get_ran(1,0,5) < 3)) + new_item.variety = 0; + } + + // if forced, keep dipping until a treasure comes uo + if ((mode == 1) && (max >= 20)) { + do + new_item = return_treasure(treas_chart[loot][j],level,mode); + while ((new_item.variety == 0) || (item_val(new_item) > max)); + } + + // Not many cursed items + if (new_item.isCursed() && (get_ran(1,0,2) == 1)) + new_item.variety = 0; + + if (new_item.variety != 0) { + for (i = 0; i < 6; i++) + if ((adven[i].isAlive()) + && (get_ran(1,0,100) < id_odds[adven[i].skills[13]])) + new_item.item_properties = new_item.item_properties | 1; + place_item(new_item,where,FALSE); + } + } + } + +} + +short pc_array::getTotalLuck() +{ + short i = 0; + + for (i = 0; i < NUM_OF_PCS; i++) + if (pc[i].isAlive()) + i += pc[i].skills[SKILL_LUCK]; + + return i; +} + +void get_text_response_event_filter (short) +{ + cd_get_text_edit_str(store_dnum,(char *) store_str); + dialog_not_toast = FALSE; +} + +item_record_type return_treasure(short loot,short,short) +{ + item_record_type treas; + short which_treas_chart[48] = {1,1,1,1,1,2,2,2,2,2, + 3,3,3,3,3,2,2,2,4,4, + 4,4,5,5,5,6,6,6,7,7, + 7,8,8,9,9,10,11,12,12,13, + 13,14, 9,10,11,9,10,11}; + short r1; + + treas.variety = 0; + r1 = get_ran(1,0,41); + if (loot >= 3) r1 += 3; + switch (which_treas_chart[r1]) { + case 1: treas = get_food(); break; + case 2: treas = get_weapon(loot); break; + case 3: treas = get_armor(loot); break; + case 4: treas = get_shield(loot); break; + case 5: treas = get_helm(loot); break; + case 6: treas = get_missile(loot); break; + case 7: treas = get_potion(loot); break; + case 8: treas = get_scroll(loot); break; + case 9: treas = get_wand(loot); break; + case 10: treas = get_ring(loot); break; + case 11: treas = get_necklace(loot); break; + case 12: treas = get_poison(loot); break; + case 13: treas = get_gloves(loot); break; + case 14: treas = get_boots(loot); break; + } + if (treas.variety == 0) treas.value = 0; + return treas; + +} + + +void refresh_store_items() +{ + short i,j; + short loot_index[10] = {1,1,1,1,2,2,2,3,3,4}; + + for (i = 0; i < 5; i++) + for (j = 0; j < 10; j++) { + party.magic_store_items[i][j] = return_treasure(loot_index[j],7,1); + if ((party.magic_store_items[i][j].variety == 3) || + (party.magic_store_items[i][j].variety == 11)) + party.magic_store_items[i][j] = return_dummy_item(); + party.magic_store_items[i][j].item_properties = + party.magic_store_items[i][j].item_properties | 1; + } +} + +void get_text_response(short dlg,char *str,short parent_num) +{ + short i; + + SetCursor(sword_curs); + + store_str = (char *) str; + store_dnum = dlg; + + cd_create_dialog_parent_num(dlg,parent_num); + cd_set_edit_focus(); + + while (dialog_not_toast) + ModalDialog(); + for (i = 0; i < 15; i++) + if ((str[i] > 64) && (str[i] < 91)) + str[i] = str[i] + 32; + + final_process_dialog(dlg); +} + +// returns true is party has item of given item class +// mode - 0 - take one of them, 1 - don't take +bool pc_array::checkClass(short item_class, short mode) +{ + short i,j; + + if (item_class == 0) + return false; + for (i = 0; i < NUM_OF_PCS; i++) + if (pc[i].isAlive()) + for (j = 23; j >= 0; j--) + if ((pc[i].items[j].variety > 0) && (pc[i].items[j].special_class == item_class)) { + if (mode == 0) { + if (pc[i].items[j].charges > 1) + pc[i].items[j].charges--; + else pc[i].takeItem(j); + } + return true; + } + return false; +} diff --git a/Win32/Blades of Exile/ITEMS.H b/Win32/Blades of Exile/ITEMS.H new file mode 100644 index 00000000..ffdf627b --- /dev/null +++ b/Win32/Blades of Exile/ITEMS.H @@ -0,0 +1,40 @@ +#ifndef _ITEMS_H + #define _ITEMS_H + +#include "location.h" +#include "item.h" +#include "global.h" + +Boolean give_to_party(item_record_type item,short print_result); +Boolean forced_give(short item_num,short abil); +Boolean party_take_abil(short abil); +short item_weight(item_record_type item); +Boolean place_item(item_record_type item,location where,Boolean forced); +void destroy_an_item(); +void set_item_flag(item_record_type *item); +short get_item(location place,short pc_num,Boolean check_container); +void put_item_graphics(); +void make_town_hostile(); +void display_item_event_filter (short item_hit); +short display_item(location from_loc,short pc_num,short mode, bool check_container); +void fancy_choice_dialog_event_filter (short item_hit); +short fancy_choice_dialog(short which_dlog,short parent); +void select_pc_event_filter (short item_hit); +short char_select_pc(short active_only,short free_inv_only,char *title); +short select_pc(short active_only,short free_inv_only); +void get_num_of_items_event_filter (short item_hit); +short get_num_of_items(short max_num); +short choice_dialog(short pic,short num); +void make_cursor_watch() ; +void place_glands(location where,unsigned char m_type); +void reset_item_max(); +short item_val(item_record_type item); +void place_treasure(location where,short level,short loot,short mode); +item_record_type return_treasure(short loot,short level,short mode); +void frame_button(RECT button_rect); +void refresh_store_items(); +void get_text_response_event_filter (short item_hit); +void get_text_response(short dlg,char *str,short parent_num); +short custom_choice_dialog(char *strs,short pic_num,short buttons[3]) ; + +#endif diff --git a/Win32/Blades of Exile/LOCATION.CPP b/Win32/Blades of Exile/LOCATION.CPP new file mode 100644 index 00000000..d2dd9301 --- /dev/null +++ b/Win32/Blades of Exile/LOCATION.CPP @@ -0,0 +1,167 @@ +#include "location.h" // location +#include "exlsound.h" // play_sound +#include "blades.h" // out +#include "text.h" // add_string_to_buf +#include "locutils.h" // alter_space +#include "items.h" // fancy_choice_dialog + +#include "global.h" +#include "globvar.h" + +location location::toGlobal() +{ + //return local_to_global(*this); + + location global = *this; + if (party.i_w_c.x == 1) global.x = global.x + 48; + if (party.i_w_c.y == 1) global.y = global.y + 48; + return global; +} + +location location::toLocal() +{ +// return global_to_local(*this); + + location local = (*this); + if (party.i_w_c.x == 1) local.x = local.x - 48; + if (party.i_w_c.y == 1) local.y = local.y - 48; + return local; +} + +short location::countWalls() const +{ + unsigned char walls[31] = {5,6,7,8,9, 10,11,12,13,14, 15,16,17,18,19, 20,21,22,23,24, + 25,26,27,28,29, 30,31,32,33,34, 35}; + short answer = 0; + short k = 0; + + for (k = 0; k < 31 ; k++) + { + if (out[x + 1][y] == walls[k]) answer++; + if (out[x - 1][y] == walls[k]) answer++; + if (out[x][y + 1] == walls[k]) answer++; + if (out[x][y - 1] == walls[k]) answer++; + } + return answer; +} + +// 0 if no pull. +// 1 if in right position now. +// 2 if in left position +// levers should always start to left. +short location::handleLever() +{ + if (FCD(1020,0) == 1) return 0; + play_sound(94); + alter_space(x,y,scenario.ter_types[t_d.terrain[x][y]].trans_to_what); + return 1; +} + +void location::crumbleWall() +{ + unsigned char ter; + + if (loc_off_act_area(*this) == TRUE) + return; + ter = t_d.terrain[x][y]; + if (scenario.ter_types[ter].special == 7) { + play_sound(60); + t_d.terrain[x][y] = scenario.ter_types[ter].flag1; + if(scenario.ter_types[scenario.ter_types[ter].flag1].special >= 16 && scenario.ter_types[scenario.ter_types[ter].flag1].special <=19) + belt_present = TRUE; + add_string_to_buf(" Barrier crumbles."); + } +} + +bool location::isDoor() const +{ + if ((scenario.ter_types[t_d.terrain[x][y]].special == 9) || + (scenario.ter_types[t_d.terrain[x][y]].special == 1) || + (scenario.ter_types[t_d.terrain[x][y]].special == 10)) + return true; + return false; +} + +//void pick_lock(location where,short pc_num) +void location::pickLock(short pc_num) +{ + unsigned char terrain; + short r1,which_item; + Boolean will_break = FALSE; + short unlock_adjust; + + terrain = t_d.terrain[x][y]; + which_item = adven[pc_num].hasAbilEquip(161); + if (which_item == 24) { + add_string_to_buf(" Need lockpick equipped. "); + return; + } + + r1 = get_ran(1,0,100) + adven[pc_num].items[which_item].ability_strength * 7; + + if (r1 < 75) + will_break = TRUE; + + r1 = get_ran(1,0,100) - 5 * adven[pc_num].statAdj(1) + c_town.difficulty * 7 + - 5 * adven[pc_num].skills[15] - adven[pc_num].items[which_item].ability_strength * 7; + + // Nimble? + if (adven[pc_num].traits[TRAIT_NIMBLE] == TRUE) r1 -= 8; + + if (adven[pc_num].hasAbilEquip(42) < 24) + r1 = r1 - 12; + + if ((scenario.ter_types[terrain].special < 9) || (scenario.ter_types[terrain].special > 10)) { + add_string_to_buf(" Wrong terrain type. "); + return; + } + unlock_adjust = scenario.ter_types[terrain].flag2; + if ((unlock_adjust >= 5) || (r1 > (unlock_adjust * 15 + 30))) { + add_string_to_buf(" Didn't work. "); + if (will_break == TRUE) + { + add_string_to_buf(" Pick breaks. "); + adven[pc_num].removeCharge(which_item); + } + play_sound(41); + } + else { + add_string_to_buf(" Door unlocked. "); + play_sound(9); + t_d.terrain[x][y] = scenario.ter_types[terrain].flag1; + if(scenario.ter_types[scenario.ter_types[terrain].flag1].special >= 16 && scenario.ter_types[scenario.ter_types[terrain].flag1].special <=19) + belt_present = TRUE; + } +} + +//void bash_door(location where,short pc_num) +void location::bashDoor(short pc_num) +{ + unsigned char terrain; + short r1,unlock_adjust; + + terrain = t_d.terrain[x][y]; + r1 = get_ran(1,0,100) - 15 * adven[pc_num].statAdj(0) + c_town.difficulty * 4; + + if ((scenario.ter_types[terrain].special < 9) || (scenario.ter_types[terrain].special > 10)) + { + add_string_to_buf(" Wrong terrain type. "); + return; + } + + unlock_adjust = scenario.ter_types[terrain].flag2; + + if ((unlock_adjust >= 5) || (r1 > (unlock_adjust * 15 + 40)) || (scenario.ter_types[terrain].special != 10)) + { + add_string_to_buf(" Didn't work. "); + adven[pc_num].damage(get_ran(1,1,4),4,-1); + } + else + { + add_string_to_buf(" Lock breaks. "); + play_sound(9); + t_d.terrain[x][y] = scenario.ter_types[terrain].flag1; + if(scenario.ter_types[scenario.ter_types[terrain].flag1].special >= 16 && scenario.ter_types[scenario.ter_types[terrain].flag1].special <=19) + belt_present = TRUE; + } +} diff --git a/Win32/Blades of Exile/LOCATION.H b/Win32/Blades of Exile/LOCATION.H new file mode 100644 index 00000000..f4224bc6 --- /dev/null +++ b/Win32/Blades of Exile/LOCATION.H @@ -0,0 +1,24 @@ +#ifndef _LOCATION_H + #define _LOCATION_H + +struct location +{ + char x, y; + + /* functions */ + location() : x(0), y(0) { } + location(int ix, int iy) { x = ix; y = iy; } + location toGlobal(); /* convert local coordinates to global*/ + location toLocal(); /* convert global coordinates to local*/ + location randomShift(); + + short countWalls() const; /* count number of walls around */ + short handleLever(); /* call dialog and eventually pull lever */ + void crumbleWall(); + bool isDoor() const; + + void pickLock(short pcNum); + void bashDoor(short pcNum); +}; + +#endif diff --git a/Win32/Blades of Exile/LOCUTILS.CPP b/Win32/Blades of Exile/LOCUTILS.CPP new file mode 100644 index 00000000..c905f0a4 --- /dev/null +++ b/Win32/Blades of Exile/LOCUTILS.CPP @@ -0,0 +1,673 @@ +#include +#include "math.h" +#include "global.h" +#include "locutils.h" +#include "text.h" +#include "monster.h" +#include "fields.h" + +#include "globvar.h" + +short dist(location p1,location p2) +{ + return (short) sqrt((double)((p1.x - p2.x) * (p1.x - p2.x) + + (p1.y - p2.y) * (p1.y - p2.y))); +} + +short vdist(location p1,location p2) { + short i,j; + i = ex_abs((short) (p1.x - p2.x)); j = ex_abs((short) (p1.y - p2.y)); + return max(i,j); +} + +Boolean adjacent(location p1,location p2) +{ + if ((ex_abs((short) (p1.x - p2.x)) <= 1) && (ex_abs((short) (p1.y - p2.y)) <= 1)) + return TRUE; + else return FALSE; +} + +Boolean point_onscreen(location center,location check) +{ + if ((ex_abs((short) (center.x - check.x)) <=4) && (ex_abs((short) (center.y - check.y)) <= 4)) + return TRUE; + else return FALSE; +} + + +short set_direction (location old_pt, location new_pt) +{ + if (old_pt.x == new_pt.x) + if (old_pt.y > new_pt.y) + return 0; + else return 4; + if (old_pt.x > new_pt.x) { + if (old_pt.y > new_pt.y) + return 7; + if (old_pt.y < new_pt.y) + return 5; + return 6; + } + if (old_pt.y > new_pt.y) + return 1; + if (old_pt.y < new_pt.y) + return 3; + return 2; +} + +Boolean loc_off_world(location p1) +{ + if ((p1.x < 0) || (p1.x > town_size[town_type]) || (p1.y < 0) || (p1.y > town_size[town_type])) + return TRUE; + else return FALSE; +} + +Boolean loc_off_act_area(location p1) +{ + if ((p1.x > c_town.town.in_town_rect.left) && (p1.x < c_town.town.in_town_rect.right) && + (p1.y > c_town.town.in_town_rect.top) && (p1.y < c_town.town.in_town_rect.bottom)) + return FALSE; + return TRUE; +} + +location get_cur_loc() +{ + switch (overall_mode) { + case MODE_OUTDOORS: case 35: + return party.p_loc; + break; + + case MODE_TOWN: case 2: case 3: case 4: case 36: + return c_town.p_loc; + break; + + default: + return pc_pos[current_pc]; + break; + } +} + +short short_can_see(shortloc p1,shortloc p2) +{ + location s1,s2; + + s1.x = (char) p1.x; + s1.y = (char) p1.y; + s2.x = (char) p2.x; + s2.y = (char) p2.y; + return (can_see(s1,s2,0)); +} + +Boolean is_lava(short x,short y)//// +{ + unsigned char ter = coord_to_ter(x,y); + if (scenario.ter_types[ter].picture == 404) + return TRUE; + else return FALSE; +} + + +short can_see(location p1,location p2,short mode) +//short mode; // 0 - normal 1 - counts 1 for blocked spaces or lava (used for party placement in + // town combat) + // 2 - no light check +{ + short dx,dy,count,storage = 0; + + if (is_combat()) { // Light check + if ((mode != 2) && (combat_pt_in_light(p2) == FALSE)) { + return 6; + } + } + else { + if ((mode != 2) && (pt_in_light(p1,p2) == FALSE)) { + return 6; + } + } + + if (p1.y == p2.y) { + if (p1.x > p2.x) { + for (count = p2.x + 1; count < p1.x; count++) { + storage = storage + get_obscurity(count, p1.y); + if (((terrain_blocked[coord_to_ter(count,p1.y)] > 2) || (is_lava(count,p1.y) == TRUE)) && (mode == 1)) + return 5; + } + } + else { + for (count = p1.x + 1; count < p2.x; count++) { + + storage = storage + get_obscurity(count, p1.y); + if (((terrain_blocked[coord_to_ter(count,p1.y)] > 2) || (is_lava(count,p1.y) == TRUE)) && (mode == 1)) + return 5; + } + } + return storage; + } + if (p1.x == p2.x) { + if (p1.y > p2.y) { + for (count = p1.y - 1; count > p2.y; count--) { + storage = storage + get_obscurity(p1.x, count); + if (((terrain_blocked[coord_to_ter(p1.x,count)] > 2) || (is_lava(p1.x,count) == TRUE)) && (mode == 1)) + return 5; + } + } + else { + for (count = p1.y + 1; count < p2.y; count++) { + storage = storage + get_obscurity(p1.x, count); + if (((terrain_blocked[coord_to_ter(p1.x,count)] > 2) || (is_lava(p1.x,count) == TRUE)) && (mode == 1)) + return 5; + } + } + return storage; + } + dx = p2.x - p1.x; + dy = p2.y - p1.y; + + if (ex_abs(dy) > ex_abs(dx)) { + if (p2.y > p1.y) { + for (count = 1; count < dy; count++) { + storage = storage + get_obscurity(p1.x + (count * dx) / dy, p1.y + count); + if ( ((terrain_blocked[coord_to_ter(p1.x + (count * dx) / dy,p1.y + count)] > 2) || + (is_lava(p1.x + (count * dx) / dy,p1.y + count) == TRUE)) + && (mode == 1)) + return 5; + } + } + else { + for (count = -1; count > dy; count--) { + storage = storage + get_obscurity(p1.x + (count * dx) / dy, p1.y + count); + if ( ((terrain_blocked[coord_to_ter(p1.x + (count * dx) / dy, p1.y + count)] > 2) || + (is_lava(p1.x + (count * dx) / dy, p1.y + count) == TRUE)) + && (mode == 1)) + return 5; + } + } + return storage; + } + if (ex_abs(dy) <= ex_abs(dx)) { + if (p2.x > p1.x) { + for (count = 1; count < dx; count++) { + storage = storage + get_obscurity(p1.x + count, p1.y + (count * dy) / dx); + if (((terrain_blocked[coord_to_ter(p1.x + count,p1.y + (count * dy) / dx)] > 2) || + (is_lava(p1.x + count,p1.y + (count * dy) / dx) == TRUE)) + && (mode == 1)) + return 5; + } + } + else { + for (count = -1; count > dx; count--) { + storage = storage + get_obscurity(p1.x + count, p1.y + (count * dy) / dx); + if ( ((terrain_blocked[coord_to_ter(p1.x + count,p1.y + (count * dy) / dx)] > 2) || + (is_lava(p1.x + count,p1.y + (count * dy) / dx) == TRUE)) + && (mode == 1)) + return 5; + } + } + return storage; + } + if (storage > 5) + return 5; + else return storage; +} + +short get_obscurity(short x,short y) +{ + unsigned char what_terrain; + short store; + + what_terrain = coord_to_ter(x,y); + + if ((what_terrain >= 237) && (what_terrain <= 242)) + return 1; + + store = get_blockage(what_terrain); + + if (is_town()) + if (special(x,y)) store++; + + if ((is_town()) || (is_combat())) + { + if (is_web(x,y)) store += 2; + if ((is_fire_barrier(x,y)) || (is_force_barrier(x,y))) return 5; + if ((is_crate(x,y)) || (is_barrel(x,y)))store++; + } + return store; +} + +unsigned char coord_to_ter(short x,short y) +{ + char what_terrain; + + if ((overall_mode == MODE_OUTDOORS) || (overall_mode == 35)) what_terrain = out[x][y]; + else if (((overall_mode > MODE_OUTDOORS) && (overall_mode < MODE_COMBAT))|| (overall_mode == 36)) + what_terrain = t_d.terrain[x][y]; + else what_terrain = combat_terrain[x][y]; + return what_terrain; +} + + +Boolean is_container(location loc) +{ + unsigned char ter; + + if ((is_barrel(loc.x,loc.y)) || (is_crate(loc.x,loc.y))) return TRUE; + ter = coord_to_ter(loc.x,loc.y); + if (scenario.ter_types[ter].special == 14) return TRUE; + return FALSE; +} + +void update_explored(location dest) +{ + shortloc shortdest,look; + + location look2; + + shortdest.x = (short) dest.x; + shortdest.y = (short) dest.y; + + which_party_sec.x = party.outdoor_corner.x + party.i_w_c.x; + which_party_sec.y = party.outdoor_corner.y + party.i_w_c.y; + + if (overall_mode == MODE_OUTDOORS) { + out_e[dest.x][dest.y] = 2; + for (look.x = shortdest.x - 4; look.x < shortdest.x + 5; look.x++) + for (look.y = shortdest.y - 4; look.y < shortdest.y + 5; look.y++) { + if ((look.x == minmax(0,95,(int)look.x)) && (look.y == minmax(0,95,(int)look.y))) { + if (out_e[look.x][look.y] == 0) + if (short_can_see(shortdest, look) < 5) + out_e[look.x][look.y] = 1; + } + } + + + } + + if (overall_mode > MODE_OUTDOORS) { + make_explored(dest.x,dest.y); + for (look2.x = max(0,dest.x - 4); look2.x < min(town_size[town_type],dest.x + 5); look2.x++) + for (look2.y = max(0,dest.y - 4); look2.y < min(town_size[town_type],dest.y + 5); look2.y++) + if (is_explored(look2.x,look2.y) == FALSE) + if ((can_see(dest, look2,0) < 5) && (pt_in_light(dest,look2) == TRUE)) + make_explored(look2.x,look2.y); + } +} + + +// All purpose function to check is spot is free for travel into. +Boolean is_blocked(location to_check) +{ + short i,gr; + unsigned char ter; + + if (is_out()) { + if (impassable(out[to_check.x][to_check.y]) == TRUE) { + return TRUE; + } + if (same_point (to_check,party.p_loc) == TRUE) + return TRUE; + for (i = 0; i < 20; i++) + if ((party.out_c[i].exists) == TRUE) + if (same_point(party.out_c[i].m_loc, to_check) == TRUE) + return TRUE; + return FALSE; + } + + if ((is_town()) || (is_combat())) { + ter = (is_town()) ? t_d.terrain[to_check.x][to_check.y] : combat_terrain[to_check.x][to_check.y]; + gr = scenario.ter_types[ter].picture; + + // Terrain blocking? + if (impassable(ter) == TRUE) { + return TRUE; + } + + // Keep away from marked specials during combat + if ((is_combat()) && (gr <= 212) && (gr >= 207)) + return TRUE; + if ((is_combat()) && (gr == 406)) + return TRUE; + + // Party there? + if (is_town()) + if (same_point (to_check,c_town.p_loc) == TRUE) + return TRUE; + if (is_combat()) + for (i = 0; i < 6; i++) + if ((adven[i].isAlive()) && (same_point (to_check,pc_pos[i]) == TRUE)) + return TRUE; + + // Monster there? + if (monst_there(to_check) < 90) + return TRUE; + + // Magic barrier? + if (is_force_barrier(to_check.x,to_check.y)) + return TRUE; + + return FALSE; + } + return TRUE; +} + +Boolean monst_on_space(location loc,short m_num) +{ + if (c_town.monst.dudes[m_num].active == 0) + return FALSE; + if ((loc.x - c_town.monst.dudes[m_num].m_loc.x >= 0) && + (loc.x - c_town.monst.dudes[m_num].m_loc.x <= c_town.monst.dudes[m_num].m_d.x_width - 1) && + (loc.y - c_town.monst.dudes[m_num].m_loc.y >= 0) && + (loc.y - c_town.monst.dudes[m_num].m_loc.y <= c_town.monst.dudes[m_num].m_d.y_width - 1)) + return TRUE; + return FALSE; + +} +short monst_there(location where) // returns 90 if no +{ + short i; + + for (i = 0; i < T_M; i++) + if ((c_town.monst.dudes[i].active != 0) && (monst_on_space(where,i) == TRUE)) + return i; + return 90; +} +Boolean monst_can_be_there(location loc,short m_num) +{ + short i,j; + location destination; + + // First clear monst away so it doesn't block itself + c_town.monst.dudes[m_num].m_loc.x += 100; + + for (i = 0; i < c_town.monst.dudes[m_num].m_d.x_width; i++) + for (j = 0; j < c_town.monst.dudes[m_num].m_d.y_width; j++) { + destination.x = loc.x + i; destination.y = loc.y + j; + if ((is_blocked(destination) == TRUE) + || (loc_off_act_area(destination) == TRUE)) { + c_town.monst.dudes[m_num].m_loc.x -= 100; + return FALSE; + } + } + c_town.monst.dudes[m_num].m_loc.x -= 100; + return TRUE; +} + +Boolean monst_adjacent(location loc,short m_num) +{ + short i,j; + location destination; + + for (i = 0; i < c_town.monst.dudes[m_num].m_d.x_width; i++) + for (j = 0; j < c_town.monst.dudes[m_num].m_d.y_width; j++) { + destination.x = c_town.monst.dudes[m_num].m_loc.x + i; + destination.y = c_town.monst.dudes[m_num].m_loc.y + j; + if (adjacent(destination,loc) == TRUE) + return TRUE; + } + return FALSE; +} + +Boolean monst_can_see(short m_num,location l) +{ + short i,j; + location destination; + + for (i = 0; i < c_town.monst.dudes[m_num].m_d.x_width; i++) + for (j = 0; j < c_town.monst.dudes[m_num].m_d.y_width; j++) { + destination.x = c_town.monst.dudes[m_num].m_loc.x + i; + destination.y = c_town.monst.dudes[m_num].m_loc.y + j; + if (can_see(destination,l,0) < 5) + return TRUE; + } + return FALSE; +} + +Boolean party_can_see_monst(short m_num) +{ + short i,j; + location destination; + + for (i = 0; i < c_town.monst.dudes[m_num].m_d.x_width; i++) + for (j = 0; j < c_town.monst.dudes[m_num].m_d.y_width; j++) { + destination.x = c_town.monst.dudes[m_num].m_loc.x + i; + destination.y = c_town.monst.dudes[m_num].m_loc.y + j; + if (party_can_see(destination) < 6) + return TRUE; + } + return FALSE; +} + +Boolean can_see_monst(location l,short m_num) +{ + short i,j; + location destination; + + for (i = 0; i < c_town.monst.dudes[m_num].m_d.x_width; i++) + for (j = 0; j < c_town.monst.dudes[m_num].m_d.y_width; j++) { + destination.x = c_town.monst.dudes[m_num].m_loc.x + i; + destination.y = c_town.monst.dudes[m_num].m_loc.y + j; + if (can_see(l,destination,0) < 5) + return TRUE; + } + return FALSE; +} + +Boolean outd_is_blocked(location to_check) +{ + short i; + + if (overall_mode == MODE_OUTDOORS) { + if (impassable(out[to_check.x][to_check.y]) == TRUE) { + return TRUE; + } + for (i = 0; i < 10; i++) + if ((party.out_c[i].exists) == TRUE) + if (same_point(party.out_c[i].m_loc, to_check) == TRUE) + return TRUE; + return FALSE; + } +return FALSE; +} + +// Checks if space is a special that prevents movement into or placement of a PC on +Boolean is_special(location to_check) +{ + unsigned char which_ter; + + if (terrain_blocked[coord_to_ter(to_check.x,to_check.y)] == 2) + return FALSE; + which_ter = coord_to_ter(to_check.x,to_check.y); + if (terrain_blocked[which_ter] == 2) + return TRUE; + else return FALSE; +} + +Boolean outd_is_special(location to_check) +{ + if (overall_mode == MODE_OUTDOORS) { + if (terrain_blocked[out[to_check.x][to_check.y]] == 2) { + return TRUE; + } + else return FALSE; + } + return FALSE; +} + +Boolean impassable(unsigned char terrain_to_check) +{ + if (terrain_blocked[terrain_to_check] > 2) + return TRUE; + else return FALSE; +} + +short get_blockage(unsigned char terrain_type) +{ + // little kludgy in here for pits + if ((terrain_type == 90) && (is_combat()) && (which_combat_type == 0)) + return 5; + if ((terrain_blocked[terrain_type] == 5) || (terrain_blocked[terrain_type] == 1)) + return 5; + else if (terrain_blocked[terrain_type] > 3) + return 1; + else { + return 0; + } +} + + + +short light_radius() +{ + short store = 1,i; + short extra_levels[6] = {10,20,50,75,110,140}; + + if (((which_combat_type == 0) && (is_combat())) + || (is_out()) || (c_town.town.lighting == 0)) + return 200; + for (i = 0; i < 6; i++) + if (party.light_level > extra_levels[i]) + store++; + return store; +} + +Boolean pt_in_light(location from_where,location to_where) // Assumes, of course, in town or combat +{ + if (c_town.town.lighting == 0) + return TRUE; + if ((to_where.x < 0) || (to_where.x >= town_size[town_type]) + || (to_where.y < 0) || (to_where.y >= town_size[town_type])) + return TRUE; + if (t_d.lighting[to_where.x / 8][to_where.y] & (char) (s_pow(2,to_where.x % 8))) + return TRUE; + + if (dist(from_where,to_where) <= light_radius()) + return TRUE; + + return FALSE; +} + +Boolean combat_pt_in_light(location to_where) +{ + short i, rad; + + if ((c_town.town.lighting == 0) || (which_combat_type == 0)) + return TRUE; + if ((to_where.x < 0) || (to_where.x >= town_size[town_type]) + || (to_where.y < 0) || (to_where.y >= town_size[town_type])) + return TRUE; + if (t_d.lighting[to_where.x / 8][to_where.y] & (char) (s_pow(2,to_where.x % 8))) + return TRUE; + + rad = light_radius(); + for (i = 0; i < 6; i++) + if (adven[i].isAlive()) { + if (dist(pc_pos[i],to_where) <= rad) + return TRUE; + } + + return FALSE; +} + +Boolean party_sees_a_monst() // Returns true is a hostile monster is in sight. +{ + short i; + + for (i = 0; i < T_M; i++) { + if (c_town.monst.dudes[i].active > 0) + if ((c_town.monst.dudes[i].attitude == 1) && + (party_can_see_monst(i) == TRUE)) + return TRUE; + } + + return FALSE; +} + + +// Returns 6 if can't see, O.W. returns the # of a PC that can see +short party_can_see(location where) +{ + short i; + + if (is_out()) { + if ((point_onscreen(party.p_loc,where) == TRUE) && (can_see(party.p_loc,where,0) < 5)) + return 1; + else return 6; + } + if (is_town()) { + if ( ((point_onscreen(c_town.p_loc,where) == TRUE) || (overall_mode == 36)) && (pt_in_light(c_town.p_loc,where) == TRUE) + && (can_see(c_town.p_loc,where,0) < 5)) + return 1; + else return 6; + } + + // Now for combat checks. Doing separately for efficiency. Check first for light. If + // dark, give up. + if ((which_combat_type != 0) && (combat_pt_in_light(where) == FALSE)) + return 6; + + for (i = 0; i < 6; i++) + if (adven[i].isAlive()) { + if (can_see(pc_pos[i],where,0) < 5) + return i; + } + + return 6; +} +location push_loc(location from_where,location to_where) +{ + location loc_to_try; + + loc_to_try = to_where; + loc_to_try.x = loc_to_try.x + (to_where.x - from_where.x); + loc_to_try.y = loc_to_try.y + (to_where.y - from_where.y); + if ((t_d.terrain[loc_to_try.x][loc_to_try.y] == 90) || + ((t_d.terrain[loc_to_try.x][loc_to_try.y] >= 50)&& (t_d.terrain[loc_to_try.x][loc_to_try.y] <= 64)) + || (t_d.terrain[loc_to_try.x][loc_to_try.y] == 71) + || ((t_d.terrain[loc_to_try.x][loc_to_try.y] >= 74)&& (t_d.terrain[loc_to_try.x][loc_to_try.y] <= 78)) + ) { + // Destroy crate + loc_to_try.x = 0; + return loc_to_try; + } + if ((get_obscurity((short) loc_to_try.x,(short) loc_to_try.y) > 0) || + (terrain_blocked[t_d.terrain[loc_to_try.x][loc_to_try.y]] > 0) || + (loc_off_act_area(loc_to_try) == TRUE) || + (monst_there(loc_to_try) < 90) || + (pc_there(loc_to_try) < 6)) + return from_where; + else return loc_to_try; +} + + + +Boolean spot_impassable(short i,short j) +{ + unsigned char ter; + + ter = coord_to_ter(i,j); + if (terrain_blocked[ter] == 5) + return TRUE; + else return FALSE; +} + +void alter_space(short i,short j,unsigned char ter) +{ + location l; + + l.x = i; + l.y = j; + map_graphic_placed[i / 8][j] = + map_graphic_placed[i / 8][j] & ~((unsigned char)(s_pow(2,i % 8))); + + if (is_out()) { + l = l.toGlobal(); + out[l.x][l.y] = ter; + outdoors[party.i_w_c.x][party.i_w_c.y].terrain[i][j] = ter; + } + else { + t_d.terrain[i][j] = ter; + combat_terrain[i][j] = ter; + if ((scenario.ter_types[t_d.terrain[i][j]].special >= 16) && + (scenario.ter_types[t_d.terrain[i][j]].special <= 19)) + belt_present = TRUE; + } +} diff --git a/Win32/Blades of Exile/LOCUTILS.H b/Win32/Blades of Exile/LOCUTILS.H new file mode 100644 index 00000000..d009b84b --- /dev/null +++ b/Win32/Blades of Exile/LOCUTILS.H @@ -0,0 +1,47 @@ +#ifndef _LOCUTILS_H + #define _LOCUTILS_H + +#include "location.h" +#include "global.h" + +short dist(location p1,location p2); +short vdist(location p1,location p2) ; +Boolean adjacent(location p1,location p2); +Boolean point_onscreen(location center,location check); +short set_direction (location old_pt, location new_pt); +location global_to_local(location global); +location local_to_global(location local); +Boolean loc_off_world(location p1); +Boolean loc_off_act_area(location p1); +location get_cur_loc(); +short short_can_see(shortloc p1,shortloc p2); +Boolean is_lava(short x,short y); +short can_see(location p1,location p2,short mode); +short get_obscurity(short x,short y); +unsigned char coord_to_ter(short x,short y); +Boolean is_container(location loc); +void update_explored(location dest); +Boolean is_blocked(location to_check); +Boolean monst_on_space(location loc,short m_num); +short monst_there(location where) ; +Boolean monst_can_be_there(location loc,short m_num); +Boolean monst_adjacent(location loc,short m_num); +Boolean monst_can_see(short m_num,location l); +Boolean party_can_see_monst(short m_num); +Boolean can_see_monst(location l,short m_num); +Boolean outd_is_blocked(location to_check); +Boolean special_which_blocks_monst(location to_check); +Boolean is_special(location to_check); +Boolean outd_is_special(location to_check); +Boolean impassable(unsigned char terrain_to_check); +short get_blockage(unsigned char terrain_type); +short light_radius(); +Boolean pt_in_light(location from_where,location to_where) ;// Assumes, of course, in town or combat +Boolean combat_pt_in_light(location to_where); +Boolean party_sees_a_monst(); // Returns true is a hostile monster is in sight. +short party_can_see(location where); +location push_loc(location from_where,location to_where); +Boolean spot_impassable(short i,short j); +void alter_space(short i,short j,unsigned char ter); + +#endif diff --git a/Win32/Blades of Exile/MONSTER.CPP b/Win32/Blades of Exile/MONSTER.CPP new file mode 100644 index 00000000..5541485b --- /dev/null +++ b/Win32/Blades of Exile/MONSTER.CPP @@ -0,0 +1,1344 @@ +#include +#include "stdio.h" +#include "global.h" +#include "locutils.h" +#include "fields.h" +#include "monster.h" +#include "text.h" +#include "specials.h" +#include "exlsound.h" +#include "graphics.h" +#include "newgraph.h" + +#include "globvar.h" + +monster_record_type return_monster_template(unsigned char store) +{ + monster_record_type monst; + short m_num,i; + + m_num = store; + monst = scenario.scen_monsters[store]; + if (monst.spec_skill == 11) + monst.picture_num = 0; + + monst.m_num = m_num; + monst.health = (PSD[306][7] == 0) ? monst.health : monst.health / 2; + + // now adjust for difficulty + monst.health = monst.health * difficulty_adjust(); + + monst.m_health = monst.health; // in scenario file, health is stored in health field + monst.max_mp = 0; + monst.mp = monst.max_mp; + + monst.ap = 0; + + if ((monst.mu > 0) || (monst.cl > 0)) + monst.max_mp = monst.mp = 12 * monst.level; + + monst.m_morale = 10 * monst.level; + if (monst.level >= 20) + monst.m_morale += 10 * (monst.level - 20); + + monst.morale = monst.m_morale; + monst.direction = 0; + for (i = 0; i < 15; i++) + monst.status[i] = 0; + + return monst; +} + +short difficulty_adjust() +{ + short i, j = 0; + short to_return = 1; + + for (i = 0; i < 6; i++) + if (adven[i].isAlive()) j += adven[i].level; + + if ((scenario.difficulty <= 0) && (j >= 60)) to_return++; + if ((scenario.difficulty <= 1) && (j >= 130)) to_return++; + if ((scenario.difficulty <= 2) && (j >= 210)) to_return++; + return to_return; +} + +short out_enc_lev_tot(short which) +{ + short count = 0,i; + monster_record_type store_m; + short num[7] = {22,8,4,4,3,2,1}; + + if (party.out_c[which].what_monst.cant_flee == TRUE) + return 10000; + + for (i = 0; i < 7; i++) + if (party.out_c[which].what_monst.monst[i] != 0) { + store_m = return_monster_template(party.out_c[which].what_monst.monst[i]); + count += store_m.level * num[i]; + } + return count; +} + +short current_town_type::countMonsters() +{ + short to_ret = 0; + + for (int i = 0; i < T_M; i++) + if (monst.dudes[i].active > 0) + ++to_ret; + + return to_ret; +} + +void create_wand_monst() +{ + short r1,r2,r3, i = 0,num_tries = 0; + location p_loc; + + r1 = get_ran(1,0,3); + if (overall_mode == MODE_OUTDOORS) + if (outdoors[party.i_w_c.x][party.i_w_c.y].wandering[r1].isNull() == false) { + r2 = get_ran(1,0,3); + while ((point_onscreen(outdoors[party.i_w_c.x][party.i_w_c.y].wandering_locs[r2], + party.p_loc.toLocal()) == TRUE) && (num_tries++ < 100)) + r2 = get_ran(1,0,3); + if (is_blocked(outdoors[party.i_w_c.x][party.i_w_c.y].wandering_locs[r2]) == FALSE) + place_outd_wand_monst(outdoors[party.i_w_c.x][party.i_w_c.y].wandering_locs[r2], + outdoors[party.i_w_c.x][party.i_w_c.y].wandering[r1],0); + } + +//// + + if (overall_mode != MODE_OUTDOORS) // won't place wandering is more than 50 monsters + if ((c_town.town.wandering[r1].isNull() == false) && (c_town.countMonsters() <= 50) + && (party.m_killed[c_town.town_num] < c_town.town.max_num_monst)) { + r2 = get_ran(1,0,3); + while ((point_onscreen(c_town.town.wandering_locs[r2],c_town.p_loc) == TRUE) && + (loc_off_act_area(c_town.town.wandering_locs[r2]) == FALSE) && (num_tries++ < 100)) + r2 = get_ran(1,0,3); + for (i = 0; i < 4; i++) { + if (c_town.town.wandering[r1].monst[i] != 0) { // place a monster + p_loc = c_town.town.wandering_locs[r2]; + p_loc.x += get_ran(1,0,4) - 2; + p_loc.y += get_ran(1,0,4) - 2; + if (is_blocked(p_loc) == FALSE) + c_town.placeMonster(c_town.town.wandering[r1].monst[i],p_loc); + p_loc = c_town.town.wandering_locs[r2]; + p_loc.x += get_ran(1,0,4) - 2; + p_loc.y += get_ran(1,0,4) - 2; + r3 = get_ran(1,0,3); + if ((r3 >= 2) && (i == 3) && (is_blocked(p_loc) == FALSE)) // place extra monsters? + c_town.placeMonster(c_town.town.wandering[r1].monst[i],p_loc); + } + } + } +} + +void place_outd_wand_monst(location where,out_wandering_type group,short forced) +{ + short i = 0,j = 0; + location l; + + + while (i < 10) { + //// + if ((party.out_c[i].exists == FALSE) || ((i == 9) && (forced > 0))) { + if ((sd_legit(group.end_spec1,group.end_spec2) == TRUE) && (PSD[group.end_spec1][group.end_spec2] > 0)) + return; + party.out_c[i].exists = TRUE; + party.out_c[i].direction = 0; + party.out_c[i].what_monst = group; + party.out_c[i].which_sector = party.i_w_c; + party.out_c[i].m_loc = where; + if (party.out_c[i].which_sector.x == 1) + party.out_c[i].m_loc.x += 48; + if (party.out_c[i].which_sector.y == 1) + party.out_c[i].m_loc.y += 48; + l = party.out_c[i].m_loc; + while ((forced == TRUE) && (is_blocked(l)) && (j < 50)) { + l = party.out_c[i].m_loc; + l.x += get_ran(1,0,2) - 1; + l.y += get_ran(1,0,2) - 1; + j++; + } + party.out_c[i].m_loc = l; + + i = 50; + } + i++; + } +} + +bool wandering_type::isNull() const +{ + short i = 0; + + while (i < 4) { + if (monst[i] != 0) return false; + i++; + } + return true; +} + +bool out_wandering_type::isNull() const +{ + short i = 0; + + while (i < 7) { + if (monst[i] != 0) return false; + i++; + } + return true; +} + +short get_monst_picnum(unsigned char monst) +{ + return scenario.scen_monsters[monst].picture_num; +} + +void get_monst_dims(unsigned char monst,short *width, short *height) +{ + + *width = scenario.scen_monsters[monst].x_width; + *height = scenario.scen_monsters[monst].y_width; +} + +// Used to set up monsters for outdoor wandering encounters. +void set_up_monst(short mode,unsigned char m_num) +//mode; // 0 - unfriendly 1 - friendly & fightin' +{ + short which; + + for (which = 0; which < T_M; which++) + if (c_town.monst.dudes[which].active == 0) { + c_town.monst.dudes[which].active = 2; + c_town.monst.dudes[which].summoned = 0; + c_town.monst.dudes[which].attitude = mode + 1; + c_town.monst.dudes[which].number = m_num; + c_town.monst.dudes[which].m_d = return_monster_template(m_num); + c_town.monst.dudes[which].mobile = TRUE; + c_town.monst.dudes[which].monst_start = null_start_type; + which = T_M; + } +} + +void do_monsters() +{ + short i,j,r1,target; + location l1,l2; + Boolean acted_yet = FALSE; + + if (overall_mode == MODE_TOWN) + for (i = 0; i < T_M; i++) + if ((c_town.monst.dudes[i].active != 0) && (c_town.monst.dudes[i].m_d.status[11] <= 0) + && (c_town.monst.dudes[i].m_d.status[12] <= 0)) { + // have to pick targets + if (c_town.monst.dudes[i].active == 1) + target = 6; + else { + target = monst_pick_target(i); // will return 0 if target party + target = switch_target_to_adjacent(i,target); + if (target == 0) { + if (dist(c_town.monst.dudes[i].m_loc,c_town.p_loc) > 8) + target = 6; + else target = select_active_pc(); + } + if ((c_town.monst.dudes[i].attitude % 2 != 1) && (target < 6)) + target = 6; + } + monst_target[i] = target; + + if ((c_town.monst.dudes[i].active == 2) + || ((c_town.monst.dudes[i].active != 0) && (c_town.monst.dudes[i].attitude % 2 != 1))) { + acted_yet = FALSE; + if (((c_town.monst.dudes[i].attitude == 0) || (monst_target[i] == 6)) && (c_town.hostile == 0)) { + if (c_town.monst.dudes[i].mobile == TRUE) { // OK, it doesn't see the party or + // isn't nasty, and the town isn't totally hostile. + if ((c_town.monst.dudes[i].attitude % 2 != 1) || (get_ran(1,0,1) == 0)) { + acted_yet = rand_move(i); + } + else acted_yet = seek_party(i,c_town.monst.dudes[i].m_loc,c_town.p_loc); + } + } + if ((c_town.monst.dudes[i].attitude > 0) || (c_town.hostile == 1)) { + if ((c_town.monst.dudes[i].mobile == TRUE) && (monst_target[i] != 6)) { + l1 = c_town.monst.dudes[i].m_loc; + l2 = (monst_target[i] <= 6) ? c_town.p_loc : c_town.monst.dudes[target - 100].m_loc; + + if ((c_town.monst.dudes[i].m_d.morale < 0) && (c_town.monst.dudes[i].m_d.spec_skill != 13) + && (c_town.monst.dudes[i].m_d.m_type != 8)) { + acted_yet = flee_party(i,l1,l2); + if (get_ran(1,0,10) < 6) + c_town.monst.dudes[i].m_d.morale++; + } + else if (monst_hate_spot(i,&l2) == TRUE) + acted_yet = seek_party(i,l1,l2); + else if (((c_town.monst.dudes[i].m_d.mu == 0) && (c_town.monst.dudes[i].m_d.mu == 0)) + || (can_see(l1,l2,0) > 3)) + acted_yet = seek_party(i,l1,l2); + } + } + } + + + // Make hostile monsters active + if ((c_town.monst.dudes[i].active == 1) && (c_town.monst.dudes[i].attitude % 2 == 1) + && (dist(c_town.monst.dudes[i].m_loc,c_town.p_loc) <= 8)) { + r1 = get_ran(1,1,100); + r1 += (party.stuff_done[305][0] > 0) ? 46 : 0; + r1 += can_see(c_town.monst.dudes[i].m_loc,c_town.p_loc,0) * 10; + if (r1 < 50) { + c_town.monst.dudes[i].active = 2; + add_string_to_buf("Monster saw you!"); + // play go active sound + switch (c_town.monst.dudes[i].m_d.m_type) { + case 0: case 3: case 4: case 5: case 6: case 9: + play_sound(18); break; + default: play_sound(46); break; + } + } + for (j = 0; j < T_M; j++) + if ((c_town.monst.dudes[j].active == 2) + && ((dist(c_town.monst.dudes[i].m_loc,c_town.monst.dudes[j].m_loc) <= 5) == TRUE)) + c_town.monst.dudes[i].active = 2; + } + + } + if (overall_mode == MODE_OUTDOORS) { + for (i = 0; i < 10; i++) + if (party.out_c[i].exists == TRUE) { + acted_yet = FALSE; + l1 = party.out_c[i].m_loc; + l2 = party.p_loc; + + r1 = get_ran(1,1,6); + if (r1 == 3) + acted_yet = rand_move(i); + else acted_yet = seek_party(i,l1,l2); + } + } +} + +Boolean monst_hate_spot(short which_m,location *good_loc) +{ + location prospect,loc; + + loc = c_town.monst.dudes[which_m].m_loc; + if ((misc_i[loc.x][loc.y] & 224) + || (c_town.explored[loc.x][loc.y] & 64) // hate regular fields + || ((c_town.explored[loc.x][loc.y] & 32) && (c_town.monst.dudes[which_m].m_d.radiate_1 != 2) + && (c_town.monst.dudes[which_m].m_d.immunities & 32 == 0)) // hate ice wall? + || ((c_town.explored[loc.x][loc.y] & 4) && (c_town.monst.dudes[which_m].m_d.radiate_1 != 1) + && (c_town.monst.dudes[which_m].m_d.immunities & 8 == 0)) // hate fire wall? + || ((c_town.explored[loc.x][loc.y] & 16) && (c_town.monst.dudes[which_m].m_d.radiate_1 != 6) + && (c_town.monst.dudes[which_m].m_d.immunities & 3 == 0)) // hate stink cloud? + || ((c_town.explored[loc.x][loc.y] & 128) && (c_town.monst.dudes[which_m].m_d.radiate_1 != 5) + && (c_town.monst.dudes[which_m].m_d.immunities & 3 == 0)) // hate sleep cloud? + || ((c_town.explored[loc.x][loc.y] & 2) && (c_town.monst.dudes[which_m].m_d.radiate_1 != 3) + && (c_town.monst.dudes[which_m].m_d.immunities & 3 == 0)) // hate shock cloud? + || (((c_town.monst.dudes[which_m].m_d.mu > 0) || (c_town.monst.dudes[which_m].m_d.cl > 0)) + && (c_town.explored[loc.x][loc.y] & 8))) // hate antimagic + { + prospect = find_clear_spot(loc,1); + if (prospect.x > 0) { + *good_loc = prospect; + return TRUE; + } + return FALSE; + } + else return FALSE; +} + +short monst_pick_target(short which_m) +{ + creature_data_type *cur_monst; + short targ_pc,targ_m; + + cur_monst = &c_town.monst.dudes[which_m]; + + // First, any chance target is screwed? + if (monst_target[which_m] >= 100) { + if (((cur_monst->attitude % 2 == 1) && + (c_town.monst.dudes[monst_target[which_m] - 100].attitude == cur_monst->attitude)) || + ((cur_monst->attitude % 2 == 0) && (c_town.monst.dudes[monst_target[which_m] - 100].attitude % 2 == 0))) + monst_target[which_m] = 6; + else if (c_town.monst.dudes[monst_target[which_m] - 100].active == 0) + monst_target[which_m] = 6; + } + if (monst_target[which_m] < 6) + if (adven[monst_target[which_m]].isAlive() == false) + monst_target[which_m] = 6; + + if ((is_combat()) && (cur_monst->attitude % 2 == 1)) { + if (spell_caster < 6) + if ((get_ran(1,1,5) < 5) && (monst_can_see(which_m,pc_pos[spell_caster]) == TRUE) + && (adven[spell_caster].isAlive())) + return spell_caster; + if (missile_firer < 6) + if ((get_ran(1,1,5) < 3) && (monst_can_see(which_m,pc_pos[missile_firer]) == TRUE) + && (adven[missile_firer].isAlive())) + return missile_firer; + if (monst_target[which_m] < 6) + if ((monst_can_see(which_m,pc_pos[monst_target[which_m]]) == TRUE) + && (adven[monst_target[which_m]].isAlive())) + return monst_target[which_m]; + } + + // Now pick a target pc and a target monst and see which is more attractive + targ_pc = monst_pick_target_pc(which_m,cur_monst); + targ_m = monst_pick_target_monst(cur_monst); + + if ((targ_pc != 6) && (targ_m == 6)) return targ_pc; + if ((targ_pc == 6) && (targ_m != 6)) return targ_m; + if ((targ_pc == 6) && (targ_m == 6)) return 6; + + if (is_town()) { + if (cur_monst->attitude % 2 == 0) { + return targ_m; + } + if ((targ_m == 6) && (cur_monst->attitude % 2 == 1)) + return 0; + if (dist(cur_monst->m_loc,c_town.monst.dudes[targ_m - 100].m_loc) < + dist(cur_monst->m_loc,c_town.p_loc)) + return targ_m; + else return 0; + } + // Otherwise we're in combat + if ((dist(cur_monst->m_loc,c_town.monst.dudes[targ_m - 100].m_loc) == + dist(cur_monst->m_loc,pc_pos[targ_pc])) && (get_ran(1,0,6) < 3)) + return targ_m; + else return targ_pc; + if (dist(cur_monst->m_loc,c_town.monst.dudes[targ_m - 100].m_loc) < + dist(cur_monst->m_loc,pc_pos[targ_pc])) + return targ_m; + else return targ_pc; + +} + +short monst_pick_target_monst(creature_data_type *which_m) +{ + short min_dist = 1000,i,cur_targ = 6; + + for (i = 0; i < T_M; i++) { + if ((c_town.monst.dudes[i].active > 0) && // alive + (((which_m->attitude % 2 == 1) && (c_town.monst.dudes[i].attitude % 2 == 0)) || + ((which_m->attitude % 2 == 0) && (c_town.monst.dudes[i].attitude % 2 == 1)) || + ((which_m->attitude % 2 == 1) && (c_town.monst.dudes[i].attitude != which_m->attitude))) && // they hate each other + ((dist(which_m->m_loc,c_town.monst.dudes[i].m_loc) < min_dist) || + ((dist(which_m->m_loc,c_town.monst.dudes[i].m_loc) == min_dist) && (get_ran(1,0,7) < 4))) && + (monst_can_see(i,c_town.monst.dudes[i].m_loc) == TRUE) ) { + min_dist = dist(which_m->m_loc,c_town.monst.dudes[i].m_loc); + cur_targ = i + 100; + + } + } + return cur_targ; +} + +short monst_pick_target_pc(short m_num,creature_data_type *which_m) +{ + short num_tries = 0,r1,store_targ = 6; + + if (which_m->attitude % 2 == 0) + return 6; + if (is_town()) + return 0; + + // First pick any visible, nearby PC + r1 = get_ran(1,0,5); + while ((num_tries < 6) && ((adven[r1].isAlive() == false) || + (monst_can_see(m_num,pc_pos[r1]) == FALSE))) { + r1 = get_ran(1,0,5); + num_tries++; + } + if (num_tries < 6) + store_targ = r1; + + // Then, see if target can be replaced with someone nice and close + r1 = get_ran(1,0,5); + while ((num_tries < 4) && ((adven[r1].isAlive() == false) || + (dist(which_m->m_loc,pc_pos[r1]) > 4) || + (monst_can_see(m_num,pc_pos[r1]) == FALSE))) { + r1 = get_ran(1,0,5); + num_tries++; + } + + if (num_tries < 6) + return r1; + else return store_targ; +} + +// returns 6 if no +short select_active_pc() +{ + short r1, num_tries = 0; + + r1 = get_ran(1,0,5); + while ((adven[r1].isAlive() == false) && (num_tries++ < 50)) + r1 = get_ran(1,0,5); + + return r1; +} + +short closest_pc(location where) +{ + short how_close = 200,i,store = 6; + + for (i = 0; i < 6; i++) + if ((adven[i].isAlive()) && (dist(where,pc_pos[i]) < how_close)) { + store = i; + how_close = dist(where,pc_pos[i]); + } + return store; +} + +short switch_target_to_adjacent(short which_m,short orig_target) +{ + location monst_loc; + short i,num_adj = 0; + + monst_loc = c_town.monst.dudes[which_m].m_loc; + + // First, take care of friendly monsters. + if (c_town.monst.dudes[which_m].attitude % 2 == 0) { + if (orig_target >= 100) + if ((c_town.monst.dudes[orig_target - 100].active > 0) && + (monst_adjacent(c_town.monst.dudes[orig_target - 100].m_loc,which_m) == TRUE)) + return orig_target; + for (i = 0; i < T_M; i++) + if ((c_town.monst.dudes[i].active > 0) && + (c_town.monst.dudes[i].attitude % 2 == 1) && + (monst_adjacent(c_town.monst.dudes[i].m_loc,which_m) == TRUE)) + return i + 100; + return orig_target; + } + + // If we get here while in town, just need to check if switch to pc + if ((is_town()) && (monst_adjacent(c_town.p_loc,which_m) == TRUE)) + return 0; + if (is_town()) + return orig_target; + + // If target is already adjacent, we're done here. + if ((is_combat()) && (orig_target < 6)) + if ((adven[orig_target].isAlive()) && (monst_adjacent(pc_pos[orig_target],which_m) == TRUE)) + return orig_target; + if (orig_target >= 100) + if ((c_town.monst.dudes[orig_target - 100].active > 0) && + (monst_adjacent(c_town.monst.dudes[orig_target - 100].m_loc,which_m) == TRUE)) + return orig_target; + + // Anyone unarmored? Heh heh heh... + if (is_combat()) + for (i = 0; i < 6; i++) + if ((adven[i].isAlive()) && (monst_adjacent(pc_pos[i],which_m) == TRUE) && + (get_encumberance(i) < 2)) + return i; + + // Check for a nice, adjacent, friendly monster and maybe attack + for (i = 0; i < T_M; i++) + if ((c_town.monst.dudes[i].active > 0) && + (c_town.monst.dudes[i].attitude % 2 == 0) && + (monst_adjacent(c_town.monst.dudes[i].m_loc,which_m) == TRUE) && + (get_ran(1,0,2) < 2)) + return i + 100; + + // OK. Now if this monster has PCs adjacent, pick one at randomn and hack. Otherwise, + // stick with orig. target. + for (i = 0; i < 6; i++) + if ((adven[i].isAlive()) && (monst_adjacent(pc_pos[i],which_m) == TRUE)) + num_adj++; + + if (num_adj == 0) + return orig_target; + + i = 0; + num_adj = get_ran(1,1,num_adj); + while ((num_adj > 1) || (adven[i].isAlive() == false) || (monst_adjacent(pc_pos[i],which_m) == FALSE)) { + if (adven[i].isAlive() && (monst_adjacent(pc_pos[i],which_m) == TRUE)) + num_adj--; + i++; + } + return i; +} + + +Boolean rand_move(int i) +{ + Boolean acted_yet = FALSE; + short j; + location store_loc; + + // first, if outdoor, just roam. + if (is_out()) { + store_loc = party.out_c[i].m_loc.randomShift(); + return outdoor_move_monster(i,store_loc); + } + + if (same_point(monster_targs[i],c_town.monst.dudes[i].m_loc) == TRUE) + monster_targs[i].x = 0; + + // FIrst, try to move to monst_targs. If it don't work, then we'll shift. + if (monster_targs[i].x > 0) + acted_yet = seek_party(i,c_town.monst.dudes[i].m_loc,monster_targs[i]); + + if (acted_yet == FALSE) { + monster_targs[i].x = 0; + for (j = 0; j < 3; j++) { + store_loc = c_town.monst.dudes[i].m_loc; + store_loc.x += get_ran(1,0,24) - 12; + store_loc.y += get_ran(1,0,24) - 12; + if ((loc_off_act_area(store_loc) == FALSE) && (can_see(c_town.monst.dudes[i].m_loc,store_loc,0) < 5)) { + monster_targs[i] = store_loc; j = 3; + } + } + + if (monster_targs[i].x == 0) { + // maybe pick a wand loc, else juist pick a loc + j = get_ran(1,0,3); + store_loc = c_town.town.wandering_locs[j]; + + if ((loc_off_act_area(store_loc) == FALSE) && (get_ran(1,0,1) == 1)) + monster_targs[i] = store_loc; + else { + store_loc = c_town.monst.dudes[i].m_loc; + store_loc.x += get_ran(1,0,20) - 10; + store_loc.y += get_ran(1,0,20) - 10; + if (loc_off_act_area(store_loc) == FALSE) + monster_targs[i] = store_loc; + } + } + if (monster_targs[i].x > 0) + acted_yet = seek_party(i,c_town.monst.dudes[i].m_loc,monster_targs[i]); + } + + return acted_yet; +} + + + + + +Boolean seek_party(short i,location l1,location l2) +{ + Boolean acted_yet = FALSE; + short m,n; + if ((l1.x > l2.x) && (l1.y > l2.y)) + acted_yet = try_move(i,l1,-1,-1); + if ((l1.x < l2.x) & (l1.y < l2.y) & (acted_yet == FALSE)) + acted_yet = try_move(i,l1,1,1); + if ((l1.x > l2.x) & (l1.y < l2.y) & (acted_yet == FALSE)) + acted_yet = try_move(i,l1,-1,1); + if ((l1.x < l2.x) & (l1.y > l2.y) & (acted_yet == FALSE)) + acted_yet = try_move(i,l1,1,-1); + if ((l1.x > l2.x) & (acted_yet == FALSE)) + acted_yet = try_move(i,l1,-1,0); + if ((l1.x < l2.x) & (acted_yet == FALSE)) + acted_yet = try_move(i,l1,1,0); + if ( (l1.y < l2.y) & (acted_yet == FALSE)) + acted_yet = try_move(i,l1,0,1); + if ( (l1.y > l2.y) & (acted_yet == FALSE)) + acted_yet = try_move(i,l1,0,-1); + if (acted_yet == FALSE) { + futzing++; + m = get_ran(1,0,2) - 1; + n = get_ran(1,0,2) - 1; + acted_yet = try_move(i,l1,m,n); + } + return acted_yet; +} + +Boolean flee_party(short i,location l1,location l2) +{ + Boolean acted_yet = FALSE; + + if ((l1.x > l2.x) & (l1.y > l2.y)) + acted_yet = try_move(i,l1,1,1); + if ((l1.x < l2.x) & (l1.y < l2.y) & (acted_yet == FALSE)) + acted_yet = try_move(i,l1,-1,-1); + if ((l1.x > l2.x) & (l1.y < l2.y) & (acted_yet == FALSE)) + acted_yet = try_move(i,l1,1,-1); + if ((l1.x < l2.x) & (l1.y > l2.y) & (acted_yet == FALSE)) + acted_yet = try_move(i,l1,-1,+1); + if ((l1.x > l2.x) & (acted_yet == FALSE)) + acted_yet = try_move(i,l1,1,0); + if ((l1.x < l2.x) & (acted_yet == FALSE)) + acted_yet = try_move(i,l1,-1,0); + if ( (l1.y < l2.y) & (acted_yet == FALSE)) + acted_yet = try_move(i,l1,0,-1); + if ( (l1.y > l2.y) & (acted_yet == FALSE)) + acted_yet = try_move(i,l1,0,1); + if (acted_yet == FALSE) { + futzing++; + acted_yet = rand_move(i); + } + return acted_yet; +} + +Boolean try_move(short i,location start,short x,short y) +{ + location dest; + + dest = start; + dest.x = dest.x + x; + dest.y = dest.y + y; + + + if (overall_mode == MODE_TOWN) + return town_move_monster(i,dest); + if (overall_mode == MODE_OUTDOORS) + return outdoor_move_monster(i,dest); + if (overall_mode == MODE_COMBAT) + return combat_move_monster((short) i,dest); + return 0; +} + +Boolean combat_move_monster(short which,location destination) +{ + if (monst_can_be_there(destination,which) == FALSE) + return FALSE; + else if (monst_check_special_terrain(destination,2,which) == FALSE) + return FALSE; + else { + c_town.monst.dudes[which].m_d.direction = + set_direction(c_town.monst.dudes[which].m_loc, destination); + c_town.monst.dudes[which].m_loc = destination; + monst_inflict_fields(which); + + if ((monst_target[which] != 6) && (point_onscreen(destination,center) == TRUE)) { + if (is_combat()) + move_sound(combat_terrain[destination.x][destination.y], + (short) c_town.monst.dudes[which].m_d.ap); + else move_sound(t_d.terrain[destination.x][destination.y], + (short) c_town.monst.dudes[which].m_d.ap); + } + + return TRUE; + } + return FALSE; +} + +// Looks at all spaces within 2, looking for a spot which is clear of nastiness and beings +// returns {0,0} if none found +// THIS MAKES NO ADJUSTMENTS FOR BIG MONSTERS!!! +location find_clear_spot(location from_where,short mode) +//mode; // 0 - normal 1 - prefer adjacent space +{ + location loc,store_loc; + short num_tries = 0,r1; + + while (num_tries < 75) { + num_tries++; + loc = from_where; + r1 = get_ran(1,-2,2); + loc.x = loc.x + r1; + r1 = get_ran(1,-2,2); + loc.y = loc.y + r1; + if ((loc_off_act_area(loc) == FALSE) && (is_blocked(loc) == FALSE) + && (can_see(from_where,loc,1) == 0) + && (!(is_combat()) || (pc_there(loc) == 6)) + && (!(is_town()) || (same_point(loc,c_town.p_loc) == FALSE)) + && (!(misc_i[loc.x][loc.y] & 248)) && + (!(c_town.explored[loc.x][loc.y] & 254))) { + if ((mode == 0) || ((mode == 1) && (adjacent(from_where,loc) == TRUE))) + return loc; + else store_loc = loc; + } + } + return store_loc; +} + +short pc_there(location where) +{ + short i; + + for (i = 0; i < 6; i++) + if ((same_point(where,pc_pos[i]) == TRUE) && adven[i].isAlive()) + return i; + return 6; +} + +location location::randomShift() +{ + location store; + + store.x = x + get_ran(1,0,2) - 1; + store.y = y + get_ran(1,0,2) - 1; + + return store; +} + +Boolean outdoor_move_monster(short num,location dest) +{ + + if ((outd_is_blocked(dest) == FALSE) && (outd_is_special(dest) == FALSE) && + (same_point(dest, party.p_loc) != TRUE) && + ((out[dest.x][dest.y] > 21) || (out[dest.x][dest.y] < 5))) { + party.out_c[num].direction = + set_direction(party.out_c[num].m_loc, dest); + party.out_c[num].m_loc = dest; + return TRUE; + } + else return FALSE; +} + +Boolean town_move_monster(short num,location dest) +{ + if (monst_check_special_terrain(dest,1,num) == FALSE) + return FALSE; + + if (monst_can_be_there(dest,num) == TRUE) { + c_town.monst.dudes[num].m_d.direction = + set_direction(c_town.monst.dudes[num].m_loc, dest); + c_town.monst.dudes[num].m_loc = dest; + monst_inflict_fields(num); + return TRUE; + } + else return FALSE; +} + +Boolean monster_placid(short m_num) +{ + if ((c_town.monst.dudes[m_num].attitude == 0) || + ((c_town.monst.dudes[m_num].attitude == 2) && (party.stuff_done[305][9] == 0))) + { return TRUE;} + else { return FALSE;} +} + +// This damages a monster by any fields it's in, and destroys any barrels or crates +// it's stiing on. +void monst_inflict_fields(short which_monst) +{ + short i,j,r1,k; + location where_check; + creature_data_type *which_m; + + if (c_town.monst.dudes[which_monst].active == 0) + return; + + which_m = &c_town.monst.dudes[which_monst]; + for (i = 0; i < c_town.monst.dudes[which_monst].m_d.x_width; i++) + for (j = 0; j < c_town.monst.dudes[which_monst].m_d.y_width; j++) + if (c_town.monst.dudes[which_monst].active > 0) { + where_check.x = c_town.monst.dudes[which_monst].m_loc.x + i; + where_check.y = c_town.monst.dudes[which_monst].m_loc.y + j; + if (is_quickfire(where_check.x,where_check.y)) { + r1 = get_ran(2,1,8); + damage_monst(which_monst,7,r1,0,1); + break; + } + if (is_blade_wall(where_check.x,where_check.y)) { + r1 = get_ran(6,1,8); + damage_monst(which_monst,7,r1,0,0); + break; + } + if (is_force_wall(where_check.x,where_check.y)) { + r1 = get_ran(3,1,6); + damage_monst(which_monst,7,r1,0,3); + break; + } + if (is_sleep_cloud(where_check.x,where_check.y)) { + which_m->charm(0,11,3); + break; + } + if (is_ice_wall(where_check.x,where_check.y)) { + r1 = get_ran(3,1,6); + if (c_town.monst.dudes[which_monst].m_d.spec_skill != 23) + damage_monst(which_monst,7,r1,0,5); + break; + } + if (is_scloud(where_check.x,where_check.y)) { + r1 = get_ran(1,2,3); + which_m->curse(r1); + break; + } + if ((is_web(where_check.x,where_check.y)) && (which_m->m_d.m_type != 12)) { + monst_spell_note(which_m->number,19); + r1 = get_ran(1,2,3); + which_m->web(r1); + take_web(where_check.x,where_check.y); + break; + } + if (is_fire_wall(where_check.x,where_check.y)) { + r1 = get_ran(2,1,6); + if (c_town.monst.dudes[which_monst].m_d.spec_skill != 22) + damage_monst(which_monst,7,r1,0,1); + break; + } + } + if (c_town.monst.dudes[which_monst].active > 0) + for (i = 0; i < c_town.monst.dudes[which_monst].m_d.x_width; i++) + for (j = 0; j < c_town.monst.dudes[which_monst].m_d.y_width; j++) { + where_check.x = c_town.monst.dudes[which_monst].m_loc.x + i; + where_check.y = c_town.monst.dudes[which_monst].m_loc.y + j; + if ((is_crate(where_check.x,where_check.y)) || + (is_barrel(where_check.x,where_check.y)) ) + for (k = 0; k < NUM_TOWN_ITEMS; k++) + if ((t_i.items[k].variety > 0) && (t_i.items[k].isContained()) + && (same_point(t_i.items[k].item_loc,where_check) == TRUE)) + t_i.items[k].item_properties = t_i.items[k].item_properties & 247; + take_crate(where_check.x,where_check.y); + take_barrel(where_check.x,where_check.y); + if (is_fire_barrier(where_check.x,where_check.y)) { + r1 = get_ran(2,1,10); + damage_monst(which_monst,7,r1,0,1); + } + } + +} + +Boolean monst_check_special_terrain(location where_check,short mode,short which_monst) +//mode; // 1 - town 2 - combat +{ + unsigned char ter; + short r1,i,guts = 0; + Boolean can_enter = TRUE,mage = FALSE; + location from_loc,to_loc; + Boolean do_look = FALSE; // If becomes true, terrain changed, so need to update what party sees + creature_data_type *which_m; + short ter_abil; + + from_loc = c_town.monst.dudes[which_monst].m_loc; + switch (mode) { + case 1: + ter = t_d.terrain[where_check.x][where_check.y]; + break; + case 2: + ter = combat_terrain[where_check.x][where_check.y]; + break; + } + which_m = &c_town.monst.dudes[which_monst]; + ter_abil = scenario.ter_types[ter].special; + + if ((mode > 0) && (ter_abil >= 16) && + (ter_abil <= 19)) { + if ( + ((ter_abil == 16) && (where_check.y > from_loc.y)) || + ((ter_abil == 17) && (where_check.x < from_loc.x)) || + ((ter_abil == 18) && (where_check.y < from_loc.y)) || + ((ter_abil == 19) && (where_check.x > from_loc.x)) ) { + return FALSE; + } + } + + // begin determining guts, which determines how enthused the monst is about entering + // nasty barriers + if ((which_m->m_d.mu > 0) || (which_m->m_d.cl > 0)) + mage = TRUE; + if (which_m->m_d.spec_skill == 13) + guts = 20; + else guts = get_ran(1,1,(which_m->m_d.level / 2)); + guts += which_m->m_d.health / 20; + if (mage == TRUE) + guts = guts / 2; + if (which_m->attitude == 0) + guts = guts / 2; + + if ((is_antimagic(where_check.x,where_check.y)) && (mage == TRUE)) + return FALSE; + if ((is_fire_wall(where_check.x,where_check.y)) && (which_m->m_d.spec_skill != 22)) { + if (guts < 3) return FALSE; + } + if (is_force_wall(where_check.x,where_check.y)) { + if (guts < 4) return FALSE; + } + if ((is_ice_wall(where_check.x,where_check.y)) && (which_m->m_d.spec_skill != 23)) { + if (guts < 5) return FALSE; + } + if (is_sleep_cloud(where_check.x,where_check.y)) { + if (guts < 8) return FALSE; + } + if (is_blade_wall(where_check.x,where_check.y)) { + if (guts < 8) return FALSE; + } + if (is_quickfire(where_check.x,where_check.y)) { + if (guts < 8) return FALSE; + } + if (is_scloud(where_check.x,where_check.y)) { + if (guts < 4) return FALSE; + } + if ((is_web(where_check.x,where_check.y)) && (which_m->m_d.m_type != 12)) { + if (guts < 3) return FALSE; + } + if (is_fire_barrier(where_check.x,where_check.y)) { + if ((which_m->attitude % 2 == 1) && (get_ran(1,0,100) < (which_m->m_d.mu * 10 + which_m->m_d.cl * 4))) { + play_sound(60); + add_string_to_buf("Monster breaks barrier."); + take_fire_barrier(where_check.x,where_check.y); + } + else { + if (guts < 6) return FALSE; + r1 = get_ran(1,0,10); + if ((r1 < 8) || (monster_placid(which_monst))) + can_enter = FALSE; + } + } + if (is_force_barrier(where_check.x,where_check.y)) { /// Not in big towns + if ((which_m->attitude % 2 == 1) && (get_ran(1,0,100) < (which_m->m_d.mu * 10 + which_m->m_d.cl * 4))) { + play_sound(60); + add_string_to_buf("Monster breaks barrier."); + take_force_barrier(where_check.x,where_check.y); + } + else can_enter = FALSE; + } + if (is_crate(where_check.x,where_check.y)) { + if (monster_placid(which_monst)) + can_enter = FALSE; + else { + to_loc = push_loc(from_loc,where_check); + take_crate((short) where_check.x,(short) where_check.y); + if (to_loc.x > 0) + make_crate((short) to_loc.x,(short) to_loc.y); + for (i = 0; i < NUM_TOWN_ITEMS; i++) + if ((t_i.items[i].variety > 0) && (same_point(t_i.items[i].item_loc,where_check)) + && (t_i.items[i].isContained())) + t_i.items[i].item_loc = to_loc; + } + } + if (is_barrel(where_check.x,where_check.y)) { + if (monster_placid(which_monst)) + can_enter = FALSE; + else { + to_loc = push_loc(from_loc,where_check); + take_barrel((short) where_check.x,(short) where_check.y); + if (to_loc.x > 0) + make_barrel((short) to_loc.x,(short) to_loc.y); + for (i = 0; i < NUM_TOWN_ITEMS; i++) + if ((t_i.items[i].variety > 0) && (same_point(t_i.items[i].item_loc,where_check)) + && (t_i.items[i].isContained())) + t_i.items[i].item_loc = to_loc; + + } + } + if (monster_placid(which_monst) && // monsters don't hop into bed when things are calm + (scenario.ter_types[ter].picture == 143)) + can_enter = FALSE; + if ((scenario.ter_types[ter].picture <= 212) && (scenario.ter_types[ter].picture >= 207)) + can_enter = FALSE; + if (ter == 90) { + if ((is_combat()) && (which_combat_type == 0)) { + c_town.monst.dudes[which_monst].active = 0; + add_string_to_buf("Monster escaped! "); + } + return FALSE; + } + switch (ter_abil) { + // changing ter + case 1: + can_enter = FALSE; + if (!(monster_placid(which_monst))) { + t_d.terrain[where_check.x][where_check.y] = scenario.ter_types[ter].flag1; + combat_terrain[where_check.x][where_check.y] = scenario.ter_types[ter].flag1; + do_look = TRUE; + if (point_onscreen(center,where_check)) + play_sound(scenario.ter_types[ter].flag2); + } + break; + + case 20: case 21: case 15: + can_enter = FALSE; + break; + + case 2: + if (c_town.monst.dudes[which_monst].m_d.immunities & 8) + return TRUE; + else return FALSE; + break; + } + + // Action may change terrain, so update what's been seen + if (do_look == TRUE) { + if (is_town()) + update_explored(c_town.p_loc); + if (is_combat()) + for (i = 0; i < 6; i++) + if (adven[i].isAlive()) + update_explored(pc_pos[i]); + } + + return can_enter; +} + +void forced_place_monster(unsigned char which,location where) +{ + Boolean free_spot = FALSE; + short i = 0,r1; + + while ((free_spot == FALSE) && (i < T_M)) { + if (c_town.monst.dudes[i].active == 0) + free_spot = TRUE; + i++; + } + do + r1 = get_ran(1,0,59); + while ((c_town.monst.dudes[r1].monst_start.spec1 != 0) || (c_town.monst.dudes[r1].monst_start.spec2 != 0)); + if (free_spot == FALSE) + c_town.monst.dudes[r1].active = 0; + c_town.placeMonster(which,where); +} + +void creature_data_type::adjustMagic(short *how_much) +{ + if (m_d.spec_skill == 26) { + *how_much = 0; + m_d.health += 3; + } + if (m_d.immunities & 1) *how_much = *how_much / 2; + if (m_d.immunities & 2) *how_much = 0; /* crash!! */ +} + +void creature_data_type::poison(short how_much) +{ + if (m_d.immunities & 64) how_much = how_much / 2; + if (m_d.immunities & 128) { + monst_spell_note(number,10); + return; + } + m_d.status[2] = min(8, m_d.status[2] + how_much); + monst_spell_note(number,(how_much == 0) ? 10 : 4); +} + +void creature_data_type::acid(short how_much) +{ + adjustMagic(&how_much); + m_d.status[13] = minmax(-8,8, m_d.status[13] + how_much); + monst_spell_note(number,31); +} + +void creature_data_type::slow(short how_much) +{ + adjustMagic(&how_much); + m_d.status[3] = minmax(-8,8, m_d.status[3] - how_much); + monst_spell_note(number,(how_much == 0) ? 10 : 2); +} +void creature_data_type::curse(short how_much) +{ + adjustMagic(&how_much); + m_d.status[1] = minmax(-8,8, m_d.status[1] - how_much); + monst_spell_note(number,(how_much == 0) ? 10 : 5); +} +void creature_data_type::web(short how_much) +{ + adjustMagic(&how_much); + m_d.status[6] = minmax(-8,8, m_d.status[6] + how_much); + monst_spell_note(number,(how_much == 0) ? 10 : 19); +} +void creature_data_type::scare(short how_much) +{ + adjustMagic(&how_much); + m_d.morale = m_d.morale - how_much; + monst_spell_note(number,(how_much == 0) ? 10 : 1); + +} +void creature_data_type::disease(short how_much) +{ + adjustMagic(&how_much); + m_d.status[7] = minmax(-8,8, m_d.status[7] + how_much); + monst_spell_note(number,(how_much == 0) ? 10 : 25); +} + +void creature_data_type::dumbfound(short how_much) +{ + adjustMagic(&how_much); + m_d.status[9] = minmax(-8,8, m_d.status[9] + how_much); + monst_spell_note(number,(how_much == 0) ? 10 : 22); +} + +void creature_data_type::charm(short penalty,short which_status,short amount) +// Also used for sleep and paralyze, which_statys is 0 means charm +{ + short r1; + + if ((which_status == 11) && (number >= 138) && (number <= 142)) return; + if ((which_status == 11) && (m_d.m_type == 8)) return; + r1 = get_ran(1,0,100); + if (m_d.immunities & 1) r1 = r1 * 2; + if (m_d.immunities & 2) r1 = 200; + r1 += penalty; + if (which_status == 11) r1 -= 25; + if (which_status == 12) r1 -= 15; + if ((which_status == 11) && (m_d.spec_skill == 32)) + return; + + if (r1 > charm_odds[m_d.level / 2]) { + monst_spell_note(number,10); + } + else { + if (which_status == 0) { + attitude = 2; + monst_spell_note(number,23); + } + else { + m_d.status[which_status] = amount; + if (which_status == 11) monst_spell_note(number,28); + if (which_status == 12) monst_spell_note(number,30); + } + } +} + +void creature_data_type::record() +{ + short r1; + char str[60]; + + r1 = get_ran(1,0,100); + r1 = (r1 * 7) / 10; + + if ((m_d.x_width > 1) || (m_d.y_width > 1)) { + ASB("Capture Soul: Monster is too big."); + } + else if ((r1 > charm_odds[m_d.level / 2]) || (m_d.spec_skill == 12) + || (m_d.m_type == 3)) { + monst_spell_note(number,10); + play_sound(68); + } + else { + monst_spell_note(number,24); + r1 = get_ran(1,0,3); + if (party.imprisoned_monst[r1] == 0) + party.imprisoned_monst[r1] = number; + else { + r1 = get_ran(1,0,3); + party.imprisoned_monst[r1] = number; + } + ASB("Capture Soul: Success!"); + sprintf((char *)str," Caught in slot %d.",r1 + 1); + add_string_to_buf((char *)str); + play_sound(53); + } +} +// returns 90 is no placement, OW returns # of spot +short current_town_type::placeMonster(unsigned char which, location where) +{ + short i = 0; + + while ((i < T_M) && ((monst.dudes[i].active != 0) || + (monst.dudes[i].monst_start.spec_enc_code > 0))) { + i++; + } + + if (i < T_M) { + monst.dudes[i].m_d = return_monster_template((unsigned char) which); + monst.dudes[i].attitude = scenario.scen_monsters[which].default_attitude; + if (monst.dudes[i].attitude % 2 == 0) + monst.dudes[i].attitude = 1; + monst.dudes[i].mobile = TRUE; + monst.dudes[i].active = 2; + monst.dudes[i].number = which; + monst.dudes[i].m_loc = where; + monst.dudes[i].summoned = 0; + monst.dudes[i].monst_start = null_start_type; + monst_target[i] = 6; + + if (monst.dudes[i].m_d.picture_num < 1000) + add_monst_graphic(which,1); + + take_crate(where.x,where.y); + take_barrel(where.x,where.y); + + return i; + } + return 90; +} + +// returns TRUE if placement was successful +Boolean summon_monster(unsigned char which,location where,short duration,short given_attitude) +//which; // if in town, this is caster loc., if in combat, this is where to try + // to put monster +{ + location loc; + short which_m,spot; + + if ((is_town()) || (monsters_going)) { + // Ooooh ... mondo kludge. Need to find caster's attitude to give it to monst. + which_m = monst_there(where); + loc = find_clear_spot(where,0); + if (loc.x == 0) + return FALSE; + } + else { + // pc may be summoning using item, in which case where will be pc's space, so fix + if (pc_there(where) < 6) { + where = find_clear_spot(where,0); + if (where.x == 0) + return FALSE; + } + if ((is_barrel(where.x,where.y)) || (is_crate(where.x,where.y))) + return FALSE; + loc = where; + } + + spot = c_town.placeMonster(which,loc); + if (spot >= T_M) { + if (duration < 100) + add_string_to_buf(" Too many monsters."); + return FALSE; + } + + c_town.monst.dudes[spot].attitude = given_attitude; + + if (which > 0) {//monster here for good + c_town.monst.dudes[spot].summoned = duration; + monst_spell_note(which,21); + } + else c_town.monst.dudes[spot].summoned = 0; + + return TRUE; +} + +void current_town_type::activateMonsters(short code) +{ + short i; + unsigned char which; + + if (code == 0) return; + + for (i = 0; i < T_M; i++) + if (monst.dudes[i].monst_start.spec_enc_code == code && party.stuff_done[monst.dudes[i].monst_start.spec1][monst.dudes[i].monst_start.spec2] == 0) + { + monst.dudes[i].monst_start.spec_enc_code = 0; + monst.dudes[i].active = 2; + which = monst.dudes[i].number; + monst.dudes[i].attitude = t_d.creatures[i].start_attitude; + + monst.dudes[i].summoned = 0; + monst.dudes[i].m_loc = t_d.creatures[i].start_loc; + monst.dudes[i].m_d = return_monster_template(monst.dudes[i].number); + monst_target[i] = 6; + + add_monst_graphic(monst.dudes[i].number,1); + take_crate(monst.dudes[i].m_loc.x,monst.dudes[i].m_loc.y); + take_barrel(monst.dudes[i].m_loc.x,monst.dudes[i].m_loc.y); + } +} + +short get_encumberance(short pc_num) +{ + short store = 0,i,what_val; + + for (i = 0; i < 16; i++) + if (adven[pc_num].equip[i] == TRUE) { + what_val = adven[pc_num].items[i].awkward; + if ((what_val == 1) && (get_ran(1,0,130) < hit_chance[adven[pc_num].skills[8]])) + what_val--; + if ((what_val > 1) && (get_ran(1,0,70) < hit_chance[adven[pc_num].skills[8]])) + what_val--; + store += what_val; + } + return store; +} + +unsigned short get_summon_monster(short summon_class) +{ + unsigned short i,j; + + for (i = 0; i < 200; i++) + { + j = get_ran(1,1,255); + if (scenario.scen_monsters[j].summon_type == summon_class) + return j; + } + ASB(" Summon failed."); + return 0; +} diff --git a/Win32/Blades of Exile/MONSTER.H b/Win32/Blades of Exile/MONSTER.H new file mode 100644 index 00000000..927182ec --- /dev/null +++ b/Win32/Blades of Exile/MONSTER.H @@ -0,0 +1,37 @@ +#ifndef _MONSTER_H + #define _MONSTER_H + +monster_record_type return_monster_template(unsigned char store); +short difficulty_adjust(); +short out_enc_lev_tot(short which); +void create_wand_monst(); +void place_outd_wand_monst(location where,out_wandering_type group,short forced); +short get_monst_picnum(unsigned char monst); +void get_monst_dims(unsigned char monst,short *width, short *height); +void set_up_monst(short mode,unsigned char m_num); +void do_monsters(); +Boolean monst_hate_spot(short which_m,location *good_loc); +short monst_pick_target(short which_m); +short monst_pick_target_monst(creature_data_type *which_m); +short monst_pick_target_pc(short m_num,creature_data_type *which_m); +short select_active_pc(); +short closest_pc(location where); +short switch_target_to_adjacent(short which_m,short orig_target); +Boolean rand_move(int i); +Boolean seek_party(short i,location l1,location l2); +Boolean flee_party(short i,location l1,location l2); +Boolean try_move(short i,location start,short x,short y); +Boolean combat_move_monster(short which,location destination); +location find_clear_spot(location from_where,short mode); +short pc_there(location where); +Boolean outdoor_move_monster(short num,location dest); +Boolean town_move_monster(short num,location dest); +Boolean monster_placid(short m_num); +void monst_inflict_fields(short which_monst); +Boolean monst_check_special_terrain(location where_check,short mode,short which_monst); +void forced_place_monster(unsigned char which,location where); +Boolean summon_monster(unsigned char which,location where,short duration,short given_attitude); +short get_encumberance(short pc_num); +unsigned short get_summon_monster(short summon_class); + +#endif diff --git a/Win32/Blades of Exile/NEWGRAPH.CPP b/Win32/Blades of Exile/NEWGRAPH.CPP new file mode 100644 index 00000000..c49e55cf --- /dev/null +++ b/Win32/Blades of Exile/NEWGRAPH.CPP @@ -0,0 +1,1309 @@ +#include + +#include "string.h" +#include "stdio.h" +#include "global.h" +#include "graphics.h" +#include "gutils.h" +#include "monster.h" +#include "dlogtool.h" +#include "newgraph.h" +#include "fileio.h" +#include "itemdata.h" +#include "locutils.h" +#include "fields.h" +#include "text.h" +#include "exlsound.h" +#include "graphutl.h" + +#include "globvar.h" + +// Missile anim vars +typedef struct { + location dest; + short missile_type; // -1 no miss + short path_type,x_adj,y_adj; + } store_missile_type; + +typedef struct { + location dest; + short val_to_place,offset; + short place_type; // 0 - on spot, 1 - random area near spot + short boom_type; // -1 no miss + short x_adj,y_adj; + } store_boom_type; + +store_missile_type store_missiles[30]; +store_boom_type store_booms[30]; +Boolean have_missile,have_boom; +RECT explode_place_rect[30]; + +char last_light_mask[13][13]; + +void MoveTo(short x, short y) +{ + store_text_x = x; + store_text_y = y - 16; +} + +void apply_unseen_mask() +{ + RECT base_rect = {8,10,43,53}/*{9,9,43,53}*/,to_rect,big_to = {13,13,265,337}; /**/ + short i,j,k,l; + Boolean need_bother = FALSE; + HDC hdc; + HBITMAP store_bmp; + HBRUSH old_brush; + HPEN old_pen; + + if (PSD[306][2] > 0) + return; + if ((is_combat()) && (which_combat_type == 0)) + return; + if (!(is_out()) && (c_town.town.lighting > 0)) + return; + + for (i = 0; i < 11; i++) + for (j = 0; j < 11; j++) + if (unexplored_area[i + 1][j + 1] == 1) + need_bother = TRUE; + if (need_bother == FALSE) + return; + + hdc = CreateCompatibleDC(main_dc); + SetBkMode(hdc,TRANSPARENT); + old_brush = (HBRUSH) SelectObject(hdc,checker_brush); + old_pen = (HPEN) SelectObject(hdc,GetStockObject(NULL_PEN)); + SetROP2(hdc,R2_MASKPEN); + + store_bmp = (HBITMAP) SelectObject(hdc,terrain_screen_gworld); + + for (i = 0; i < 11; i++) + for (j = 0; j < 11; j++) + if (unexplored_area[i + 1][j + 1] == 1) { + + to_rect = base_rect; + OffsetRect(&to_rect,-28 + i * 28 + 2,-36 + 36 * j); + //SectRect(&to_rect,&big_to,&to_rect); + IntersectRect(&to_rect,&to_rect,&big_to); + Rectangle(hdc, to_rect.left,to_rect.top,to_rect.right,to_rect.bottom); + //PaintRect(&to_rect); + for (k = i - 2; k < i + 1; k++) + for (l = j - 2; l < j + 1; l++) + if ((k >= 0) && (l >= 0) && (k < 9) && (l < 9) && ((k != i - 1) || (l != j - 1))) + terrain_there[k][l] = -1; + } + + // Now put text on window. + SelectObject(hdc,old_brush); + SelectObject(hdc,old_pen); + SelectObject(hdc,store_bmp); + if (!DeleteDC(hdc)) DebugQuit("Cannot release DC 3"); +} + +void apply_light_mask() +{ + RECT temp = {0,0,84,108},paint_rect,base_rect = {0,0,28,36}; + RECT big_to = {13,13,265,337}; /**/ + short i,j; + Boolean is_dark = FALSE,same_mask = TRUE; + + HDC hdc; + HBITMAP store_bmp; + HBRUSH old_brush; + + if (PSD[306][2] > 0) + return; + if (is_out()) + return; + if (c_town.town.lighting == 0) + return; + + if (oval_region == NULL) { + temp_rect_rgn = CreateRectRgn(0,0,0,0); + dark_mask_region = CreateRectRgn(0,0,0,0); + oval_region = CreateEllipticRgnIndirect(&temp); + } + + // Process the light array + for (i = 2; i < 11; i++) + for (j = 2; j < 11; j++) + if (light_area[i][j] == 0) is_dark = TRUE; + if (is_dark == FALSE) { + for (i = 2; i < 11; i++) + for (j = 2; j < 11; j++) + last_light_mask[i][j] = 0; + return; + } + for (i = 1; i < 12; i++) + for (j = 1; j < 12; j++) + if ((light_area[i - 1][j - 1] >= 1) && (light_area[i + 1][j - 1] >= 1) && + (light_area[i - 1][j] >= 1) && (light_area[i + 1][j] >= 1) && + (light_area[i - 1][j + 1] >= 1) && (light_area[i + 1][j + 1] >= 1) && + (light_area[i][j - 1] >= 1) && (light_area[i][j + 1] >= 1)) { + light_area[i][j] = 2; + } + for (i = 1; i < 12; i++) + for (j = 1; j < 12; j++) + if ((light_area[i - 1][j - 1] >= 2) && (light_area[i + 1][j - 1] >= 2) && + (light_area[i - 1][j] >= 2) && (light_area[i + 1][j] >= 2) && + (light_area[i - 1][j + 1] >= 2) && (light_area[i + 1][j + 1] >= 2) && + (light_area[i][j - 1] >= 2) && (light_area[i][j + 1] >= 2)) { + light_area[i][j] = 3; + } + + hdc = CreateCompatibleDC(main_dc); + SetBkMode(hdc,TRANSPARENT); + store_bmp = (HBITMAP) SelectObject(hdc,terrain_screen_gworld); + old_brush = (HBRUSH) SelectObject(hdc,GetStockObject(BLACK_BRUSH)); + + for (i = 2; i < 11; i++) + for (j = 2; j < 11; j++) { + if (light_area[i][j] == 1) + terrain_there[i - 2][j - 2] = -1; + } + for (i = 0; i < 13; i++) + for (j = 0; j < 13; j++) + if (last_light_mask[i][j] != light_area[i][j]) + same_mask = FALSE; + + if (same_mask == TRUE) { + PaintRgn(hdc,dark_mask_region); + SelectObject(hdc,store_bmp); + if (!DeleteDC(hdc)) DebugQuit("Cannot release DC 2"); + return; + } + SetRectRgn(dark_mask_region,big_to.left,big_to.top,big_to.right,big_to.bottom); + for (i = 0; i < 13; i++) + for (j = 0; j < 13; j++) + last_light_mask[i][j] = light_area[i][j]; + for (i = 1; i < 12; i++) + for (j = 1; j < 12; j++) { + if (light_area[i][j] == 2) { + + OffsetRgn(oval_region,13 + 28 * (i - 3), 13 + 36 * (j - 3)); + + CombineRgn(dark_mask_region,dark_mask_region,oval_region,RGN_DIFF); + + OffsetRgn(oval_region,-13 + -1 * (28 * (i - 3)),-13 + -1 * (36 * (j - 3))); + } + if (light_area[i][j] == 3) { + paint_rect = base_rect; + OffsetRect(&paint_rect,13 + 28 * (i - 2),13 + 36 * (j - 2)); + SetRectRgn(temp_rect_rgn,paint_rect.left,paint_rect.top, + paint_rect.right + 28,paint_rect.bottom + 36); + CombineRgn(dark_mask_region,dark_mask_region,temp_rect_rgn,RGN_DIFF); + if (light_area[i + 1][j] == 3) light_area[i + 1][j] = 0; + if (light_area[i + 1][j + 1] == 3) light_area[i + 1][j + 1] = 0; + if (light_area[i][j + 1] == 3) light_area[i][j + 1] = 0; + } + } + + PaintRgn(hdc,dark_mask_region); + SelectObject(hdc,store_bmp); + DeleteObject(hdc); +} + + + +void start_missile_anim() +{ + short i; + + if (boom_anim_active == TRUE) + return; + boom_anim_active = TRUE; + for (i = 0; i < 30; i++) { + store_missiles[i].missile_type = -1; + store_booms[i].boom_type = -1; + } + for (i = 0; i < 6; i++) + pc_marked_damage[i] = 0; + for (i = 0; i < T_M; i++) + monst_marked_damage[i] = 0; + have_missile = FALSE; + have_boom = FALSE; +} + +void end_missile_anim() +{ + boom_anim_active = FALSE; +} + +void add_missile(location dest,short missile_type,short path_type,short x_adj,short y_adj) +{ + short i; + + if (boom_anim_active == FALSE) + return; + if (PSD[306][2] > 0) + return; + // lose redundant missiles + for (i = 0; i < 30; i++) + if ((store_missiles[i].missile_type >= 0) && (same_point(dest,store_missiles[i].dest) == TRUE)) + return; + for (i = 0; i < 30; i++) + if (store_missiles[i].missile_type < 0) { + have_missile = TRUE; + store_missiles[i].dest = dest; + store_missiles[i].missile_type =missile_type; + store_missiles[i].path_type =path_type; + store_missiles[i].x_adj =x_adj; + store_missiles[i].y_adj =y_adj; + return; + } +} + +void run_a_missile(location from,location fire_to,short miss_type,short path,short sound_num,short x_adj,short y_adj,short len) +{ + start_missile_anim(); + add_missile(fire_to,miss_type,path, x_adj, y_adj); + do_missile_anim(len,from, sound_num); + end_missile_anim(); +} + +void run_a_boom(location boom_where,short type,short x_adj,short y_adj) +{ + if ((type < 0) || (type > 2)) + return; + start_missile_anim(); + add_explosion(boom_where,-1,0,type, x_adj, y_adj); + do_explosion_anim(5,0); + end_missile_anim(); +} + +void mondo_boom(location l,short type) +{ + short i; + + start_missile_anim(); + for (i = 0; i < 12; i++) + add_explosion(l,-1,1,type,0,0); + do_explosion_anim(5,0); + + end_missile_anim(); +} + +void add_explosion(location dest,short val_to_place,short place_type,short boom_type,short x_adj,short y_adj) +{ + short i; + + if (PSD[306][2] > 0) + return; + if (boom_anim_active == FALSE) + return; + // lose redundant explosions + for (i = 0; i < 30; i++) + if ((store_booms[i].boom_type >= 0) && (same_point(dest,store_booms[i].dest) == TRUE) + && (place_type == 0)) { + if (val_to_place > 0) + store_booms[i].val_to_place = val_to_place; + return; + } + for (i = 0; i < 30; i++) + if (store_booms[i].boom_type < 0) { + have_boom = TRUE; + store_booms[i].offset = (i == 0) ? 0 : -1 * get_ran(1,0,2); + store_booms[i].dest = dest; + store_booms[i].val_to_place = val_to_place; + store_booms[i].place_type = place_type; + store_booms[i].boom_type = boom_type; + store_booms[i].x_adj =x_adj; + store_booms[i].y_adj =y_adj; + return; + } +} + +void do_missile_anim(short num_steps,location missile_origin,short sound_num) +{ + RECT temp_rect,missile_origin_base = {1,1,17,17},active_area_rect,to_rect,from_rect; + short i,store_missile_dir; + POINT start_point,finish_point[30]; + location screen_ul; + + short x1[30],x2[30],y1[30],y2[30],t; // for path paramaterization + RECT missile_place_rect[30],missile_origin_rect[30],store_erase_rect[30]; + POINT current_terrain_ul; + HBITMAP temp_gworld; + long delay_dummy; + RECT ter_scrn_rect = {0,0,279,351}; + long t1,t2; + long pause_len = 0; + + t2 = t1 = (long) GetCurrentTime(); + if (sound_num == 11) pause_len = 660; + if (sound_num == 12) pause_len = 410; + if (sound_num == 14) pause_len = 200; + if (sound_num == 53) pause_len = 1000; + if (sound_num == 64) pause_len = 500; + + if ((have_missile == FALSE) || (boom_anim_active == FALSE)) { + boom_anim_active = FALSE; + return; + } + + for (i = 0; i < 30; i++) + if (store_missiles[i].missile_type >= 0) + i = 50; + if (i == 30) + return; + + // initialize general data + if ((in_startup_mode == TRUE) && (store_anim_type == 0)) { + current_terrain_ul.x = 306; + current_terrain_ul.y = 5; + } + else if ((cartoon_happening == TRUE) && (store_anim_type > 0)) { + current_terrain_ul = store_anim_ul; + } + else { + current_terrain_ul.x = current_terrain_ul.y = 5; + } + + // make terrain_template contain current terrain all nicely + draw_terrain(1); + to_rect = ter_scrn_rect; + OffsetRect(&to_rect,current_terrain_ul.x, current_terrain_ul.y); + rect_draw_some_item(terrain_screen_gworld,ter_scrn_rect, + terrain_screen_gworld,to_rect,0,1); + + // create and clip temporary anim template + temp_rect = ter_scrn_rect; + temp_gworld = CreateCompatibleBitmap(main_dc,ter_scrn_rect.right,ter_scrn_rect.bottom); + active_area_rect = temp_rect; + InflateRect(&active_area_rect,-13,-13); + + // init missile paths + for (i = 0; i < 30; i++) { + SetRectEmpty(&store_erase_rect[i]); + if ((store_missiles[i].missile_type >= 0) && (same_point(missile_origin,store_missiles[i].dest) == TRUE)) + store_missiles[i].missile_type = -1; + } + screen_ul.x = center.x - 4; screen_ul.y = center.y - 4; + start_point.x = 13 + 14 + 28 * (short) (missile_origin.x - screen_ul.x); + start_point.y = 13 + 18 + 36 * (short) (missile_origin.y - screen_ul.y); + for (i = 0; i < 30; i++) + if (store_missiles[i].missile_type >= 0) { + finish_point[i].x = 1 + 13 + 14 + store_missiles[i].x_adj + 28 * (short) (store_missiles[i].dest.x - screen_ul.x); + finish_point[i].y = 1 + 13 + 18 + store_missiles[i].y_adj + 36 * (short) (store_missiles[i].dest.y - screen_ul.y); + // note ... +1 at beginning is put in to prevent infinite slope + + if (store_missiles[i].missile_type < 7) { + store_missile_dir = get_missile_direction(start_point,finish_point[i]); + missile_origin_rect[i] = missile_origin_base; + OffsetRect(&missile_origin_rect[i],18 * store_missile_dir,18 * store_missiles[i].missile_type); + } + else { + missile_origin_rect[i] = missile_origin_base; + OffsetRect(&missile_origin_rect[i],0,18 * store_missiles[i].missile_type); + } + + // x1 slope x2 start pt + x1[i] = finish_point[i].x - start_point.x; + x2[i] = start_point.x; + y1[i] = finish_point[i].y - start_point.y; + y2[i] = start_point.y; + } + else missile_place_rect[i].top =missile_place_rect[i].left =missile_place_rect[i].bottom =missile_place_rect[i].right = 0; + + play_sound(-1 * sound_num); + + + // Now, at last, launch missile + for (t = 0; t < num_steps; t++) { + for (i = 0; i < 30; i++) + if (store_missiles[i].missile_type >= 0) { + // Where place? + temp_rect = missile_origin_base; + OffsetRect(&temp_rect,-8 + x2[i] + (x1[i] * t) / num_steps, + -8 + y2[i] + (y1[i] * t) / num_steps); + + // now adjust for different paths + if (store_missiles[i].path_type == 1) + OffsetRect(&temp_rect,0, + -1 * (t * (num_steps - t)) / 100); + + //SectRect(&temp_rect,&active_area_rect,&missile_place_rect[i]); + IntersectRect(&missile_place_rect[i],&temp_rect,&active_area_rect); + + // Now put terrain in temporary; + rect_draw_some_item(terrain_screen_gworld,missile_place_rect[i], + temp_gworld,missile_place_rect[i],0,0); + // Now put in missile + from_rect = missile_origin_rect[i]; + if (store_missiles[i].missile_type >= 7) + OffsetRect(&from_rect,18 * (t % 8),0); + rect_draw_some_item(missiles_gworld,from_rect, + temp_gworld,temp_rect,1,0); + } + + // Now draw all missiles to screen + for (i = 0; i < 30; i++) + if (store_missiles[i].missile_type >= 0) { + to_rect = store_erase_rect[i]; + OffsetRect(&to_rect,current_terrain_ul.x,current_terrain_ul.y); + rect_draw_some_item(terrain_screen_gworld,store_erase_rect[i], + terrain_screen_gworld,to_rect,0,1); + + to_rect = missile_place_rect[i]; + store_erase_rect[i] = to_rect; + OffsetRect(&to_rect,current_terrain_ul.x,current_terrain_ul.y); + rect_draw_some_item(temp_gworld,missile_place_rect[i], + temp_gworld,to_rect,0,1); + } + if ((PSD[306][6] == 3) || ((PSD[306][6] == 1) && (t % 4 == 0)) || ((PSD[306][6] == 2) && (t % 3 == 0))) + Delay(1,&delay_dummy); + if ((cartoon_happening == TRUE) && (t % 3 == 0) ) + Delay(1,&delay_dummy); + } + + // Exit gracefully, and clean up screen + for (i = 0; i < 30; i++) + store_missiles[i].missile_type = -1; + DeleteObject(temp_gworld); + + to_rect = ter_scrn_rect; + OffsetRect(&to_rect,current_terrain_ul.x,current_terrain_ul.y); + rect_draw_some_item(terrain_screen_gworld,ter_scrn_rect, + terrain_screen_gworld,to_rect,0,1); + + while (t2 - t1 < pause_len + 40) { + t2 = (long)GetCurrentTime(); + } + play_sound(99); +} + +short get_missile_direction(POINT origin_point,POINT the_point) +{ + location store_dir; + short dir = 0; + // To reuse legacy code, will renormalize the_point, which is missile destination, + // so that origin_point is moved to (149,185) and the_point is moved in proportion + the_point.x += 149 - origin_point.x; + the_point.y += 185 - origin_point.y; + + if ((the_point.x < 135) & (the_point.y >= ((the_point.x * 34) / 10) - 293) + & (the_point.y <= (-1 * ((the_point.x * 34) / 10) + 663))) + store_dir.x--; + if ((the_point.x > 163) & (the_point.y <= ((the_point.x * 34) / 10) - 350) + & (the_point.y >= (-1 * ((the_point.x * 34) / 10) + 721))) + store_dir.x++; + + if ((the_point.y < 167) & (the_point.y <= (the_point.x / 2) + 102) + & (the_point.y <= (-1 * (the_point.x / 2) + 249))) + store_dir.y--; + if ((the_point.y > 203) & (the_point.y >= (the_point.x / 2) + 123) + & (the_point.y >= (-1 * (the_point.x / 2) + 268))) + store_dir.y++; + + switch (store_dir.y) { + case 0: + dir = 4 - 2 * (store_dir.x); break; + case -1: + dir = (store_dir.x == -1) ? 7 : store_dir.x; break; + case 1: + dir = 4 - store_dir.x; break; + } + return dir; +} + +void do_explosion_anim(short, short special_draw) +// sound_num currently ignored +// special_draw - 0 normal 1 - first half 2 - second half +{ + RECT temp_rect,to_rect,from_rect; + RECT base_rect = {0,0,28,36},text_rect; + char str[256]; + short i,temp_val,temp_val2; + + location screen_ul; + + short t,cur_boom_type = 0; + POINT current_terrain_ul; + HBITMAP temp_gworld; + long delay_dummy; + short boom_type_sound[3] = {5,10,53}; + RECT ter_scrn_rect = {0,0,279,351}; + HDC hdc; + COLORREF colors[5] = {RGB(0,0,0),RGB(255,0,0),RGB(128,0,0),RGB(0,160,0),RGB(255,255,255)}; + HBITMAP store_bmp; + long t1,t2; + long snd_len[3] = {1500,1410,1100}; + + t2 = t1 = (long) GetCurrentTime(); + + if ((have_boom == FALSE) || (boom_anim_active == FALSE)) { + boom_anim_active = FALSE; + return; + } + + for (i = 0; i < 30; i++) + if (store_booms[i].boom_type >= 0) + i = 50; + if (i == 30) + return; + + // initialize general data + if ((in_startup_mode == TRUE) && (store_anim_type == 0)) { + current_terrain_ul.x = 306; + current_terrain_ul.y = 5; + } + else if ((cartoon_happening == TRUE) && (store_anim_type > 0)) { + current_terrain_ul = store_anim_ul; + } + else { + current_terrain_ul.x = current_terrain_ul.y = 5; + } + + + // make terrain_template contain current terrain all nicely + draw_terrain(1); + if (special_draw != 2) { + to_rect = ter_scrn_rect; + OffsetRect(&to_rect,current_terrain_ul.x, current_terrain_ul.y); + rect_draw_some_item(terrain_screen_gworld,ter_scrn_rect, + terrain_screen_gworld,to_rect,0,1); + } + + + // create and clip temporary anim template + temp_rect = ter_scrn_rect; + temp_gworld = CreateCompatibleBitmap(main_dc,ter_scrn_rect.right,ter_scrn_rect.bottom); + + hdc = CreateCompatibleDC(main_dc); + SetBkMode(hdc,TRANSPARENT); + SelectObject(hdc,small_bold_font); + SetTextColor(hdc,colors[4]); + + // init missile paths + screen_ul.x = center.x - 4; screen_ul.y = center.y - 4; + for (i = 0; i < 30; i++) + if ((store_booms[i].boom_type >= 0) && (special_draw < 2)) { + cur_boom_type = store_booms[i].boom_type; + explode_place_rect[i] = base_rect; + OffsetRect(&explode_place_rect[i],13 + 28 * (store_booms[i].dest.x - screen_ul.x) + store_booms[i].x_adj, + 13 + 36 * (store_booms[i].dest.y - screen_ul.y) + store_booms[i].y_adj); + + if ((store_booms[i].place_type == 1) && (special_draw < 2)) { + temp_val = get_ran(1,0,50) - 25; + temp_val2 = get_ran(1,0,50) - 25; + OffsetRect(&explode_place_rect[i],temp_val,temp_val2); + } + + // eliminate stuff that's too gone. + IntersectRect(&temp_rect,&explode_place_rect[i],&ter_scrn_rect); + if (EqualRect(&temp_rect,&explode_place_rect[i]) == FALSE) { + store_booms[i].boom_type = -1; + } + + } + else if (special_draw < 2) + explode_place_rect[i].top =explode_place_rect[i].left =explode_place_rect[i].bottom =explode_place_rect[i].right = 0; + + if (special_draw < 2) + play_sound(boom_type_sound[cur_boom_type]); + + // Now, at last, do explosion + for (t = (special_draw == 2) ? 6 : 0; t < ((special_draw == 1) ? 6 : 11); t++) { // t goes up to 10 to make sure screen gets cleaned up + // First, lay terrain in temporary graphic area; + for (i = 0; i < 30; i++) + if (store_booms[i].boom_type >= 0) + rect_draw_some_item(terrain_screen_gworld,explode_place_rect[i], + temp_gworld,explode_place_rect[i],0,0); + + // Now put in explosions + for (i = 0; i < 30; i++) + if (store_booms[i].boom_type >= 0) { + if ((t + store_booms[i].offset >= 0) && (t + store_booms[i].offset <= 7)) { + from_rect = base_rect; + OffsetRect(&from_rect,28 * (t + store_booms[i].offset),144 + 36 * (store_booms[i].boom_type)); + rect_draw_some_item(fields_gworld,from_rect, + temp_gworld,explode_place_rect[i],1,0); + + if (store_booms[i].val_to_place > 0) { + text_rect = explode_place_rect[i]; + text_rect.top += 2; + text_rect.left -= 2; + if (store_booms[i].val_to_place < 10) + text_rect.left += 4; + sprintf(str,"%d",store_booms[i].val_to_place); + store_bmp = (HBITMAP) SelectObject(hdc,temp_gworld); + char_win_draw_string(hdc,text_rect,str,1,12); + SelectObject(hdc,store_bmp); + } + } + } + // Now draw all missiles to screen + for (i = 0; i < 30; i++) + if (store_booms[i].boom_type >= 0) { + to_rect = explode_place_rect[i]; + OffsetRect(&to_rect,current_terrain_ul.x,current_terrain_ul.y); + rect_draw_some_item(temp_gworld,explode_place_rect[i], + temp_gworld,to_rect,0,1); + } + + Delay(2 * (1 + PSD[306][6]),&delay_dummy); + if (cartoon_happening == TRUE) + Delay(1,&delay_dummy); + } + + // Exit gracefully, and clean up screen + for (i = 0; i < 30; i++) + if (special_draw != 1) + store_booms[i].boom_type = -1; + SelectObject(hdc,store_bmp); + if (DeleteDC(hdc) == 0) DebugQuit("DeleteDC failed 1"); + DeleteObject(temp_gworld); + + if (special_draw != 1) { + while (t2 - t1 < snd_len[cur_boom_type] + 100) { + t2 = (long)GetCurrentTime(); + } + play_sound(99); + } +} + +/* +shop_type: +0 - weapon shop +1 - armor shop +2 - misc shop +3 - healer +4 - food +5-9 - magic shop +10 - mage spells +11 - priest spells +12 alchemy +*/ +void click_shop_rect(RECT area_rect) +{ + long dum; + + draw_shop_graphics(1,area_rect); + if (play_sounds == TRUE) play_sound(37); + else Delay(5,&dum); + + draw_shop_graphics(0,area_rect); + +} +void draw_shop_graphics(short draw_mode,RECT clip_area_rect) +// mode 1 - drawing dark for button press +{ + RECT area_rect,from_rect,item_info_from = {42,11,56,24}; + + RECT face_rect = {6,6,38,38}; + RECT title_rect = {48,15,260,42}; + RECT dest_rect,help_from = {126,23,142,36},done_from = {0,23,63,46}; /**/ + short faces[13] = {1,1,1,42,43, 1,1,1,1,1, 44,44,44}; + + short i,what_chosen; + RECT shopper_name = {6,44,260,56}; + short current_pos; + + short cur_cost,what_magic_shop,what_magic_shop_item; + char cur_name[256]; + char cur_info_str[256]; + char *cost_strs[] = + { "Extremely Cheap", + "Very Reasonable", + "Pretty Average", + "Somewhat Pricey", + "Expensive", + "Exorbitant", + "Utterly Ridiculous" + }; + item_record_type base_item; + HDC hdc; + COLORREF colors[7] = {RGB(0,0,0),RGB(255,0,130),RGB(128,0,70),RGB(0,0,100),RGB(0,0,220), + RGB(0,220,0),RGB(255,110,255)}; + HBITMAP store_bmp; + HBRUSH old_brush; + + hdc = CreateCompatibleDC(main_dc); + SetBkMode(hdc,TRANSPARENT); + SelectObject(hdc,small_bold_font); + store_bmp = (HBITMAP) SelectObject(hdc,talk_gworld); + + if (draw_mode > 0) { + IntersectClipRect(hdc,clip_area_rect.left,clip_area_rect.top,clip_area_rect.right,clip_area_rect.bottom); + } + + area_rect = talk_area_rect; + OffsetRect(&area_rect,-5,-5); + + old_brush = (HBRUSH) SelectObject(hdc,GetStockObject(NULL_BRUSH)); + Rectangle(hdc,area_rect.left,area_rect.top,area_rect.right,area_rect.bottom); + SelectObject(hdc,old_brush); + InflateRect(&area_rect,-1,-1); + SelectObject(hdc,store_bmp); + if (draw_mode > 0) { + paint_pattern(talk_gworld,0,clip_area_rect,3); + } + else paint_pattern(talk_gworld,0,area_rect,3); + + SelectObject(hdc,talk_gworld); + + old_brush = (HBRUSH) SelectObject(hdc,GetStockObject(NULL_BRUSH)); + Rectangle(hdc,shop_frame.left,shop_frame.top,shop_frame.right,shop_frame.bottom); + SelectObject(hdc,old_brush); + + SelectObject(hdc,store_bmp); + // Place store icon + if (draw_mode == 0) { + i = faces[store_shop_type]; + draw_dialog_graphic((HWND) talk_gworld, face_rect, 1000 + i, FALSE,1); + } + SelectObject(hdc,talk_gworld); + + // Place name of store and shopper name + SelectObject(hdc,fantasy_font); + SetTextColor(hdc,colors[3]); + dest_rect = title_rect; + OffsetRect(&dest_rect,1,-5); + char_win_draw_string(hdc,dest_rect,store_store_name,2,18); + OffsetRect(&dest_rect,-1,-1); + SetTextColor(hdc,colors[4]); + char_win_draw_string(hdc,dest_rect,store_store_name,2,18); + SelectObject(hdc,small_bold_font); + + SetTextColor(hdc,colors[3]); + switch (store_shop_type) { + case 3: sprintf(cur_name,"Healing for %s.",adven[current_pc].name); break; + case 10: sprintf(cur_name,"Mage Spells for %s.",adven[current_pc].name);break; + case 11: sprintf(cur_name,"Priest Spells for %s.",adven[current_pc].name); break; + case 12: sprintf(cur_name,"Buying Alchemy.");break; + case 4: sprintf(cur_name,"Buying Food.");break; + default:sprintf(cur_name,"Shopping for %s.",adven[current_pc].name); break; + } + char_win_draw_string(hdc,shopper_name,cur_name,2,18); + + // Place help and done buttons + SetTextColor(hdc,colors[0]); + SelectObject(hdc,store_bmp); + talk_help_rect.right = talk_help_rect.left + help_from.right - help_from.left; + talk_help_rect.bottom = talk_help_rect.top + help_from.bottom - help_from.top; + rect_draw_some_item(dlg_buttons_gworld,help_from,talk_gworld,talk_help_rect,0,0); + rect_draw_some_item(dlg_buttons_gworld,done_from,talk_gworld,shop_done_rect,0,0); + SelectObject(hdc,talk_gworld); + if (draw_mode == 0) + SetTextColor(hdc,colors[0]); + else SetTextColor(hdc,colors[4]); + + + SelectObject(hdc,small_bold_font); + // Place all the items + for (i = 0; i < 8; i++) { + current_pos = i + GetScrollPos(shop_sbar,SB_CTL); + if (store_shop_items[current_pos] < 0) + break; // theoretically, this shouldn't happen + cur_cost = store_shop_costs[current_pos]; + what_chosen = store_shop_items[current_pos]; + SelectObject(hdc,store_bmp); + switch (what_chosen / 100) { + case 0: case 1: case 2: case 3: case 4: + base_item = get_stored_item(what_chosen); + base_item.item_properties = base_item.item_properties | 1; + draw_dialog_graphic((HWND) talk_gworld, shopping_rects[i][2],1800 + base_item.graphic_num, FALSE,1); + strcpy(cur_name,base_item.full_name); + get_item_interesting_string(base_item,cur_info_str); + break; + case 5: + base_item = store_alchemy(what_chosen - 500); + draw_dialog_graphic((HWND) talk_gworld, shopping_rects[i][2],1853, FALSE,1);//// all graphic nums + strcpy(cur_name,base_item.full_name); + sprintf(cur_info_str,""); + break; + case 6: + break; + case 7: + what_chosen -= 700; + draw_dialog_graphic((HWND) talk_gworld, shopping_rects[i][2],1879, FALSE,1); + strcpy(cur_name,heal_types[what_chosen]); + sprintf(cur_info_str,""); + break; + case 8: + base_item = store_mage_spells(what_chosen - 800 - 30); + draw_dialog_graphic((HWND)talk_gworld, shopping_rects[i][2],1800 + base_item.graphic_num, FALSE,1); + + strcpy(cur_name,base_item.full_name); + sprintf(cur_info_str,""); + break; + case 9: + base_item = store_priest_spells(what_chosen - 900 - 30); + draw_dialog_graphic((HWND)talk_gworld, shopping_rects[i][2],1853, FALSE,1); + strcpy(cur_name,base_item.full_name); + sprintf(cur_info_str,""); + break; + default: + what_magic_shop = (what_chosen / 1000) - 1; + what_magic_shop_item = what_chosen % 1000; + base_item = party.magic_store_items[what_magic_shop][what_magic_shop_item]; + base_item.item_properties = base_item.item_properties | 1; + draw_dialog_graphic((HWND)talk_gworld, shopping_rects[i][2],1800 + base_item.graphic_num, FALSE,1); + strcpy(cur_name,base_item.full_name); + get_item_interesting_string(base_item,cur_info_str); + break; + } + + from_rect = item_info_from; + OffsetRect(&from_rect,0,1); + shopping_rects[i][6].bottom = shopping_rects[i][6].top + + (from_rect.bottom - from_rect.top); + if ((store_shop_type != 3) && (store_shop_type != 4)) + rect_draw_some_item(mixed_gworld,item_info_from,talk_gworld,shopping_rects[i][6],1,0); + SelectObject(hdc,talk_gworld); + // Now draw item shopping_rects[i][7] + // 0 - whole area, 1 - active area 2 - graphic 3 - item name + // 4 - item cost 5 - item extra str 6 - item help button + char_win_draw_string(hdc,shopping_rects[i][3],cur_name,0,12); + sprintf(cur_name,"Cost: %d",cur_cost); + char_win_draw_string(hdc,shopping_rects[i][4],cur_name,0,12); + char_win_draw_string(hdc,shopping_rects[i][5],cur_info_str,0,12); + + } + + // Finally, cost info and help strs + sprintf(cur_name,"Prices here are %s.",cost_strs[store_cost_mult]); + char_win_draw_string(hdc,bottom_help_rects[0],cur_name,0,12); + char_win_draw_string(hdc,bottom_help_rects[1],"Click on item name (or type 'a'-'h') to buy.",0,12); + char_win_draw_string(hdc,bottom_help_rects[2],"Hit done button (or Esc.) to quit.",0,12); + if ((store_shop_type != 3) && (store_shop_type != 4)) + char_win_draw_string(hdc,bottom_help_rects[3],"'I' button brings up description.",0,12); + + SelectObject(hdc,store_bmp); + if (!DeleteDC(hdc)) DebugQuit("Cannot release DC 8"); + + refresh_shopping(); + ShowScrollBar(shop_sbar,SB_CTL,TRUE); +} + +void refresh_shopping() +{ + RECT from_rects[4] = {{0,0,279,62},{0,62,253,352},{269,62,279,352},{0,352,279,415}},to_rect; + /**/ + short i; + + for (i = 0; i < 4; i++) { + to_rect = from_rects[i]; + OffsetRect(&to_rect,5,5); + rect_draw_some_item(talk_gworld,from_rects[i],talk_gworld,to_rect,0,1); + } +} + +void click_talk_rect(char *str_to_place,char *str_to_place2,RECT c_rect) +{ + + long dum; + + place_talk_str(str_to_place,str_to_place2,1,c_rect); + if (play_sounds == TRUE) + play_sound(37); + else Delay(5,&dum); + place_talk_str(str_to_place,str_to_place2,0,c_rect); +} + +item_record_type store_mage_spells(short which_s) +{ + item_record_type spell = {21,0, 0,0,0,0,0,0, 53,0,0,0,0,0, 0, 0,0, location(),"", "",0,0,0,0}; + + short cost[32] = {150,200,150,1000,1200,400,300,200, + 200,250,500,1500,300, 250,125,150, + 400,450, 800,600,700,600,7500, 500, + 5000,3000,3500,4000,4000,4500,7000,5000}; + + char str[256]; + + if (which_s != minmax(0,31,(int)which_s)) + which_s = 0; + spell.item_level = which_s + 30; + spell.value = cost[which_s]; + GetIndString(str,38,which_s + 1); + strcpy((char *)spell.full_name,(char *)str); + return spell; +} + +// which_s = 0 means that it returns first 4th level spell +item_record_type store_priest_spells(short which_s) +{ + item_record_type spell = {21,0, 0,0,0,0,0,0, 53,0,0,0,0,0, 0, 0,0, location(),"", "",0,0,0,0}; + + short cost[32] = + {100,150,75,400,200, 100,80,250, + 400,400,1200,600,300, 600,350,250, + 500,500,600,800, 1000,900,400,600, + 2500,2000,4500,4500,3000,3000,2000,2000}; + char str[256]; + + if (which_s != minmax(0,31,(int)which_s)) + which_s = 0; + spell.item_level = which_s + 30; + spell.value = cost[which_s]; + GetIndString(str,38,which_s + 50); + strcpy((char *)spell.full_name,(char *)str); + return spell; +} +item_record_type store_alchemy(short which_s) +{ + item_record_type spell = {21,0, 0,0,0,0,0,0, 53,0,0,0,0,0, 0, 0,0, location(),"", "",0,0,0,0}; +short val[20] = {50,75,30,130,100,150, 200,200,300,250,300, 500,600,750,700,1000,10000,5000,7000,12000}; + char str[256]; + + if (which_s != minmax(0,19,(int)which_s)) + which_s = 0; + spell.item_level = which_s; + spell.value = val[which_s]; + GetIndString(str,38,which_s + 100); + strcpy((char *)spell.full_name,(char *)str); + return spell; +} + +void get_item_interesting_string(item_record_type item,char *message) +{ + if (item.isProperty()) + { + sprintf(message,"Not yours."); + return; + } + if (item.isIdent() == false) + { + sprintf(message,""); + return; + } + if (item.isCursed()) + { + sprintf(message,"Cursed item."); + return; + } + switch (item.variety) { + case 1: case 2: case 5: case 6: case 24: case 25: //// + if (item.bonus != 0) + sprintf(message,"Damage: 1-%d + %d.",item.item_level,item.bonus); + else sprintf(message,"Damage: 1-%d.",item.item_level); + break; + case 12: case 13: case 14: case 15: case 16: case 17: + sprintf(message,"Blocks %d-%d damage.",item.item_level + (item.protection > 0) ? 1 : 0, + item.item_level + item.protection); + break; + case 4: case 23: + sprintf(message,"Bonus : +%d to hit.",item.bonus); + break; + case 3: + sprintf(message,"%d gold pieces.",item.item_level); + break; + case 11: + sprintf(message,"%d food.",item.item_level); + break; + case 20: + sprintf(message,"Poison: Does %d-%d damage.",item.item_level,item.item_level * 6); + break; + default: + sprintf(message,""); + if (item.charges > 0) + sprintf(message,"Uses: %d",item.charges); + break; + } + if (item.charges > 0) + sprintf(message,"Uses: %d",item.charges); + } + + +void place_talk_str(char *str_to_place,char *str_to_place2,short color,RECT c_rect) +// color 0 - regular 1 - darker +{ + RECT area_rect; + + RECT face_rect = {6,6,38,38}; + RECT title_rect = {48,19,260,42}; + RECT dest_rect,help_from = {126,23,142,36}; /**/ + + short i,j,str_len,line_height = 18; + char p_str[256],str[256],str_to_draw[256],str_to_draw2[256]; + short text_len[257],current_rect,store_last_word_break = 0,start_of_last_kept_word = -1; + short last_line_break = 0,last_word_break = 0,on_what_line = 0,last_stored_word_break = 0; + Boolean force_skip = FALSE; + short face_to_draw; + + HDC hdc; + COLORREF colors[7] = {RGB(0,0,0),RGB(0,0,204),RGB(0,0,102),RGB(0,0,100),RGB(0,0,220), + RGB(51,153,51),RGB(0,204,0)}; + HBITMAP store_bmp; + HBRUSH old_brush; + HFONT store_font; + + hdc = CreateCompatibleDC(main_dc); + SetBkMode(hdc,TRANSPARENT); + store_font = (HFONT) SelectObject(hdc,fantasy_font); + store_bmp = (HBITMAP)SelectObject(hdc,talk_gworld); + + if (c_rect.right > 0) { + IntersectClipRect(hdc,c_rect.left,c_rect.top,c_rect.right,c_rect.bottom); + } + + area_rect = talk_area_rect; + OffsetRect(&area_rect,-5,-5); + + old_brush = (HBRUSH) SelectObject(hdc,GetStockObject(NULL_BRUSH)); + Rectangle(hdc,area_rect.left,area_rect.top,area_rect.right,area_rect.bottom); + SelectObject(hdc,old_brush); + InflateRect(&area_rect,-1,-1); + + SelectObject(hdc,store_bmp); + if (c_rect.right > 0) { + paint_pattern(talk_gworld,0,c_rect,3); + } + else paint_pattern(talk_gworld,0,area_rect,3); + + // Put help button + talk_help_rect.right = talk_help_rect.left + help_from.right - help_from.left; + talk_help_rect.bottom = talk_help_rect.top + help_from.bottom - help_from.top; + rect_draw_some_item(dlg_buttons_gworld,help_from,talk_gworld,talk_help_rect,0,0); + + // Place face of talkee + if ((color == 0) && (c_rect.right == 0)) { + face_to_draw = scenario.scen_monsters[store_monst_type].default_facial_pic; + if (store_talk_face_pic >= 0) + face_to_draw = store_talk_face_pic; + if (store_talk_face_pic >= 1000) { + draw_dialog_graphic((HWND) talk_gworld, face_rect, 2400 + store_talk_face_pic - 1000, FALSE,1); + } + else { + i = get_monst_picnum(store_monst_type); + + if (face_to_draw <= 0) + draw_dialog_graphic((HWND) talk_gworld, face_rect, 400 + i, FALSE,1); + else draw_dialog_graphic((HWND) talk_gworld, face_rect, 1000 + face_to_draw, FALSE,1); + } + } + SelectObject(hdc,talk_gworld); + + // Place name oftalkee + SetTextColor(hdc,colors[3]); + dest_rect = title_rect; + OffsetRect(&dest_rect,1,-5); + char_win_draw_string(hdc,dest_rect,title_string,2,18); + OffsetRect(&dest_rect,-1,-1); + SetTextColor(hdc,colors[4]); + char_win_draw_string(hdc,dest_rect,title_string,2,18); + + // Place buttons at bottom. + if (color == 0) + SetTextColor(hdc,colors[5]); + else SetTextColor(hdc,colors[6]); + for (i = 0; i < 9; i++) + if ((talk_end_forced == FALSE) || (i == 6) || (i == 5)) { + OffsetRect(&preset_words[i].word_rect,0,-2); + char_win_draw_string(hdc,preset_words[i].word_rect,preset_words[i].word,2,18); + OffsetRect(&preset_words[i].word_rect,0,2); + } + // Place bulk of what said. Save words. + if (color == 0) + for (i = 0; i < 50; i++) + store_words[i].word_rect.left = store_words[i].word_rect.right = 0; + + str_len = (short) strlen((char *)str_to_place); + if (str_len == 0) { + sprintf((char *) str_to_place,"."); + } + strcpy((char *) str,str_to_place); + strcpy((char *) p_str,str_to_place); + + for (i = 0; i < 257; i++) + text_len[i]= 0; + MeasureText(256,p_str,text_len,hdc); + + dest_rect = word_place_rect; + + current_rect = 0; + + if (color == 0) + SetTextColor(hdc,colors[2]); + else SetTextColor(hdc,colors[1]); + MoveTo(dest_rect.left + 1 , dest_rect.top + 1 + line_height * on_what_line + 9); + + for (i = 0;i < str_len;i++) { + if (((str[i] != 39) && ((str[i] < 65) || (str[i] > 122)) && ((str[i] < 48) || (str[i] > 57))) && (color == 0)) { // New word, so set up a rect + if (((i - store_last_word_break >= 4) || (i >= str_len - 1)) + && (i - last_stored_word_break >= 4) && (talk_end_forced == FALSE)) { + store_words[current_rect].word_rect.left = dest_rect.left + (text_len[store_last_word_break] - text_len[last_line_break]) - 2; + store_words[current_rect].word_rect.right = dest_rect.left + (text_len[i + 1] - text_len[last_line_break]) - 1; + store_words[current_rect].word_rect.top = dest_rect.top + 1 + line_height * on_what_line - 5; + store_words[current_rect].word_rect.bottom = dest_rect.top + 1 + line_height * on_what_line + 13; + + if ((str[store_last_word_break] < 48) || (str[store_last_word_break] == 96) + || (str[store_last_word_break] > 122) + || ((str[store_last_word_break] >= 58) && (str[store_last_word_break] <= 64))) + store_last_word_break++; + + store_words[current_rect].word[0] = str[store_last_word_break]; + store_words[current_rect].word[1] = str[store_last_word_break + 1]; + store_words[current_rect].word[2] = str[store_last_word_break + 2]; + store_words[current_rect].word[3] = str[store_last_word_break + 3]; + store_words[current_rect].word[4] = 0; + for (j = 0; j < 4; j++) + if ((store_words[current_rect].word[j] >= 65) && (store_words[current_rect].word[j] <= 90)) + store_words[current_rect].word[j] += 32; + if (scan_for_response(store_words[current_rect].word) < 0) { + store_words[current_rect].word_rect.left = store_words[current_rect].word_rect.right = 0; + } + else { + start_of_last_kept_word = store_last_word_break; + if (current_rect < 49) + current_rect++; + } + last_stored_word_break = i + 1; + } + } + if (((text_len[i] - text_len[last_line_break] > (dest_rect.right - dest_rect.left - 6)) + && (last_word_break > last_line_break)) || (str[i] == '|') || (i == str_len - 1)) { + if (str[i] == '|') { + str[i] = ' '; + force_skip = TRUE; + } + store_last_word_break = last_word_break; + if (i == str_len - 1) + last_word_break = i + 2; + sprintf((char *)str_to_draw," "); + strncpy ((char *) str_to_draw,(char *) str + last_line_break,(size_t) (last_word_break - last_line_break - 1)); + sprintf((char *)str_to_draw2," %s",str_to_draw); + str_to_draw2[0] = (char) strlen((char *)str_to_draw); + DrawString((str_to_draw2 + 1),store_text_x,store_text_y, hdc); + on_what_line++; + MoveTo(dest_rect.left + 1 , dest_rect.top + 1 + line_height * on_what_line + 9); + last_line_break = last_word_break; + if (force_skip == TRUE) { + force_skip = FALSE; + i++; + last_line_break++; + last_word_break++; + } + if ((start_of_last_kept_word >= last_line_break) && (current_rect > 0)) { + OffsetRect(&store_words[current_rect - 1].word_rect,5 + -1 * store_words[current_rect - 1].word_rect.left,line_height); + } + } + if (str[i] == ' ') { // New word + store_last_word_break = last_word_break = i + 1; + } + if (on_what_line == 17) + i = 10000; + } + + // Now for string 2 + str_len = (short) strlen((char *)str_to_place2); + start_of_last_kept_word = -1; + + if (str_len > 0) { + + strcpy((char *) str,str_to_place2); + strcpy((char *) p_str,str_to_place2); + + for (i = 0; i < 257; i++) + text_len[i]= 0; + MeasureText(256,p_str,text_len,hdc); + + last_line_break = store_last_word_break = last_word_break = last_stored_word_break = 0; + MoveTo(dest_rect.left + 1 , dest_rect.top + 1 + line_height * on_what_line + 9); + for (i = 0;i < str_len;i++) { + if (((str[i] != 39) && ((str[i] < 65) || (str[i] > 122)) && ((str[i] < 48) || (str[i] > 57))) && (color == 0)) { // New word, so set up a rect + if (((i - store_last_word_break >= 4) || (i >= str_len - 1)) + && (i - last_stored_word_break >= 4) && (talk_end_forced == FALSE)) { + store_words[current_rect].word_rect.left = dest_rect.left + (text_len[store_last_word_break] - text_len[last_line_break]) - 2; + store_words[current_rect].word_rect.right = dest_rect.left + (text_len[i + 1] - text_len[last_line_break]) - 1; + store_words[current_rect].word_rect.top = dest_rect.top + 1 + line_height * on_what_line - 5; + store_words[current_rect].word_rect.bottom = dest_rect.top + 1 + line_height * on_what_line + 13; + + if ((str[store_last_word_break] < 48) || (str[store_last_word_break] == 96) + || (str[store_last_word_break] > 122) + || ((str[store_last_word_break] >= 58) && (str[store_last_word_break] <= 64))) + store_last_word_break++; + + store_words[current_rect].word[0] = str[store_last_word_break]; + store_words[current_rect].word[1] = str[store_last_word_break + 1]; + store_words[current_rect].word[2] = str[store_last_word_break + 2]; + store_words[current_rect].word[3] = str[store_last_word_break + 3]; + store_words[current_rect].word[4] = 0; + for (j = 0; j < 4; j++) + if ((store_words[current_rect].word[j] >= 65) && (store_words[current_rect].word[j] <= 90)) + store_words[current_rect].word[j] += 32; + if (scan_for_response(store_words[current_rect].word) < 0) + store_words[current_rect].word_rect.left = store_words[current_rect].word_rect.right = 0; + else { + start_of_last_kept_word = store_last_word_break; + if (current_rect < 49) + current_rect++; + + } + last_stored_word_break = i + 1; + } + } + if (((text_len[i] - text_len[last_line_break] > (dest_rect.right - dest_rect.left - 6)) + && (last_word_break > last_line_break)) || (str[i] == '|') || (i == str_len - 1)) { + if (str[i] == '|') { + str[i] = ' '; + force_skip = TRUE; + } + store_last_word_break = last_word_break; + if (i == str_len - 1) + last_word_break = i + 2; + sprintf((char *)str_to_draw," "); + strncpy ((char *) str_to_draw,(char *) str + last_line_break,(size_t) (last_word_break - last_line_break - 1)); + sprintf((char *)str_to_draw2," %s",str_to_draw); + str_to_draw2[0] = (char) strlen((char *)str_to_draw); + DrawString((str_to_draw2 + 1),store_text_x,store_text_y, hdc); + on_what_line++; + MoveTo(dest_rect.left + 1 , dest_rect.top + 1 + line_height * on_what_line + 9); + last_line_break = last_word_break; + if (force_skip == TRUE) { + force_skip = FALSE; + i++; + last_line_break++; + last_word_break++; + } + if ((start_of_last_kept_word >= last_line_break) && (current_rect > 0)) { + OffsetRect(&store_words[current_rect - 1].word_rect,5 + -1 * store_words[current_rect - 1].word_rect.left,line_height); + } + } + if (str[i] == ' ') { // New word + store_last_word_break = last_word_break = i + 1; + } + if (on_what_line == 17) + i = 10000; + } + } + + SelectObject(hdc,store_bmp); + SelectObject(hdc,store_font); + if (!DeleteDC(hdc)) DebugQuit("Cannot release DC 7"); + + refresh_talking(); + + // Clean up strings + for (i = 0; i < 50; i++) + for (j = 0; j < 4; j++) + if ((store_words[current_rect].word[j] >= 65) && (store_words[current_rect].word[j] <= 90)) + store_words[current_rect].word[j] += 32; + +} + +void refresh_talking() +{ + RECT from = {0,0,279,415}; + rect_draw_some_item(talk_gworld,from,talk_gworld,talk_area_rect,0,1); +} + +short scan_for_response(char *str) +// returns -1 if no go +{ + short i; + + for (i = 0; i < 60; i++) { // 60 response in each bunch + if ((talking.talk_nodes[i].personality != -1) && + ((talking.talk_nodes[i].personality == store_personality) + || (talking.talk_nodes[i].personality == -2)) && + (((str[0] == talking.talk_nodes[i].link1[0]) && (str[1] == talking.talk_nodes[i].link1[1]) + && (str[2] == talking.talk_nodes[i].link1[2]) && (str[3] == talking.talk_nodes[i].link1[3])) + || ((str[0] == talking.talk_nodes[i].link2[0]) && (str[1] == talking.talk_nodes[i].link2[1]) + && (str[2] == talking.talk_nodes[i].link2[2]) && (str[3] == talking.talk_nodes[i].link2[3])))) + return i; + } + return -1; +} diff --git a/Win32/Blades of Exile/NEWGRAPH.H b/Win32/Blades of Exile/NEWGRAPH.H new file mode 100644 index 00000000..7697cb69 --- /dev/null +++ b/Win32/Blades of Exile/NEWGRAPH.H @@ -0,0 +1,34 @@ +#ifndef _NEWGRAPH_H + #define _NEWGRAPH_H + +typedef struct { + char word[15]; + RECT word_rect; + } word_rect_type; + +void apply_unseen_mask(); +void apply_light_mask(); + +void start_missile_anim(); +short get_missile_direction(POINT origin_point,POINT the_point); +void end_missile_anim() ; +void run_a_missile(location from,location fire_to,short miss_type,short path,short sound_num,short x_adj,short y_adj,short len); +void run_a_boom(location boom_where,short type,short x_adj,short y_adj); +void mondo_boom(location l,short type); +void add_missile(location dest,short missile_type,short path_type,short x_adj,short y_adj); +void add_explosion(location dest,short val_to_place,short place_type,short boom_type,short x_adj,short y_adj); +void do_missile_anim(short num_steps,location missile_origin,short sound_num) ; +void do_explosion_anim(short sound_num,short expand); +void click_shop_rect(RECT area_rect); +void draw_shop_graphics(short draw_mode,RECT clip_area_rect); +void refresh_shopping(); +item_record_type store_mage_spells(short which_s) ; +item_record_type store_priest_spells(short which_s); +item_record_type store_alchemy(short which_s); +void get_item_interesting_string(item_record_type item,char *message); +void click_talk_rect(char *str_to_place,char *str_to_place2,RECT c_rect); +void place_talk_str(char *str_to_place,char *str_to_place2,short color,RECT c_rect); +short scan_for_response(char *str); +void refresh_talking(); + +#endif diff --git a/Win32/Blades of Exile/PARTY.CPP b/Win32/Blades of Exile/PARTY.CPP new file mode 100644 index 00000000..ce64580f --- /dev/null +++ b/Win32/Blades of Exile/PARTY.CPP @@ -0,0 +1,2993 @@ +#include +#include "stdio.h" +#include "global.h" +#include "fileio.h" +#include "graphics.h" +#include "gutils.h" +#include "newgraph.h" +#include "specials.h" +#include "itemdata.h" +#include "infodlgs.h" +#include "items.h" +#include "string.h" +#include "party.h" +#include "monster.h" +#include "dlogtool.h" +#include "town.h" +#include "combat.h" +#include "locutils.h" +#include "fields.h" +#include "text.h" +#include "exlsound.h" +#include "graphutl.h" +#include "globvar.h" + +void draw_caster_buttons(); +void draw_spell_info(); +void draw_spell_pc_info(); +void put_pc_caster_buttons(); +void put_pc_target_buttons(); +void put_spell_led_buttons(); +void put_spell_list(); + +//mode; // 0 - prefab 1 - regular +void init_party(short mode) +{ + short i,j,k,l; + Boolean store_help; + + boat_record_type null_boat = {location(),location(),location(),200,FALSE,FALSE}; + horse_record_type null_horse = {location(),location(),location(),200,FALSE,FALSE}; + + party.age = 0; + party.gold = 200; + party.food = 100; + + store_help = PSD[SDF_NO_INSTANT_HELP]; + + for (i = 0; i < 310; i++) + for (j = 0; j < 10; j++) + party.stuff_done[i][j] = 0; + if(scenario.prog_make_ver[0] < 2) PSD[305][8] = 1; //old scenario format ? so, no resurrection balm needed + else PSD[305][8] = 0; + + PSD[SDF_NO_INSTANT_HELP] = store_help; + + party.light_level = 0; + party.outdoor_corner.x = 7; + party.outdoor_corner.y = 8; + party.i_w_c.x = 1; + party.i_w_c.y = 1; + party.loc_in_sec.x = 36; + party.loc_in_sec.y = 36; + party.p_loc.x = 84; + party.p_loc.y = 84; + for (i = 0; i < 30; i++) party.boats[i] = null_boat; + for (i = 0; i < 30; i++) party.horses[i] = null_horse; + + party.in_boat = -1; + party.in_horse = -1; + + for (i = 0; i < 4; i++) party.creature_save[i].which_town = 200; + for (i = 0; i < 10; i++) party.out_c[i].exists = FALSE; + for (i = 0; i < 5; i++) + for (j = 0; j < 10; j++) party.magic_store_items[i][j].variety = 0; + for (i = 0; i < 4; i++) party.imprisoned_monst[i] = 0; + for (i = 0; i < 256; i++) party.m_seen[i] = 0; + for (i = 0; i < 50; i++) party.journal_str[i] = -1; + for (i = 0; i < 140; i++) + for (j = 0; j < 2; j++) party.special_notes_str[i][j] = 0; + for (i = 0; i < 120; i++) party.talk_save[i].personality = -1; + + party.total_m_killed = 0; + party.total_dam_done = 0; + party.total_xp_gained = 0; + party.total_dam_taken = 0; + party.direction = 0; + party.at_which_save_slot = 0; + + for (i = 0; i < 20; i++) party.alchemy[i] = 0; + for (i = 0; i < 200; i++) party.can_find_town[i] = 0; + for (i = 0; i < 20; i++) party.key_times[i] = 30000; + for (i = 0; i < 30; i++) party.party_event_timers[i] = 0; + for (i = 0; i < 50; i++) party.spec_items[i] = 0; + for (i = 0; i < 120; i++) party.help_received[i] = 0; + for (i = 0; i < 200; i++) party.m_killed[i] = 0; + + sprintf((char *) party.scen_name,""); + + for (i = 0; i < 200; i++) + for (j = 0; j < 8; j++) + party.item_taken[i][j] = 0; + + refresh_store_items(); + + for (i = 0; i < 6; i++) + { + adven[i] = return_dummy_pc(); + if (mode != 1) adven[i] = create_prefab_pc(i); + } + + for (i = 0; i < 96; i++) + for (j = 0; j < 96; j++) + out_e[i][j] = 0; + + for (i = 0; i < 3;i++) + for (j = 0; j < NUM_TOWN_ITEMS; j++) + stored_items[i].items[j] = return_dummy_item(); + + for (i = 0; i < 200; i++) + for (j = 0; j < 8; j++) + for (k = 0; k < 64; k++) { + town_maps.town_maps[i][j][k] = 0; + } + + for (i = 0; i < 100; i++) + for (k = 0; k < 6; k++) + for (l = 0; l < 48; l++) + o_maps.outdoor_maps[i][k][l] = 0; + + // Default is save maps + party.stuff_done[306][0] = 0; + save_maps = TRUE; + + // NOT DEBUG + build_outdoors(); + update_pc_graphics(); + get_reg_data(); +} + +// This is only called after a scenario is loaded and the party is put into it. +// Until that time, the party scen vals are uninited +// Then, it inits the party properly for starting the scenario based +// on the loaded scenario +void init_party_scen_data() +{ + short i,j,k,l; + Boolean stored_item = FALSE; + short store_help; + + party.age = 0; + store_help = PSD[SDF_NO_INSTANT_HELP]; + for (i = 0; i < 310; i++) + for (j = 0; j < 10; j++) + party.stuff_done[i][j] = 0; + PSD[SDF_NO_INSTANT_HELP] = store_help; + if(scenario.prog_make_ver[0] < 2) PSD[305][8] = 1; //old scenario format ? so, no resurrection balm needed + else PSD[305][8] = 0; + + party.light_level = 0; + party.outdoor_corner.x = scenario.out_sec_start.x; + party.outdoor_corner.y = scenario.out_sec_start.y; + party.i_w_c.x = 0; + party.i_w_c.y = 0; + party.loc_in_sec.x = scenario.out_start.x; + party.loc_in_sec.y = scenario.out_start.y; + party.p_loc.x = scenario.out_start.x; + party.p_loc.y = scenario.out_start.y; + for (i = 0; i < NUM_OF_BOATS; i++) party.boats[i] = scenario.scen_boats[i]; + for (i = 0; i < NUM_OF_HORSES; i++) party.horses[i] = scenario.scen_horses[i]; + for (i = 0; i < 30; i++) + { + if ((scenario.scen_boats[i].which_town >= 0) && (scenario.scen_boats[i].boat_loc.x >= 0)) { + if (party.boats[i].exists == FALSE) { + party.boats[i] = scenario.scen_boats[i]; + party.boats[i].exists = TRUE; + } + } + if ((scenario.scen_horses[i].which_town >= 0) && (scenario.scen_horses[i].horse_loc.x >= 0)) { + if (party.horses[i].exists == FALSE) { + party.horses[i] = scenario.scen_horses[i]; + party.horses[i].exists = TRUE; + } + } + } + + party.in_boat = -1; + party.in_horse = -1; + + for (i = 0; i < 4; i++) party.creature_save[i].which_town = INVALID_TOWN; + for (i = 0; i < 10; i++) party.out_c[i].exists = FALSE; + for (i = 0; i < 5; i++) + for (j = 0; j < 10; j++) + party.magic_store_items[i][j].variety = 0; + for (i = 0; i < 4; i++) party.imprisoned_monst[i] = 0; + for (i = 0; i < 256; i++) party.m_seen[i] = 0; + for (i = 0; i < 50; i++) party.journal_str[i] = -1; + for (i = 0; i < 140; i++) + for (j = 0; j < 2; j++) + party.special_notes_str[i][j] = 0; + for (i = 0; i < 120; i++) party.talk_save[i].personality = -1; + + party.direction = 0; + party.at_which_save_slot = 0; + for (i = 0; i < 200; i++) party.can_find_town[i] = 1 - scenario.town_hidden[i]; + for (i = 0; i < 20; i++) party.key_times[i] = 30000; + for (i = 0; i < 30; i++) party.party_event_timers[i] = 0; + for (i = 0; i < 50; i++) party.spec_items[i] = (scenario.special_items[i] >= 10) ? 1 : 0; + for (i = 0; i < 200; i++) party.m_killed[i] = 0; + + for (i = 0; i < 200; i++) + for (j = 0; j < 8; j++) + party.item_taken[i][j] = 0; + + refresh_store_items(); + + for (i = 0; i < 96; i++) + for (j = 0; j < 96; j++) + out_e[i][j] = 0; + + for (i = 0; i < 3;i++) + for (j = 0; j < NUM_TOWN_ITEMS; j++) + if (stored_items[i].items[j].variety != 0) + stored_item = TRUE; + if (stored_item == TRUE) + if (FCD(911,0) == 1) { + for (i = 0; i < 3;i++) + for (j = 0; j < NUM_TOWN_ITEMS; j++) + if (stored_items[i].items[j].variety != 0) + if (give_to_party(stored_items[i].items[j],FALSE) == FALSE) { + i = 20; j = NUM_TOWN_ITEMS + 1; + } + } + for (i = 0; i < 3;i++) + for (j = 0; j < NUM_TOWN_ITEMS; j++) { + stored_items[i].items[j] = return_dummy_item(); + } + + for (i = 0; i < 200; i++) + for (j = 0; j < 8; j++) + for (k = 0; k < 64; k++) { + town_maps.town_maps[i][j][k] = 0; + } + + for (i = 0; i < 100; i++) + for (k = 0; k < 6; k++) + for (l = 0; l < 48; l++) + o_maps.outdoor_maps[i][k][l] = 0; + get_reg_data(); +} + +// When the party is placed into a scen from the startinbg screen, this is called to put the game into game +// mode and load in the scen and init the party info +// party record already contains scen name +void put_party_in_scen() +{ + short i,j; + char strs[6][256] = {"","","","","",""}; + short buttons[3] = {-1,-1,-1}; + Boolean item_took = FALSE; + + for (j = 0; j < 6; j++) + for (i = 0; i < 15; i++) + adven[j].status[i] = 0; + + for (j = 0; j < 6; j++) + { + // unite party + if (adven[j].main_status >= MAIN_STATUS_SPLIT) adven[j].main_status -= MAIN_STATUS_SPLIT; + // start with maximum health + adven[j].cur_health = adven[j].max_health; + // start with maximum amount of spell points + adven[j].cur_sp = adven[j].max_sp; + } + + for (j = 0; j < 6; j++) + for (i = 23; i >= 0; i--) + { + adven[j].items[i].special_class = 0; + if (adven[j].items[i].graphic_num >= 150) + { + adven[j].takeItem(i + 30); // strip away special items + item_took = TRUE; + } + if (adven[j].items[i].ability == 119) + { + adven[j].takeItem(i + 30); // strip away summoning items + item_took = TRUE; + } + if (adven[j].items[i].ability == 120) + { + adven[j].takeItem(i + 30); // strip away summoning items + item_took = TRUE; + } + } + + if (item_took == TRUE) FCD(910,0); + + if (load_scenario() == FALSE) return; + + init_party_scen_data(); + + // if at this point, startup must be over, so make this call to make sure we're ready, + // graphics wise + end_startup(); + in_startup_mode = FALSE; + + set_up_ter_pics(); + + load_outdoors(party.outdoor_corner.x + 1,party.outdoor_corner.y + 1,1,1,0,0,NULL); + load_outdoors(party.outdoor_corner.x,party.outdoor_corner.y + 1,0,1,0,0,NULL); + load_outdoors(party.outdoor_corner.x + 1,party.outdoor_corner.y,1,0,0,0,NULL); + load_outdoors(party.outdoor_corner.x,party.outdoor_corner.y,0,0,0,0,NULL); + + stat_screen_mode = 0; + build_outdoors(); + erase_out_specials(); + update_pc_graphics(); + + current_pc = first_active_pc(); + force_town_enter(scenario.which_town_start, scenario.where_start); + start_town_mode(scenario.which_town_start, 9); + center = scenario.where_start; + update_explored(scenario.where_start); + overall_mode = MODE_TOWN; + load_area_graphics(); + create_clip_region(); + redraw_screen(0); + set_stat_window(0); + adjust_spell_menus(); + adjust_monst_menu(); + + // Throw up intro dialog + buttons[0] = 1; + for (j = 0; j < 6; j++) + if (strlen(data_store5->scen_strs[4 + j]) > 0) { + for (i = 0; i < 6; i++) + strcpy((char *) strs[i],data_store5->scen_strs[4 + i]); + custom_choice_dialog((char *) strs,-1 * (1600 + scenario.intro_pic),buttons) ; + j = 6; + } + give_help(1,2,0); + // this is kludgy, put here to prevent problems + for (i = 0; i < 50; i++) + party.spec_items[i] = (scenario.special_items[i] >= 10) ? 1 : 0; +} + + +pc_record_type return_dummy_pc() +{ + pc_record_type dummy_pc; + short i; + + dummy_pc.main_status = MAIN_STATUS_ABSENT; + sprintf ((char *) dummy_pc.name, "\n"); + + for (i = 0; i < 30; i++) + dummy_pc.skills[i] = (i < 3) ? 1 : 0; + dummy_pc.cur_health = 6; + dummy_pc.max_health = 6; + dummy_pc.cur_sp = 0; + dummy_pc.max_sp = 0; + dummy_pc.experience = 0; + dummy_pc.skill_pts = 60; + dummy_pc.level = 1; + for (i = 0; i < 15; i++) dummy_pc.status[i] = 0; + for (i = 0; i < 24; i++) dummy_pc.items[i] = return_dummy_item(); + for (i = 0; i < 24; i++) dummy_pc.equip[i] = FALSE; + + for (i = 0; i < 62; i++) { + dummy_pc.priest_spells[i] = (i < 30) ? TRUE : FALSE; + dummy_pc.mage_spells[i] = (i < 30) ? TRUE : FALSE; + } + dummy_pc.which_graphic = 0; + dummy_pc.weap_poisoned = 24; + + for (i = 0; i < 15; i++) { + dummy_pc.advan[i] = FALSE; + dummy_pc.traits[i] = FALSE; + } + dummy_pc.race = RACE_HUMAN; + dummy_pc.exp_adj = 100; + dummy_pc.direction = 0; + + return dummy_pc; +} + +pc_record_type create_prefab_pc(short num) +{ + pc_record_type dummy_pc; + short i; + short pc_stats[6][19] = + { + {8,6,2, 6,0,0,0,0,0, 0,0,0,0,1, 0,0,2,0,0}, + {8,7,2, 0,0,6,3,0,3, 0,0,0,0,0, 0,0,0,2,0}, + {8,6,2, 3,3,0,0,2,0, 0,0,0,0,0, 4,4,0,2,1}, + {3,2,6, 2,0,0,2,0,0, 3,0,3,0,1, 0,0,0,0,0}, + {2,2,6, 3,0,0,2,0,0, 2,1,4,0,0, 0,0,0,0,1}, + {2,2,6, 0,2,0,2,0,1, 0,3,3,2,0, 0,0,0,0,0} + }; + short pc_health[6] = {22,24,24,16,16,18}; + short pc_sp[6] = {0,0,0,20,20,21}; + short pc_graphics[6] = {3,32,29,16,23,14}; + short pc_race[6] = {0,2,1,0,0,0}; + short pc_t[6][15] = {{0,0,1,0,0,0,1,0,0,0, 0,1,0,0,0}, + {1,0,0,0,0,1,0,0,0,0, 1,0,0,0,0}, + {0,0,0,1,0,0,0,0,0,0, 0,0,1,0,0}, + {0,1,0,0,0,0,0,0,0,0, 0,0,0,0,0}, + {0,0,0,0,1,0,1,1,0,0, 0,0,0,0,1}, + {0,1,0,0,0,0,0,0,0,0, 0,0,0,0,0}}; + + + dummy_pc.main_status = MAIN_STATUS_ALIVE; + + switch (num) { + case 0: strncpy ((char *) dummy_pc.name, "Jenneke", (size_t) 20); + break; + case 1: strncpy ((char *) dummy_pc.name, "Thissa", (size_t) 20); + break; + case 2: strncpy ((char *) dummy_pc.name, "Frrrrrr", (size_t) 20); + break; + case 3: strncpy ((char *) dummy_pc.name, "Adrianna", (size_t) 20); + break; + case 4: strncpy ((char *) dummy_pc.name, "Feodoric", (size_t) 20); + break; + case 5: strncpy ((char *) dummy_pc.name, "Michael", (size_t) 20); + break; + + } + + for (i = 0; i < 19; i++) + dummy_pc.skills[i] = pc_stats[num][i]; + + dummy_pc.cur_health = pc_health[num]; + dummy_pc.max_health = pc_health[num]; + dummy_pc.experience = 0; + dummy_pc.skill_pts = 0; + dummy_pc.level = 1; + + for (i = 0; i < 15; i++) dummy_pc.status[i] = 0; + for (i = 0; i < 24; i++) dummy_pc.items[i] = return_dummy_item(); + for (i = 0; i < 24; i++) dummy_pc.equip[i] = FALSE; + dummy_pc.cur_sp = pc_sp[num]; + dummy_pc.max_sp = pc_sp[num]; + + for (i = 0; i < 62; i++) { + dummy_pc.priest_spells[i] = (i < 30) ? TRUE : FALSE;//// + dummy_pc.mage_spells[i] = (i < 30) ? TRUE : FALSE; + } + + for (i = 0; i < 15; i++) { + dummy_pc.traits[i] = pc_t[num][i]; + dummy_pc.advan[i] = FALSE; + } + + dummy_pc.race = pc_race[num]; + dummy_pc.exp_adj = 100; + dummy_pc.direction = 0; + + dummy_pc.which_graphic = pc_graphics[num]; + + return dummy_pc; +} + +Boolean create_pc(short spot,short parent_num) +//spot; // if spot is 6, find one +{ + Boolean still_ok = TRUE; + + if (spot == INVALID_PC) { + for (spot = 0; spot < INVALID_PC; spot++) + if (adven[spot].main_status == MAIN_STATUS_ABSENT) + break; + } + if (spot == INVALID_PC) + return FALSE; + + adven[spot] = return_dummy_pc(); + + pick_race_abil(&adven[spot],0,parent_num); + + if (parent_num != 0) + cd_initial_draw(989); + + still_ok = spend_xp(spot,0,parent_num); + if (still_ok == FALSE) + return FALSE; + adven[spot].cur_health = adven[spot].max_health; + adven[spot].cur_sp = adven[spot].max_sp; + if (parent_num != 0) + cd_initial_draw(989); + + pick_pc_graphic(spot,0,parent_num); + + if (parent_num != 0) + cd_initial_draw(989); + pick_pc_name(spot,parent_num); + + adven[spot].main_status = MAIN_STATUS_ALIVE; + + if (in_startup_mode == FALSE) { + adven[spot].items[0] = start_items[adven[spot].race * 2]; + adven[spot].equip[0] = TRUE; + adven[spot].items[1] = start_items[adven[spot].race * 2 + 1]; + adven[spot].equip[1] = TRUE; + + // Do stat adjs for selected race. + if (adven[spot].race == 1) + adven[spot].skills[1] += 2; + if (adven[spot].race == 2) { + adven[spot].skills[0] += 2; + adven[spot].skills[2] += 1; + } + adven[spot].max_sp += adven[spot].skills[9] * 3 + adven[spot].skills[10] * 3; + adven[spot].cur_sp = adven[spot].max_sp; + } + + update_pc_graphics(); + return TRUE; +} + +void pc_array::heal(short amt) +{ + for (int i = 0; i < NUM_OF_PCS; i++) pc[i].heal(amt); +} + +void pc_array::cure(short amt) +{ + for (int i = 0; i < NUM_OF_PCS; i++) pc[i].cure(amt); +} + +void pc_array::dumbfound(short amt) +{ + for (int i = 0; i < NUM_OF_PCS; i++) pc[i].dumbfound(amt); +} + +void pc_array::disease(short amt) +{ + for (int i = 0; i < NUM_OF_PCS; i++) pc[i].disease(amt); +} + +void increase_light(short amt) +{ + short i; + location where; + + party.light_level += amt; + if (is_combat()) { + for (i = 0; i < 6; i++) + if (adven[i].isAlive()) { + update_explored(pc_pos[i]); + } + } + else { + where = get_cur_loc(); + update_explored(where); + } + put_pc_screen(); +} + +void pc_array::restoreSP(short amt) +{ + for (int i = 0; i < NUM_OF_PCS; i++) + pc[i].restoreSP(amt); +} + +void pc_array::giveXP(short amt) +{ + for (int i = 0; i < NUM_OF_PCS; i++) + pc[i].giveXP(amt); +} + +void pc_array::drainXP(short amt) +{ + for (int i = 0; i < NUM_OF_PCS; i++) + pc[i].drainXP(amt); +} + +void do_xp_keep(short pc_num,short mode) +{ + for (i = 0; i < 20; i++) + adven[pc_num].skills[i] = store_skills[i]; + adven[pc_num].cur_health += store_h - adven[pc_num].max_health; + adven[pc_num].max_health = store_h; + adven[pc_num].cur_sp += store_sp - adven[pc_num].max_sp; + adven[pc_num].max_sp = store_sp; + if (mode == 1) + party.gold = store_g; + adven[pc_num].skill_pts = store_skp; +} + +void draw_xp_skills() +{ + short i; + for (i = 0; i < 19; i++) { + if ((store_skp >= skill_cost[i]) && (store_g >= skill_g_cost[i])) + cd_text_frame(1010,54 + i,11); + else cd_text_frame(1010,54 + i,1); + cd_set_item_num(1010,54 + i,store_skills[i]); + } + + if ((store_skp >= 1) && (store_g >= 10)) + cd_text_frame(1010,52,11); + else cd_text_frame(1010,52,1); + cd_set_item_num(1010,52,store_h); + if ((store_skp >= 1) && (store_g >= 15)) + cd_text_frame(1010,53,11); + else cd_text_frame(1010,53,1); + cd_set_item_num(1010,53,store_sp); +} + + +void do_xp_draw() +{ + char get_text[256]; + short mode,pc_num; + + mode = store_train_mode; + pc_num = store_train_pc; + if (mode == 0) { + if (adven[pc_num].main_status == MAIN_STATUS_ALIVE) + sprintf((char *) get_text, "%s",(char *) adven[pc_num].name); + else sprintf((char *) get_text, "New PC"); + } + else sprintf((char *) get_text, "%s",(char *) adven[pc_num].name); + + cd_set_item_text (1010, 51,get_text); + + for (i = 0; i < 20; i++) + store_skills[i] = adven[pc_num].skills[i]; + store_h = adven[pc_num].max_health; + store_sp = adven[pc_num].max_sp; + store_g = (mode == 0) ? 20000 : party.gold; + store_skp = adven[pc_num].skill_pts; + + draw_xp_skills(); + + update_gold_skills(); +} + +Boolean spend_xp_event_filter (short item_hit) +{ + short i,j,mode,pc_num; + + Boolean talk_done = FALSE; + + mode = store_train_mode; + pc_num = store_train_pc; + + switch (item_hit) { + case 73: + if ((mode == 0) && (adven[pc_num].main_status < MAIN_STATUS_ABSENT)) + adven[pc_num].main_status = MAIN_STATUS_ABSENT; + dialog_answer = 0; + talk_done = TRUE; + break; + + case 82: + party.help_received[10] = 0; + give_help(210,11,1010); + break; + + case 3: case 4: + if (((store_h >= 250) && (item_hit == 4)) || + ((store_h == adven[pc_num].max_health) && (item_hit == 3) && (mode == 1)) || + ((store_h == 6) && (item_hit == 3) && (mode == 0))) + MessageBeep(MB_OK); + else { + if (item_hit == 3) { + store_g += 10; + store_h -= 2; + store_skp += 1; + } + else { + if ((store_g < 10) || (store_skp < 1)) { + if (store_g < 10) + give_help(24,0,1010); + else give_help(25,0,1010); + MessageBeep(MB_OK); + } + else { + store_g -= 10; + store_h += 2; + store_skp -= 1; + } + } + + update_gold_skills(); + cd_set_item_num(1010,52,store_h); + draw_xp_skills(); + + } + break; + + case 5: case 6: + if (((store_sp >= 150) && (item_hit == 6)) || + ((store_sp == adven[pc_num].max_sp) && (item_hit == 5) && (mode == 1)) || + ((store_sp == 0) && (item_hit == 5) && (mode == 0))) + MessageBeep(MB_OK); + else { + if (item_hit == 5) { + store_g += 15; + store_sp -= 1; + store_skp += 1; + } + else { + if ((store_g < 15) || (store_skp < 1)) { + if (store_g < 15) + give_help(24,0,1010); + else give_help(25,0,1010); + MessageBeep(MB_OK); + } + else { + store_sp += 1; + store_g -= 15; + store_skp -= 1; + } + } + + update_gold_skills(); + cd_set_item_num(1010,53,store_sp); + draw_xp_skills(); + } + break; + + case 48: + do_xp_keep(pc_num,mode); + dialog_answer = 1; + talk_done = TRUE; + break; + + case 49: + if (mode == 0) { + MessageBeep(MB_OK); + break; + } + else { + do_xp_keep(pc_num,mode); + do { + pc_num = (pc_num == 0) ? 5 : pc_num - 1; + } while (adven[pc_num].isAlive() == false); + store_train_pc = pc_num; + do_xp_draw(); + } + break; + + case 50: + if (mode == 0) { + MessageBeep(MB_OK); + break; + } + else { + do_xp_keep(pc_num,mode); + do { + pc_num = (pc_num == 5) ? 0 : pc_num + 1; + } while (adven[pc_num].isAlive() == false); + store_train_pc = pc_num; + do_xp_draw(); + } + break; + + case 100: + break; + + default: + if (item_hit >= 100) { + item_hit -= 100; + if ((item_hit == 3) || (item_hit == 4)) { + display_strings_with_nums(10,63,0,0,"About Health",57,724,1010); + } + else if ((item_hit == 5) || (item_hit == 6)){ + display_strings_with_nums(10,64,0,0,"About Spell Points",57,724,1010); + } + else { + which_skill = (item_hit - 7) / 2; + display_skills(which_skill,1010); + } + } + else { + which_skill = (item_hit - 7) / 2; + + if (((store_skills[which_skill] >= skill_max[which_skill]) && ((item_hit - 7) % 2 == 1)) || + ((store_skills[which_skill] == adven[pc_num].skills[which_skill]) && ((item_hit - 7) % 2 == 0) && (mode == 1)) || + ((store_skills[which_skill] == 0) && ((item_hit - 7) % 2 == 0) && (mode == 0) && (which_skill > 2)) || + ((store_skills[which_skill] == 1) && ((item_hit - 7) % 2 == 0) && (mode == 0) && (which_skill <= 2))) + MessageBeep(MB_OK); + else { + if ((item_hit - 7) % 2 == 0) { + store_g += skill_g_cost[which_skill]; + store_skills[which_skill] -= 1; + store_skp += skill_cost[which_skill]; + } + else { + if ((store_g < skill_g_cost[which_skill]) || (store_skp < skill_cost[which_skill])) { + if (store_g < skill_g_cost[which_skill]) + give_help(24,0,1010); + else give_help(25,0,1010); + MessageBeep(MB_OK); + } + else { + store_skills[which_skill] += 1; + store_g -= skill_g_cost[which_skill]; + store_skp -= skill_cost[which_skill]; + } + } + + update_gold_skills(); + cd_set_item_num(1010,54 + which_skill,store_skills[which_skill]); + draw_xp_skills(); + } + } + break; + } + + store_train_pc = pc_num; + if (talk_done == TRUE) { + dialog_not_toast = FALSE; + } + return FALSE; +} + +void update_gold_skills() +{ + cd_set_item_num(1010,47,((store_train_mode == 0) ? 0 : (short) store_g)); + cd_set_item_num(1010,46,(short) store_skp); +} + +Boolean spend_xp(short pc_num, short mode, short parent) +//short mode; // 0 - create 1 - train +// returns 1 if cancelled +{ + char get_text[256],text2[256]; + + + store_train_pc = pc_num; + store_train_mode = mode; + + SetCursor(sword_curs); + + cd_create_dialog_parent_num(1010,parent); + sprintf((char *) get_text,"Health (%d/%d)",1,10); + cd_add_label(1010,52,(char *) get_text,1075); + sprintf((char *) get_text,"Spell Pts. (%d/%d)",1,15); + cd_add_label(1010,53,(char *) get_text,1075); + for (i = 54; i < 73; i++) { + GetIndString(text2,9,1 + 2 * (i - 54)); + sprintf((char *) get_text,"%s (%d/%d)",text2,skill_cost[i - 54],skill_g_cost[i - 54]); + cd_add_label(1010,i,(char *) get_text,(i < 63) ? 1075 : 1069); + } + do_xp_draw(); + + dialog_answer = 0; + + if (party.help_received[10] == 0) { + cd_initial_draw(1010); + give_help(10,11,1010); + } + + while (dialog_not_toast) + ModalDialog(); + + cd_kill_dialog(1010,0); + + return dialog_answer; +} + + +short pc_array::getMageLore() +{ + short total = 0; + + for (int i = 0; i < NUM_OF_PCS; i++) + if (pc[i].isAlive()) + total += pc[i].skills[SKILL_MAGE_LORE]; + + return total; +} + + +Boolean poison_weapon( short pc_num, short how_much,short safe) +//short safe; // 1 - always succeeds +{ + short i,weap = 24,p_level,r1; + short p_chance[21] = {40,72,81,85,88,89,90, + 91,92,93,94,94,95,95,96,97,98,100,100,100,100}; + + for (i = 0; i < 24; i++) + if ((adven[pc_num].equip[i] == TRUE) && (is_weapon(pc_num,i) == TRUE)) { + weap = i; + i = 30; + } + if (weap == 24) { + add_string_to_buf(" No weapon equipped. "); + return FALSE; + } + else { + p_level = how_much; + add_string_to_buf(" You poison your weapon. "); + r1 = get_ran(1,0,100); + // Nimble? + if (adven[pc_num].traits[TRAIT_NIMBLE] == TRUE) + r1 -= 6; + if ((r1 > p_chance[adven[pc_num].skills[17]]) && (safe == 0)) { + add_string_to_buf(" Poison put on badly. "); + p_level = p_level / 2; + r1 = get_ran(1,0,100); + if (r1 > p_chance[adven[pc_num].skills[17]] + 10) { + add_string_to_buf(" You nick yourself. "); + adven[pc_num].status[2] += p_level; + } + } + if (safe != 1) + play_sound(55); + adven[pc_num].weap_poisoned = weap; + adven[pc_num].status[0] = max (adven[pc_num].status[0], + p_level); + + return TRUE; + } +} + +Boolean is_weapon(short pc_num,short item) +{ + if ((adven[pc_num].items[item].variety == 1) || + (adven[pc_num].items[item].variety == 2) || + (adven[pc_num].items[item].variety == 5) || + (adven[pc_num].items[item].variety == 24)) + return TRUE; + else return FALSE; +} + +void cast_spell(short type,short situation) +//short type; // 0 - mage 1 - priest +//short situation; // 0 - out 1 - town +{ + short spell; + + if ((is_town()) && (is_antimagic(c_town.p_loc.x,c_town.p_loc.y))) { + add_string_to_buf(" Not in antimagic field."); + return; + } + + if (spell_forced == FALSE) + spell = pick_spell(6, type, situation); + else { + if (repeat_cast_ok(type) == FALSE) + return; + spell = (type == 0) ? store_mage : store_priest; + } + if (spell < 70) { + print_spell_cast(spell,type); + + if (type == 0) + do_mage_spell(pc_casting,spell); + else do_priest_spell(pc_casting,spell); + put_pc_screen(); + + } +} + +Boolean repeat_cast_ok(short type) +{ + short store_select,who_would_cast,what_spell; + + if (overall_mode == MODE_COMBAT) + who_would_cast = current_pc; + else if (overall_mode < 2) + who_would_cast = pc_casting; + else return FALSE; + + if (is_combat()) + what_spell = pc_last_cast[type][who_would_cast]; + else what_spell = (type == 0) ? store_mage : store_priest; + + if (pc_can_cast_spell(who_would_cast,type,what_spell) == FALSE) { + add_string_to_buf("Repeat cast: Can't cast."); + return FALSE; + } + store_select = (type == 0) ? mage_need_select[what_spell] : + priest_need_select[what_spell]; + if ((store_select > 0) && (store_spell_target == 6)) { + add_string_to_buf("Repeat cast: No target stored."); + return FALSE; + } + if ((store_select == 2) && + ((adven[store_spell_target].main_status == MAIN_STATUS_ABSENT) || + (adven[store_spell_target].main_status > MAIN_STATUS_STONE))) + { + add_string_to_buf("Repeat cast: No target stored."); + return FALSE; + } + if ((store_select == 1) && + (adven[store_spell_target].isAlive() == false)) { + add_string_to_buf("Repeat cast: No target stored."); + return FALSE; + } + + return TRUE; + +} + +void do_mage_spell(short pc_num,short spell_num) +{ + short i,j,item,target,adj,store; + location where; + unsigned short r1; + + where = c_town.p_loc; + play_sound(25); + current_spell_range = 8; + + adj = adven[who_cast].statAdj(2); + + switch (spell_num) { + case 0: // Light + adven[pc_num].cur_sp -= spell_cost[0][spell_num]; + increase_light(50); + break; + + case 6: // Identify + adven[pc_num].cur_sp -= spell_cost[0][spell_num]; + ASB("All of your items are identified."); + for (i = 0; i < 6; i++) + for (j = 0; j < 24; j++) + adven[i].items[j].item_properties = adven[i].items[j].item_properties | 1; + break; + + case 9: // true sight + adven[pc_num].cur_sp -= spell_cost[0][spell_num]; + for (where.x = 0; where.x < 64; where.x++) + for (where.y = 0; where.y < 64; where.y++) + if (dist(where,c_town.p_loc) <= 2) + make_explored(where.x,where.y); + clear_map(); + break; + + case 16: // summon beast //// + r1 = get_summon_monster(1); + if (r1 == 0) break; + adven[pc_num].cur_sp -= spell_cost[0][spell_num]; + store = get_ran(3,1,4) + adj; + if (summon_monster(r1,where,store,2) == FALSE) + add_string_to_buf(" Summon failed."); + break; + case 26: // summon 1 + store = adven[who_cast].level / 5 + adven[who_cast].statAdj(2) / 3 + get_ran(1,0,2); + j = minmax(1,7,(int)store); + r1 = get_summon_monster(1); //// + if (r1 == 0) break; + adven[pc_num].cur_sp -= spell_cost[0][spell_num]; + store = get_ran(4,1,4) + adj; + for (i = 0; i < j; i++) + if (summon_monster(r1,where,store,2) == FALSE) + add_string_to_buf(" Summon failed."); + break; + case 43: // summon 2 + store = adven[who_cast].level / 7 + adven[who_cast].statAdj(2) / 3 + get_ran(1,0,1); + j = minmax(1,6,(int)store); + r1 = get_summon_monster(2); //// + if (r1 == 0) break; + adven[pc_num].cur_sp -= spell_cost[0][spell_num]; + store = get_ran(5,1,4) + adj; + for (i = 0; i < j; i++) + if (summon_monster(r1,where,store,2) == FALSE) + add_string_to_buf(" Summon failed."); + break; + case 58: // summon 3 + store = adven[who_cast].level / 10 + adven[who_cast].statAdj(2) / 3 + get_ran(1,0,1); + j = minmax(1,5,(int)store); + r1 = get_summon_monster(3); //// + if (r1 == 0) break; + adven[pc_num].cur_sp -= spell_cost[0][spell_num]; + store = get_ran(7,1,4) + adven[who_cast].statAdj(2); + for (i = 0; i < j; i++) + if (summon_monster(r1,where,store,2) == FALSE) + add_string_to_buf(" Summon failed."); + break; + case 50: + store = get_ran(5,1,4) + 2 * adven[who_cast].statAdj(2); + if (summon_monster(85,where,store,2) == FALSE) + add_string_to_buf(" Summon failed."); + else adven[pc_num].cur_sp -= spell_cost[0][spell_num]; + break; + + case 18: // dispel field + add_string_to_buf(" Target spell. "); + current_pat = square; + overall_mode = 3; + set_town_spell(spell_num,pc_num); + break; + + case 23: // Long light + adven[pc_num].cur_sp -= spell_cost[0][spell_num]; + increase_light(200); + break; + + case 33: // Magic map + item = adven[pc_num].hasAbil(158);//// + if (item == 24) + add_string_to_buf(" You need a sapphire. "); + else if (c_town.town.specials2 % 10 == 1) + add_string_to_buf(" The spell fails. "); + else { + adven[pc_num].removeCharge(item); + adven[pc_num].cur_sp -= spell_cost[0][spell_num]; + add_string_to_buf(" As the sapphire dissolves, "); + add_string_to_buf(" you have a vision. "); + for (i = 0; i < 64; i++) + for (j = 0; j < 64; j++) + make_explored(i,j); + clear_map(); + } + break; + + + case 38: // Stealth + adven[pc_num].cur_sp -= spell_cost[0][spell_num]; + party.stuff_done[305][0] += max(6,adven[pc_num].level * 2); + break; + + + case 7: case 20: case 34: case 41: // Scry monster, Unlock, disp. barrier, Capture SOul + + add_string_to_buf(" Target spell. "); + current_pat = single; + overall_mode = 3; + set_town_spell(spell_num,pc_num); + break; + + case 42: case 59: case 60: // fire and force barriers, quickfire + add_string_to_buf(" Target spell. "); + overall_mode = 3; + current_pat = single; + set_town_spell(spell_num,pc_num); + break; + + case 51: // antimagic + add_string_to_buf(" Target spell. "); + overall_mode = 3; + current_pat = radius2; + set_town_spell(spell_num,pc_num); + break; + + case 53: // fly + if (party.stuff_done[305][1] > 0) { + add_string_to_buf(" Not while already flying. "); + return; + } + if (party.in_boat >= 0) + add_string_to_buf(" Leave boat first. "); + else if (party.in_horse >= 0) //// + add_string_to_buf(" Leave horse first. "); + else { + adven[pc_num].cur_sp -= spell_cost[0][spell_num]; + add_string_to_buf(" You start flying! "); + party.stuff_done[305][1] = 3; + } + break; + + case 29: case 57: // resist magic protection + target = store_spell_target; + if (target < 6) + adven[pc_num].cur_sp -= spell_cost[0][spell_num]; + if ((spell_num == 57) && (target < 6)) { + adven[target].status[4] += 2 + adven[pc_num].statAdj(2) + get_ran(2,1,2); + for (i = 0; i < 6; i++) + if (adven[i].isAlive()) { + adven[i].status[5] += 4 + adven[pc_num].level / 3 + adven[pc_num].statAdj(2); + } + sprintf ((char *) c_line, " Party protected. "); + } + if ((spell_num == 29) && (target < 6)) { + adven[target].status[5] += 2 + adven[pc_num].statAdj(2) + get_ran(2,1,2); + sprintf ((char *) c_line, " %s protected.",adven[target].name); + } + add_string_to_buf((char *) c_line); + break; + } +} + +void do_priest_spell(short pc_num,short spell_num) +{ + short r1,r2, target, i,item,store,adj,x,y; + location loc; + location where; + + short store_victim_health,store_caster_health,targ_damaged; // for symbiosis + + where = c_town.p_loc; + + adj = adven[pc_num].statAdj(2); + + play_sound(24); + current_spell_range = 8; + + switch (spell_num) { + case 4: + adven[pc_num].cur_sp -= spell_cost[1][spell_num]; + + if (is_town()) { + loc = (overall_mode == MODE_OUTDOORS) ? party.p_loc : c_town.p_loc; + sprintf ((char *) c_line, " You're at: x %d y %d.", + (short) loc.x, (short) loc.y); + } + if (is_out()) { + loc = (overall_mode == MODE_OUTDOORS) ? party.p_loc : c_town.p_loc; + x = loc.x; y = loc.y; + x += 48 * party.outdoor_corner.x; y += 48 * party.outdoor_corner.y; + sprintf ((char *) c_line, " You're outside at: x %d y %d.",x,y); + + } + add_string_to_buf((char *) c_line); + break; + + case 7: case 25: // manna spells + adven[pc_num].cur_sp -= spell_cost[1][spell_num]; + store = adven[pc_num].level / 3 + 2 * adven[who_cast].statAdj(2) + get_ran(2,1,4); + r1 = max(0,store); + if (spell_num == 7) + r1 = r1 / 3 + 1; + sprintf ((char *) c_line, " You gain %d food. ",r1); + add_string_to_buf((char *) c_line); + party.giveFood(r1,true); + break; + + case 8: // Ritual - Sanctify + add_string_to_buf(" Sanctify which space? "); + current_pat = single; + overall_mode = 3; + set_town_spell(100 + spell_num,pc_num); + break; + + case 13: + adven[pc_num].cur_sp -= spell_cost[1][spell_num]; + party.light_level += 210; + break; + + case 15: + store = adven[who_cast].statAdj(2); + if (summon_monster(125,where,get_ran(2,1,4) + store,2) == FALSE) + add_string_to_buf(" Summon failed."); + else adven[pc_num].cur_sp -= spell_cost[1][spell_num]; + break; + case 34: + adven[pc_num].cur_sp -= spell_cost[1][spell_num]; + r1 = adven[who_cast].level / 6 + adven[who_cast].statAdj(2) / 3 + get_ran(1,0,1); + for (i = 0; i < r1; i++) { + r2 = get_ran(1,0,7); + store = get_ran(2,1,5) + adven[who_cast].statAdj(2); + if (summon_monster((r2 == 1) ? 100 : 99,where,store,2 ) == FALSE) + add_string_to_buf(" Summon failed."); + } + break; + case 43: + adven[pc_num].cur_sp -= spell_cost[1][spell_num]; + store = get_ran(2,1,4) + adven[who_cast].statAdj(2); + if (summon_monster(126,where,store,2) == FALSE) + add_string_to_buf(" Summon failed."); + for (i = 0; i < 4; i++) { + store = get_ran(2,1,4) + adven[who_cast].statAdj(2); + if (summon_monster(125,where,store,2) == FALSE) + add_string_to_buf(" Summon failed."); + } + break; + case 50: + store = get_ran(6,1,4) + adven[who_cast].statAdj(2); + if (summon_monster(122,where,store,2) == FALSE) + add_string_to_buf(" Summon failed."); + else adven[pc_num].cur_sp -= spell_cost[1][spell_num]; + break; + + case 16: + add_string_to_buf(" Destroy what? "); + current_pat = (spell_num == 16) ? single : square; + overall_mode = 3; + set_town_spell(100 + spell_num,pc_num); + break; + + case 45: // dispelling fields + add_string_to_buf(" Target spell. "); + current_pat = (spell_num == 19) ? single : radius2; + overall_mode = 3; + set_town_spell(100 + spell_num,pc_num); + break; + + case 23: // Detect life + add_string_to_buf(" Monsters now on map. "); + party.stuff_done[305][2] += 6 + get_ran(1,0,6); + clear_map(); + adven[pc_num].cur_sp -= spell_cost[1][spell_num]; + break; + case 37: // firewalk + add_string_to_buf(" You are now firewalking. "); + party.stuff_done[305][3] += adven[pc_num].level / 12 + 2; + adven[pc_num].cur_sp -= spell_cost[1][spell_num]; + break; + + case 44: // shatter + add_string_to_buf(" You send out a burst of energy. "); + adven[pc_num].cur_sp -= spell_cost[1][spell_num]; + for (loc.x = where.x - 1;loc.x < where.x + 2; loc.x++) + for (loc.y = where.y - 1;loc.y < where.y + 2; loc.y++) + loc.crumbleWall(); + update_explored(c_town.p_loc); + break; + + case 60: + if (overall_mode > MODE_OUTDOORS) { + add_string_to_buf(" Can only cast outdoors. "); + return; + } + if (party.in_boat >= 0) { + add_string_to_buf(" Not while in boat. "); + return; + } + if (party.in_horse >= 0) {//// + add_string_to_buf(" Not while on horseback. "); + return; + } + adven[pc_num].cur_sp -= spell_cost[1][spell_num]; + add_string_to_buf(" You are moved... "); + force_town_enter(scenario.which_town_start,scenario.where_start); + start_town_mode(scenario.which_town_start,9); + position_party(scenario.out_sec_start.x,scenario.out_sec_start.y, + scenario.out_start.x,scenario.out_start.y); + center = c_town.p_loc = scenario.where_start; +// overall_mode = 0; +// center = party.p_loc; +// update_explored(party.p_loc); + redraw_screen(0); + break; + + case 1: case 20: case 39: case 2: case 11: case 27: case 28: case 36: case 19: case 24: +// target = select_pc(11,0); + target = store_spell_target; + if (target < 6) { + adven[pc_num].cur_sp -= spell_cost[1][spell_num]; + switch(spell_num) { + case 1: case 20: case 39: + r1 = get_ran(2 + 2 * (spell_num / 6), 1, 4); + sprintf ((char *) c_line, " %s healed %d. ", + (char *) adven[target].name,r1); + adven[target].heal(r1); + one_sound(52); + break; + + case 2: case 11: + sprintf ((char *) c_line, " %s cured. " + ,(char *) adven[target].name); + r1 = ((spell_num == 2) ? 1 : 3) + get_ran(1,0,2) + adven[pc_num].statAdj(2) / 2; + adven[target].cure(r1); + break; + + case 19: // awaken + if (adven[target].status[11] <= 0) { + sprintf ((char *) c_line, " %s is already awake! " + ,(char *) adven[target].name); + break; + } + sprintf ((char *) c_line, " %s wakes up. " + ,(char *) adven[target].name); + adven[target].status[11] = 0; + break; + case 24: // cure paralysis + if (adven[target].status[12] <= 0) { + sprintf ((char *) c_line, " %s isn't paralyzed! " + ,(char *) adven[target].name); + break; + } + sprintf ((char *) c_line, " %s can move now. " + ,(char *) adven[target].name); + adven[target].status[12] = 0; + break; + + case 27: + sprintf ((char *) c_line, " %s recovers. " + ,(char *) adven[target].name); + r1 = 2 + get_ran(1,0,2) + adven[pc_num].statAdj(2) / 2; + adven[target].status[7] = max(0,adven[target].status[7] - r1); + break; + + case 28: + sprintf ((char *) c_line, " %s restored. " + ,(char *) adven[target].name); + r1 = 1 + get_ran(1,0,2) + adven[pc_num].statAdj(2) / 2; + adven[target].status[9] = max(0,adven[target].status[9] - r1); + break; + + case 36: + sprintf ((char *) c_line, " %s cleansed. " + ,(char *) adven[target].name); + adven[target].status[7] = 0; + adven[target].status[6] = 0; + break; + } + } + add_string_to_buf((char *) c_line); + put_pc_screen(); + break; + + case 47: case 49: case 40: case 56: case 33: case 5: case 6: case 35: + target = store_spell_target; + + if (target < 6) { + if ((spell_num == 6) && (target == pc_num)) { // check symbiosis + add_string_to_buf(" Can't cast on self."); + return; + } + + adven[pc_num].cur_sp -= spell_cost[1][spell_num]; + if (spell_num == 35) { // martyr's shield + sprintf ((char *) c_line, " %s shielded. ", + (char *) adven[target].name); + r1 = max(1,get_ran((adven[pc_num].level + 5) / 5,1,3) + adj); + adven[target].status[10] += r1; + } + if (spell_num == 5) { // sanctuary + sprintf ((char *) c_line, " %s hidden. ", + (char *) adven[target].name); + r1 = max(0,get_ran(0,1,3) + adven[pc_num].level / 4 + adj); + adven[target].status[8] += r1; + } + if (spell_num == 6) { // symbiosis + store_victim_health = adven[target].cur_health; + store_caster_health = adven[pc_num].cur_health; + targ_damaged = adven[target].max_health - adven[target].cur_health; + while ((targ_damaged > 0) && (adven[pc_num].cur_health > 0)) { + adven[target].cur_health++; + r1 = get_ran(1,0,100) + adven[pc_num].level / 2 + 3 * adj; + if (r1 < 100) + adven[pc_num].cur_health--; + if (r1 < 50) + move_to_zero(adven[pc_num].cur_health); + targ_damaged = adven[target].max_health - adven[target].cur_health; + } + add_string_to_buf(" You absorb damage."); + sprintf ((char *) c_line, " %s healed %d. ", (char *) adven[target].name, + adven[target].cur_health - store_victim_health); + add_string_to_buf ((char *) c_line); + sprintf ((char *) c_line, " %s takes %d. ", (char *) adven[pc_num].name, + store_caster_health - adven[pc_num].cur_health); + } + if (spell_num == 47) { + sprintf ((char *) c_line, " %s healed. ", + (char *) adven[target].name); + adven[target].heal(250); + adven[target].status[2] = 0; + one_sound(-53); one_sound(52); + } + if (spell_num == 49) { + if (adven[target].main_status == MAIN_STATUS_STONE) { + adven[target].main_status = MAIN_STATUS_ALIVE; + sprintf ((char *) c_line, " %s destoned. ", + (char *) adven[target].name); + play_sound(53); + } + else sprintf ((char *) c_line," Wasn't stoned. "); + } + if (spell_num == 33) { + for (i = 0; i < 24; i++) + if (adven[target].items[i].isCursed()) + { + r1 = get_ran(1,0,200) - 10 * adven[pc_num].statAdj(2); + if (r1 < 60) { + adven[target].items[i].item_properties = + adven[target].items[i].item_properties & 239; + } + } + play_sound(52); + sprintf ((char *) c_line," Your items glow. "); + } + if (PSD[305][8] == 0 && ((spell_num == 40) || (spell_num == 56))){ + if ((item = adven[pc_num].hasAbil(160)) == 24) { + sprintf(c_line," Need resurrection balm. "); + spell_num = 500; + } + else adven[pc_num].takeItem(item); + } + if (spell_num == 40) { + if (adven[target].main_status == MAIN_STATUS_DEAD) + if (get_ran(1,1,adven[pc_num].level / 2) == 1) { + sprintf ((char *) c_line, " %s now dust. ", + (char *) adven[target].name); + play_sound(5); + adven[target].main_status = MAIN_STATUS_DUST; + } + else { + adven[target].main_status = MAIN_STATUS_ALIVE; + for (i = 0; i < 3; i++) + if (get_ran(1,0,2) < 2) + adven[target].skills[i] -= (adven[target].skills[i] > 1) ? 1 : 0; + adven[target].cur_health = 1; + sprintf ((char *) c_line, " %s raised. ", + (char *) adven[target].name); + play_sound(52); + } + else sprintf ((char *) c_line," Didn't work. "); + + } + if (spell_num == 56) { + if (adven[target].isAlive() == false) { + adven[target].main_status = MAIN_STATUS_ALIVE; + for (i = 0; i < 3; i++) + if (get_ran(1,0,2) < 1) + adven[target].skills[i] -= (adven[target].skills[i] > 1) ? 1 : 0; + adven[target].cur_health = 1; + sprintf ((char *) c_line, " %s raised.", + (char *) adven[target].name); + play_sound(52); + } + else sprintf ((char *) c_line," Was OK. "); + } + add_string_to_buf((char *) c_line); + put_pc_screen(); + } + break; + + case 21: case 46: case 54: + adven[pc_num].cur_sp -= spell_cost[1][spell_num]; + r1 = get_ran(spell_num / 7 + adj, 1, 4); + if (spell_num < 54) { + sprintf ((char *) c_line, " Party healed %d. ", r1); + add_string_to_buf((char *) c_line); + adven.heal(r1); + play_sound(52); + } + else if (spell_num == 54) { + sprintf ((char *) c_line, " Party revived. "); + add_string_to_buf((char *) c_line); + r1 = r1 * 2; + adven.heal(r1); + play_sound(-53); + play_sound(-52); + adven.cure(3 + adj); + } + break; + + case 30: + adven[pc_num].cur_sp -= spell_cost[1][spell_num]; + sprintf ((char *) c_line, " Party cured. "); + add_string_to_buf((char *) c_line); + adven.cure(3 + adven[pc_num].statAdj(2)); + break; + + case 42: case 61: case 48: + adven[pc_num].cur_sp -= spell_cost[1][spell_num]; + switch (spell_num) { + case 42: add_string_to_buf(" Party hidden.");break; + case 61: add_string_to_buf(" Party cleansed.");break; + case 48: add_string_to_buf(" Party is now really, REALLY awake.");break; + } + + for (i = 0; i < 6; i++) + if (adven[i].isAlive()) { + if (spell_num == 42) { + store = get_ran(0,1,3) + adven[pc_num].level / 6 + adven[pc_num].statAdj(2); + r1 = max(0,store); + adven[i].status[8] += r1; + } + if (spell_num == 61) { + adven[i].status[6] = 0; + adven[i].status[7] = 0; + } + if (spell_num == 48) { // Hyperactivity + adven[i].status[11] -= 6 + 2 * adven[pc_num].statAdj(2); + adven[i].status[3] = max(0,adven[i].status[3]); + } + } + break; + } +} + +void cast_town_spell(location where) +{ + short adjust,r1,targ,store; + location loc; + unsigned char ter; + + if ((where.x <= c_town.town.in_town_rect.left) || + (where.x >= c_town.town.in_town_rect.right) || + (where.y <= c_town.town.in_town_rect.top) || + (where.y >= c_town.town.in_town_rect.bottom)) { + add_string_to_buf(" Can't target outside town."); + return; + } + + adjust = can_see(c_town.p_loc,where,0); + if (town_spell < 1000) + adven[who_cast].cur_sp -= spell_cost[town_spell / 100][town_spell % 100]; + else town_spell -= 1000; + ter = t_d.terrain[where.x][where.y]; + + if (adjust > 4) + add_string_to_buf(" Can't see target. "); + else switch (town_spell) { + case 7: case 34: // Scry, Capture Soul + targ = monst_there(where); + if (targ < T_M) { + if (town_spell == 7) { + party.m_seen[c_town.monst.dudes[targ].number] = TRUE; + adjust_monst_menu(); + display_monst(0,&c_town.monst.dudes[targ],0); + } + else c_town.monst.dudes[targ].record(); + } + else add_string_to_buf(" No monster there."); + break; + + case 119: case 145: case 18: + add_string_to_buf(" You attempt to dispel. "); + place_spell_pattern(current_pat,where,11,FALSE,7); + break; + case 116: // Move M. + add_string_to_buf(" You blast the area. "); + where.crumbleWall(); + update_explored(c_town.p_loc); + break; + case 42: + if ((get_obscurity(where.x,where.y) == 5) || (monst_there(where) < 90)) { + add_string_to_buf(" Target space obstructed."); + break; + } + make_fire_barrier(where.x,where.y); + if (is_fire_barrier(where.x,where.y)) + add_string_to_buf(" You create the barrier. "); + else add_string_to_buf(" Failed."); + break; + case 59: + if ((get_obscurity(where.x,where.y) == 5) || (monst_there(where) < 90)) { + add_string_to_buf(" Target space obstructed."); + break; + } + make_force_barrier(where.x,where.y); + if (is_force_barrier(where.x,where.y)) + add_string_to_buf(" You create the barrier. "); + else add_string_to_buf(" Failed."); + break; + case 60: + make_quickfire(where.x,where.y); + if (is_quickfire(where.x,where.y)) + add_string_to_buf(" You create quickfire. "); + else add_string_to_buf(" Failed."); + break; + + case 51: // am cloud + add_string_to_buf(" You create an antimagic cloud. "); + for (loc.x = 0; loc.x < town_size[town_type]; loc.x++) + for (loc.y = 0; loc.y < town_size[town_type]; loc.y++) + if ((dist(where,loc) <= 2) && (can_see(where,loc,2) < 5) && + ((ex_abs(loc.x - where.x) < 2) || (ex_abs(loc.y - where.y) < 2))) + make_antimagic(loc.x,loc.y); + break; + + case 108: // RItual - sanctify + sanctify_space(where); + break; + + case 20: + switch (scenario.ter_types[ter].special) { //// + case 9: case 10: + r1 = get_ran(1,0,100) - 5 * adven[who_cast].statAdj(2) + 5 * c_town.difficulty; + r1 += scenario.ter_types[ter].flag2 * 7; + if (scenario.ter_types[ter].flag2 == 10) + r1 = 10000; + if (r1 < (135 - combat_percent[min(19,adven[who_cast].level)])) { + add_string_to_buf(" Door unlocked. "); + play_sound(9); + t_d.terrain[where.x][where.y] = scenario.ter_types[ter].flag1; + if(scenario.ter_types[scenario.ter_types[ter].flag1].special >= 16 && scenario.ter_types[scenario.ter_types[ter].flag1].special <=19) + belt_present = TRUE; + } + else { + play_sound(41); + add_string_to_buf(" Didn't work. "); + } + break; + + default: + add_string_to_buf(" Wrong terrain type. "); + break; + } + break; + + case 41: + if ((is_fire_barrier(where.x,where.y)) || (is_force_barrier(where.x,where.y))) { + r1 = get_ran(1,0,100) - 5 * adven[who_cast].statAdj(2) + 5 * (c_town.difficulty / 10); + if (is_fire_barrier(where.x,where.y)) + r1 -= 8; + if (r1 < (120 - combat_percent[min(19,adven[who_cast].level)])) { + add_string_to_buf(" Barrier broken. "); + take_fire_barrier(where.x,where.y); + take_force_barrier(where.x,where.y); + + // Now, show party new things + update_explored(c_town.p_loc); + } + else { + store = get_ran(1,0,1); + play_sound(41); + add_string_to_buf(" Didn't work. "); + } + } + + else add_string_to_buf(" No barrier there."); + + break; + + } +} + +void sanctify_space(location where) +{ + short i,s1,s2,s3; + + for (i = 0; i < 50; i++) + if ((same_point(where,c_town.town.special_locs[i]) == TRUE) + //GK && (c_town.town.spec_id[i] >= 0) + ) + { + if (c_town.town.specials[c_town.town.spec_id[i]].type == 24) + run_special(16,2,c_town.town.spec_id[i],where,&s1,&s2,&s3); + return; + } + add_string_to_buf(" Nothing happens."); +} + +void do_mindduel(short pc_num,creature_data_type *monst) +{ + short i = 0,adjust,r1,r2,balance = 0; + + adjust = (adven[pc_num].level + adven[pc_num].skills[2]) / 2 - monst->m_d.level * 2; + + if (adven[pc_num].hasAbilEquip(53) < 24) + adjust += 20; + if (monst->attitude % 2 != 1) + make_town_hostile(); + monst->attitude = 1; + + add_string_to_buf("Mindduel!"); + while ((adven[pc_num].isAlive()) && (monst->active > 0) && (i < 10)) { + play_sound(1); + r1 = get_ran(1,0,100) + adjust; + r1 += 5 * (monst->m_d.status[9] - adven[pc_num].status[9]); + r1 += 5 * balance; + r2 = get_ran(1,1,6); + if (r1 < 30) { + sprintf((char *)c_line, " %s is drained %d.",adven[pc_num].name,r2); + add_string_to_buf((char *) c_line); + monst->m_d.mp += r2; + balance++; + if (adven[pc_num].cur_sp == 0) { + adven[pc_num].status[9] += 2; + sprintf((char *) c_line," %s is dumbfounded.",adven[pc_num].name); + add_string_to_buf((char *) c_line); + if (adven[pc_num].status[9] > 7) { + sprintf((char *) c_line," %s is killed!",adven[pc_num].name); + add_string_to_buf((char *) c_line); + adven[pc_num].kill(2); + } + } + else adven[pc_num].cur_sp = max(0,adven[pc_num].cur_sp - r2); + } + if (r1 > 70) + { + sprintf((char *)c_line, " %s drains %d.",adven[pc_num].name,r2); + add_string_to_buf((char *) c_line); + adven[pc_num].cur_sp += r2; + balance--; + if (monst->m_d.mp == 0) + { + monst->m_d.status[9] += 2; + monst_spell_note(monst->number,22); + if (monst->m_d.status[9] > 7) kill_monst(monst,pc_num); + } + else monst->m_d.mp = max(0,monst->m_d.mp - r2); + } + print_buf(); + i++; + } +} + +// mode 0 - dispel spell, 1 - always take 2 - always take and take fire and force too +void dispel_fields(short i,short j,short mode) +{ + short r1; + + if (mode == 2) { + take_fire_barrier(i,j); + take_force_barrier(i,j); + take_barrel(i,j); + take_crate(i,j); + take_web(i,j); + } + if (mode >= 1) + mode = -10; + take_fire_wall(i,j); + take_force_wall(i,j); + take_scloud(i,j); + r1 = get_ran(1,1,6) + mode; + if (r1 <= 1) + take_web(i,j); + r1 = get_ran(1,1,6) + mode; + if (r1 < 6) + take_ice_wall(i,j); + r1 = get_ran(1,1,6) + mode; + if (r1 < 5) + take_sleep_cloud(i,j); + r1 = get_ran(1,1,8) + mode; + if (r1 <= 1) + take_quickfire(i,j); + r1 = get_ran(1,1,7) + mode; + if (r1 < 5) + take_blade_wall(i,j); +} +Boolean pc_can_cast_spell(short pc_num,short type,short spell_num) +//short type; // 0 - mage 1 - priest +{ + short level,store_w_cast; + + level = spell_level[spell_num]; + + if (overall_mode >= 20) + return FALSE; + if ((spell_num < 0) || (spell_num > 61)) + return FALSE; + if (adven[pc_num].skills[SKILL_MAGE_SPELLS + type] < level) + return FALSE; + if (adven[pc_num].isAlive() == false) + return FALSE; + if (adven[pc_num].cur_sp < spell_cost[type][spell_num]) + return FALSE; + if ((type == 0) && (adven[pc_num].mage_spells[spell_num] == FALSE)) + return FALSE; + if ((type == 1) && (adven[pc_num].priest_spells[spell_num] == FALSE)) + return FALSE; + if (adven[pc_num].status[9] >= 8 - level) + return FALSE; + if (adven[pc_num].status[12] != 0) + return FALSE; + if (adven[pc_num].status[11] > 0) + return FALSE; + +// 0 - everywhere 1 - combat only 2 - town only 3 - town & outdoor only 4 - town & combat only 5 - outdoor only + store_w_cast = spell_w_cast[type][spell_num]; + + if (is_out()) + if ((store_w_cast == 1) || (store_w_cast == 2) || (store_w_cast == 4)) + return FALSE; + + if (is_town()) + if ((store_w_cast == 1) || (store_w_cast == 5)) + return FALSE; + + if (is_combat()) + if ((store_w_cast == 2) || (store_w_cast == 3) || (store_w_cast == 5)) + return FALSE; + + return TRUE; +} + + +void draw_caster_buttons() +{ + short i; + + if (can_choose_caster == FALSE) { + for (i = 0; i < 6; i++) { + if (i == pc_casting) + cd_activate_item(1098,4 + i,1); + else cd_activate_item(1098,4 + i,0); + } + } + else { + for (i = 0; i < 6; i++) { + if (pc_can_cast_spell(i,store_situation,store_situation) == TRUE) + cd_activate_item(1098,4 + i,1); + else cd_activate_item(1098,4 + i,0); + } + } +} + +void draw_spell_info() +{ + if (((store_situation == 0) && (store_mage == 70)) || + ((store_situation == 1) && (store_priest == 70))) { // No spell selected + for (i = 0; i < 6; i++) + cd_activate_item(1098,10 + i,0); + } + else { // Spell selected + for (i = 0; i < 6; i++) { + switch (((store_situation == 0) ? + mage_need_select[store_mage] : priest_need_select[store_priest])) { + case 0: + cd_activate_item(1098,10 + i,0); + break; + case 1: + if (adven[i].isAlive() == false) + cd_activate_item(1098,10 + i,0); + else cd_activate_item(1098,10 + i,1); + break; + case 2: + if (adven[i].main_status > MAIN_STATUS_ABSENT) + cd_activate_item(1098,10 + i,1); + else cd_activate_item(1098,10 + i,0); + break; + } + } + } +} + +void draw_spell_pc_info() +{ + for (int i = 0; i < 6; i++) { + if (adven[i].main_status != MAIN_STATUS_ABSENT) + { + cd_set_item_text(1098,18 + i,adven[i].name); + + if (adven[i].isAlive()) { + cd_set_item_num(1098,24 + i, adven[i].cur_health); + cd_set_item_num(1098,30 + i, adven[i].cur_sp); + } + } + } +} + + +void put_pc_caster_buttons() +{ + for (int i = 0; i < 6; i++) + if (cd_get_active(1098,i + 4) > 0) { + if (i == pc_casting) + cd_text_frame(1098,i + 18,11); + else cd_text_frame(1098,i + 18,1); + } +} +void put_pc_target_buttons() +{ + if (store_spell_target < 6) { + cd_text_frame(1098,24 + store_spell_target,11); + cd_text_frame(1098,30 + store_spell_target,11); + } + if ((store_last_target_darkened < 6) && (store_last_target_darkened != store_spell_target)) { + cd_text_frame(1098,24 + store_last_target_darkened,1); + cd_text_frame(1098,30 + store_last_target_darkened,1); + } + store_last_target_darkened = store_spell_target; +} + +void put_spell_led_buttons() +{ + short i,spell_for_this_button; + + for (i = 0; i < 38; i++) { + spell_for_this_button = (on_which_spell_page == 0) ? i : spell_index[i]; + + if (spell_for_this_button < 90) { + if (((store_situation == 0) && (store_mage == spell_for_this_button)) || + ((store_situation == 1) && (store_priest == spell_for_this_button))) { + cd_set_led(1098,i + 37,2); + } + else if (pc_can_cast_spell(pc_casting,store_situation,spell_for_this_button) == TRUE) + cd_set_led(1098,i + 37,1); + else cd_set_led(1098,i + 37,0); + } + } + +} + +void put_spell_list() +{ + short i; + char add_text[256]; + + if (on_which_spell_page == 0) { + csit(1098,80,"Level 1:"); + csit(1098,81,"Level 2:"); + csit(1098,82,"Level 3:"); + csit(1098,83,"Level 4:"); + for (i = 0; i < 38; i++) { + if (store_situation == 0) { + if (i == 35) + sprintf((char *) add_text,"%s %c ?",mage_s_name[i], + (char) ((97 + i > 122) ? 65 + (i - 26) : 97 + i)); + else sprintf((char *) add_text,"%s %c %d",mage_s_name[i], + (char) ((97 + i > 122) ? 65 + (i - 26) : 97 + i),spell_cost[0][i]); + } + else sprintf((char *) add_text,"%s %c %d",priest_s_name[i], + (char) ((97 + i > 122) ? 65 + (i - 26) : 97 + i),spell_cost[1][i]); + //for (j = 0; j < 30; i++) + // if (add_text[j] == '&') + // add_text[j] = (char) ((97 + i > 122) ? 65 + (i - 26) : 97 + i); + cd_add_label(1098,37 + i,(char *) add_text,53); + if (spell_index[i] == 90) + cd_activate_item(1098,37 + i,1); + } + } + else { + csit(1098,80,"Level 5:"); + csit(1098,81,"Level 6:"); + csit(1098,82,"Level 7:"); + csit(1098,83,""); + for (i = 0; i < 38; i++) + if (spell_index[i] < 90) { + if (store_situation == 0) + sprintf((char *) add_text,"%s %c %d",mage_s_name[spell_index[i]], + (char) ((97 + i > 122) ? 65 + (i - 26) : 97 + i),spell_cost[0][spell_index[i]]); + else sprintf((char *) add_text,"%s %c %d",priest_s_name[spell_index[i]], + (char) ((97 + i > 122) ? 65 + (i - 26) : 97 + i),spell_cost[1][spell_index[i]]); + cd_add_label(1098,37 + i,(char *) add_text,53); + } + else cd_activate_item(1098,37 + i,0); + } +} + +void pick_spell_event_filter (short item_hit) +{ + char *choose_target = " Now pick a target."; + char *no_target = " No target needed."; + char *bad_target = " Can't cast on him/her."; + char *got_target = " Target selected."; + char *bad_spell = " Spell not available."; + Boolean spell_toast = FALSE,dialog_done = FALSE; + + switch (item_hit) { + case 4: case 5: case 6: case 7: case 8: case 9: // pick caster + if (cd_get_active(1098,item_hit) == 1) { + pc_casting = item_hit - 4; + if (pc_can_cast_spell(pc_casting,store_situation, + ((store_situation == 0) ? store_mage : store_priest)) == FALSE) { + if (store_situation == 0) + store_mage = 70; + else store_priest = 70; + store_spell_target = 6; + } + draw_spell_info(); + draw_spell_pc_info(); + put_spell_led_buttons(); + put_pc_caster_buttons(); + put_pc_target_buttons(); + } + break; + case 10: case 11: case 12: case 13: case 14: case 15: // pick target + if (cd_get_active(1098,10 + pc_casting) == FALSE) { + cd_set_item_text(1098,36,no_target); + } + else if (cd_get_active(1098,item_hit) == FALSE) { + cd_set_item_text(1098,36,bad_target); + } + else { + + cd_set_item_text(1098,36,got_target); + store_spell_target = item_hit - 10; + draw_spell_info(); + put_pc_target_buttons(); + } + break; + + case 16: // cancel + spell_toast = TRUE; + dialog_done = TRUE; + break; + case 1: case 17: // cast! + dialog_done = TRUE; + break; + + case 75: // other spells + on_which_spell_page = 1 - on_which_spell_page; + put_spell_list(); + put_spell_led_buttons(); + break; + + case 79: // help + party.help_received[7] = 0; + give_help(207,8,1098); + break; + + case 100: + break; + + default: + if (item_hit >= 100) { + item_hit -= 100; + i = (on_which_spell_page == 0) ? item_hit - 37 : spell_index[item_hit - 37]; + display_spells(store_situation,i,1098); + } + else if (cd_get_led(1098,item_hit) == 0) { + cd_set_item_text(1098,36,bad_spell); + } + else { + + if (store_situation == 0) + store_mage = (on_which_spell_page == 0) ? item_hit - 37 : spell_index[item_hit - 37]; + else store_priest = (on_which_spell_page == 0) ? item_hit - 37 : spell_index[item_hit - 37]; + draw_spell_info(); + put_spell_led_buttons(); + + if (store_spell_target < 6) { + if (cd_get_active(1098,10 + store_spell_target) == FALSE) { + store_spell_target = 6; + draw_spell_info(); + put_pc_target_buttons(); + } + } + // Cute trick now... if a target is needed, caster can always be picked + if ((store_spell_target == 6) && (cd_get_active(1098,10 + pc_casting) == 1)) { + cd_set_item_text(1098,36,choose_target); + draw_spell_info(); + force_play_sound(45); + } + else if (cd_get_active(1098,10 + pc_casting) == 0) { + store_spell_target = 6; + put_pc_target_buttons(); + } + + } + break; + } + if (dialog_done == TRUE) { + if (spell_toast == TRUE) { + store_mage = store_mage_store; + store_priest = store_priest_store; + store_spell_target = store_store_target ; + if (store_situation == 0) + store_last_cast_mage = pc_casting; + else store_last_cast_priest = pc_casting; + dialog_not_toast = FALSE; + dialog_answer = 70; + return; + } + + if (((store_situation == 0) && (store_mage == 70)) || + ((store_situation == 1) && (store_priest == 70))) { + add_string_to_buf("Cast: No spell selected."); + store_mage = store_mage_store; + store_priest = store_priest_store; + store_spell_target = store_store_target ; + dialog_not_toast = FALSE; + dialog_answer = 70; + return; + } + if ((store_situation == 0) && (mage_need_select[store_mage] == 0)) { + store_last_cast_mage = pc_casting; + pc_last_cast[store_situation][pc_casting] = store_mage; + dialog_not_toast = FALSE; + dialog_answer = store_mage; + return; + } + if ((store_situation == 1) && (priest_need_select[store_priest] == 0)) { + store_last_cast_priest = pc_casting; + pc_last_cast[store_situation][pc_casting] = store_priest; + dialog_not_toast = FALSE; + dialog_answer = store_priest; + return; + } + if (store_spell_target == 6) { + add_string_to_buf("Cast: Need to select target."); + store_mage = store_mage_store; + store_priest = store_priest_store; + store_spell_target = store_store_target ; + dialog_not_toast = FALSE; + give_help(39,0,1098); + dialog_answer = 70; + return; + } + item_hit = ((store_situation == 0) ? store_mage : store_priest); + if (store_situation == 0) + store_last_cast_mage = pc_casting; + else store_last_cast_priest = pc_casting; + pc_last_cast[store_situation][pc_casting] = ((store_situation == 0) ? store_mage : store_priest); + dialog_not_toast = FALSE; + dialog_answer = item_hit; + } + +} + +short pick_spell(short pc_num,short type,short) // 70 - no spell OW spell num +//short pc_num; // if 6, anyone +//short type; // 0 - mage 1 - priest +//short situation; // 0 - out 1 - town 2 - combat +{ + store_mage_store = store_mage; + store_priest_store = store_priest; + store_store_target = store_spell_target; + store_situation = type; + store_last_target_darkened = 6; + can_choose_caster = (pc_num < 6) ? FALSE : TRUE; + + pc_casting = (type == 0) ? store_last_cast_mage : store_last_cast_priest; + if (pc_casting == 6) + pc_casting = current_pc; + + if (pc_num == 6) { // See if can keep same caster + can_choose_caster = TRUE; + if (pc_can_cast_spell(pc_casting,type,type) == FALSE) { + for (i = 0; i < 6; i++) + if (pc_can_cast_spell(i,type,type)) { + pc_casting = i; + i = 500; + } + if (i == 6) { + add_string_to_buf("Cast: Nobody can."); + return 70; + } + } + } + else { + can_choose_caster = FALSE; + pc_casting = pc_num; + } + + if (can_choose_caster == FALSE) { + if ((type == 0) && (adven[pc_num].skills[SKILL_MAGE_SPELLS] == 0)) { + add_string_to_buf("Cast: No mage skill."); + return 70; + } + if ((type == 1) && (adven[pc_num].skills[SKILL_PRIEST_SPELLS] == 0)) { + add_string_to_buf("Cast: No priest skill."); + return 70; + } + if (adven[pc_casting].cur_sp == 0) { + add_string_to_buf("Cast: No spell points."); + return 70; + } + + } + + // If in combat, make the spell being cast this PCs most recent spell + if (is_combat()) { + if (type == 0) + store_mage = pc_last_cast[0][pc_casting]; + else store_priest = pc_last_cast[1][pc_casting]; + } + + // Keep the stored spell, if it's still castable + if (pc_can_cast_spell(pc_casting,type,((type == 0) ? store_mage : store_priest)) == FALSE) { + if (type == 0) { + store_mage = 0; + store_mage_lev = 1; + } + else { + store_priest = 1; + store_priest_lev = 1; + } + } + + // If a target is needed, keep the same target if that PC still targetable + if (((type == 0) && (mage_need_select[store_mage] > 0)) || + ((type == 1) && (priest_need_select[store_priest] > 0))) { + if (adven[store_spell_target].isAlive() == false) + store_spell_target = 6; + } + else store_spell_target = 6; + + // Set the spell page, based on starting spell + if (((type == 0) && (store_mage >= 38)) || ((type == 1) && (store_priest >= 38))) + on_which_spell_page = 1; + else on_which_spell_page = 0; + + + SetCursor(sword_curs); + + cd_create_dialog(1098,mainPtr); + cd_set_pict(1098,2,714 + type); + for (i = 37; i < 75; i++) { + cd_add_label(1098,i,"",55); + if (i > 62) + cd_attach_key(1098,i,(char ) (65 + i - 63)); + else cd_attach_key(1098,i,(char) (97 + i - 37)); + cd_set_led(1098,i,( pc_can_cast_spell(pc_casting,type, + (on_which_spell_page == 0) ? i - 37 : spell_index[i - 37]) == TRUE) ? 1 : 0); + } + cd_attach_key(1098,10,'!'); + cd_attach_key(1098,11,'@'); + cd_attach_key(1098,12,'#'); + cd_attach_key(1098,13,'$'); + cd_attach_key(1098,14,'%'); + cd_attach_key(1098,15,'^'); + for (i = 0; i < 6; i++) + cd_key_label(1098,10 + i,0); + for (i = 24; i < 36; i++) + cd_text_frame(1098,i,1); + + cd_set_flag(1098,78,0); + + put_spell_list(); + draw_spell_info(); + put_pc_caster_buttons(); + draw_spell_pc_info(); + draw_caster_buttons(); + put_spell_led_buttons(); + + if (party.help_received[7] == 0) { + cd_initial_draw(1098); + give_help(7,8,1098); + } + + while (dialog_not_toast) + ModalDialog(); + final_process_dialog(1098); + + return dialog_answer; +} + + +void print_spell_cast(short spell_num,short which) +//short which; // 0 - mage 1 - priest +{ + sprintf ((char *) c_line, "Spell: %s ", + (which == 0) ? (char *) mage_s_name[spell_num] : (char *) priest_s_name[spell_num]); + add_string_to_buf((char *) c_line); +} + +void set_town_spell(short s_num,short who_c) +{ + town_spell = s_num; + who_cast = who_c; +} + +void do_alchemy() +{ + short abil1_needed[20] = {150,151,150,151,153, 152,152,153,156,153, + 156,154,156,157,155, 157,157,152,156,157}; + short abil2_needed[20] = {0,0,0,153,0, 0,0,152,0,154, + 150,0,151,0,0, 154,155,155,154,155}; + short difficulty[20] = {1,1,1,3,3, 4,5,5,7,9, 9,10,12,12,9, 14,19,10,16,20}; + short fail_chance[20] = {50,40,30,20,10,8,6,4,2,0,0,0,0,0,0,0,0,0,0,0}; + short which_p,which_item,which_item2,r1; + short pc_num; + item_record_type store_i = {7,0, 0,0,0,1,0,0, 50,0,0,0,0,0, 0, 8,0, location(),"Potion","Potion",0,5,0,0}; + + short potion_abils[20] = {72,87,70,73,70, 87,72,73,77,88, + 79,70,87,70,160, 88,86,71,84,88}; + short potion_strs[20] = {2,2,2,2,4, 5,8,5,4,2, + 8,6,8,8,0, 5,2,8,5,8}; + short potion_val[20] = {40,60,15,50,50, 180,200,100,150,100, + 200,150,300,400,100, 300,500,175,250,500}; + + pc_num = select_pc(1,0); + if (pc_num == INVALID_PC) + return; + + which_p = alch_choice(pc_num); + if (which_p < 20) { + if (adven[pc_num].hasSpace() == 24) { + add_string_to_buf("Alchemy: Can't carry another item."); + return; + } + if (((which_item = adven[pc_num].hasAbil(abil1_needed[which_p])) == 24) || + ((abil2_needed[which_p] > 0) && ((which_item2 = adven[pc_num].hasAbil(abil2_needed[which_p])) == 24))) { + add_string_to_buf("Alchemy: Don't have ingredients."); + return; + } + play_sound(8); + adven[pc_num].removeCharge(which_item); + if (abil2_needed[which_p] > 0) + adven[pc_num].removeCharge(which_item2); + + r1 = get_ran(1,0,100); + if (r1 < fail_chance[adven[pc_num].skills[SKILL_ALCHEMY] - difficulty[which_p]]) { + add_string_to_buf("Alchemy: Failed. "); + r1 = get_ran(1,0,1); + play_sound(41 ); + } + else { + store_i.value = potion_val[which_p]; + store_i.ability_strength = potion_strs[which_p]; + store_i.ability = potion_abils[which_p]; + if (which_p == 8) + store_i.magic_use_type = 2; + strcpy(store_i.full_name,alch_names_short[which_p]); + if (adven[pc_num].skills[SKILL_ALCHEMY] - difficulty[which_p] >= 5) + store_i.charges++; + if (adven[pc_num].skills[SKILL_ALCHEMY] - difficulty[which_p] >= 11) + store_i.charges++; + if (store_i.variety == 7) + store_i.graphic_num += get_ran(1,0,2); + if (adven[pc_num].giveToPC(store_i,0) == false) { + ASB("No room in inventory."); + ASB(" Potion placed on floor."); + place_item(store_i,c_town.p_loc,TRUE); + } + else add_string_to_buf("Alchemy: Successful. "); + } + put_item_screen(stat_window,0); + } + +} + +void alch_choice_event_filter (short item_hit) +{ + if (item_hit == 49) { //OBoE changed + party.help_received[20] = 0; + give_help(220,21,1047); + return; + } + if (item_hit == 1) + dialog_answer = 20; + else { + item_hit = (item_hit - 9) / 2; + dialog_answer = item_hit; + } + dialog_not_toast = FALSE; +} + +short alch_choice(short pc_num) +{ + short difficulty[20] = {1,1,1,3,3, 4,5,5,7,9, 9,10,12,12,9, 14,19,10,16,20}; + short store_alchemy_pc; + char get_text[256]; + + SetCursor(sword_curs); + + store_alchemy_pc = pc_num; + + cd_create_dialog(1047,mainPtr); + for (i = 0; i < 20; i++) { + cd_set_item_text(1047,10 + i * 2,alch_names[i]); + if ((adven[pc_num].skills[SKILL_ALCHEMY] < difficulty[i]) || (party.alchemy[i] == 0)) + cd_activate_item(1047,9 + i * 2,0); + } + sprintf((char *) get_text, "%s (skill %d)", + adven[pc_num].name,adven[pc_num].skills[SKILL_ALCHEMY]); + cd_set_item_text(1047,4,get_text); + if (party.help_received[20] == 0) { + cd_initial_draw(1047); + give_help(20,21,1047); + } +while (dialog_not_toast) + ModalDialog(); + + final_process_dialog(1047); + return dialog_answer; +} + +void pc_graphic_event_filter (short item_hit) +{ + switch (item_hit) { + case 1: + adven[store_graphic_pc_num].which_graphic = store_pc_graphic; + update_pc_graphics(); + if (store_graphic_mode == 0) + dialog_not_toast = FALSE; + else { + dialog_not_toast = FALSE; + dialog_answer = TRUE; + } + break; + + case 4: + update_pc_graphics(); + if (store_graphic_mode == 0) { + if (adven[store_graphic_pc_num].main_status < MAIN_STATUS_ABSENT) + adven[store_graphic_pc_num].main_status = MAIN_STATUS_ABSENT; + dialog_not_toast = FALSE; + } + else { + dialog_not_toast = FALSE; + dialog_answer = TRUE; + } + break; + + default: + cd_set_led(1050,store_pc_graphic + 5,0); + store_pc_graphic = item_hit - 5; + cd_set_led(1050,item_hit,1); + break; + } + + dialog_answer = FALSE; +} + +Boolean pick_pc_graphic(short pc_num,short mode,short parent_num) +// mode ... 0 - create 1 - created +{ + short i; + Boolean munch_pc_graphic = FALSE; + + store_graphic_pc_num = pc_num; + store_graphic_mode = mode; + store_pc_graphic = adven[pc_num].which_graphic; + + SetCursor(sword_curs); + + if (pcs_gworld == NULL) { + munch_pc_graphic = TRUE; + pcs_gworld = load_pict(902,main_dc); + } + cd_create_dialog_parent_num(1050,parent_num); + + for (i = 41; i < 77; i++) + csp(1050,i,800 + i - 41); + for (i = 5; i < 41; i++) { + if (store_pc_graphic + 5 == i) + cd_set_led(1050,i,1); + else cd_set_led(1050,i,0); + } + while (dialog_not_toast) + ModalDialog(); cd_kill_dialog(1050,0); + + if (munch_pc_graphic == TRUE) { + DeleteObject(pcs_gworld); + pcs_gworld = NULL; + } + return dialog_answer; +} + +void pc_name_event_filter () +{ + char get_text[256]; + + cd_get_text_edit_str(1051,(char *) get_text); + if ((get_text[0] < 33) || (get_text[0] > 126)) { + csit(1051,6,"Must begin with a letter."); + } + else { + sprintf((char *) adven[store_train_pc].name,"%.18s",(char *) get_text); + dialog_not_toast = FALSE; + } +} + +Boolean pick_pc_name(short pc_num,short parent_num) +//town_num; // Will be 0 - 200 for town, 200 - 290 for outdoors +//short sign_type; // terrain type +{ + store_train_pc = pc_num; + + SetCursor(sword_curs); + + cd_create_dialog_parent_num(1051,parent_num); + cd_set_edit_focus(); + + while (dialog_not_toast) + ModalDialog(); + cd_kill_dialog(1051,0); + + return 1; +} + +void pick_trapped_monst_event_filter (short item_hit) +{ + dialog_not_toast = FALSE; + dialog_answer = item_hit; +} + +unsigned char pick_trapped_monst() +// ignore parent in Mac version +{ + short i; + char sp[256]; + monster_record_type get_monst; + + SetCursor(sword_curs); + + cd_create_dialog_parent_num(988,0); + + for (i = 0; i < 4; i++) + if (party.imprisoned_monst[i] == 0) { + cd_activate_item(988, 2 + 3 * i, 0); + } + else { + get_m_name((char *) sp,(unsigned char)(party.imprisoned_monst[i])); + csit(988,3 + 3 * i,(char *) sp); + get_monst = return_monster_template((unsigned char)(party.imprisoned_monst[i])); + cdsin(988,4 + 3 * i,get_monst.level); + } + + while (dialog_not_toast) + ModalDialog(); cd_kill_dialog(988,0); + + if (dialog_answer == 1) + return 0; + else return ((unsigned char)(party.imprisoned_monst[(dialog_answer - 2) / 3])); +} + +void pc_record_type::poison(short how_much) +{ + short tlevel = 0; + + if (isAlive()) { + if ((tlevel = getProtLevel(34)) > 0)//// + how_much -= tlevel / 2; + if ((tlevel = getProtLevel(31)) > 0)//// + how_much -= tlevel / 3; + if ((traits[12] == TRUE) && (how_much > 1)) how_much++; + if ((traits[12] == TRUE) && (how_much == 1) && (get_ran(1,0,1) == 0)) + how_much++; + + if (how_much > 0) { + status[2] = min(status[2] + how_much,8); + sprintf ((char *) c_line, " %s poisoned.", (char *) name); + add_string_to_buf((char *) c_line); + one_sound(17); + give_help(33,0,0); + } + } + put_pc_screen(); +} + +void pc_array::poison(short how_much) +{ + for (int i = 0; i < 6; i++) pc[i].poison(how_much); +} + +void affect_pc(short which_pc,short type,short how_much)//// +//type; // which status to affect +{ + + if (adven[which_pc].isAlive() == false) + return; + adven[which_pc].status[type] = minmax (-8,8,adven[which_pc].status[type] + how_much); + if (((type >= 4) && (type <= 10)) || (type == 12) || (type == 13)) + adven[which_pc].status[type] = max(adven[which_pc].status[type],0); + put_pc_screen(); +} + +void pc_array::affect(short type, short how_much) +//type; // which status to affect +{ + for (int i = 0; i < 6; i++) + adven[i].status[type] = minmax (-8,8,adven[i].status[type] + how_much); + put_pc_screen(); +} + +void void_sanctuary(short pc_num) +{ + if (adven[pc_num].status[8] > 0) + { + add_string_to_buf("You become visible!"); + adven[pc_num].status[8] = 0; + } +} + +void pc_array::damage(short how_much,short damage_type) +{ + for (int i = 0; i < NUM_OF_PCS; i++) + pc[i].damage(how_much,damage_type,-1); + + put_pc_screen(); +} + +void pc_array::kill(short mode) +{ + short i; + + boom_anim_active = FALSE; + for (i = 0; i < 6; i++) + if (pc[i].isAlive()) + pc[i].main_status = mode; + + put_pc_screen(); +} + +bool pc_record_type::damage(short how_much, short damage_type, short type_of_attacker) +//short damage_type; // 0 - weapon 1 - fire 2 - poison 3 - general magic 4 - unblockable + // 5 - cold 6 - undead attack 7 - demon attack + // 10 - marked damage, from during anim mode ... no boom, and totally unblockable + // 30 + * same as *, but no print + // 100s digit - sound data +{ + short i, r1, sound_type, tlevel; + bool do_print = true; + + if (!isAlive()) return false; + + sound_type = damage_type / 100; + damage_type = damage_type % 100; + + if (damage_type >= DAMAGE_NO_PRINT) + { + do_print = false; + damage_type -= DAMAGE_NO_PRINT; + } + + if (sound_type == 0) { + if ((damage_type == DAMAGE_FIRE) || (damage_type == DAMAGE_UNBLOCKABLE)) + sound_type = 5; + if (damage_type == DAMAGE_MAGIC) sound_type = 12; + if (damage_type == DAMAGE_COLD) sound_type = 7; + if (damage_type == DAMAGE_POISON) sound_type = 11; + } + + // armor + if ((damage_type == DAMAGE_WEAPON) || (damage_type == DAMAGE_UNDEAD) ||(damage_type == DAMAGE_DEMON)) { + how_much -= minmax(-5, 5, (int)status[STATUS_BLESS]); + for (i = 0; i < 24; i++) + if ((items[i].variety != 0) && (equip[i] == TRUE)) { + if ((items[i].variety >= 12) && (items[i].variety <= 17)) { + r1 = get_ran(1,1,items[i].item_level); + how_much -= r1; + + // bonus for magical items + if (items[i].bonus > 0) { + r1 = get_ran(1,1,items[i].bonus); + how_much -= r1; + how_much -= items[i].bonus / 2; + } + + if (items[i].bonus < 0) how_much -= items[i].bonus; + + r1 = get_ran(1,0,100); + if (r1 < hit_chance[skills[8]] - 20) + how_much -= 1; + } + if (items[i].protection > 0) { + r1 = get_ran(1,1,items[i].protection); + how_much -= r1; + } + if (items[i].protection < 0) { + r1 = get_ran(1,1,-1 * items[i].protection); + how_much += r1; + } + } + } + + // parry + + // ugly hack + short which_pc = getNum(); + +// temporarily disabled + if ((damage_type < DAMAGE_POISON) && (pc_parry[which_pc] < 100)) + how_much -= pc_parry[which_pc] / 4; + + + + if (damage_type != DAMAGE_MARKED) + { + if (PSD[306][7] > 0) how_much -= 3; + + // toughness + if (traits[TRAIT_TOUGHNESS] == TRUE) how_much--; + + // luck + if (get_ran(1,0,100) < 2 * (hit_chance[skills[SKILL_LUCK]] - 20)) + how_much -= 1; + } + + if ((damage_type == DAMAGE_WEAPON) && ((tlevel = getProtLevel(30)) > 0)) + how_much -= tlevel; + if ((damage_type == DAMAGE_UNDEAD) && ((tlevel = getProtLevel(57)) > 0)) + how_much /= ((tlevel >= 7) ? 4 : 2); + if ((damage_type == DAMAGE_DEMON) && ((tlevel = getProtLevel(58)) > 0)) + how_much /= ((tlevel >= 7) ? 4 : 2); + + if ((type_of_attacker == 6) && ((tlevel = getProtLevel(59)) > 0)) + how_much /= ((tlevel >= 7) ? 4 : 2); + if ((type_of_attacker == 1) && ((tlevel = getProtLevel(60)) > 0)) + how_much /= ((tlevel >= 7) ? 4 : 2); + if ((type_of_attacker == 9) && ((tlevel = getProtLevel(61)) > 0)) + how_much /= ((tlevel >= 7) ? 4 : 2); + + + // invuln + if (status[STATUS_INVULNERABLE] > 0) how_much = 0; + + // magic resistance + if ((damage_type == DAMAGE_MAGIC) && ((tlevel = getProtLevel(35)) > 0)) + how_much /= ((tlevel >= 7) ? 4 : 2); + + // Mag. res helps w. fire and cold + if (((damage_type == DAMAGE_FIRE) || (damage_type == DAMAGE_COLD)) && (status[5] > 0)) + how_much /= 2; + + // fire res. + if ((damage_type == DAMAGE_FIRE) && ((tlevel = getProtLevel(32)) > 0)) + how_much /= ((tlevel >= 7) ? 4 : 2); + + // cold res. + if ((damage_type == DAMAGE_COLD) && ((tlevel = getProtLevel(33)) > 0)) + how_much /= ((tlevel >= 7) ? 4 : 2); + + // major resistance + if (((damage_type == DAMAGE_FIRE) || (damage_type == DAMAGE_POISON) + || (damage_type == DAMAGE_MAGIC) || (damage_type == DAMAGE_COLD)) + && ((tlevel = getProtLevel(31)) > 0)) + how_much /= ((tlevel >= 7) ? 4 : 2); + + //ugly hack +// short which_pc = getNum(); + +// temporarily disabled + if (boom_anim_active == TRUE) + { + if (how_much < 0) + how_much = 0; + pc_marked_damage[which_pc] += how_much; + + if (is_town()) + add_explosion(c_town.p_loc,how_much,0,(damage_type > DAMAGE_POISON) ? 2 : 0,0,0); + else add_explosion(pc_pos[which_pc],how_much,0,(damage_type > DAMAGE_POISON) ? 2 : 0,0,0); + + if (how_much == 0) + return false; + else + return true; + } + + if (how_much <= 0) { + if ((damage_type == DAMAGE_WEAPON) || (damage_type == DAMAGE_UNDEAD) || (damage_type == DAMAGE_DEMON)) + play_sound(2); + add_string_to_buf (" No damage."); + return FALSE; + } + else { + // if asleep, get bonus + if (status[11] > 0) status[11]--; + + sprintf ((char *) c_line, " %s takes %d. ",(char *) name, how_much); + if (do_print) add_string_to_buf((char *) c_line); + if (damage_type != DAMAGE_MARKED) { + if (is_combat()) + boom_space(pc_pos[which_pc],overall_mode,boom_gr[damage_type],how_much,sound_type); + else if (is_town()) + boom_space(c_town.p_loc,overall_mode,boom_gr[damage_type],how_much,sound_type); + else boom_space(c_town.p_loc,100,boom_gr[damage_type],how_much,sound_type); + } + if (overall_mode != MODE_OUTDOORS) + FlushEvents(1); + FlushEvents(0); + } + + party.total_dam_taken += how_much; + + if (cur_health >= how_much) + cur_health -= how_much; + else if (cur_health > 0) + cur_health = 0; + else // Check if PC can die + if (how_much > 25) { + sprintf ((char *) c_line, " %s is obliterated. ",(char *) name); + add_string_to_buf((char *) c_line); + kill(3); + } + else { + sprintf ((char *) c_line, " %s is killed.",(char *) name); + add_string_to_buf((char *) c_line); + kill(2); + } + if ((cur_health == 0) && isAlive()) play_sound(3); + put_pc_screen(); + return true; +} + +void set_pc_moves() +{ + short i,r,i_level; + + for (i = 0; i < 6; i++) + if (adven[i].isAlive() == false) + pc_moves[i] = 0; + else { + pc_moves[i] = (adven[i].traits[10] == TRUE) ? 3 : 4; + r = get_encumberance(i); + pc_moves[i] = minmax(1,8,pc_moves[i] - (r / 3)); + + if ((i_level = adven[i].getProtLevel(55)) > 0) + pc_moves[i] += i_level / 7 + 1; + if ((i_level = adven[i].getProtLevel(56)) > 0) + pc_moves[i] -= i_level / 5; + + if ((adven[i].status[3] < 0) && (party.age % 2 == 1)) // slowed? + pc_moves[i] = 0; + else { // do webs + pc_moves[i] = max(0,pc_moves[i] - adven[i].status[6] / 2); + if (pc_moves[i] == 0) { + sprintf((char *) c_line,"%s must clean webs.",adven[i].name); + add_string_to_buf((char *) c_line); + adven[i].status[6] = max(0,adven[i].status[6] - 3); + } + } + if (adven[i].status[3] > 7) + pc_moves[i] = pc_moves[i] * 3; + else if (adven[i].status[3] > 0) + pc_moves[i] = pc_moves[i] * 2; + if ((adven[i].status[11] > 0) || (adven[i].status[12] > 0)) + pc_moves[i] = 0; + + } + +} + +void take_ap(short num) +{ + pc_moves[current_pc] = max(0,pc_moves[current_pc] - num); +} + +short cave_lore_present() +{ + short i,ret = 0; + for (i = 0; i < 6; i++) + if ((adven[i].isAlive()) && (adven[i].traits[TRAIT_CAVE_LORE] > 0)) + ret += 1; + return ret; +} + +// Time for some chicanery +// The how to item for mage will be 399, for priest will be 499 +// item 400 + i will mean cast mage spell i. +// item 500 + i will mean cast priest spell i. +void adjust_spell_menus() +{ + short i,j,spell_pos = 0; + short total_added = 0; + char spell_name[256]; + short old_on_spell_menu[2][62]; + Boolean need_menu_change = FALSE; + HMENU menu,big_menu; + + if (in_startup_mode == TRUE) + return; + + big_menu = GetMenu(mainPtr); + menu = GetSubMenu(big_menu,6); + if (menu == NULL) + return; + for (i = 0; i < 2; i++) + for (j = 0; j < 62; j++) + old_on_spell_menu[i][j] = on_spell_menu[i][j]; + + for (i = 0; i < 62; i++) { + on_spell_menu[0][i] = -1; + } + for (i = 0; i < 62; i++) + if (pc_can_cast_spell(current_pc,0,i)) { + on_spell_menu[0][spell_pos] = i; + spell_pos++; + } + + for (i = 0; i < 62; i++) + if (on_spell_menu[0][i] != old_on_spell_menu[0][i]) + need_menu_change = TRUE; + + + if (need_menu_change) { + for (i = 0; i < 62; i++) { + DeleteMenu(menu,400 + i,MF_BYCOMMAND); + } + + for (i = 0; i < 62; i++) + if (pc_can_cast_spell(current_pc,0,i) == TRUE) { + if (spell_cost[0][i] > 0) + sprintf((char *)spell_name,"L%d - %s, C %d",spell_level[i], + (char *) mage_s_name[i],spell_cost[0][i]); + else sprintf((char *)spell_name,"L%d - %s, C ?",spell_level[i], + (char *) mage_s_name[i]); + total_added++; + if (total_added % 24 == 0) + InsertMenu(menu,399,MF_MENUBREAK | MF_BYCOMMAND | MF_ENABLED | MF_STRING, 400 + i, spell_name); + else InsertMenu(menu,399,MF_BYCOMMAND | MF_ENABLED | MF_STRING, 400 + i, spell_name); + + //InsertMenu(menu,399,MF_BYCOMMAND | MF_ENABLED | MF_STRING, + // 400 + i, spell_name); + //beep(); + } + } + + need_menu_change = FALSE; + spell_pos = 0; + total_added = 0; + menu = GetSubMenu(big_menu,7); + if (menu == NULL) + return; + + for (i = 0; i < 62; i++) { + on_spell_menu[1][i] = -1; + } + for (i = 0; i < 62; i++) + if (pc_can_cast_spell(current_pc,1,i)) { + on_spell_menu[1][spell_pos] = i; + spell_pos++; + } + for (i = 0; i < 62; i++) + if (on_spell_menu[1][i] != old_on_spell_menu[1][i]) + need_menu_change = TRUE; + if (need_menu_change) { + for (i = 0; i < 62; i++) { + DeleteMenu(menu,500 + i,MF_BYCOMMAND); + } + for (i = 0; i < 62; i++) + if (pc_can_cast_spell(current_pc,1,i) == TRUE) { + //spell_name[0] = strlen((char *) priest_s_name[on_spell_menu[1][i]]); + //strcpy((char *) (spell_name + 1),priest_s_name[on_spell_menu[1][i]]); + if (spell_cost[1][i] > 0) + sprintf((char *)spell_name," L%d - %s, C %d",spell_level[i], + (char *) priest_s_name[i],spell_cost[1][i]); + else sprintf((char *)spell_name," L%d - %s, C ?",spell_level[i], + (char *) priest_s_name[i]); + total_added++; + if (total_added % 24 == 0) + InsertMenu(menu,499,MF_MENUBREAK | MF_BYCOMMAND | MF_ENABLED | MF_STRING, 500 + i, spell_name); + else InsertMenu(menu,499,MF_BYCOMMAND | MF_ENABLED | MF_STRING, 500 + i, spell_name); + } + } +} diff --git a/Win32/Blades of Exile/PARTY.H b/Win32/Blades of Exile/PARTY.H new file mode 100644 index 00000000..9dd3eccf --- /dev/null +++ b/Win32/Blades of Exile/PARTY.H @@ -0,0 +1,51 @@ +#ifndef _PARTY_H + #define _PARTY_H + +void init_party(short mode); +void init_party_scen_data(); +void make_boats() ; +pc_record_type return_dummy_pc(); +pc_record_type create_debug_pc(short num); +pc_record_type create_prefab_pc(short num); +Boolean create_pc(short spot,short parent_num); +void increase_light(short amt); +void do_xp_keep(short pc_num,short mode); +Boolean spend_xp_event_filter (short item_hit); +void do_xp_draw(); +void draw_xp_skills(); +Boolean spend_xp(short pc_num, short mode, short parent); +Boolean poison_weapon( short pc_num, short how_much,short safe); +Boolean is_weapon(short pc_num,short item); +void cast_spell(short type,short situation); +Boolean repeat_cast_ok(short type); +void give_party_spell(short which); +void do_mage_spell(short pc_num,short spell_num); +void do_priest_spell(short pc_num,short spell_num); +void cast_town_spell(location where); +void sanctify_space(location where); +void do_mindduel(short pc_num,creature_data_type *monst); +void dispel_fields(short i,short j,short mode); +Boolean pc_can_cast_spell(short pc_num,short type,short spell_num); +void pick_spell_event_filter (short item_hit); +short pick_spell(short pc_num,short type,short situation) ; +void set_town_spell(short s_num,short who_c); +void alch_choice_event_filter (short item_hit); +void do_alchemy(); +short alch_choice(short pc_num); +void pc_graphic_event_filter (short item_hit); +Boolean pick_pc_graphic(short pc_num,short mode,short parent_num); +void pc_name_event_filter (); +Boolean pick_pc_name(short pc_num,short parent_num) ; +void pick_trapped_monst_event_filter (short item_hit); +unsigned char pick_trapped_monst() ; +void affect_pc(short which_pc,short type,short how_much); +void void_sanctuary(short pc_num); +void set_pc_moves(); +void take_ap(short num); +short cave_lore_present(); +void adjust_spell_menus(); +void print_spell_cast(short spell_num,short which); +void update_gold_skills(); +void put_party_in_scen(); + +#endif diff --git a/Win32/Blades of Exile/PC.CPP b/Win32/Blades of Exile/PC.CPP new file mode 100644 index 00000000..70dbad16 --- /dev/null +++ b/Win32/Blades of Exile/PC.CPP @@ -0,0 +1,982 @@ +#include "pc.h" // party_record_type +#include "location.h" // location +#include "text.h" // add_string_to_buf +#include "blades.h" // globals +#include "exlsound.h" // play_sound +#include "combat.h" // hit_chance +#include "items.h" // place_item +#include "fields.h" // make_sfx +#include "global.h" // get_ran +#include "infodlgs.h" // give_help +#include "party.h" // adjust_spell_menu +#include "itemdata.h" // return_dummy_item +#include "locutils.h" // is_container +#include "globvar.h" + +void pc_record_type::kill(short type) +{ + short i = 24; + bool dummy, no_save = false; + location item_loc; + + if (type >= 10) + { + type -= 10; + no_save = true; + } + + if (type != 4) + i = hasAbilEquip(48); //check if has life saving items + else + i = hasAbilEquip(49); //check if has protection vs petrification items + + short which_pc = getNum(); + + if ((no_save == false) && (type != 0) && (skills[SKILL_LUCK] > 0) && + (get_ran(1,0,100) < hit_chance[skills[SKILL_LUCK]])) { + add_string_to_buf(" But you luck out! "); + cur_health = 0; + } + else if ((i == 24) || (type == 0)) { + if (combat_active_pc == which_pc) + combat_active_pc = 6; + + for (i = 0; i < 24; i++) + equip[i] = FALSE; + + item_loc = (overall_mode >= MODE_COMBAT) ? pc_pos[which_pc] : c_town.p_loc; + + if (type == 2) + make_sfx(item_loc.x,item_loc.y,3); + else if (type == 3) + make_sfx(item_loc.x,item_loc.y,6); + + if (overall_mode != 0) + for (i = 0; i < 24; i++) + if (items[i].variety != 0) { + dummy = place_item(items[i],item_loc,TRUE); + items[i].variety = 0; + } + if ((type == 2) || (type == 3)) + play_sound(21); + if(type == 4){ + play_sound(43); + sprintf ((char *) create_line, " %s is turned to stone. ",(char *) name); + add_string_to_buf((char *) create_line); + } + main_status = type; + pc_moves[which_pc] = 0; + } + else { + if (type == 4) { + sprintf ((char *) create_line, " %s is immuned to petrification. ",(char *) name); + add_string_to_buf((char*) create_line); //inform of what has happened + } + else{ + add_string_to_buf(" Life saved! "); + takeItem(i); + heal(200); + } + } + if (!isAlive()) current_pc = first_active_pc(); + + if (current_pc > 5) { + for (i = 0; i < NUM_OF_PCS; i++) + if (adven[i].status > 0) + current_pc = i; + } + + put_pc_screen(); + set_stat_window(current_pc); +} + +bool pc_record_type::runTrap(short trap_type, short trap_level, short diff) +{ + short r1,skill,i,num_hits = 1,i_level; + short trap_odds[30] = {5,30,35,42,48, 55,63,69,75,77, + 78,80,82,84,86, 88,90,92,94,96,98,99,99,99,99,99,99,99,99,99}; + + num_hits += trap_level; + + if (trap_type == TRAP_RANDOM) + trap_type = get_ran(1,1,4); + + /// ??? => no trap after all ;) + if (trap_type == 6) + return true; + + i = statAdj(1); + + if ((i_level = getProtLevel(42)) > 0) + i += i_level / 2; + + skill = minmax(0, 20, skills[14] + skills[SKILL_LUCK] / 2 + 1 - c_town.difficulty + 2 * i); + + r1 = get_ran(1,0,100) + diff; + // Nimble? + if (traits[TRAIT_NIMBLE] == TRUE) r1 -= 6; + + if (r1 < trap_odds[skill]) + { + add_string_to_buf(" Trap disarmed. "); + return true; + } + else add_string_to_buf(" Disarm failed. "); + + switch (trap_type) + { + case TRAP_BLADE: + for (i = 0; i < num_hits; i++) + { + add_string_to_buf(" A knife flies out! "); + damage(get_ran(2 + c_town.difficulty / 14,1,10),DAMAGE_WEAPON,-1); + } + break; + + case TRAP_DART: + add_string_to_buf(" A dart flies out. "); + poison((3 + c_town.difficulty / 14) + (trap_level * 2)); + break; + + case TRAP_GAS: + add_string_to_buf(" Poison gas pours out. "); + adven.poison((2 + c_town.difficulty / 14) + trap_level * 2); + break; + + case TRAP_EXPLOSION: + for (i = 0; i < num_hits; i++) + { + add_string_to_buf(" There is an explosion. "); + adven.damage(get_ran(3 + c_town.difficulty / 13,1,8), DAMAGE_FIRE); + } + break; + + case TRAP_SLEEP_RAY: + add_string_to_buf(" A purple ray flies out. "); + sleep((200 + c_town.difficulty * 100) + (trap_level * 400),12,50); + break; + + case TRAP_DRAIN_XP: + add_string_to_buf(" You feel weak. "); + experience = max(0, experience - (40 + trap_level * 30)); + break; + + case TRAP_ALERT: + add_string_to_buf(" An alarm goes off!!! "); + make_town_hostile(); + break; + + case TRAP_FLAMES: + add_string_to_buf(" Flames shoot from the walls. "); + adven.damage(get_ran(10 + trap_level * 5,1,8),DAMAGE_FIRE); + break; + + case TRAP_DUMBFOUND: + add_string_to_buf(" You feel disoriented. "); + adven.dumbfound(2 + trap_level * 2); + break; + + case TRAP_DISEASE: + add_string_to_buf(" You prick your finger. "); + disease((3 + c_town.difficulty / 14) + (trap_level * 2)); + break; + + case TRAP_DISEASE_ALL: + add_string_to_buf(" A foul substance sprays out."); + adven.disease((2 + c_town.difficulty / 14) + (trap_level * 2)); + break; + + default: + add_string_to_buf(" (ERROR: Unknown type of trap!)"); + break; + } + + put_pc_screen(); + put_item_screen(stat_window,0); + return true; +} + +short pc_record_type::statAdj(short which) +{ + short tr; + + tr = skill_bonus[skills[which]]; + + if (which == 2) { + if (traits[1] == TRUE) tr++; + if (hasAbilEquip(40) < 24) tr++; + } + + if (which == 0) + if (traits[8] == TRUE) tr++; + if (hasAbilEquip(38) < 24) + tr++; + + if (which == 1) { + if (hasAbilEquip(39) < 24) + tr++; + } + + return tr; +} + +void pc_record_type::giveXP(short amt) +{ + short adjust,add_hp; + short xp_percent[30] = {150,120,100,90,80,70,60,50,50,50, + 45,40,40,40,40,35,30,25,23,20, + 15,15,15,15,15,15,15,15,15,15}; + + if (!isAlive()) return; + + if (level > 49) + { + level = 50; + return; + } + + if (amt > 200) { // debug + MessageBeep(MB_OK); + ASB("Oops! Too much xp!"); + ASB("Report this!"); + return; + } + + if (amt < 0) { // debug + MessageBeep(MB_OK); + ASB("Oops! Negative xp!"); + ASB("Report this!"); + return; + } + + if (level >= 40) adjust = 15; + else adjust = xp_percent[level / 2]; + + if ((amt > 0) && (level > 7)) + { + if (get_ran(1,0,100) < xp_percent[level / 2]) amt--; + } + + if (amt <= 0) return; + + experience += (max(((amt * adjust) / 100), 0) * 100) / 100; + + party.total_xp_gained += (max(((amt * adjust) / 100), 0) * 100) / 100; + + if (experience < 0) { + MessageBeep(MB_OK); + ASB("Oops! Xp became negative somehow!"); + ASB("Report this!"); + experience = level * (get_tnl(this)) - 1; + return; + } + + if (experience > 15000) + { + experience = 15000; + return; + } + + while (experience >= (level * (get_tnl(this)))) + { + play_sound(7); + level++; + + sprintf ((char *) c_line, " %s is level %d! ",(char *) name, level); + add_string_to_buf((char *) c_line); + skill_pts += (level < 20) ? 5 : 4; + add_hp = (level < 26) ? get_ran(1,2,6) + skill_bonus[skills[0]] + : max (skill_bonus[skills[0]],0); + + if (add_hp < 0) add_hp = 0; + max_health += add_hp; + + if (max_health > 250) max_health = 250; + cur_health += add_hp; + + if (cur_health > 250) cur_health = 250; + + put_pc_screen(); + } +} + +void pc_record_type::drainXP(short how_much) +{ + if (!isAlive()) return; + + experience = max(experience - how_much, 0); + sprintf ((char *) c_line, " %s drained.",(char *) name); + add_string_to_buf((char *) c_line); +} + +void pc_record_type::restoreSP(short amt) +{ + if (!isAlive()) return; + if (cur_sp > max_sp) return; + cur_sp += amt; + if (cur_sp > max_sp) cur_sp = max_sp; +} + +void pc_record_type::cure(short amt) +{ + if (!isAlive()) return; + + if (status[STATUS_POISON] <= amt) + status[STATUS_POISON] = 0; + else + status[STATUS_POISON] -= amt; + + one_sound(51); +} + +void pc_record_type::curse(short how_much) +{ + if (!isAlive()) return; + + status[STATUS_BLESS] = max(status[STATUS_BLESS] - how_much, -8); + sprintf ((char *) c_line, " %s cursed.",(char *) name); + add_string_to_buf((char *) c_line); + + put_pc_screen(); + give_help(59,0,0); +} + +void pc_record_type::dumbfound(short how_much) +{ + short r1; + + if (!isAlive()) return; + + r1 = get_ran(1,0,90); + + if (hasAbilEquip(53) < 24) { + add_string_to_buf(" Ring of Will glows."); + r1 -= 10; + } + + if (r1 < level) + how_much -= 2; + + if (how_much <= 0) { + sprintf ((char *) c_line, " %s saved.",(char *) name); + add_string_to_buf((char *) c_line); + return; + } + + status[STATUS_DUMB] = min(status[STATUS_DUMB] + how_much, 8); + sprintf ((char *) c_line, " %s dumbfounded.",(char *) name); + add_string_to_buf((char *) c_line); + + one_sound(67); + put_pc_screen(); + adjust_spell_menus(); + give_help(28,0,0); +} + +void pc_record_type::disease(short how_much) +{ + short r1, tlevel; + + if (!isAlive()) return; + + r1 = get_ran(1,0,100); + + if (r1 < level * 2) + how_much -= 2; + + if (how_much <= 0) + { + sprintf ((char *) c_line, " %s saved.",(char *) name); + add_string_to_buf((char *) c_line); + return; + } + + if ((tlevel = getProtLevel(62)) > 0) + how_much -= tlevel / 2; + + if ((traits[12] == TRUE) && (how_much > 1)) how_much++; + if ((traits[12] == TRUE) && (how_much == 1) && (get_ran(1,0,1) == 0)) how_much++; + + status[STATUS_DISEASE] = min(status[STATUS_DISEASE] + how_much,8); + sprintf ((char *) c_line, " %s diseased.",(char *) name); + add_string_to_buf((char *) c_line); + + one_sound(66); + put_pc_screen(); + give_help(29,0,0); +} + + +void pc_record_type::sleep(short how_much,short what_type,short adjust) +// higher adjust, less chance of saving +{ + short r1, tlevel; + if (!isAlive()) return; + + if (how_much == 0) + return; + + if ((what_type == STATUS_ASLEEP) || (what_type == STATUS_PARALYZED)) { //// + if ((tlevel = getProtLevel(53)) > 0) + how_much -= tlevel / 2; + if ((tlevel = getProtLevel(54)) > 0) + how_much -= (what_type == STATUS_ASLEEP) ? tlevel : tlevel * 300; + + } + + r1 = get_ran(1,0,100) + adjust; + if (r1 < 30 + level * 2) + how_much = -1; + if ((what_type == STATUS_ASLEEP) && ((traits[7] > 0) || (status[STATUS_ASLEEP] < 0))) + how_much = -1; + if (how_much <= 0) { + sprintf ((char *) c_line, " %s resisted.",(char *) name); + add_string_to_buf((char *) c_line); + return; + } + if (isAlive()) { + status[what_type] = how_much; + if (what_type == STATUS_ASLEEP) + sprintf ((char *) c_line, " %s falls asleep.",(char *) name); + else sprintf ((char *) c_line, " %s paralyzed.",(char *) name); + if (what_type == STATUS_ASLEEP) + play_sound(96); + else play_sound(90); + add_string_to_buf((char *) c_line); + pc_moves[getNum()] = 0; + } + put_pc_screen(); + if (what_type == STATUS_ASLEEP) + give_help(30,0,0); + else give_help(32,0,0); +} + +void pc_record_type::slow(short how_much) +{ + if (!isAlive()) return; + + status[STATUS_HASTE] = minmax(-8,8,status[STATUS_HASTE] - how_much); + if (how_much < 0) + sprintf ((char *) c_line, " %s hasted.",(char *) name); + else sprintf ((char *) c_line, " %s slowed.",(char *) name); + add_string_to_buf((char *) c_line); + + put_pc_screen(); + if (how_much < 0) + give_help(35,0,0); +} + +void pc_record_type::web(short how_much) +{ + if (!isAlive()) return; + + status[STATUS_WEBS] = min(status[STATUS_WEBS] + how_much,8); + sprintf ((char *) c_line, " %s webbed.",(char *) name); + add_string_to_buf((char *) c_line); + one_sound(17); + + put_pc_screen(); + give_help(31,0,0); +} + +void pc_record_type::acid(short how_much) +{ + if (!isAlive()) return; + + if (hasAbilEquip(122) < 24) { + sprintf ((char *) c_line, " %s resists acid.",(char *) name); + add_string_to_buf((char *) c_line); + return; + } + + status[STATUS_ACID] += how_much; + sprintf ((char *) c_line, " %s covered with acid!",(char *) name); + add_string_to_buf((char *) c_line); + one_sound(42); + + put_pc_screen(); +} + +void pc_record_type::heal(short amt) +{ + if (!isAlive()) return; + if (cur_health > max_health) return; + + cur_health += amt; + + if (cur_health > max_health) + cur_health = max_health; +} + +void pc_record_type::sortItems() +{ + item_record_type store_item; + short item_priority[26] = {20,8,8,20,9, 9,3,2,1,0, 7,20,10,10,10, 10,10,10,5,6, 4,11,12,9,9, 9}; + bool no_swaps = false, store_equip; + int i; + + while (no_swaps == false) { + no_swaps = true; + for (i = 0; i < 23; i++) + if (item_priority[items[i + 1].variety] < + item_priority[items[i].variety]) { + no_swaps = false; + store_item = items[i + 1]; + items[i + 1] = items[i]; + items[i] = store_item; + store_equip = equip[i + 1]; + equip[i + 1] = equip[i]; + equip[i] = store_equip; + if (weap_poisoned == i + 1) + weap_poisoned--; + else if (weap_poisoned == i) + weap_poisoned++; + } + } +} + +short pc_record_type::getNum() +{ + short i; + + for (i = 0; i < NUM_OF_PCS; i++) + { + if (&adven[i] == this) break;; + } + + return i; +} + +bool pc_record_type::giveToPC(item_record_type item, bool print_result) +{ + short free_space; + char announce_string[60]; + + if (item.variety == 0) + return true; + + if (item.variety == 3) { + party.gold += item.item_level; + ASB("You get some gold."); + return true; + } + if (item.variety == 11) { + party.food += item.item_level; + ASB("You get some food."); + return true; + } + if (item_weight(item) > amountCanCarry() - amountCarried()) { + if (print_result == true) { + MessageBeep(MB_OK); + ASB("Item too heavy to carry."); + } + return false; + } + if (((free_space = hasSpace()) == 24) || (!isAlive())) + return false; + else { + item.item_properties = item.item_properties & 253; // not property + item.item_properties = item.item_properties & 247; // not contained + items[free_space] = item; + + + if (print_result == 1) { + if (stat_window == getNum()) + put_item_screen(stat_window,0); + } + if (in_startup_mode == FALSE) { + if (item.isIdent() == false) + sprintf((char *) announce_string," %s gets %s.",name,item.name); + else sprintf((char *) announce_string," %s gets %s.",name,item.full_name); + if (print_result) + add_string_to_buf((char *)announce_string); + } + + combineThings(); + sortItems(); + return true; + } + return false; +} + +// returnes equipped protection level of specified abil, or -1 if no such abil is equipped +short pc_record_type::getProtLevel(short abil) +{ + for (int i = 0; i < 24; i++) + if ((items[i].variety != 0) && (items[i].ability == abil) && (equip[i] == TRUE)) + return items[i].ability_strength; + return (-1); +} + +short pc_record_type::hasAbilEquip(short abil) +{ + short i = 0; + + while (((items[i].variety == 0) || (items[i].ability != abil) + || (equip[i] == FALSE)) && (i < 24)) + i++; + return i; +} + +short pc_record_type::hasAbil(short abil) +{ + short i = 0; + + while (((items[i].variety == 0) || (items[i].ability != abil)) && (i < 24)) i++; + return i; +} + +short pc_record_type::amountCanCarry() +{ + return 100 + (15 * min(skills[0],20)) + ((traits[8] == 0) ? 0 : 30) + + ((traits[14] == 0) ? 0 : -50); +} + +short pc_record_type::amountCarried() +{ + short i, storage = 0; + bool airy = false, heavy = false; + + for (i = 0; i < 24; i++) + if (items[i].variety > 0) + { + storage += item_weight(items[i]); + if (items[i].ability == 44) airy = true; + if (items[i].ability == 45) heavy = true; + } + + if (airy) storage -= 30; + if (heavy) storage += 30; + if (storage < 0) storage = 0; + + return storage; +} + +short pc_record_type::hasSpace() +{ + int i = 0; + + while (i < 24) + { + if (items[i].variety == 0) + return i; + i++; + } + + return 24; +} + +// returns 1 if OK, 2 if no room, 3 if not enough cash, 4 if too heavy, 5 if too many of item +short pc_record_type::okToBuy(short cost, item_record_type item) +{ + int i; + + if ((item.variety != 3) && (item.variety != 11)) { + for (i = 0; i < 24; i++) + if ((items[i].variety > 0) && (items[i].type_flag == item.type_flag) + && (items[i].charges > 123)) + return 5; + + if (hasSpace() == 24) return 2; + if (item_weight(item) > amountCanCarry() - amountCarried()) return 4; + } + + if (party.takeGold(cost, false) == false) + return 3; + return 1; +} + +void pc_record_type::takeItem(short which_item) +//short pc_num,which_item; // if which_item > 30, don't update stat win, item is which_item - 30 +{ + int i; + bool do_print = true; + + if (which_item >= 30) { + do_print = false; + which_item -= 30; + } + + if ((weap_poisoned == which_item) && (status[0] > 0)) { + add_string_to_buf(" Poison lost. "); + status[0] = 0; + } + + if ((weap_poisoned > which_item) && (status[0] > 0)) + weap_poisoned--; + + for (i = which_item; i < 23; i++) { + items[i] = items[i + 1]; + equip[i] = equip[i + 1]; + } + items[23] = return_dummy_item(); + equip[23] = FALSE; + + if ((stat_window == getNum()) && (do_print)) + put_item_screen(stat_window,1); +} + +void pc_record_type::removeCharge(short which_item) +{ + if (items[which_item].charges > 0) + { + items[which_item].charges--; + if (items[which_item].charges == 0) takeItem(which_item); + } + + if (stat_window == getNum()) + put_item_screen(stat_window,1); + +} + +void pc_record_type::enchantWeapon(short item_hit, short enchant_type, short new_val) +{ + char store_name[60]; + + if ((items[item_hit].isMagic()) || (items[item_hit].ability != 0)) return; + + items[item_hit].item_properties |= 4; + + switch (enchant_type) { + case 0: + sprintf((char *)store_name,"%s (+1)", items[item_hit].full_name); + items[item_hit].bonus++; + items[item_hit].value = new_val; + break; + case 1: + sprintf((char *)store_name,"%s (+2)", items[item_hit].full_name); + items[item_hit].bonus += 2; + items[item_hit].value = new_val; + break; + case 2: + sprintf((char *)store_name,"%s (+3)", items[item_hit].full_name); + items[item_hit].bonus += 3; + items[item_hit].value = new_val; + break; + case 3: + sprintf((char *)store_name,"%s (F)", items[item_hit].full_name); + items[item_hit].ability = 110; + items[item_hit].ability_strength = 5; + items[item_hit].charges = 8; + break; + case 4: + sprintf((char *)store_name,"%s (F!)", items[item_hit].full_name); + items[item_hit].value = new_val; + items[item_hit].ability = 1; + items[item_hit].ability_strength = 5; + break; + case 5: + sprintf((char *)store_name,"%s (+5)", items[item_hit].full_name); + items[item_hit].value = new_val; + items[item_hit].bonus += 5; + break; + case 6: + sprintf((char *)store_name,"%s (B)", items[item_hit].full_name); + items[item_hit].bonus++; + items[item_hit].ability = 71; + items[item_hit].ability_strength = 5; + items[item_hit].magic_use_type = 0; + items[item_hit].charges = 8; + break; + default: + strcpy(store_name, items[item_hit].full_name); + break; + } + if (items[item_hit].value > 15000) + items[item_hit].value = 15000; + if (items[item_hit].value < 0) + items[item_hit].value = 15000; + strcpy(items[item_hit].full_name,store_name); +} + +void pc_record_type::equipItem(short item_num) +{ + short num_equipped_of_this_type = 0; + short num_hands_occupied = 0; + short i; + short equip_item_type = 0; + + if ((overall_mode == MODE_COMBAT) && (items[item_num].variety == 11)) + add_string_to_buf("Equip: Not in combat"); + else { + // unequip + if (equip[item_num] == TRUE) { + if ((equip[item_num] == TRUE) && + (items[item_num].isCursed())) + add_string_to_buf("Equip: Item is cursed. "); + else { + equip[item_num] = FALSE; + add_string_to_buf("Equip: Unequipped"); + if ((weap_poisoned == item_num) && (status[0] > 0)) { + add_string_to_buf(" Poison lost. "); + status[0] = 0; + } + } + } + + else { // equip + if (equippable[items[item_num].variety] == FALSE) + add_string_to_buf("Equip: Can't equip this item."); + else { + for (i = 0; i < 24; i++) + if (equip[i] == TRUE) { + if (items[i].variety == items[item_num].variety) + num_equipped_of_this_type++; + num_hands_occupied = num_hands_occupied + num_hands_to_use[items[i].variety]; + } + + + equip_item_type = excluding_types[items[item_num].variety]; + // Now if missile is already equipped, no more missiles + if (equip_item_type > 0) { + for (i = 0; i < 24; i++) + if ((equip[i] == TRUE) && (excluding_types[items[i].variety] == equip_item_type)) { + add_string_to_buf("Equip: You have something of"); + add_string_to_buf(" this type equipped."); + return; + } + } + + if ((is_combat()) && (items[item_num].variety == 13)) + add_string_to_buf("Equip: Not armor in combat"); + else if ((2 - num_hands_occupied) < num_hands_to_use[items[item_num].variety]) + add_string_to_buf("Equip: Not enough free hands"); + else if (num_that_can_equip[items[item_num].variety] <= num_equipped_of_this_type) + add_string_to_buf("Equip: Can't equip another"); + else { + equip[item_num] = TRUE; + add_string_to_buf("Equip: OK"); + } + } + + } + } + + if (stat_window == getNum()) + put_item_screen(stat_window,1); +} + + +void pc_record_type::dropItem(short item_num, location where_drop) +{ + short choice, how_many = 0; + item_record_type item_store; + bool take_given_item = true; + location loc; + + item_store = items[item_num]; + + if ((equip[item_num] == TRUE) && (items[item_num].isCursed())) + add_string_to_buf("Drop: Item is cursed. "); + else switch (overall_mode) { + case 0: + choice = fancy_choice_dialog(1093,0); + if (choice == 1) + return; + add_string_to_buf("Drop: OK"); + if ((item_store.type_flag > 0) && (item_store.charges > 1)) { + how_many = get_num_of_items(item_store.charges); + if (how_many == item_store.charges) + takeItem(item_num); + else items[item_num].charges -= how_many; + } + else takeItem(item_num); + break; + + case 5: case 15: + loc = where_drop; + if ((item_store.type_flag > 0) && (item_store.charges > 1)) { + how_many = get_num_of_items(item_store.charges); + if (how_many <= 0) + return; + if (how_many < item_store.charges) + take_given_item = false; + item_store.charges = how_many; + } + if (is_container(loc) == TRUE) + item_store.item_properties = item_store.item_properties | 8; + if (place_item(item_store,loc,FALSE) == FALSE) { + add_string_to_buf("Drop: Too many items on ground"); + item_store.item_properties = item_store.item_properties & 247; // not contained + } + else { + if (item_store.isContained()) + add_string_to_buf("Drop: Item put away"); + else add_string_to_buf("Drop: OK"); + items[item_num].charges -= how_many; + if (take_given_item) takeItem(item_num); + } + break; + } +} + +void pc_record_type::giveThing(short item_num) +{ + short who_to,how_many = 0; + item_record_type item_store; + bool take_given_item = true; + short pc_num = getNum(); + + if ((equip[item_num] == TRUE) && (items[item_num].isCursed())) + add_string_to_buf("Give: Item is cursed. "); + else { + item_store = items[item_num]; + who_to = char_select_pc(1,1,"Give item to who?"); + if ((overall_mode == MODE_COMBAT) && (adjacent(pc_pos[pc_num],pc_pos[who_to]) == FALSE)) { + add_string_to_buf("Give: Must be adjacent."); + who_to = 6; + } + + if ((who_to < 6) && (who_to != pc_num) + && ((overall_mode != MODE_COMBAT) || (adjacent(pc_pos[pc_num],pc_pos[who_to]) == TRUE))) { + if ((item_store.type_flag > 0) && (item_store.charges > 1)) { + how_many = get_num_of_items(item_store.charges); + if (how_many == 0) + return; + if (how_many < item_store.charges) + take_given_item = false; + items[item_num].charges -= how_many; + item_store.charges = how_many; + } + if (adven[who_to].giveToPC(item_store,0) == true) { + if (take_given_item) takeItem(item_num); + } + else { + if (adven[who_to].hasSpace() == 24) + ASB("Can't give: PC has max. # of items."); + else ASB("Can't give: PC carrying too much."); + if (how_many > 0) + items[item_num].charges += how_many; + } + } + } +} + +void pc_record_type::combineThings() +{ + int i,j,test; + + for (i = 0; i < 24; i++) { + if ((items[i].variety > 0) && (items[i].type_flag > 0) && (items[i].isIdent())) + { + for (j = i + 1; j < 24; j++) + if ((items[j].variety > 0) && (items[j].type_flag == items[i].type_flag) && (items[j].isIdent())) + { + add_string_to_buf("(items combined)"); + test = items[i].charges + items[j].charges; + if (test > 125) { + items[i].charges = 125; + ASB("(Can have at most 125 of any item."); + } + else items[i].charges += items[j].charges; + if (equip[j] == TRUE) { + equip[i] = TRUE; + equip[j] = FALSE; + } + takeItem(30 + j); + } + } + if ((items[i].variety > 0) && (items[i].charges < 0)) + items[i].charges = 1; + } +} diff --git a/Win32/Blades of Exile/PC.H b/Win32/Blades of Exile/PC.H new file mode 100644 index 00000000..ca86c6bb --- /dev/null +++ b/Win32/Blades of Exile/PC.H @@ -0,0 +1,88 @@ +#ifndef _PC_H + #define _PC_H + +#include "item.h" //item_record_type +#include "consts.h" + +/* do not change */ +/* dummy_pc_record_type is temporarily used in file reading/writing operations */ +struct dummy_pc_record_type +{ + short main_status; + char name[20]; + short skills[30]; + short max_health, cur_health, max_sp, cur_sp, experience, skill_pts, level; + short status[15]; + item_record_type items[24]; + char equip[24]; // boolean + char priest_spells[62], mage_spells[62]; // boolean + short which_graphic, weap_poisoned; + char advan[15], traits[15]; // boolean + short race, exp_adj, direction; +}; + +class pc_record_type +{ +public: + /* DO NOT CHANGE */ + short main_status; + char name[20]; + short skills[30]; + short max_health, cur_health, max_sp, cur_sp, experience, skill_pts, level; + short status[15]; + item_record_type items[24]; + char equip[24]; // boolean + char priest_spells[62], mage_spells[62]; // boolean + short which_graphic, weap_poisoned; + char advan[15], traits[15]; // boolean + short race, exp_adj, direction; + /* end of DO NOT CHANGE */ + + /* functions */ + void acid(short how_much); + void cure(short how_much); // cure + void curse(short how_much); // curse + void disease(short how_much); // disease + void dumbfound(short how_much); // dumbfound + void heal(short how_much); // heal + void kill(short type); // kill + void poison(short how_much); + void sleep(short how_much,short what_type,short adjust); + void slow(short how_much); + void web(short how_much); + + bool damage(short how_much, short damage_type, short type_of_attacker); + + void drainXP(short how_much); // drain experience points + void giveXP(short how_much); // give experience points + void restoreSP(short how_much); // restore spell points + //bool takeSP(short how_much); // take spell points + void takeItem(short which_item); + void removeCharge(short which_item); + void enchantWeapon(short item_hit,short enchant_type,short new_val); + void equipItem(short item_num); + void dropItem(short item_num,location where_drop); + void giveThing(short item_num); + bool giveToPC(item_record_type item, bool print_result); + void combineThings(); + + bool runTrap(short trap_type, short trap_level, short diff); + + short getProtLevel(short ability); + short hasAbilEquip(short ability); + short hasAbil(short ability); + short hasSpace(); + short okToBuy(short cost, item_record_type item); + short statAdj(short which); + + short amountCanCarry(); + short amountCarried(); + + bool isAlive() { return (main_status == MAIN_STATUS_ALIVE); } + + void sortItems(); + + short getNum(); +}; + +#endif diff --git a/Win32/Blades of Exile/Resources/BLADEXIL.ICO b/Win32/Blades of Exile/Resources/BLADEXIL.ICO new file mode 100644 index 00000000..6cfced9b Binary files /dev/null and b/Win32/Blades of Exile/Resources/BLADEXIL.ICO differ diff --git a/Win32/Blades of Exile/Resources/BOOT.CUR b/Win32/Blades of Exile/Resources/BOOT.CUR new file mode 100644 index 00000000..0bb41768 Binary files /dev/null and b/Win32/Blades of Exile/Resources/BOOT.CUR differ diff --git a/Win32/Blades of Exile/Resources/C.CUR b/Win32/Blades of Exile/Resources/C.CUR new file mode 100644 index 00000000..bcc4fefc Binary files /dev/null and b/Win32/Blades of Exile/Resources/C.CUR differ diff --git a/Win32/Blades of Exile/Resources/D.CUR b/Win32/Blades of Exile/Resources/D.CUR new file mode 100644 index 00000000..68617d3e Binary files /dev/null and b/Win32/Blades of Exile/Resources/D.CUR differ diff --git a/Win32/Blades of Exile/Resources/DL.CUR b/Win32/Blades of Exile/Resources/DL.CUR new file mode 100644 index 00000000..c4861293 Binary files /dev/null and b/Win32/Blades of Exile/Resources/DL.CUR differ diff --git a/Win32/Blades of Exile/Resources/DR.CUR b/Win32/Blades of Exile/Resources/DR.CUR new file mode 100644 index 00000000..7c1ae737 Binary files /dev/null and b/Win32/Blades of Exile/Resources/DR.CUR differ diff --git a/Win32/Blades of Exile/Resources/KEY.CUR b/Win32/Blades of Exile/Resources/KEY.CUR new file mode 100644 index 00000000..3cdf2d4a Binary files /dev/null and b/Win32/Blades of Exile/Resources/KEY.CUR differ diff --git a/Win32/Blades of Exile/Resources/L.CUR b/Win32/Blades of Exile/Resources/L.CUR new file mode 100644 index 00000000..be7af994 Binary files /dev/null and b/Win32/Blades of Exile/Resources/L.CUR differ diff --git a/Win32/Blades of Exile/Resources/LOOK.CUR b/Win32/Blades of Exile/Resources/LOOK.CUR new file mode 100644 index 00000000..ca1ad8e5 Binary files /dev/null and b/Win32/Blades of Exile/Resources/LOOK.CUR differ diff --git a/Win32/Blades of Exile/Resources/R.CUR b/Win32/Blades of Exile/Resources/R.CUR new file mode 100644 index 00000000..39f194ec Binary files /dev/null and b/Win32/Blades of Exile/Resources/R.CUR differ diff --git a/Win32/Blades of Exile/Resources/SWORD.CUR b/Win32/Blades of Exile/Resources/SWORD.CUR new file mode 100644 index 00000000..938203a3 Binary files /dev/null and b/Win32/Blades of Exile/Resources/SWORD.CUR differ diff --git a/Win32/Blades of Exile/Resources/TALK.CUR b/Win32/Blades of Exile/Resources/TALK.CUR new file mode 100644 index 00000000..2d0fe3e6 Binary files /dev/null and b/Win32/Blades of Exile/Resources/TALK.CUR differ diff --git a/Win32/Blades of Exile/Resources/TARGET.CUR b/Win32/Blades of Exile/Resources/TARGET.CUR new file mode 100644 index 00000000..a077508f Binary files /dev/null and b/Win32/Blades of Exile/Resources/TARGET.CUR differ diff --git a/Win32/Blades of Exile/Resources/U.CUR b/Win32/Blades of Exile/Resources/U.CUR new file mode 100644 index 00000000..56ef1d9c Binary files /dev/null and b/Win32/Blades of Exile/Resources/U.CUR differ diff --git a/Win32/Blades of Exile/Resources/UL.CUR b/Win32/Blades of Exile/Resources/UL.CUR new file mode 100644 index 00000000..9ffadb99 Binary files /dev/null and b/Win32/Blades of Exile/Resources/UL.CUR differ diff --git a/Win32/Blades of Exile/Resources/UR.CUR b/Win32/Blades of Exile/Resources/UR.CUR new file mode 100644 index 00000000..113bd7a3 Binary files /dev/null and b/Win32/Blades of Exile/Resources/UR.CUR differ diff --git a/Win32/Blades of Exile/SPECIALS.CPP b/Win32/Blades of Exile/SPECIALS.CPP new file mode 100644 index 00000000..305bf0a1 --- /dev/null +++ b/Win32/Blades of Exile/SPECIALS.CPP @@ -0,0 +1,2950 @@ +#include +#include "stdio.h" +#include "string.h" +#include "global.h" +#include "party.h" +#include "town.h" +#include "text.h" +#include "infodlgs.h" +#include "items.h" +#include "itemdata.h" +#include "combat.h" +#include "monster.h" +#include "locutils.h" +#include "fields.h" +#include "exlsound.h" +#include "graphics.h" +#include "fileio.h" +#include "specials.h" +#include "newgraph.h" +#include "dlgutils.h" + +#include "globvar.h" + + +void start_split(short a, short b, short noise) +{ + party.stuff_done[304][0] = 1; + party.stuff_done[304][1] = c_town.p_loc.x; + party.stuff_done[304][2] = c_town.p_loc.y; + c_town.p_loc.x = a; + c_town.p_loc.y = b; + for (int i = 0; i < NUM_OF_PCS; i++) + if (i != party.stuff_done[304][3] && adven[i].main_status > 0) + adven[i].main_status += MAIN_STATUS_SPLIT; + current_pc = party.stuff_done[304][3]; + update_explored(c_town.p_loc); + center = c_town.p_loc; + + if (noise > 0) + play_sound(10); +} + +void end_split(short noise) +{ + if (party.stuff_done[304][0] == 0) { + ASB("Party already together!"); + return; + } + + c_town.p_loc.x = party.stuff_done[304][1]; + c_town.p_loc.y = party.stuff_done[304][2]; + party.stuff_done[304][0] = 0; + for (int i = 0; i < NUM_OF_PCS; i++) + if (adven[i].main_status >= MAIN_STATUS_SPLIT) + adven[i].main_status -= MAIN_STATUS_SPLIT; + update_explored(c_town.p_loc); + center = c_town.p_loc; + if (noise > 0) + play_sound(10); + add_string_to_buf("You are reunited."); +} + +Boolean handle_wandering_specials (short mode) +//short mode; // 0 - pre 1 - end by victory 2 - end by flight +// wanderin spec 99 -> generic spec +{ + short s1 = 0,s2 = 0,s3 = 0; + location null_loc; + + if ((mode == 0) && (store_wandering_special.spec_on_meet >= 0)) { // When encountering + run_special(13,1,store_wandering_special.spec_on_meet,null_loc,&s1,&s2,&s3); + if (s1 > 0) + return FALSE; + } + + if ((mode == 1) && (store_wandering_special.spec_on_win >= 0)) {// After defeating + run_special(15,1,store_wandering_special.spec_on_win,null_loc,&s1,&s2,&s3); + } + if ((mode == 2) && (store_wandering_special.spec_on_flee >= 0)) {// After fleeing like a buncha girly men + run_special(14,1,store_wandering_special.spec_on_flee,null_loc,&s1,&s2,&s3); + } +return TRUE; +} + + +Boolean check_special_terrain(location where_check,short mode,short which_pc,short *spec_num, + Boolean *forced) +//short mode; // 0 - out 1 - town 2 - combat +{ + unsigned char ter; + short r1,i,choice,door_pc,ter_special,ter_flag1,ter_flag2,dam_type = 0,pic_type = 0,ter_pic = 0; + Boolean can_enter = TRUE; + location out_where,from_loc,to_loc; + short s1 = 0,s2 = 0,s3 = 0; + + *spec_num = -1; + *forced = FALSE; + + switch (mode) { + case 0: + ter = out[where_check.x][where_check.y]; + from_loc = party.p_loc; + break; + case 1: + ter = t_d.terrain[where_check.x][where_check.y]; + from_loc = c_town.p_loc; + break; + case 2: + ter = combat_terrain[where_check.x][where_check.y]; + from_loc = pc_pos[current_pc]; + break; + } + ter_special = scenario.ter_types[ter].special; + ter_flag1 = scenario.ter_types[ter].flag1; + ter_flag2 = scenario.ter_types[ter].flag2; + ter_pic = scenario.ter_types[ter].picture; + + if ((mode > 0) && (ter_special >= 16) && + (ter_special <= 19)) { + if ( + ((ter_special == 16) && (where_check.y > from_loc.y)) || + ((ter_special == 17) && (where_check.x < from_loc.x)) || + ((ter_special == 18) && (where_check.y < from_loc.y)) || + ((ter_special == 19) && (where_check.x > from_loc.x)) ) { + ASB("The moving floor prevents you."); + return FALSE; + } + } + + if (mode == 0) { + out_where = where_check.toLocal(); + + for (i = 0; i < 18; i++) + if (same_point(out_where,outdoors[party.i_w_c.x][party.i_w_c.y].special_locs[i]) == TRUE) { + *spec_num = outdoors[party.i_w_c.x][party.i_w_c.y].special_id[i]; + if ((*spec_num >= 0) && + (outdoors[party.i_w_c.x][party.i_w_c.y].specials[*spec_num].type == 4)) + *forced = TRUE; + // call special + run_special(mode,1,outdoors[party.i_w_c.x][party.i_w_c.y].special_id[i],out_where,&s1,&s2,&s3); + if (s1 > 0) + can_enter = FALSE; + erase_out_specials(); + put_pc_screen(); + put_item_screen(stat_window,0); + } + } + + if ((is_combat()) && (((ter_pic <= 207) && (ter_pic >= 212)) || (ter_pic == 406))) { + ASB("Move: Can't trigger this special in combat."); + return FALSE; + } + + if (((mode == 1) || ((mode == 2) && (which_combat_type == 1))) + && (special(where_check.x,where_check.y))) { + if (is_force_barrier(where_check.x,where_check.y)) { + add_string_to_buf(" Magic barrier! "); + return FALSE; + } + for (i = 0; i < 50; i++) + if ((same_point(where_check,c_town.town.special_locs[i]) == TRUE)) + //GK && (c_town.town.spec_id[i] >= 0)) + { + if (c_town.town.specials[c_town.town.spec_id[i]].type == 4) { + *forced = TRUE; + } + *spec_num = c_town.town.spec_id[i]; + if ((is_blocked(where_check) == FALSE) || (ter_special == 1) + || (ter_special == 12) || (ter_special == 13)) { + give_help(54,0,0); + run_special(mode,2,c_town.town.spec_id[i],where_check,&s1,&s2,&s3); + if (s1 > 0) + can_enter = FALSE; + } + } + put_pc_screen(); + put_item_screen(stat_window,0); + } + + if (can_enter == FALSE) + return FALSE; + + if ((!is_out()) && (overall_mode < MODE_TALKING)) { + check_fields(where_check,mode,which_pc); + + if (is_web(where_check.x,where_check.y)) { + add_string_to_buf(" Webs! "); + if (mode < 2) { + suppress_stat_screen = TRUE; + for (i = 0; i < 6; i++) { + r1 = get_ran(1,2,3); + adven[i].web(r1); + } + suppress_stat_screen = TRUE; + put_pc_screen(); + } + else adven[current_pc].web(get_ran(1,2,3)); + take_web(where_check.x,where_check.y); + } + if (is_force_barrier(where_check.x,where_check.y)) { + add_string_to_buf(" Magic barrier! "); + can_enter = FALSE; + } + if (is_crate(where_check.x,where_check.y)) { + add_string_to_buf(" You push the crate."); + to_loc = push_loc(from_loc,where_check); + take_crate((short) where_check.x,(short) where_check.y); + if (to_loc.x > 0) + make_crate((short) to_loc.x,(short) to_loc.y); + for (i = 0; i < NUM_TOWN_ITEMS; i++) + if ((t_i.items[i].variety > 0) && (same_point(t_i.items[i].item_loc,where_check)) + && (t_i.items[i].isContained())) + t_i.items[i].item_loc = to_loc; + } + if (is_barrel(where_check.x,where_check.y)) { + add_string_to_buf(" You push the barrel."); + to_loc = push_loc(from_loc,where_check); + take_barrel((short) where_check.x,(short) where_check.y); + if (to_loc.x > 0) + make_barrel((short) to_loc.x,(short) to_loc.y); + for (i = 0; i < NUM_TOWN_ITEMS; i++) + if ((t_i.items[i].variety > 0) && (same_point(t_i.items[i].item_loc,where_check)) + && (t_i.items[i].isContained())) + t_i.items[i].item_loc = to_loc; + } + } + + + switch (ter_special) { + case 1: + alter_space(where_check.x,where_check.y,ter_flag1); + if (ter_flag2 < 200) { + play_sound(-1 * ter_flag2); + } + give_help(47,65,0); + if (scenario.ter_types[ter].blockage > 2) + can_enter = FALSE; + break; + case 2: case 3:case 4: + if (party.isFlying() || party.in_boat >= 0) + break; + if (ter_special == 2) { + add_string_to_buf(" It's hot!"); + dam_type = 1; pic_type = 0; + if (party.stuff_done[305][3] > 0) { + add_string_to_buf(" It doesn't affect you."); + break; + } + } + if (ter_special == 3) { + add_string_to_buf(" You feel cold!"); + dam_type = 5; pic_type = 4; + } + if (ter_special == 4) { + add_string_to_buf(" Something shocks you!"); + dam_type = 3; pic_type = 1; + } + r1 = get_ran(ter_flag2,dam_type,ter_flag1); + if (mode < 2) + adven.damage(r1,dam_type); + fast_bang = 1; + if (mode == 2) + adven[which_pc].damage(r1,dam_type,-1); + fast_bang = 0; + break; + case 5: case 6: + if (party.isFlying()) break; + if (party.in_boat >= 0) + return TRUE; + one_sound(17); + if (mode < 2) { + for (i = 0; i < 6; i++) + if (adven[i].isAlive()) + { + if (get_ran(1,1,100) <= ter_flag2) { + if (ter_special == 5) + adven[i].poison(ter_flag1); + else adven[i].disease(ter_flag1); + } + } + } + //print_nums(1,which_pc,current_pc); + if (mode == 2) { + if (get_ran(1,1,100) <= ter_flag2){ + if (ter_special == 5) + adven[which_pc].poison(ter_flag1); + else adven[which_pc].disease(ter_flag1); + } + } + break; + case 12: // local special + if(mode == 0){ + run_special(mode,1,ter_flag1,where_check,&s1,&s2,&s3); + if (s1 > 0) + can_enter = FALSE; + } + else if(mode == 1){ + run_special(mode,2,ter_flag1,where_check,&s1,&s2,&s3); + if (s1 > 0) + can_enter = FALSE; + } + else if(mode == 2){ + if(which_combat_type == 0)//outdoor combat + run_special(mode,1,ter_flag1,where_check,&s1,&s2,&s3); + else + run_special(mode,2,ter_flag1,where_check,&s1,&s2,&s3); + } + break; + case 13: // global special + run_special(mode,0,ter_flag1,where_check,&s1,&s2,&s3); + if (s1 > 0) + can_enter = FALSE; + break; + + + // Locked doors + case 9: case 10: + if (is_combat()) { // No lockpicking in combat + add_string_to_buf(" Can't enter: It's locked."); + break; + } + + // See what party wants to do. + choice = fancy_choice_dialog(993,0); + + can_enter = FALSE; + if (choice == 1) break; + if ((door_pc = select_pc(1,0)) < 6) { + if (choice == 2) + where_check.pickLock(door_pc); + else where_check.bashDoor(door_pc); + } + break; + + + } + + // Action may change terrain, so update what's been seen + if (is_town()) + update_explored(c_town.p_loc); + if (is_combat()) + update_explored(pc_pos[current_pc]); + + return can_enter; +} + +// This procedure find the effects of fields that would affect a PC who moves into +// a space or waited in that same space +void check_fields(location where_check,short mode,short which_pc) +//mode; // 0 - out 1 - town 2 - combat +{ + short r1,i; + + if (is_out()) return; + if (is_town()) fast_bang = 1; + if (is_fire_wall(where_check.x,where_check.y)) { + add_string_to_buf(" Fire wall! "); + r1 = get_ran(1,1,6) + 1; + if (mode == 2) + adven[which_pc].damage(r1,1,-1); + if (overall_mode < MODE_COMBAT) + boom_space(party.p_loc,overall_mode,0,r1,5); + } + if (is_force_wall(where_check.x,where_check.y)) { + add_string_to_buf(" Force wall! "); + r1 = get_ran(2,1,6); + if (mode == 2) + adven[which_pc].damage(r1,3,-1); + if (overall_mode < MODE_COMBAT) + boom_space(party.p_loc,overall_mode,1,r1,12); + } + if (is_ice_wall(where_check.x,where_check.y)) { + add_string_to_buf(" Ice wall! "); + r1 = get_ran(2,1,6); + if (mode == 2) + adven[which_pc].damage(r1,5,-1); + if (overall_mode < MODE_COMBAT) + boom_space(party.p_loc,overall_mode,4,r1,7); + } + if (is_blade_wall(where_check.x,where_check.y)) { + add_string_to_buf(" Blade wall! "); + r1 = get_ran(4,1,8); + if (mode == 2) + adven[which_pc].damage(r1,0,-1); + if (overall_mode < MODE_COMBAT) + boom_space(party.p_loc,overall_mode,3,r1,2); + } + if (is_quickfire(where_check.x,where_check.y)) { + add_string_to_buf(" Quickfire! "); + r1 = get_ran(2,1,8); + if (mode == 2) + adven[which_pc].damage(r1,1,-1); + if (overall_mode < MODE_COMBAT) + boom_space(party.p_loc,overall_mode,0,r1,5); + } + if (is_scloud(where_check.x,where_check.y)) { + add_string_to_buf(" Stinking cloud! "); + if (mode < 2) { + suppress_stat_screen = TRUE; + for (i = 0; i < 6; i++) { + r1 = get_ran(1,2,3); + adven[i].curse(r1); + } + suppress_stat_screen = FALSE; + put_pc_screen(); + } + else adven[current_pc].curse(get_ran(1,2,3)); + } + if (is_sleep_cloud(where_check.x,where_check.y)) { + add_string_to_buf(" Sleep cloud! "); + if (mode < 2) { + suppress_stat_screen = TRUE; + for (i = 0; i < NUM_OF_PCS; i++) { + adven[i].sleep(3,11,0); + } + suppress_stat_screen = FALSE; + put_pc_screen(); + } + else adven[current_pc].sleep(3,11,0); + } + if (is_fire_barrier(where_check.x,where_check.y)) { + add_string_to_buf(" Magic barrier! "); + r1 = get_ran(2,1,10); + if (mode < 2) + adven.damage(r1,3); + if (mode == 2) + adven[which_pc].damage(r1,3,-1); + if (overall_mode < MODE_COMBAT) + boom_space(party.p_loc,overall_mode,1,r1,12); + } + fast_bang = 0; +} +void use_item(short pc,short item) +{ + Boolean take_charge = TRUE,inept_ok = FALSE; + short abil,level,i,j,item_use_code,str,type,which_stat,r1; + char to_draw[60]; + location user_loc; +//creature_data_type *which_m; +effect_pat_type s = {{{0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0}, + {0,0,0,0,1,0,0,0,0}, + {0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0}}}; + abil = adven[pc].items[item].ability; + level = adven[pc].items[item].item_level; + + item_use_code = abil_chart[abil]; + if (item_use_code >= 10) { + item_use_code -= 10; + inept_ok = TRUE; + } + + if (is_out()) user_loc = party.p_loc; + if (is_town()) user_loc = c_town.p_loc; + if (is_combat()) user_loc = pc_pos[current_pc]; + + if (item_use_code == 4) { + add_string_to_buf("Use: Can't use this item. "); + take_charge = FALSE; + } + if ((adven[pc].traits[TRAIT_MAGICALLY_INEPT] == TRUE) && (inept_ok == FALSE)){ + add_string_to_buf("Use: Can't - magically inept. "); + take_charge = FALSE; + } + + if (take_charge == TRUE) { + if ((overall_mode == MODE_OUTDOORS) && (item_use_code > 0) && (item_use_code != 5)) { + add_string_to_buf("Use: Not while outdoors. "); + take_charge = FALSE; + } + if ((overall_mode == MODE_TOWN) && (item_use_code == 1)) { + add_string_to_buf("Use: Not while in town. "); + take_charge = FALSE; + } + if ((overall_mode == MODE_COMBAT) && (item_use_code == 2)) { + add_string_to_buf("Use: Not in combat. "); + take_charge = FALSE; + } + if ((overall_mode != MODE_OUTDOORS) && (item_use_code == 5)){ + add_string_to_buf("Use: Only outdoors. "); + take_charge = FALSE; + } + } + if (take_charge == TRUE) { + if (adven[pc].items[item].isIdent() == false) + sprintf((char *) to_draw, "Use: %s",adven[pc].items[item].name); + else sprintf((char *) to_draw, "Use: %s",adven[pc].items[item].full_name); + add_string_to_buf((char *) to_draw); + + if ((adven[pc].items[item].variety == 7) && + (adven[pc].items[item].graphic_num >= 50) && (adven[pc].items[item].graphic_num <= 52)) + play_sound(56); + + str = adven[pc].items[item].ability_strength; + store_item_spell_level = str * 2 + 1; + type = adven[pc].items[item].magic_use_type; + + switch (abil) { + case 70: // poison weapon + take_charge = poison_weapon(pc,str,0); + break; + case 71: case 73: case 74: case 75: case 76: case 78: case 80: + switch (abil) { + case 71: + play_sound(4); + which_stat = 1; + if (type % 2 == 1) { + ASB(" You feel awkward."); str = str * -1;} + else ASB(" You feel blessed."); + break; + case 73: + play_sound(75); + which_stat = 3; + if (type % 2 == 1) { + ASB(" You feel sluggish."); str = str * -1;} + else ASB(" You feel speedy."); + break; + case 74: + play_sound(68); + which_stat = 4; + if (type % 2 == 1) { + ASB(" You feel odd."); str = str * -1;} + else ASB(" You feel protected."); + break; + case 75: + play_sound(51); + which_stat = 5; + if (type % 2 == 1) { + ASB(" You feel odd."); str = str * -1;} + else ASB(" You feel protected."); + break; + case 76: + which_stat = 6; + if (type % 2 == 1) + ASB(" You feel sticky."); + else { + ASB(" Your skin tingles."); str = str * -1;} + break; + case 78: + play_sound(43); + which_stat = 8; + if (type % 2 == 1) { + ASB(" You feel exposed."); str = str * -1;} + else ASB(" You feel obscure."); + break; + case 80: + play_sound(43); + which_stat = 10; + if (type % 2 == 1) { + ASB(" You feel dull."); str = str * -1;} + else ASB(" You start to glow slightly."); + break; + } + if (type > 1) + adven.affect(which_stat,str); + else affect_pc(pc,which_stat,str); + break; + case 72: + switch (type) { + case 0: ASB(" You feel better."); adven[pc].cure(str); break; + case 1: ASB(" You feel ill."); adven[pc].poison(str); break; + case 2: ASB(" You all feel better."); adven.cure(str); break; + case 3: ASB(" You all feel ill."); adven.poison(str); break; + } + break; + case 77: + switch (type) { + case 0: ASB(" You feel healthy."); affect_pc(pc,7,-1 * str); break; + case 1: ASB(" You feel sick."); adven[pc].disease(str); break; + case 2: ASB(" You all feel healthy."); adven.affect(7,-1 * str); break; + case 3: ASB(" You all feel sick."); adven.disease(str); break; + } + break; + case 79: + switch (type) { + case 0: ASB(" You feel clear headed."); affect_pc(pc,9,-1 * str); break; + case 1: ASB(" You feel confused."); adven[pc].dumbfound(str); break; + case 2: ASB(" You all feel clear headed."); adven.affect(9,-1 * str); break; + case 3: ASB(" You all feel confused."); adven.dumbfound(str); break; + } + break; + case 81: + switch (type) { + case 0: ASB(" You feel alert."); affect_pc(pc,11,-1 * str); break; + case 1: ASB(" You feel very tired."); adven[pc].sleep(str + 1,11,200); break; + case 2: ASB(" You all feel alert."); adven.affect(11,-1 * str); break; + case 3: ASB(" You all feel very tired."); for (i = 0; i < 6; i++) adven[i].sleep(str + 1,11,200); break; + } + break; + case 82: + switch (type) { + case 0: ASB(" You find it easier to move."); affect_pc(pc,12,-1 * str * 100); break; + case 1: ASB(" You feel very stiff."); adven[pc].sleep(str * 20 + 10,12,200); break; + case 2: ASB(" You all find it easier to move."); adven.affect(12,-1 * str * 100); break; + case 3: ASB(" You all feel very stiff."); for (i = 0; i < 6; i++) adven[i].sleep(str * 20 + 10,12,200); break; + } + break; + case 83: + switch (type) { + case 0: ASB(" Your skin tingles pleasantly."); affect_pc(pc,13,-1 * str); break; + case 1: ASB(" Your skin burns!"); adven[pc].acid(str); break; + case 2: ASB(" You all tingle pleasantly."); adven.affect(13,-1 * str); break; + case 3: ASB(" Everyone's skin burns!"); for (i = 0; i < 6; i++) adven[i].acid(str); break; + } + break; + case 84: + switch (type) { + case 0: + case 1: + ASB(" You feel wonderful!"); + adven[pc].heal(str * 20); + affect_pc(pc,1,str); + break; + case 2: + case 3: + ASB(" Everyone feels wonderful!"); + adven.heal(str * 20); + adven.affect(1, str); + break; + } + break; + case 85: + switch (type) { + case 0: ASB(" You feel much smarter."); adven[pc].giveXP(str * 5); break; + case 1: ASB(" You feel forgetful."); adven[pc].drainXP(str * 5); break; + case 2: ASB(" You all feel much smarter."); adven.giveXP(str * 5); break; + case 3: ASB(" You all feel forgetful."); adven.drainXP(str * 5); break; + } + break; + case 86: + play_sound(68); + switch (type) { + case 0: ASB(" You feel much smarter."); adven[pc].skill_pts += str; break; + case 1: ASB(" You feel forgetful."); adven[pc].skill_pts = max(0,adven[pc].skill_pts - str); break; + case 2: ASB(" You all feel much smarter."); for (i = 0; i < 6; i++) adven[i].skill_pts += str; break; + case 3: ASB(" You all feel forgetful."); for (i = 0; i < 6; i++) adven[i].skill_pts = max(0,adven[i].skill_pts - str); break; + } + break; + case 87: + switch (type) { + case 0: ASB(" You feel better."); adven[pc].heal(str * 20); break; + case 1: ASB(" You feel sick."); adven[pc].damage(20 * str,4,0); break; + case 2: ASB(" You all feel better."); adven.heal(str * 20); break; + case 3: ASB(" You all feel sick."); adven.damage(20 * str,4); break; + } + break; + case 88: + switch (type) { + case 0: ASB(" You feel energized."); adven[pc].restoreSP(str * 5); break; + case 1: ASB(" You feel drained."); adven[pc].cur_sp = max(0,adven[pc].cur_sp - str * 5); break; + case 2: ASB(" You all feel energized."); adven.restoreSP(str * 5); break; + case 3: ASB(" You all feel drained."); for (i = 0; i < 6; i++) adven[i].cur_sp = max(0,adven[i].cur_sp - str * 5); break; + } + break; + case 89: + switch (type) { + case 0: + case 1: ASB(" You feel terrible."); + adven[pc].drainXP(str * 5); + adven[pc].damage(20 * str,4,0); + adven[pc].disease(2 * str); + adven[pc].dumbfound(2 * str); + break; + case 2: + case 3: ASB(" You all feel terrible."); for (i = 0; i < 6; i++) { + adven[i].drainXP(str * 5); + adven[i].damage(20 * str,4,0); + adven[i].disease(2 * str); + adven[i].dumbfound(2 * str);} + break; + } + break; + case 90: + ASB(" You have more light."); increase_light(50 * str); + break; + case 91: + ASB(" Your footsteps become quieter."); party.stuff_done[305][0] += 5 * str; + break; + case 92: + ASB(" You feel chilly."); party.stuff_done[305][3] += 2 * str; + break; + case 93: + if (party.stuff_done[305][1] > 0) { + add_string_to_buf(" Not while already flying. "); + break; + } + if (party.in_boat >= 0) + add_string_to_buf(" Leave boat first. "); + else if (party.in_horse >= 0)//// + add_string_to_buf(" Leave horse first. "); + else { + ASB(" You rise into the air!"); party.stuff_done[305][1] += str; + } + break; + case 94: + switch (type) { + case 0: + case 1: + ASB(" You feel wonderful."); + adven[pc].heal(200); + adven[pc].cure(8); + break; + case 2: + case 3: + ASB(" You all feel wonderful."); + adven.heal(200); + adven.cure(8); + break; + } + break; + + // spell effects + case 110: + add_string_to_buf(" It fires a bolt of flame."); + start_spell_targeting(1011); + break; + case 111: + add_string_to_buf(" It shoots a fireball. "); + start_spell_targeting(1022); + break; + case 112: + add_string_to_buf(" It shoots a huge fireball. "); + start_spell_targeting(1040); + break; + case 113: + add_string_to_buf(" It shoots a black ray. "); + start_spell_targeting(1048); + break; + case 114: + add_string_to_buf(" It fires a ball of ice. "); + start_spell_targeting(1031); + break; + case 115: + add_string_to_buf(" It fires a purple ray. "); + start_spell_targeting(1012); + break; + case 116: + add_string_to_buf(" The ground shakes! "); + do_shockwave(pc_pos[current_pc]); + break; + case 117: + add_string_to_buf(" It shoots a white ray. "); + start_spell_targeting(1132); + break; + case 118: + add_string_to_buf(" It shoots a golden ray. "); + start_spell_targeting(1155); + break; + case 119: + if (summon_monster(str,user_loc,50,2) == FALSE) + add_string_to_buf(" Summon failed."); + break; + case 120: + r1 = get_ran(6,1,4); + for (i = 0; i < get_ran(1,3,5); i++) + if (summon_monster(str,user_loc,r1,2) == FALSE) + add_string_to_buf(" Summon failed."); + break; + case 121: + add_string_to_buf(" Acid sprays from the tip! "); + start_spell_targeting(1068); + break; + case 122: + add_string_to_buf(" It creates a cloud of gas. "); + start_spell_targeting(1066); + break; + case 123: + add_string_to_buf(" It creates a shimmering cloud. "); + start_spell_targeting(1019); + break; + case 124: + add_string_to_buf(" A green ray emerges. "); + start_spell_targeting(1030); + break; + case 125: + add_string_to_buf(" Sparks fly."); + start_spell_targeting(1044); + break; + case 126: + add_string_to_buf(" It shoots a silvery beam. "); + start_spell_targeting(1069); + break; + case 127: + add_string_to_buf(" It explodes!"); + start_spell_targeting(1065); + break; + case 128: + add_string_to_buf(" It shoots a fiery red ray. "); + start_spell_targeting(1062); + break; + case 129: + add_string_to_buf("Fire pours out!"); + make_quickfire(user_loc.x,user_loc.y); + break; + case 130: + ASB("It throbs, and emits odd rays."); + for (i = 0; i < T_M; i++) { + if ((c_town.monst.dudes[i].active != 0) && (c_town.monst.dudes[i].attitude % 2 == 1) + && (dist(pc_pos[current_pc],c_town.monst.dudes[i].m_loc) <= 8) + && (can_see(pc_pos[current_pc],c_town.monst.dudes[i].m_loc,0) < 5)) + { + c_town.monst.dudes[i].charm(0,0,8); + } + } + break; + case 131: + if (c_town.town.specials2 % 10 == 1) { + add_string_to_buf(" It doesn't work."); + break; + } + add_string_to_buf(" You have a vision. "); + for (i = 0; i < town_size[town_type]; i++) + for (j = 0; j < town_size[town_type]; j++) + make_explored(i,j); + clear_map(); + break; + case 132: + add_string_to_buf(" It fires a blinding ray."); + add_string_to_buf(" Target spell. "); + overall_mode = 3; + current_pat = s; + set_town_spell(1041,current_pc); + break; + case 133: + add_string_to_buf(" It shoots a blue sphere. "); + start_spell_targeting(1064); + break; + case 134: + add_string_to_buf(" It fires a lovely, sparkling beam."); + start_spell_targeting(1117); + break; + case 135: + add_string_to_buf(" Your hair stands on end. "); + start_spell_targeting(1051); + break; + } +// Special spells: +// 62 - Carrunos +// 63 - Summon Rat +// 64 - Ice Wall Balls +// 65 - Goo Bomb +// 66 - Foul Vapors +// 67 - Sleep cloud +// 68 - spray acid +// 69 - paralyze +// 70 - mass sleep + } + + put_pc_screen(); + if ((take_charge == TRUE) && (adven[pc].items[item].charges > 0)) + adven[pc].removeCharge(item); + if (take_charge == FALSE) { + draw_terrain(0); + put_item_screen(stat_window,0); + } +} + +// Returns TRUE if an action is actually carried out. This can only be reached in town. +Boolean use_space(location where) +{ + unsigned char ter; + short i; + location from_loc,to_loc; + + ter = t_d.terrain[where.x][where.y]; + from_loc = c_town.p_loc; + + add_string_to_buf("Use..."); + + if (is_web(where.x,where.y)) { + add_string_to_buf(" You clear the webs."); + take_web(where.x,where.y); + return TRUE; + } + if (is_crate(where.x,where.y)) { + to_loc = push_loc(from_loc,where); + if (same_point(from_loc,to_loc) == TRUE) { + add_string_to_buf(" Can't push crate."); + return FALSE; + } + add_string_to_buf(" You push the crate."); + take_crate((short) where.x,(short) where.y); + make_crate((short) to_loc.x,(short) to_loc.y); + for (i = 0; i < NUM_TOWN_ITEMS; i++) + if ((t_i.items[i].variety > 0) && (same_point(t_i.items[i].item_loc,where)) + && (t_i.items[i].isContained())) + t_i.items[i].item_loc = to_loc; + } + if (is_barrel(where.x,where.y)) { + to_loc = push_loc(from_loc,where); + if (same_point(from_loc,to_loc) == TRUE) { + add_string_to_buf(" Can't push barrel."); + return FALSE; + } + add_string_to_buf(" You push the barrel."); + take_barrel((short) where.x,(short) where.y); + make_barrel((short) to_loc.x,(short) to_loc.y); + for (i = 0; i < NUM_TOWN_ITEMS; i++) + if ((t_i.items[i].variety > 0) && (same_point(t_i.items[i].item_loc,where)) + && (t_i.items[i].isContained())) + t_i.items[i].item_loc = to_loc; + } + + switch (scenario.ter_types[ter].special) { + case 22: + if (same_point(where,from_loc) == TRUE) { + add_string_to_buf(" Not while on space."); + return FALSE; + } + add_string_to_buf(" OK."); + alter_space(where.x,where.y,scenario.ter_types[ter].flag1); + play_sound(scenario.ter_types[ter].flag2); + return TRUE; + break; + case 23: // call special + run_special(17,0,scenario.ter_types[ter].flag1,where,&i,&i,&i); + break; + } + add_string_to_buf(" Nothing to use."); + + return FALSE; +} + +// Note ... if this is a container, the code must first process any specials. If +//specials return FALSE, can't get items inside. If TRUE, can get items inside. +// Can't get items out in combat. +Boolean adj_town_look(location where) +{ + char terrain; + Boolean can_open = TRUE,item_there = FALSE,got_special = FALSE; + short i = 0, s1 = 0, s2 = 0, s3 = 0; + + for (i = 0; i < NUM_TOWN_ITEMS; i++) + if ((t_i.items[i].variety > 0) && (t_i.items[i].isContained()) && + (same_point(where,t_i.items[i].item_loc) == TRUE)) + item_there = TRUE; + + terrain = t_d.terrain[where.x][where.y]; + if (special(where.x,where.y)) {// && (get_blockage(terrain) > 0)) { + if (adjacent(c_town.p_loc,where) == FALSE) + add_string_to_buf(" Not close enough to search."); + else { + for (i = 0; i < 50; i++) + if (same_point(where,c_town.town.special_locs[i]) == TRUE) { + run_special(4,2,c_town.town.spec_id[i],where,&s1,&s2,&s3); + if (s1 > 0) can_open = FALSE; + got_special = TRUE; + } + put_item_screen(stat_window,0); + } + } + if ((is_container(where)) && (item_there == TRUE) && (can_open == TRUE)) + get_item(where,6,TRUE); + + else switch (terrain) + { + case 22: case 23: + add_string_to_buf(" (Use this space to do something"); + add_string_to_buf(" with it.)"); + break; + default: + if (got_special == FALSE) add_string_to_buf(" Search: You don't find anything. "); + return FALSE; + } + return FALSE; +} + +void out_move_party(char x,char y) +{ + location l; + + l.x = x; + l.y = y; + l = l.toGlobal(); + party.p_loc = l; + center = l; + update_explored(l); +} + +void teleport_party(short x,short y,short mode) +// mode - 0 full teleport flash 1 no teleport flash 2 only fade flash +{ + short i; + location l; + + if (is_combat()) mode = 1; + + l = c_town.p_loc; + update_explored(l); + + if (mode != 1) { + start_missile_anim(); + for (i = 0; i < 9; i++) + add_explosion(l,-1,1,1,0,0); + do_explosion_anim(5,1); + } + if (mode != 1) + can_draw_pcs = FALSE; + if (mode != 1) { + do_explosion_anim(5,2); + end_missile_anim(); + } + center.x = x; center.y = y; + if (is_combat()) { + pc_pos[current_pc].x = x;pc_pos[current_pc].y = y; + } + l.x = x; l.y = y; + c_town.p_loc.x = x; + c_town.p_loc.y = y; + update_explored(l); + draw_terrain(0); + + if (mode == 0) { + start_missile_anim(); + for (i = 0; i < 14; i++) + add_explosion(center,-1,1,1,0,0); + do_explosion_anim(5,1); + } + can_draw_pcs = TRUE; + if (mode == 0) { + do_explosion_anim(5,2); + end_missile_anim(); + } + draw_map(modeless_dialogs[5],5); +} + +void change_level(short town_num,short x,short y) +{ + location l; + + if ((town_num < 0) || (town_num >= scenario.num_towns)) { + give_error("The scenario special encounter tried to put you into a town that doesn't exist.","",0); + return; + } + + l.x = x; l.y = y; + + force_town_enter(town_num,l); + end_town_mode(1,l); + start_town_mode(town_num,9); +} + + +// Damaging and killing monsters needs to be here because several have specials attached to them. +Boolean damage_monst(short which_m, short who_hit, short how_much, short how_much_spec, short dam_type) +//short which_m, who_hit, how_much, how_much_spec; // 6 for who_hit means dist. xp evenly 7 for no xp +//short dam_type; // 0 - weapon 1 - fire 2 - poison 3 - general magic 4 - unblockable 5 - cold + // 6 - demon 7 - undead + // 9 - marked damage, from during anim mode + //+10 = no_print + // 100s digit - damage sound for boom space +{ + creature_data_type *victim; + short r1,which_spot,sound_type; + location where_put; + + Boolean do_print = TRUE; + char resist; + + if (c_town.monst.dudes[which_m].active == 0) return FALSE; + + sound_type = dam_type / 100; + dam_type = dam_type % 100; + + if (dam_type >= 10) { + do_print = FALSE; + dam_type -= 10; + } + + if (sound_type == 0) { + if ((dam_type == 1) || (dam_type == 4) ) + sound_type = 5; + if (dam_type == 5) + sound_type = 7; + if (dam_type == 3) + sound_type = 12; + if (dam_type == 2) + sound_type = 11; + } + + + victim = &c_town.monst.dudes[which_m]; + resist = victim->m_d.immunities; + + if (dam_type == 3) { + if (resist & 1) + how_much = how_much / 2; + if (resist & 2) + how_much = 0; + } + if (dam_type == 1) { + if (resist & 4) + how_much = how_much / 2; + if (resist & 8) + how_much = 0; + } + if (dam_type == 5) { + if (resist & 16) + how_much = how_much / 2; + if (resist & 32) + how_much = 0; + } + if (dam_type == 2) { + if (resist & 64) + how_much = how_much / 2; + if (resist & 128) + how_much = 0; + } + + // Absorb damage? + if (((dam_type == 1) || (dam_type == 3) || (dam_type == 5)) + && (victim->m_d.spec_skill == 26)) { + victim->m_d.health += how_much; + ASB(" Magic absorbed."); + return FALSE; + } + + // Saving throw + if (((dam_type == 1) || (dam_type == 5)) && (get_ran(1,0,20) <= victim->m_d.level)) + how_much = how_much / 2; + if ((dam_type == 3) && (get_ran(1,0,24) <= victim->m_d.level)) + how_much = how_much / 2; + + // Rentar-Ihrno? + if (victim->m_d.spec_skill == 36) + how_much = how_much / 10; + + + r1 = get_ran(1,0,(victim->m_d.armor * 5) / 4); + r1 += victim->m_d.level / 4; + if (dam_type == 0) + how_much -= r1; + + if (boom_anim_active == TRUE) { + if (how_much < 0) + how_much = 0; + monst_marked_damage[which_m] += how_much; + add_explosion(victim->m_loc,how_much,0,(dam_type > 2) ? 2 : 0,14 * (victim->m_d.x_width - 1),18 * (victim->m_d.y_width - 1)); + if (how_much == 0) + return FALSE; + else return TRUE; + } + + if (how_much <= 0) { + if (is_combat()) + monst_spell_note(victim->number,7); + if ((how_much <= 0) && ((dam_type == 0) || (dam_type == 6) || (dam_type == 7))) { + draw_terrain(2); + play_sound(2); + } + + return FALSE; + } + + if (do_print == TRUE) + monst_damaged_mes(which_m,how_much,how_much_spec); + victim->m_d.health = victim->m_d.health - how_much - how_much_spec; + + if (in_scen_debug == TRUE) + victim->m_d.health = -1; + // splitting monsters + if ((victim->m_d.spec_skill == 12) && (victim->m_d.health > 0)){ + where_put = find_clear_spot(victim->m_loc,1); + if (where_put.x > 0) + if ((which_spot = c_town.placeMonster(victim->number,where_put)) < 90) { + c_town.monst.dudes[which_spot].m_d.health = victim->m_d.health; + c_town.monst.dudes[which_spot].monst_start = victim->monst_start; + monst_spell_note(victim->number,27); + } + } + if (who_hit < 7) + party.total_dam_done += how_much + how_much_spec; + + // Monster damages. Make it hostile. + victim->active = 2; + + + if (dam_type != 9) { // note special damage only gamed in hand-to-hand, not during animation + if (party_can_see_monst(which_m) == TRUE) { + pre_boom_space(victim->m_loc,100,boom_gr[dam_type],how_much,sound_type); + if (how_much_spec > 0) + boom_space(victim->m_loc,100,51,how_much_spec,5); + } + else { + pre_boom_space(victim->m_loc,overall_mode, boom_gr[dam_type],how_much,sound_type); + if (how_much_spec > 0) + boom_space(victim->m_loc,overall_mode,51,how_much_spec,5); + } + } + + if (victim->m_d.health < 0) { + monst_killed_mes(which_m); + kill_monst(victim,who_hit); + } + else { + if (how_much > 0) + victim->m_d.morale = victim->m_d.morale - 1; + if (how_much > 5) + victim->m_d.morale = victim->m_d.morale - 1; + if (how_much > 10) + victim->m_d.morale = victim->m_d.morale - 1; + if (how_much > 20) + victim->m_d.morale = victim->m_d.morale - 2; + } + + if ((victim->attitude % 2 != 1) && (who_hit < 7) && + (processing_fields == FALSE) && (monsters_going == FALSE)) { + add_string_to_buf("Damaged an innocent. "); + victim->attitude = 1; + make_town_hostile(); + } + if ((victim->attitude % 2 != 1) && (who_hit < 7) && + ((processing_fields == TRUE) && (party.stuff_done[305][9] == 0))) { + add_string_to_buf("Damaged an innocent."); + victim->attitude = 1; + make_town_hostile(); + } + + return TRUE; +} + +void kill_monst(creature_data_type *which_m,short who_killed) +{ + short xp,i,j,s1,s2,s3; + location l; + + switch (which_m->m_d.m_type) { + case 0: case 3: case 4: case 5: case 6: + if (( which_m->number == 38) || + ( which_m->number == 39)) + i = 4; + else if ( which_m->number == 45) + i = 0; + else i = get_ran(1,0,1); + play_sound(29 + i); break; + case 9: play_sound(29); break; + case 1: case 2: case 7: case 8: case 11: + i = get_ran(1,0,1); play_sound(31 + i); break; + default: play_sound(33); break; + } + + // Special killing effects + if (sd_legit(which_m->monst_start.spec1,which_m->monst_start.spec2) == TRUE) + party.stuff_done[which_m->monst_start.spec1][which_m->monst_start.spec2] = 1; + + run_special(12,2,which_m->monst_start.special_on_kill,which_m->m_loc,&s1,&s2,&s3); + if (which_m->m_d.radiate_1 == 15) + run_special(12,0,which_m->m_d.radiate_2,which_m->m_loc,&s1,&s2,&s3); + + if ((in_scen_debug == FALSE) && ((which_m->summoned >= 100) || (which_m->summoned == 0))) { // no xp for party-summoned monsters + xp = which_m->m_d.level * 2; + if (who_killed < NUM_OF_PCS) + adven[who_killed].giveXP(xp); + else if (who_killed == INVALID_PC) + adven.giveXP(xp / 6 + 1); + if (who_killed < 7) { + i = max((xp / 6),1); + adven.giveXP(i); + } + l = which_m->m_loc; + place_glands(l,which_m->number); + + } + if ((in_scen_debug == FALSE) && (which_m->summoned == 0)) + place_treasure(which_m->m_loc, which_m->m_d.level / 2, which_m->m_d.treasure, 0); + + i = which_m->m_loc.x; + j = which_m->m_loc.y; + switch (which_m->m_d.m_type) { + case 7: make_sfx(i,j,6); break; + case 8: if (which_m->number <= 59) make_sfx(i,j,7); break; + case 10: case 12: make_sfx(i,j,4); break; + case 11: make_sfx(i,j,8); break; + default: make_sfx(i,j,1); break; + } + + + + if (((is_town()) || (which_combat_type == 1)) && (which_m->summoned == 0)) { + party.m_killed[c_town.town_num]++; + } + + party.total_m_killed++; + + which_m->monst_start.spec1 = 0; // make sure, if this is a spec. activated monster, it won't come back + + which_m->active = 0; +} + +// Pushes party and monsters around by moving walls and conveyor belts. +//This is very fragils, and only hands a few cases. +void push_things() +{ + Boolean redraw = FALSE; + short i,k; + unsigned char ter; + location l; + + if (is_out()) + return; + if (belt_present == FALSE) + return; + + for (i = 0; i < T_M; i++) + if (c_town.monst.dudes[i].active > 0) { + l = c_town.monst.dudes[i].m_loc; + ter = t_d.terrain[l.x][l.y]; + switch (scenario.ter_types[ter].special) { + case 16: l.y--; break; + case 17: l.x++; break; + case 18: l.y++; break; + case 19: l.x--; break; + } + if (same_point(l,c_town.monst.dudes[i].m_loc) == FALSE) { + c_town.monst.dudes[i].m_loc = l; + if ((point_onscreen(center,c_town.monst.dudes[i].m_loc) == TRUE) || + (point_onscreen(center,l) == TRUE)) + redraw = TRUE; + } + } + for (i = 0; i < NUM_TOWN_ITEMS; i++) + if (t_i.items[i].variety > 0) { + l = t_i.items[i].item_loc; + ter = t_d.terrain[l.x][l.y]; + switch (scenario.ter_types[ter].special) { + case 16: l.y--; break; + case 17: l.x++; break; + case 18: l.y++; break; + case 19: l.x--; break; + } + if (same_point(l,t_i.items[i].item_loc) == FALSE) { + t_i.items[i].item_loc = l; + if ((point_onscreen(center,t_i.items[i].item_loc) == TRUE) || + (point_onscreen(center,l) == TRUE)) + redraw = TRUE; + } + } + + if (is_town()) { + ter = t_d.terrain[c_town.p_loc.x][c_town.p_loc.y]; + l = c_town.p_loc; + switch (scenario.ter_types[ter].special) { + case 16: l.y--; break; + case 17: l.x++; break; + case 18: l.y++; break; + case 19: l.x--; break; + } + if (same_point(l,c_town.p_loc) == FALSE) { + ASB("You get pushed."); + if (scenario.ter_types[ter].special >= 16) + draw_terrain(0); + center = l; + c_town.p_loc = l; + update_explored(l); + ter = t_d.terrain[c_town.p_loc.x][c_town.p_loc.y]; + draw_map(modeless_dialogs[5],5); + if (is_barrel(c_town.p_loc.x,c_town.p_loc.y)) { + take_barrel(c_town.p_loc.x,c_town.p_loc.y); + ASB("You smash the barrel."); + } + if (is_crate(c_town.p_loc.x,c_town.p_loc.y)) { + take_crate(c_town.p_loc.x,c_town.p_loc.y); + ASB("You smash the crate."); + } + for (k = 0; k < NUM_TOWN_ITEMS; k++) + if ((t_i.items[k].variety > 0) && (t_i.items[k].isContained()) + && (same_point(t_i.items[k].item_loc,c_town.p_loc) == TRUE)) + t_i.items[k].item_properties = t_i.items[k].item_properties & 247; + redraw = TRUE; + } + } + if (is_combat()) { + for (i = 0; i < 6; i++) + if (adven[i].isAlive()) { + ter = t_d.terrain[pc_pos[i].x][pc_pos[i].y]; + l = pc_pos[i]; + switch (scenario.ter_types[ter].special) { + case 16: l.y--; break; + case 17: l.x++; break; + case 18: l.y++; break; + case 19: l.x--; break; + } + if (same_point(l, pc_pos[i]) == FALSE) { + ASB("Someone gets pushed."); + ter = t_d.terrain[l.x][l.y]; + if (scenario.ter_types[ter].special >= 16) + draw_terrain(0); + pc_pos[i] = l; + update_explored(l); + draw_map(modeless_dialogs[5],5); + if (is_barrel(pc_pos[i].x,pc_pos[i].y)) { + take_barrel(pc_pos[i].x,pc_pos[i].y); + ASB("You smash the barrel."); + } + if (is_crate(pc_pos[i].x,pc_pos[i].y)) { + take_crate(pc_pos[i].x,pc_pos[i].y); + ASB("You smash the crate."); + } + for (k = 0; k < NUM_TOWN_ITEMS; k++) + if ((t_i.items[k].variety > 0) && (t_i.items[k].isContained()) + && (same_point(t_i.items[k].item_loc,pc_pos[i]) == TRUE)) + t_i.items[k].item_properties = t_i.items[k].item_properties & 247; + redraw = TRUE; + } + } + } + if (redraw == TRUE) { + print_buf(); + draw_terrain(0); + } +} + +void special_increase_age() +{ + short i,s1,s2,s3; + Boolean redraw = FALSE,stat_area = FALSE; + + for (i = 0; i < 8; i++) + if ((c_town.town.timer_spec_times[i] > 0) && (party.age % c_town.town.timer_spec_times[i] == 0) + && ((is_town() == TRUE) || ((is_combat() == TRUE) && (which_combat_type == 1)))) { + run_special(9,2,c_town.town.timer_specs[i],location(),&s1,&s2,&s3); + stat_area = TRUE; + if (s3 > 0) + redraw = TRUE; + } + for (i = 0; i < 20; i++) + if ((scenario.scenario_timer_times[i] > 0) && (party.age % scenario.scenario_timer_times[i] == 0)) { + run_special(10,0,scenario.scenario_timer_specs[i],location(),&s1,&s2,&s3); + stat_area = TRUE; + if (s3 > 0) + redraw = TRUE; + } + for (i = 0; i < 30; i++) + if (party.party_event_timers[i] > 0) { + if (party.party_event_timers[i] == 1) { + if (party.global_or_town[i] == 0) + run_special(11,0,party.node_to_call[i],location(),&s1,&s2,&s3); + else run_special(11,2,party.node_to_call[i],location(),&s1,&s2,&s3); + party.party_event_timers[i] = 0; + stat_area = TRUE; + if (s3 > 0) + redraw = TRUE; + } + else party.party_event_timers[i]--; + } + if (stat_area == TRUE) { + put_pc_screen(); + put_item_screen(stat_window,0); + } + if (redraw == TRUE) + draw_terrain(0); + +} + +// This is the big painful one, the main special engine +// which_mode - says when it was called +// 0 - out moving (a - 1 if blocked) +// 1 - town moving (a - 1 if blocked) +// 2 - combat moving (a - 1 if blocked) +// 3 - out looking (a - 1 if don't get items inside) NOT USED!!! +// 4 - town looking (a - 1 if don't get items inside) +// 5 - entering town +// 6 - leaving town +// 7 - talking (a,b - numbers of strings to respond) +// 8 - using a special item +// 9 - town timer +// 10 - scen timer +// 11 - party countdown timer +// 12 - killed a monst +// 13 - encountering outdoor enc (a - 1 if no fight) +// 14 - winning outdoor enc +// 15 - fleeing outdoor enc +// 16 - ritual of sanct +// 17 - using space +// which_type - 0 - scen 1 - out 2 - town +// start spec - the number of the first spec to call +// a,b - 2 values that can be returned +// redraw - 1 if now need redraw +void run_special(short which_mode,short which_type,short start_spec,location spec_loc,short *a,short *b,short *redraw) +{ + short cur_spec,cur_spec_type,next_spec,next_spec_type; + special_node_type cur_node; + short num_nodes = 0; + + if (special_in_progress == TRUE) { + give_error("The scenario called a special node while processing another special encounter. The second special will be ignored.","",0); + return; + } + special_in_progress = TRUE; + next_spec = start_spec; + next_spec_type = which_type; + current_pc_picked_in_spec_enc = -1; + store_special_loc = spec_loc; + if (end_scenario == TRUE) { + special_in_progress = FALSE; + return; + } + + while (next_spec >= 0) { + + cur_spec = next_spec; + cur_spec_type = next_spec_type; + next_spec = -1; + cur_node = get_node(cur_spec,cur_spec_type); + + if (cur_node.type == -1) { /// got an error + special_in_progress = FALSE; + return; + } + if ((cur_node.type >= 0) && (cur_node.type <= 27)) { + general_spec(which_mode,cur_node,cur_spec_type,&next_spec,&next_spec_type,a,b,redraw); + } + if ((cur_node.type >= 50) && (cur_node.type <= 63)) { + oneshot_spec(which_mode,cur_node,cur_spec_type,&next_spec,&next_spec_type,a,b,redraw); + } + if ((cur_node.type >= 80) && (cur_node.type <= 106)) { + affect_spec(which_mode,cur_node,cur_spec_type,&next_spec,&next_spec_type,a,b,redraw); + } + if ((cur_node.type >= 130) && (cur_node.type <= 155)) { + ifthen_spec(which_mode,cur_node,cur_spec_type,&next_spec,&next_spec_type,a,b,redraw); + } + if ((cur_node.type >= 170) && (cur_node.type <= 195)) { + townmode_spec(which_mode,cur_node,cur_spec_type,&next_spec,&next_spec_type,a,b,redraw); + } + if ((cur_node.type >= 200) && (cur_node.type <= 218)) { + rect_spec(which_mode,cur_node,cur_spec_type,&next_spec,&next_spec_type,a,b,redraw); + } + if ((cur_node.type >= 225) && (cur_node.type <= 229)) { + outdoor_spec(which_mode,cur_node,cur_spec_type,&next_spec,&next_spec_type,a,b,redraw); + } + + num_nodes++; + if (num_nodes >= 50) { + give_error("A special encounter can be at most 50 nodes long. The 50th node was just processed. The encounter will now end.","",0); + next_spec = -1; + } + } + if (is_out()) + erase_out_specials(); + else erase_specials(); + special_in_progress = FALSE; +} + +special_node_type get_node(short cur_spec,short cur_spec_type) +{ + special_node_type dummy_node; + + dummy_node = scenario.scen_specials[0]; + dummy_node.type = -1; + if (cur_spec_type == 0) { + if (cur_spec != minmax(0,255,(int)cur_spec)) { + give_error("The scenario called a scenario special node out of range.","",0); + return dummy_node; + } + return scenario.scen_specials[cur_spec]; + } + if (cur_spec_type == 1) { + if (cur_spec != minmax(0,59,(int)cur_spec)) { + give_error("The scenario called an outdoor special node out of range.","",0); + return dummy_node; + } + return outdoors[party.i_w_c.x][party.i_w_c.y].specials[cur_spec]; + } + if (cur_spec_type == 2) { + if (cur_spec != minmax(0,99,(int)cur_spec)) { + give_error("The scenario called a town special node out of range.","",0); + return dummy_node; + } + return c_town.town.specials[cur_spec]; + } + return dummy_node; +} + +void general_spec(short which_mode,special_node_type cur_node,short cur_spec_type, + short *next_spec,short *next_spec_type,short *a,short *b,short *redraw) +{ + Boolean check_mess = FALSE; + char str1[256] = "",str2[256] = ""; + short store_val = 0,i; + special_node_type spec; + short mess_adj[3] = {160,10,20}; + + spec = cur_node; + *next_spec = cur_node.jumpto; + + switch (cur_node.type) { + case 0: break; // null spec + case 1: + check_mess = TRUE; setsd(cur_node.sd1,cur_node.sd2,cur_node.ex1a); + break; + case 2: + check_mess = TRUE; + setsd(cur_node.sd1,cur_node.sd2, + PSD[cur_node.sd1][cur_node.sd2] + ((cur_node.ex1b == 0) ? 1 : -1) * cur_node.ex1a); + break; + case 3: + check_mess = TRUE;break; + case 5: + get_strs((char *) str1,(char *) str2, cur_spec_type,cur_node.m1 + mess_adj[cur_spec_type], + cur_node.m2 + mess_adj[cur_spec_type]); + if (cur_node.m1 >= 0) + ASB((char *) str1); + if (cur_node.m2 >= 0) + ASB((char *) str2); + break; + case 6: + setsd(cur_node.sd1,cur_node.sd2, + ((PSD[cur_node.sd1][cur_node.sd2] == 0) ? 1 : 0) ); + check_mess = TRUE;break; + case 7: + if (is_out()) *next_spec = -1; + if ((is_out()) && (spec.ex1a != 0) && (which_mode == 0)) { + ASB("Can't go here while outdoors."); + *a = 1; + } + break; + case 8: + if (is_town()) *next_spec = -1; + if ((is_town()) && (spec.ex1a != 0) && (which_mode == 1)) { + ASB("Can't go here while in town mode."); + *a = 1; + } + break; + case 9: + if (is_combat()) *next_spec = -1; + if ((is_combat()) && (spec.ex1a != 0) && (which_mode == 2)) { + ASB("Can't go here during combat."); + *a = 1; + } + break; + case 10: + if ((which_mode == 3) || (which_mode == 4)) *next_spec = -1; + break; + case 11: + check_mess = TRUE; + if (which_mode < 3) { + if (spec.ex1a != 0) + *a = 1; + else *a = 0; + } + break; + case 12: + check_mess = TRUE; party.age += spec.ex1a; + break; + case 13: + check_mess = TRUE; + for (i = 0; i < 30; i++) + if (party.party_event_timers[i] == 0) { + party.party_event_timers[i] = spec.ex1a; + party.node_to_call[i] = spec.ex1b; + party.global_or_town[i] = 0; + i = 30; + } + break; + case 14: + play_sound(1000 + spec.ex1a); + break; + case 15: + check_mess = TRUE; + if (spec.ex1a != minmax(0,29,(int)spec.ex1a)) + give_error("Horse out of range.","",0); + else party.horses[spec.ex1a].property = (spec.ex2a == 0) ? 1 : 0; + break; + case 16: + check_mess = TRUE; + if (spec.ex1a != minmax(0,29,(int)spec.ex1a)) + give_error("Boat out of range.","",0); + else party.boats[spec.ex1a].property = (spec.ex2a == 0) ? 1 : 0; + break; + case 17: + check_mess = TRUE; + if (spec.ex1a != minmax(0,scenario.num_towns - 1,(int)spec.ex1a)) + give_error("Town out of range.","",0); + else party.can_find_town[spec.ex1a] = (spec.ex1b == 0) ? 0 : 1; + *redraw = TRUE; + break; + case 18: + check_mess = TRUE; + if (spec.ex1a != minmax(1,10,(int)spec.ex1a)) + give_error("Event code out of range.","",0); + else if (party.key_times[spec.ex1a] == 30000) + party.key_times[spec.ex1a] = calc_day(); + break; + case 19: + check_mess = TRUE; + if ((forced_give(spec.ex1a,0) == FALSE) && ( spec.ex1b >= 0)) + *next_spec = spec.ex1b; + break; + case 20: + for (i = 0; i < 144; i++) + if (adven.checkClass(spec.ex1a,0) == true) + store_val++; + if (store_val == 0) { + if ( spec.ex1b >= 0) + *next_spec = spec.ex1b; + } + else { + check_mess = TRUE; + party.giveGold(store_val * spec.ex2a,true); + } + break; + case 21: + *next_spec_type = 0; + break; + case 22: + if (spec.sd1 != minmax(0,299,(int)spec.sd1)) + give_error("Stuff Done flag out of range.","",0); + else for (i = 0; i < 10; i++) PSD[spec.sd1][i] = spec.ex1a; + break; + case 23: + if ((sd_legit(spec.sd1,spec.sd2) == FALSE) || (sd_legit(spec.ex1a,spec.ex1b) == FALSE)) + give_error("Stuff Done flag out of range.","",0); + else PSD[spec.sd1][spec.sd2] = PSD[spec.ex1a][spec.ex1b]; + break; + case 24: + if (which_mode != 16) + *next_spec = spec.ex1b; + break; + case 25: + check_mess = TRUE; + party.age += spec.ex1a; + adven.heal(spec.ex1b); + adven.restoreSP(spec.ex1b); + break; + case 26: + if (which_mode != 13) + break; + *a = (spec.ex1a == 0) ? 1 : 0; + break; + case 27: + end_scenario = TRUE; + break; + } + if (check_mess == TRUE) { + handle_message(which_mode,cur_spec_type,cur_node.m1,cur_node.m2,a,b); + } +} + + +void oneshot_spec(short which_mode,special_node_type cur_node,short cur_spec_type, + short *next_spec,short *,short *a,short *b,short *redraw) +{ + Boolean check_mess = TRUE,set_sd = TRUE; + char strs[6][256] = {"","","","","",""}; + short i,j,buttons[3] = {-1,-1,-1}; + special_node_type spec; + item_record_type store_i; + location l; + + spec = cur_node; + *next_spec = cur_node.jumpto; + if ((sd_legit(spec.sd1,spec.sd2) == TRUE) && (PSD[spec.sd1][spec.sd2] == 250)) { + *next_spec = -1; + return; + } + switch (cur_node.type) { + case 50: + if (forced_give(spec.ex1a,0) == FALSE) { + set_sd = FALSE; + if ( spec.ex2b >= 0) + *next_spec = spec.ex2b; + } + else { + party.giveGold(spec.ex1b,true); + party.giveFood(spec.ex2a,true); + } + break; + case 51: + if (spec.ex1a != minmax(0,49,(int)spec.ex1a)) { + give_error("Special item is out of range.","",0); + set_sd = FALSE; + } + else { + party.spec_items[spec.ex1a] = (spec.ex1b == 0) ? 1 : 0; + } + if (stat_window == 6) + set_stat_window(6); + *redraw = 1; + break; + case 52: + set_sd = FALSE; + check_mess = FALSE; + break; + case 53: + check_mess = FALSE; + break; + case 55: case 56: case 57: + check_mess = FALSE; + if (spec.m1 < 0) + break; + for (i = 0; i < 3; i++) + get_strs((char *) strs[i * 2],(char *) strs[i * 2 + 1],cur_spec_type, + spec.m1 + i * 2 + spec_str_offset[cur_spec_type],spec.m1 + i * 2 + 1 + spec_str_offset[cur_spec_type]); + if (spec.m2 > 0) + {buttons[0] = 1; buttons[1] = spec.ex1a; buttons[2] = spec.ex2a; + if ((spec.ex1a >= 0) || (spec.ex2a >= 0)) buttons[0] = 20; } + if (spec.m2 <= 0) {buttons[0] = spec.ex1a;buttons[1] = spec.ex2a;} + if ((buttons[0] < 0) && (buttons[1] < 0)) { + give_error("Dialog box ended up with no buttons.","",0); + break; + } + switch (cur_node.type) { + case 55: if (spec.pic >= 1000) i = custom_choice_dialog((char *) strs,(spec.pic % 1000) + 2400,buttons) ; + else i = custom_choice_dialog((char *) strs,spec.pic ,buttons) ; break; + case 56: if (spec.pic >= 1000) i = custom_choice_dialog((char *) strs,(spec.pic % 1000) + 2000,buttons) ; + else i = custom_choice_dialog((char *) strs,spec.pic,buttons) ; break; + case 57: if (spec.pic >= 1000) i = custom_choice_dialog((char *) strs,(spec.pic % 1000) + 2000,buttons) ; + else i = custom_choice_dialog((char *) strs,spec.pic ,buttons) ; break; + } + if (spec.m2 > 0) { + if (i == 1) { + if ((spec.ex1a >= 0) || (spec.ex2a >= 0)) { + set_sd = FALSE; + } + } + if (i == 2) *next_spec = spec.ex1b; + if (i == 3) *next_spec = spec.ex2b; + } + else { + if (i == 1) *next_spec = spec.ex1b; + if (i == 2) *next_spec = spec.ex2b; + } + break; + case 58: case 59: case 60: + check_mess = FALSE; + if (spec.m1 < 0) + break; + for (i = 0; i < 3; i++) + get_strs((char *) strs[i * 2],(char *) strs[i * 2 + 1],cur_spec_type, + spec.m1 + i * 2 + spec_str_offset[cur_spec_type],spec.m1 + i * 2 + 1 + spec_str_offset[cur_spec_type]); + buttons[0] = 20; buttons[1] = 19; + switch (cur_node.type) { + case 58: if (spec.pic >= 1000) i = custom_choice_dialog((char *) strs,(spec.pic % 1000) + 2400,buttons) ; + else i = custom_choice_dialog((char *) strs,spec.pic,buttons) ; break; + case 59: if (spec.pic >= 1000) i = custom_choice_dialog((char *) strs,(spec.pic % 1000) + 2000,buttons) ; + else i = custom_choice_dialog((char *) strs,spec.pic,buttons) ; break; + case 60: if (spec.pic >= 1000) i = custom_choice_dialog((char *) strs,(spec.pic % 1000) + 2000,buttons) ; + else i = custom_choice_dialog((char *) strs,spec.pic,buttons) ; break; + } + if (i == 1) {set_sd = FALSE; *next_spec = -1;} + else { + store_i = get_stored_item(spec.ex1a); + if ((spec.ex1a >= 0) && (give_to_party(store_i,TRUE) == FALSE)) { + set_sd = FALSE; *next_spec = -1; + } + else { + party.giveGold(spec.ex1b,true); + party.giveFood(spec.ex2a,true); + if ((spec.m2 >= 0) && (spec.m2 < 50)) { + if (party.spec_items[spec.m2] == 0) + ASB("You get a special item."); + party.spec_items[spec.m2] = 1; + *redraw = TRUE; + if (stat_window == 6) + set_stat_window(6); + } + if (spec.ex2b >= 0) *next_spec = spec.ex2b; + } + } + break; + case 61: + if (spec.ex1a != minmax(0,3,(int)spec.ex1a)) { + give_error("Special outdoor enc. is out of range. Must be 0-3.","",0); + set_sd = FALSE; + } + else { + l = party.p_loc.toLocal(); + place_outd_wand_monst(l, + outdoors[party.i_w_c.x][party.i_w_c.y].special_enc[spec.ex1a],TRUE); + } + break; + case 62: + c_town.activateMonsters(spec.ex1a); + break; + case 63: + check_mess = FALSE; + if ((spec.m1 >= 0) || (spec.m2 >= 0)) { + get_strs((char *) strs[0],(char *) strs[1], + cur_spec_type, + spec.m1 + ((spec.m1 >= 0) ? spec_str_offset[cur_spec_type] : 0), + spec.m2 + ((spec.m2 >= 0) ? spec_str_offset[cur_spec_type] : 0)); + buttons[0] = 3; buttons[1] = 2; + i = custom_choice_dialog((char *) strs,727,buttons); + } + else i = FCD(872,0); + if (i == 1) {set_sd = FALSE; *next_spec = -1; *a = 1;} + else { + if (is_combat() == TRUE) + j = adven[current_pc].runTrap(spec.ex1a,spec.ex1b,spec.ex2a); + else + { + short tmp = select_pc(1,0); + + if (tmp == INVALID_PC) j = FALSE; + else j = adven[tmp].runTrap(spec.ex1a,spec.ex1b,spec.ex2a); + } + + if (j == 0) + { + *a = 1; + set_sd = FALSE; + } + } + break; + } + if (check_mess == TRUE) { + handle_message(which_mode,cur_spec_type,cur_node.m1,cur_node.m2,a,b); + } + if ((set_sd == TRUE) && (sd_legit(spec.sd1,spec.sd2) == TRUE)) + PSD[spec.sd1][spec.sd2] = 250; + +} + +void affect_spec(short which_mode,special_node_type cur_node,short cur_spec_type, + short *next_spec,short *,short *a,short *b,short *redraw) +{ + Boolean check_mess = TRUE; + short i,pc,r1; + special_node_type spec; + + spec = cur_node; + *next_spec = cur_node.jumpto; + pc = current_pc_picked_in_spec_enc; + + + if ((check_mess == TRUE) && (cur_node.type != 80)) { + handle_message(which_mode,cur_spec_type,cur_node.m1,cur_node.m2,a,b); + } + + + switch (cur_node.type) { + case 80: + if (spec.ex1a == 2) + current_pc_picked_in_spec_enc = -1; + else if (spec.ex1a == 1) { + i = select_pc(0,0); + if (i != 6) + current_pc_picked_in_spec_enc = i; + } + else if (spec.ex1a == 0) { + i = select_pc(1,0); + if (i != 6) + current_pc_picked_in_spec_enc = i; + } + if (i == 6)// && (spec.ex1b >= 0)) + *next_spec = spec.ex1b; + break; + case 81: + r1 = get_ran(spec.ex1a,1,spec.ex1b) + spec.ex2a; + if (pc < 0) { + if(spec.pic == 1 && overall_mode == MODE_COMBAT) + adven[current_pc].damage(r1,spec.ex2b,0); + else + adven.damage(r1,spec.ex2b); + } + else adven[pc].damage(r1,spec.ex2b,0); + break; + case 82: + for (i = 0; i < 6; i++) + if(PSD[304][0] > 0 && adven[i].main_status == MAIN_STATUS_ALIVE) //party split ? + adven[i].cur_health = minmax(0, (int)adven[i].max_health, + adven[i].cur_health + spec.ex1a * ((spec.ex1b != 0) ? -1: 1)); + else if (PSD[304][0] == 0 && ((pc < 0) || (pc == i))) + adven[i].cur_health = minmax(0, (int)adven[i].max_health, + adven[i].cur_health + spec.ex1a * ((spec.ex1b != 0) ? -1: 1)); + break; + case 83: + for (i = 0; i < 6; i++){ + if(PSD[304][0] > 0 && adven[i].main_status == MAIN_STATUS_ALIVE) //party split ? + adven[i].cur_sp = minmax(0, (int)adven[i].max_sp, + adven[i].cur_sp + spec.ex1a * ((spec.ex1b != 0) ? -1: 1)); + else if (PSD[304][0] == 0 && ((pc < 0) || (pc == i))) + adven[i].cur_sp = minmax(0, (int)adven[i].max_sp, + adven[i].cur_sp + spec.ex1a * ((spec.ex1b != 0) ? -1: 1)); + } + break; + case 84: + for (i = 0; i < 6; i++) + if ((pc < 0) || (pc == i)) { + if (spec.ex1b == 0) adven[i].giveXP(spec.ex1a); + else adven[i].drainXP(spec.ex1a); + } + break; + case 85: + for (i = 0; i < 6; i++) + if(PSD[304][0] > 0 && adven[i].main_status == MAIN_STATUS_ALIVE) //party split ? + adven[i].skill_pts = minmax(0, 100, + adven[i].skill_pts + spec.ex1a * ((spec.ex1b != 0) ? -1: 1)); + else if (PSD[304][0] == 0 && ((pc < 0) || (pc == i))) + adven[i].skill_pts = minmax(0, 100, + adven[i].skill_pts + spec.ex1a * ((spec.ex1b != 0) ? -1: 1)); + break; + case 86: + for (i = 0; i < 6; i++) + if ((pc < 0) || (pc == i)) { + if (spec.ex1b == 0) { + if ((adven[i].main_status > MAIN_STATUS_ABSENT) && (adven[i].main_status < MAIN_STATUS_SPLIT)) + adven[i].main_status=MAIN_STATUS_ALIVE; + } + else + if(party.stuff_done[309][1] == 0){//legacy behavior + adven[i].kill(spec.ex1a + 2 + 10); + } + else{//kill only present pc + if ((adven[i].main_status > MAIN_STATUS_ABSENT) && (adven[i].main_status < MAIN_STATUS_SPLIT)) + adven[i].kill(spec.ex1a + 2 + 10); + } + + } + *redraw = 1; + break; + case 87: + for (i = 0; i < 6; i++) + if ((pc < 0) || (pc == i)) { + if (spec.ex1b == 0) + adven[i].cure(spec.ex1a); + else + adven[i].poison(spec.ex1a); + } + break; + case 88: + for (i = 0; i < 6; i++) + if ((pc < 0) || (pc == i)) { + if (spec.ex1b == 0) { + adven[i].slow(-1 * spec.ex1a); + } + else adven[i].slow(spec.ex1a); + } + break; + case 89: + for (i = 0; i < 6; i++) + if ((pc < 0) || (pc == i)) + affect_pc(i,4,spec.ex1a * ((spec.ex1b != 0) ? -1: 1)); + break; + case 90: + for (i = 0; i < 6; i++) + if ((pc < 0) || (pc == i)) + affect_pc(i,5,spec.ex1a * ((spec.ex1b != 0) ? -1: 1)); + break; + case 91: + for (i = 0; i < 6; i++) + if ((pc < 0) || (pc == i)) + affect_pc(i,6,spec.ex1a * ((spec.ex1b != 0) ? -1: 1)); + break; + case 92: + for (i = 0; i < 6; i++) + if ((pc < 0) || (pc == i)) + affect_pc(i,7,spec.ex1a * ((spec.ex1b != 0) ? 1: -1)); + break; + case 93: + for (i = 0; i < 6; i++) + if ((pc < 0) || (pc == i)) + affect_pc(i,8,spec.ex1a * ((spec.ex1b != 0) ? -1: 1)); + break; + case 94: + for (i = 0; i < 6; i++) + if ((pc < 0) || (pc == i)) + affect_pc(i,1,spec.ex1a * ((spec.ex1b != 0) ? -1: 1)); + break; + case 95: + for (i = 0; i < 6; i++) + if ((pc < 0) || (pc == i)) + affect_pc(i,9,spec.ex1a * ((spec.ex1b == 0) ? -1: 1)); + break; + case 96: + for (i = 0; i < 6; i++) + if ((pc < 0) || (pc == i)) { + if (spec.ex1b == 0) { + affect_pc(i,11,-1 * spec.ex1a); + } + else adven[i].sleep(spec.ex1a,11,10); + } + break; + case 97: + for (i = 0; i < 6; i++) + if ((pc < 0) || (pc == i)) { + if (spec.ex1b == 0) { + affect_pc(i,12,-1 * spec.ex1a); + } + else adven[i].sleep(spec.ex1a,12,10); + } + break; + case 98: + if (spec.ex2a != minmax(0,18,(int)spec.ex2a)) { + give_error("Skill is out of range.","",0); + break; + } + for (i = 0; i < 6; i++) + if(PSD[304][0] > 0 && adven[i].main_status == MAIN_STATUS_ALIVE && (get_ran(1,1,100) <= spec.pic)) //party split ? + adven[i].skills[spec.ex2a] = minmax(0, (int)skill_max[spec.ex2a], + adven[i].skills[spec.ex2a] + spec.ex1a * ((spec.ex1b != 0) ? -1: 1)); + else if (PSD[304][0] == 0 && ((pc < 0) || (pc == i)) && (get_ran(1,1,100) <= spec.pic)) + adven[i].skills[spec.ex2a] = minmax(0, (int)skill_max[spec.ex2a], + adven[i].skills[spec.ex2a] + spec.ex1a * ((spec.ex1b != 0) ? -1: 1)); + break; + case 99: + if (spec.ex1a != minmax(0,31,(int)spec.ex1a)) { + give_error("Mage spell is out of range (0 - 31). See docs.","",0); + break; + } + for (i = 0; i < 6; i++) + if(PSD[304][0] > 0 && adven[i].main_status == MAIN_STATUS_ALIVE && (get_ran(1,1,100) <= spec.pic)) //party split ? + adven[i].mage_spells[spec.ex1a + 30] = TRUE; + else if (PSD[304][0] == 0 && ((pc < 0) || (pc == i))) + adven[i].mage_spells[spec.ex1a + 30] = TRUE; + break; + case 100: + if (spec.ex1a != minmax(0,31,(int)spec.ex1a)) { + give_error("Priest spell is out of range (0 - 31). See docs.","",0); + break; + } + for (i = 0; i < 6; i++) + if(PSD[304][0] > 0 && adven[i].main_status == MAIN_STATUS_ALIVE && (get_ran(1,1,100) <= spec.pic)) //party split ? + adven[i].priest_spells[spec.ex1a + 30] = TRUE; + else if (PSD[304][0] == 0 && ((pc < 0) || (pc == i))) + adven[i].priest_spells[spec.ex1a + 30] = TRUE; + break; + case 101: + if (spec.ex1b == 0) + party.giveGold(spec.ex1a,true); + else if (party.gold < spec.ex1a) + party.gold = 0; + else party.takeGold(spec.ex1a,false); + break; + case 102: + if (spec.ex1b == 0) + party.giveFood(spec.ex1a,true); + else if (party.food < spec.ex1a) + party.food = 0; + else party.takeFood(spec.ex1a,false); + break; + case 103: + if (spec.ex1a != minmax(0,19,(int)spec.ex1a)) { + give_error("Alchemy is out of range.","",0); + break; + } + party.alchemy[spec.ex1a] = TRUE; + break; + case 104: + r1 = (short) party.stuff_done[305][0]; + r1 = minmax(0,250,r1 + spec.ex1a); + party.stuff_done[305][0] = r1; + break; + case 105: + r1 = (short) party.stuff_done[305][3]; + r1 = minmax(0,250,r1 + spec.ex1a); + party.stuff_done[305][3] = r1; + break; + case 106: + if (party.in_boat >= 0) + add_string_to_buf(" Can't fly when on a boat. "); + else if (party.in_horse >= 0)//// + add_string_to_buf(" Can't fly when on a horse. "); + else { + r1 = (short) party.stuff_done[305][1]; + r1 = minmax(0,250,r1 + spec.ex1a); + party.stuff_done[305][1] = r1; + } + break; + } +} + +void ifthen_spec(short which_mode,special_node_type cur_node,short cur_spec_type, + short *next_spec,short *,short *a,short *b,short *redraw) +{ + Boolean check_mess = FALSE; + char str1[256] = "",str2[256] = "",str3[256] = ""; + short i,j,k; + special_node_type spec; + location l; + + spec = cur_node; + *next_spec = cur_node.jumpto; + + switch (cur_node.type) { + case 130: + if (sd_legit(spec.sd1,spec.sd2) == TRUE) { + if ((spec.ex1a >= 0) && (PSD[spec.sd1][spec.sd2] >= spec.ex1a)) + *next_spec = spec.ex1b; + else if ((spec.ex2a >= 0) && (PSD[spec.sd1][spec.sd2] < spec.ex2a)) + *next_spec = spec.ex2b; + } + break; + case 131: + if (((is_town()) || (is_combat())) && (c_town.town_num == spec.ex1a)) + *next_spec = spec.ex1b; + break; + case 132: + if (get_ran(1,1,100) <= spec.ex1a) + *next_spec = spec.ex1b; + break; + case 133: + if (spec.ex1a != minmax(0,49,(int)spec.ex1a)) { + give_error("Special item is out of range.","",0); + } + else if (party.spec_items[spec.ex1a] > 0) + *next_spec = spec.ex1b; + break; + case 134: + if ((sd_legit(spec.sd1,spec.sd2) == TRUE) && (sd_legit(spec.ex1a,spec.ex1b) == TRUE)) { + if (PSD[spec.ex1a][spec.ex1b] < PSD[spec.sd1][spec.sd2]) + *next_spec = spec.ex2b; + } + else give_error("A Stuff Done flag is out of range.","",0); + break; + case 135: + if (((is_town()) || (is_combat())) && (t_d.terrain[spec.ex1a][spec.ex1b] == spec.ex2a)) + *next_spec = spec.ex2b; + break; + case 136: + l.x = spec.ex1a; l.y = spec.ex1b; + l = l.toGlobal(); + if ((is_out()) && (out[l.x][l.y] == spec.ex2a)) + *next_spec = spec.ex2b; + break; + case 137: + if (party.gold >= spec.ex1a) + *next_spec = spec.ex1b; + break; + case 138: + if (party.food >= spec.ex1a) + *next_spec = spec.ex1b; + break; + case 139: + if (is_out()) + break; + l.x = spec.ex1a; l.y = spec.ex1b; + for (i = 0; i < NUM_TOWN_ITEMS; i++) + if ((t_i.items[i].variety > 0) && (t_i.items[i].special_class == spec.ex2a) + && (same_point(l,t_i.items[i].item_loc) == TRUE)) + *next_spec = spec.ex2b; + break; + case 140: + if (adven.checkClass(spec.ex1a,1) == true) + *next_spec = spec.ex1b; + break; + case 141: + for (i = 0; i < 6; i++) + if (adven[i].isAlive()) + for (j = 0; j < 24; j++) + if ((adven[i].items[j].variety > 0) && (adven[i].items[j].special_class == spec.ex1a) + && (adven[i].equip[j] == TRUE)) + *next_spec = spec.ex1b; + break; + case 142: + if (party.gold >= spec.ex1a) { + party.takeGold(spec.ex1a,true); + *next_spec = spec.ex1b; + } + break; + case 143: + if (party.food >= spec.ex1a) { + party.takeFood(spec.ex1a,true); + *next_spec = spec.ex1b; + } + break; + case 144: + if (is_out()) + break; + l.x = spec.ex1a; l.y = spec.ex1b; + for (i = 0; i < NUM_TOWN_ITEMS; i++) + if ((t_i.items[i].variety > 0) && (t_i.items[i].special_class == spec.ex2a) + && (same_point(l,t_i.items[i].item_loc) == TRUE)) { + *next_spec = spec.ex2b; + *redraw = 1; + t_i.items[i].variety = 0; + } + break; + case 145: + if (adven.checkClass(spec.ex1a,0) == true) + *next_spec = spec.ex1b; + break; + case 146: + for (i = 0; i < 6; i++) + if (adven[i].isAlive()) + for (j = 0; j < 24; j++) + if ((adven[i].items[j].variety > 0) && (adven[i].items[j].special_class == spec.ex1a) + && (adven[i].equip[j] == TRUE)) { + *next_spec = spec.ex1b; + *redraw = 1; + adven[i].takeItem(j); + } + break; + case 147: + if (calc_day() >= spec.ex1a) + *next_spec = spec.ex1b; + break; + case 148: + for (j = 0; j < town_size[town_type]; j++) + for (k = 0; k < town_size[town_type]; k++) + if (is_barrel(j,k)) + *next_spec = spec.ex1b; + break; + case 149: + for (j = 0; j < town_size[town_type]; j++) + for (k = 0; k < town_size[town_type]; k++) + if (is_crate(j,k)) + *next_spec = spec.ex1b; + break; + case 150: + if (day_reached(spec.ex1a,spec.ex1b) == TRUE) + *next_spec = spec.ex2b; + break; + case 151: + for (i = 0; i < 6; i++) + if ((adven[i].isAlive()) && (adven[i].traits[TRAIT_CAVE_LORE] > 0)) + *next_spec = spec.ex1b; + break; + case 152: + for (i = 0; i < 6; i++) + if ((adven[i].isAlive()) && (adven[i].traits[5] > 0)) + *next_spec = spec.ex1b; + break; + case 153: + if (adven.getMageLore() >= spec.ex1a) + *next_spec = spec.ex1b; + break; + case 154: // text response + check_mess = FALSE; + get_text_response(873,str3,0); + j = 1; k = 1; + spec.pic = minmax(0,8,(int)spec.pic); + get_strs((char *) str1,(char *) str2,0,spec.ex1a,spec.ex2a); + for (i = 0; i < spec.pic;i++) { + if ((spec.ex1a < 0) || (str3[i] != str1[i])) + j = 0; + if ((spec.ex2a < 0) || (str3[i] != str2[i])) + k = 0; + } + if (j == 1) + *next_spec = spec.ex1b; + else if (k == 1) + *next_spec = spec.ex2b; + break; + case 155: + if (sd_legit(spec.sd1,spec.sd2) == TRUE) { + if (PSD[spec.sd1][spec.sd2] == spec.ex1a) + *next_spec = spec.ex1b; + } + break; + } + if (check_mess == TRUE) { + handle_message(which_mode,cur_spec_type,cur_node.m1,cur_node.m2,a,b); + } +} + +void townmode_spec(short which_mode,special_node_type cur_node,short cur_spec_type, + short *next_spec,short *,short *a,short *b,short *redraw) +{ + Boolean check_mess = TRUE; + char strs[6][256] = {"","","","","",""}; + short i,buttons[3] = {-1,-1,-1},r1; + special_node_type spec; + location l; + unsigned char ter; + item_record_type store_i; + + spec = cur_node; + *next_spec = cur_node.jumpto; + + l.x = spec.ex1a; l.y = spec.ex1b; + + if (is_out()) + return; + switch (cur_node.type) { + case 170: + make_town_hostile(); + break; + case 171: + set_terrain(l,spec.ex2a); + if(scenario.ter_types[spec.ex2a].special >= 16 && scenario.ter_types[spec.ex2a].special <=19) + belt_present = TRUE; + if(party.stuff_done[308][0] == 0) + draw_map_rect(modeless_dialogs[5],l.x,l.y,l.x,l.y); + *redraw = TRUE; + break; + case 172: + if (coord_to_ter(spec.ex1a,spec.ex1b) == spec.ex2a){ + set_terrain(l,spec.ex2b); + if(scenario.ter_types[spec.ex2b].special >= 16 && scenario.ter_types[spec.ex2b].special <=19) + belt_present = TRUE; + } + else if (coord_to_ter(spec.ex1a,spec.ex1b) == spec.ex2b){ + set_terrain(l,spec.ex2a); + if(scenario.ter_types[spec.ex2a].special >= 16 && scenario.ter_types[spec.ex2a].special <=19) + belt_present = TRUE; + } + *redraw = 1; + if(party.stuff_done[308][0] == 0) + draw_map_rect(modeless_dialogs[5],l.x,l.y,l.x,l.y); + break; + case 173: + ter = coord_to_ter(spec.ex1a,spec.ex1b); + set_terrain(l,scenario.ter_types[ter].trans_to_what); + if(scenario.ter_types[scenario.ter_types[ter].trans_to_what].special >= 16 && scenario.ter_types[scenario.ter_types[ter].trans_to_what].special <=19) + belt_present = TRUE; + *redraw = 1; + if(party.stuff_done[308][0] == 0) + draw_map_rect(modeless_dialogs[5],l.x,l.y,l.x,l.y); + break; + case 174: + if (is_combat()) { + ASB("Not while in combat."); + if (which_mode < 3) + *a = 1; + *next_spec = -1; + check_mess = FALSE; + } + else { // 1 no + *a = 1; + if ((which_mode == 7) || (spec.ex2a == 0)) + teleport_party(spec.ex1a,spec.ex1b,1); + else teleport_party(spec.ex1a,spec.ex1b,0); + } + *redraw = 1; + break; + case 175: + if (which_mode == 7) + break; + hit_space(l,spec.ex2a,spec.ex2b,1,1); + *redraw = 1; + break; + case 176: + if (which_mode == 7) + break; + radius_damage(l,spec.pic, spec.ex2a, spec.ex2b); + *redraw = 1; + break; + case 177: + ter = coord_to_ter(spec.ex1a,spec.ex1b); + if (scenario.ter_types[ter].special == 8) + set_terrain(l,scenario.ter_types[ter].flag1); + *redraw = 1; + break; + case 178: + ter = coord_to_ter(spec.ex1a,spec.ex1b); + if ((scenario.ter_types[ter].special == 9) || (scenario.ter_types[ter].special == 10)) + set_terrain(l,scenario.ter_types[ter].flag1); + *redraw = 1; + break; + case 179: + if (which_mode == 7) + break; + run_a_boom(l,spec.ex2a,0,0); + break; + case 180: + create_wand_monst(); + *redraw = 1; + break; + case 181: + if (spec.ex2a > 0) + forced_place_monster(spec.ex2a,l); + else c_town.placeMonster(spec.ex2a,l); + *redraw = 1; + break; + case 182: + for (i = 0; i < T_M; i++) + if (c_town.monst.dudes[i].number == spec.ex1a) { + c_town.monst.dudes[i].active = 0; + } + *redraw = 1; + break; + case 183: + for (i = 0; i < T_M; i++) + if ((c_town.monst.dudes[i].active > 0) && + (((spec.ex1a == 0) && (1 == 1)) || + ((spec.ex1a == 1) && (c_town.monst.dudes[i].attitude % 2 == 0)) || + ((spec.ex1a == 2) && (c_town.monst.dudes[i].attitude % 2 == 1)))){ + c_town.monst.dudes[i].active = 0; + } + *redraw = 1; + break; + case 184: + check_mess = FALSE; + if (which_mode > 4) { + ASB("Can't use lever now."); + check_mess = FALSE; + *next_spec = -1; + } + else if (store_special_loc.handleLever() > 0) *next_spec = spec.ex1b; + break; + case 185: + check_mess = FALSE; + if (is_combat()) { + ASB("Not while in combat."); + if (which_mode < 3) *a = 1; + *next_spec = -1; + } + else if ((which_mode != 1) && (which_mode != 4)) { + ASB("Can't teleport now."); + if (which_mode < 3) *a = 1; + *next_spec = -1; + } + else if (FCD(870,0) == 1) { *next_spec = -1; if (which_mode < 3) *a = 1;} + else{ + *a = 1; + if ((which_mode == 7) || (spec.ex2a == 0)) + teleport_party(spec.ex1a,spec.ex1b,1); + else teleport_party(spec.ex1a,spec.ex1b,0); + } + break; + case 186: + check_mess = FALSE; + if (FCD(871,0) == 2) + *next_spec = spec.ex1b; + break; + case 187: + check_mess = FALSE; + if (is_combat()) { + ASB("Can't change level in combat."); + if (which_mode < 3) + *a = 1; + *next_spec = -1; + } + else if (which_mode != 1) { + ASB("Can't change level now."); + if (which_mode < 3) + *a = 1; + *next_spec = -1; + } + else { + if (spec.ex2b < 0) spec.ex2b = 0; + if (spec.ex2b > 7) spec.ex2b = 7; + if (FCD(880 + spec.ex2b,0) == 1) { *next_spec = -1; if (which_mode < 3) *a = 1;} + else { + *a = 1; + change_level(spec.ex2a,l.x,l.y); + } + } + break; + case 188: + check_mess = FALSE; + if (spec.m1 < 0) + break; + if (which_mode > 4) { + ASB("Can't use lever now."); + check_mess = FALSE; + *next_spec = -1; + } + else { + for (i = 0; i < 3; i++) + get_strs((char *) strs[i * 2],(char *) strs[i * 2 + 1],cur_spec_type, + spec.m1 + i * 2 + spec_str_offset[cur_spec_type],spec.m1 + i * 2 + 1 + spec_str_offset[cur_spec_type]); + buttons[0] = 9; buttons[1] = 35; + i = custom_choice_dialog((char *) strs,spec.pic,buttons); + if (i == 1) {*next_spec = -1;} + else { + ter = coord_to_ter(store_special_loc.x,store_special_loc.y); + set_terrain(store_special_loc,scenario.ter_types[ter].trans_to_what); + *next_spec = spec.ex1b; + } + } + break; + case 189: + check_mess = FALSE; + if (spec.m1 < 0) + break; + if (is_combat()) { + ASB("Not while in combat."); + if (which_mode < 3) + *a = 1; + *next_spec = -1; + check_mess = FALSE; + } + else if ((which_mode != 1) && (which_mode != 4)) { + ASB("Can't teleport now."); + if (which_mode < 3) + *a = 1; + *next_spec = -1; + check_mess = FALSE; + } + else { + for (i = 0; i < 3; i++) + get_strs((char *) strs[i * 2],(char *) strs[i * 2 + 1] + ,cur_spec_type,spec.m1 + i * 2 + spec_str_offset[cur_spec_type],spec.m1 + i * 2 + 1 + spec_str_offset[cur_spec_type]); + buttons[0] = 9; buttons[1] = 8; + i = custom_choice_dialog((char *) strs,722,buttons); + if (i == 1) { *next_spec = -1; if (which_mode < 3) *a = 1;} + else { + *a = 1; + if (which_mode == 7 || (spec.ex2a == 0)) + teleport_party(spec.ex1a,spec.ex1b,1); + else teleport_party(spec.ex1a,spec.ex1b,0); + } + } + break; + case 190: + check_mess = FALSE; + if ((spec.m1 < 0) && (spec.ex2b != 1)) + break; + if (is_combat()) { + ASB("Can't change level in combat."); + if (which_mode < 3) + *a = 1; + *next_spec = -1; + check_mess = FALSE; + } + else if (which_mode != 1) { + ASB("Can't change level now."); + if (which_mode < 3) + *a = 1; + *next_spec = -1; + check_mess = FALSE; + } + else { + if (spec.m1 >= 0) { + for (i = 0; i < 3; i++) + get_strs((char *) strs[i * 2],(char *) strs[i * 2 + 1],cur_spec_type, + spec.m1 + i * 2 + spec_str_offset[cur_spec_type],spec.m1 + i * 2 + 1 + spec_str_offset[cur_spec_type]); + buttons[0] = 20; buttons[1] = 24; + } + if (spec.ex2b == 1) + i = 2; + else i = custom_choice_dialog((char *) strs,719,buttons) ; + *a = 1; + if (i == 1) { *next_spec = -1;} + else { + *a = 1; + change_level(spec.ex2a,l.x,l.y); + } + } + break; + case 191: + position_party(spec.ex1a,spec.ex1b,spec.ex2a,spec.ex2b); + break; + case 192: + store_i = get_stored_item(spec.ex2a); + place_item(store_i,l,TRUE); + break; + case 193: + if (which_mode == 7) + break; + if (is_combat()) { + ASB("Not while in combat."); + if (which_mode < 3) + *a = 1; + *next_spec = -1; + check_mess = FALSE; + } + if (party.stuff_done[304][0] > 0) { + ASB("Party is already split."); + if (which_mode < 3) + *a = 1; + *next_spec = -1; + check_mess = FALSE; + } + r1 = char_select_pc(1,0,"Which character goes?"); + if (which_mode < 3) + *a = 1; + if (r1 != 6) { + party.stuff_done[304][3] = r1; + *next_spec = -1; + start_split(spec.ex1a,spec.ex1b,spec.ex2a); + } + else check_mess = FALSE; + break; + case 194: + if (is_combat()) { + ASB("Not while in combat."); + break; + } + if (which_mode < 3) + *a = 1; + *next_spec = -1; + check_mess = FALSE; + end_split(spec.ex1a); + break; + case 195: + for (i = 0; i < 30; i++) + if (party.party_event_timers[i] == 0) { + party.party_event_timers[i] = spec.ex1a; + party.node_to_call[i] = spec.ex1b; + party.global_or_town[i] = 1; + i = 30; + } + break; + } + if (check_mess == TRUE) { + handle_message(which_mode,cur_spec_type,cur_node.m1,cur_node.m2,a,b); + } +} + +void rect_spec(short which_mode,special_node_type cur_node,short cur_spec_type, + short *next_spec,short *,short *a,short *b,short *redraw) +{ + Boolean check_mess = TRUE; + short i,j,k; + special_node_type spec; + location l; + unsigned char ter; + + spec = cur_node; + *next_spec = cur_node.jumpto; + + if (is_out()) + return; + + *redraw = 1; + for (i = spec.ex1b;i <= spec.ex2b;i++){ + for (j = spec.ex1a; j <= spec.ex2a; j++) { + + l.x = i; l.y = j; + switch (cur_node.type) { + case 200: if (get_ran(1,1,100) <= spec.sd1 ) make_fire_wall(i,j); break; + case 201: if (get_ran(1,1,100) <= spec.sd1 ) make_force_wall(i,j); break; + case 202: if (get_ran(1,1,100) <= spec.sd1 ) make_ice_wall(i,j); break; + case 203: if (get_ran(1,1,100) <= spec.sd1 ) make_blade_wall(i,j); break; + case 204: if (get_ran(1,1,100) <= spec.sd1 ) make_scloud(i,j); break; + case 205: if (get_ran(1,1,100) <= spec.sd1 ) make_sleep_cloud(i,j); break; + case 206: if (get_ran(1,1,100) <= spec.sd1 ) make_quickfire(i,j); break; + case 207: if (get_ran(1,1,100) <= spec.sd1 ) make_fire_barrier(i,j); break; + case 208: if (get_ran(1,1,100) <= spec.sd1 ) make_force_barrier(i,j); break; + case 209: if (spec.sd1 == 0) dispel_fields(i,j,1); else dispel_fields(i,j,2);break; + case 210: if (get_ran(1,1,100) <= spec.sd1 ) make_sfx(i,j,spec.sd2 + 1); break; + case 211: if (get_ran(1,1,100) <= spec.sd1 ) { + if (spec.sd2 == 0) make_web(i,j); + if (spec.sd2 == 1) make_barrel(i,j); + if (spec.sd2 == 2) make_crate(i,j); + } break; + case 212: + for (k = 0; k < NUM_TOWN_ITEMS; k++) + if ((t_i.items[k].variety > 0) && (same_point(t_i.items[k].item_loc,l) == TRUE)) { + t_i.items[k].item_loc.x = spec.sd1; + t_i.items[k].item_loc.y = spec.sd2; + } + break; + case 213: + for (k = 0; k < NUM_TOWN_ITEMS; k++) + if ((t_i.items[k].variety > 0) && (same_point(t_i.items[k].item_loc,l) == TRUE)) { + t_i.items[k].variety = 0; + } + break; + case 214: + if (get_ran(1,1,100) <= spec.sd2){ + set_terrain(l,spec.sd1); + if(scenario.ter_types[spec.sd1].special >= 16 && scenario.ter_types[spec.sd1].special <=19) + belt_present = TRUE; + if(party.stuff_done[308][0] == 0) + draw_map_rect(modeless_dialogs[5],l.x,l.y,l.x,l.y); + + } + break; + case 215: + if (coord_to_ter(i,j) == spec.sd1){ + set_terrain(l,spec.sd2); + if(scenario.ter_types[spec.sd2].special >= 16 && scenario.ter_types[spec.sd2].special <=19) + belt_present = TRUE; + } + else if (coord_to_ter(i,j) == spec.sd2){ + set_terrain(l,spec.sd1); + if(scenario.ter_types[spec.sd1].special >= 16 && scenario.ter_types[spec.sd1].special <=19) + belt_present = TRUE; + } + if(party.stuff_done[308][0] == 0) + draw_map_rect(modeless_dialogs[5],l.x,l.y,l.x,l.y); + break; + case 216: + ter = coord_to_ter(i,j); + set_terrain(l,scenario.ter_types[ter].trans_to_what); + if(scenario.ter_types[scenario.ter_types[ter].trans_to_what].special >= 16 && scenario.ter_types[scenario.ter_types[ter].trans_to_what].special <=19) + belt_present = TRUE; + if(party.stuff_done[308][0] == 0) + draw_map_rect(modeless_dialogs[5],l.x,l.y,l.x,l.y); + break; + case 217: + ter = coord_to_ter(i,j); + if (scenario.ter_types[ter].special == 8) + set_terrain(l,scenario.ter_types[ter].flag1); + if(scenario.ter_types[scenario.ter_types[ter].flag1].special >= 16 && scenario.ter_types[scenario.ter_types[ter].flag1].special <=19) + belt_present = TRUE; + if(party.stuff_done[308][0] == 0) + draw_map_rect(modeless_dialogs[5],l.x,l.y,l.x,l.y); + break; + case 218: + ter = coord_to_ter(i,j); + if ((scenario.ter_types[ter].special == 9) || (scenario.ter_types[ter].special == 10)) + set_terrain(l,scenario.ter_types[ter].flag1); + if(scenario.ter_types[scenario.ter_types[ter].flag1].special >= 16 && scenario.ter_types[scenario.ter_types[ter].flag1].special <=19) + belt_present = TRUE; + if(party.stuff_done[308][0] == 0) + draw_map_rect(modeless_dialogs[5],l.x,l.y,l.x,l.y); + break; + + } + } +} + if (check_mess == TRUE) { + handle_message(which_mode,cur_spec_type,cur_node.m1,cur_node.m2,a,b); + } +} + +void outdoor_spec(short which_mode,special_node_type cur_node,short cur_spec_type, + short *next_spec,short *,short *a,short *b,short *redraw) +{ + Boolean check_mess = FALSE; + char str1[256] = "",str2[256] = ""; + special_node_type spec; + location l; + + spec = cur_node; + *next_spec = cur_node.jumpto; + + if (is_out() == FALSE) return; + + switch (cur_node.type) { + case 225: create_wand_monst(); + *redraw = 1; + break; + case 226: + outdoors[party.i_w_c.x][party.i_w_c.y].terrain[spec.ex1a][spec.ex1b] = spec.ex2a; + l.x = spec.ex1a; + l.y = spec.ex1b; + l = l.toGlobal(); + out[l.x][l.y] = spec.ex2a; + *redraw = 1; + check_mess = TRUE; + break; + case 227: + if (spec.ex1a != minmax(0,3,(int)spec.ex1a)) { + give_error("Special outdoor enc. is out of range. Must be 0-3.","",0); + //set_sd = FALSE; + } + else { + l = party.p_loc.toLocal(); + place_outd_wand_monst(l, + outdoors[party.i_w_c.x][party.i_w_c.y].special_enc[spec.ex1a],TRUE); + check_mess = TRUE; + } + break; + case 228: + check_mess = TRUE; + out_move_party(spec.ex1a,spec.ex1b); + *redraw = 1; + *a = 1; + break; + case 229: + get_strs((char *) str1,(char *) str2,1,spec.m1 + 10,-1); + if (spec.ex2a >= 40) + spec.ex2a = 39; + if (spec.ex2a < 1) + spec.ex2a = 1; + spec.ex2b = minmax(0,6,(int)spec.ex2b); + switch (spec.ex1b) { + case 0: start_shop_mode(0,spec.ex1a,spec.ex1a + spec.ex2a - 1,spec.ex2b,(char *) str1); break; + case 1: start_shop_mode(10,spec.ex1a,spec.ex1a + spec.ex2a - 1,spec.ex2b,(char *) str1); break; + case 2: start_shop_mode(11,spec.ex1a,spec.ex1a + spec.ex2a - 1 ,spec.ex2b,(char *) str1); break; + case 3: start_shop_mode(12,spec.ex1a,spec.ex1a + spec.ex2a - 1,spec.ex2b,(char *) str1); break; + case 4: start_shop_mode(3,spec.ex1a,spec.ex1a + spec.ex2a - 1,spec.ex2b,(char *) str1); break; + } + *next_spec = -1; + break; + } + + if (check_mess == TRUE) { + handle_message(which_mode,cur_spec_type,cur_node.m1,cur_node.m2,a,b); + } +} + +void setsd(short a,short b,short val) +{ + if (sd_legit(a,b) == FALSE) { + give_error("The scenario attempted to change an out of range Stuff Done flag.","",0); + return; + } + PSD[a][b] = val; +} + +void handle_message(short which_mode,short cur_type,short mess1,short mess2,short *a,short *b) +{ + char str1[256] = "",str2[256] = ""; + short label1 = -1,label2 = -1,label1b = -1,label2b = -1; + short mess_adj[3] = {160,10,20}; + + if ((mess1 < 0) && (mess2 < 0)) + return; + if (which_mode == 7) { // talking + *a = mess1 + ((mess1 >= 0) ? mess_adj[cur_type] : 0); + *b = mess2 + ((mess2 >= 0) ? mess_adj[cur_type] : 0); + return; + } + get_strs((char *) str1,(char *) str2, cur_type, mess1 + ((mess1 >= 0) ? mess_adj[cur_type] : 0), + mess2 + ((mess2 >= 0) ? mess_adj[cur_type] : 0)) ; + if (mess1 >= 0) { + label1 = 1000 * cur_type + mess1 + mess_adj[cur_type]; + label1b = (is_out()) ? (party.outdoor_corner.x + party.i_w_c.x) + + scenario.out_width * (party.outdoor_corner.y + party.i_w_c.y) : c_town.town_num; + } + if (mess2 >= 0) { + label2 = 1000 * cur_type + mess2 + mess_adj[cur_type]; + label2b = (is_out()) ? (party.outdoor_corner.x + party.i_w_c.x) + + scenario.out_width * (party.outdoor_corner.y + party.i_w_c.y) : c_town.town_num; + } + display_strings((char *) str1, (char *) str2,label1,label2, label1b,label2b, + "",57,1600 + scenario.intro_pic,0); +} + +void get_strs(char *str1,char *str2,short cur_type,short which_str1,short which_str2) +{ + short num_strs[3] = {260,108,135}; + + if (((which_str1 >= 0) && (which_str1 != minmax((short) 0,num_strs[cur_type],which_str1))) || + ((which_str2 >= 0) && (which_str2 != minmax((short) 0,num_strs[cur_type],which_str2)))) { + give_error("The scenario attempted to access a message out of range.","",0); + return; + } + switch (cur_type) { + case 0: + if (which_str1 >= 0) { + if (which_str1 < 160) + strcpy((char *) str1,data_store5->scen_strs[which_str1]); + else strcpy((char *) str1,scen_strs2[which_str1 - 160]); + + } + if (which_str2 >= 0){ + if (which_str2 < 160) + strcpy((char *) str2,data_store5->scen_strs[which_str2]); + else strcpy((char *) str2,scen_strs2[which_str2 - 160]); + } + break; + case 1: + if (which_str1 >= 0) + load_outdoors(party.outdoor_corner.x + party.i_w_c.x, + party.outdoor_corner.y + party.i_w_c.y, party.i_w_c.x, party.i_w_c.y, + 1,which_str1,(char *) str1); + if (which_str2 >= 0) + load_outdoors(party.outdoor_corner.x + party.i_w_c.x, + party.outdoor_corner.y + party.i_w_c.y, party.i_w_c.x, party.i_w_c.y, + 1,which_str2,(char *) str2); + break; + case 2: + if (which_str1 >= 0) + strcpy((char *) str1,data_store->town_strs[which_str1]); + if (which_str2 >= 0) + strcpy((char *) str2,data_store->town_strs[which_str2]); + break; + } + +} + +void use_spec_item(short item) +{ + short i,j,k; + + run_special(8,0,scenario.special_item_special[item],location(),&i,&j,&k); +} diff --git a/Win32/Blades of Exile/SPECIALS.H b/Win32/Blades of Exile/SPECIALS.H new file mode 100644 index 00000000..7ff09a3b --- /dev/null +++ b/Win32/Blades of Exile/SPECIALS.H @@ -0,0 +1,40 @@ +void start_split(short a,short b,short noise); +void end_split(short noise); +Boolean town_specials(short which,short t_num); +Boolean handle_wandering_specials (short mode); +Boolean check_special_terrain(location where_check,short mode,short which_pc,short *spec_num, + Boolean *forced); +void check_fields(location where_check,short mode,short which_pc); +void use_spec_item(short item); +void use_item(short pc,short item); +Boolean use_space(location where); +Boolean adj_town_look(location where); +void PSOE(short str1a,short str1b,short str2a,short str2b, + short which_special,unsigned char *stuff_done_val,short where_put); +Boolean damage_monst(short which_m, short who_hit, short how_much, short how_much_spec, short dam_type); +void kill_monst(creature_data_type *which_m,short who_killed); +void special_increase_age(); +void out_move_party(char x,char y) ; +void teleport_party(short x,short y,short mode); +Boolean run_stone_circle(short which); +void change_level(short town_num,short x,short y); +void push_things(); +void run_special(short which_mode,short which_type,short start_spec,location spec_loc,short *a,short *b,short *redraw); +special_node_type get_node(short cur_spec,short cur_spec_type); +void general_spec(short which_mode,special_node_type cur_node,short cur_spec_type, + short *next_spec,short *next_spec_type,short *a,short *b,short *redraw); +void setsd(short a,short b,short val); +void handle_message(short which_mode,short cur_type,short mess1,short mess2,short *a,short *b); +void get_strs(char *str1,char *str2,short cur_type,short which_str1,short which_str2) ; +void ifthen_spec(short which_mode,special_node_type cur_node,short cur_spec_type, + short *next_spec,short *next_spec_type,short *a,short *b,short *redraw); +void affect_spec(short which_mode,special_node_type cur_node,short cur_spec_type, + short *next_spec,short *next_spec_type,short *a,short *b,short *redraw); +void oneshot_spec(short which_mode,special_node_type cur_node,short cur_spec_type, + short *next_spec,short *next_spec_type,short *a,short *b,short *redraw); +void townmode_spec(short which_mode,special_node_type cur_node,short cur_spec_type, + short *next_spec,short *next_spec_type,short *a,short *b,short *redraw); +void rect_spec(short which_mode,special_node_type cur_node,short cur_spec_type, + short *next_spec,short *next_spec_type,short *a,short *b,short *redraw); +void outdoor_spec(short which_mode,special_node_type cur_node,short cur_spec_type, + short *next_spec,short *next_spec_type,short *a,short *b,short *redraw); diff --git a/Win32/Blades of Exile/TEXT.CPP b/Win32/Blades of Exile/TEXT.CPP new file mode 100644 index 00000000..a506acd1 --- /dev/null +++ b/Win32/Blades of Exile/TEXT.CPP @@ -0,0 +1,1537 @@ +#define LINES_IN_TEXT_WIN 11 +#define TEXT_BUF_LEN 70 + +#include "global.h" +#include "stdio.h" +#include "text.h" +#include "string.h" +#include "locutils.h" +#include "fields.h" +#include "exlsound.h" +#include "graphutl.h" + +#include "globvar.h" + +typedef struct { + char line[50]; + } buf_line; + +buf_line text_buffer[TEXT_BUF_LEN]; + +void InsetRect(RECT *rect,short x, short y); + +short text_pc_has_abil_equip(short pc_num, short abil) +{ + short i = 0; + + while (((adven[pc_num].items[i].variety == 0) || (adven[pc_num].items[i].ability != abil) + || (adven[pc_num].equip[i] == FALSE)) && (i < 24)) + i++; + return i; + +} + +// Draws the pc area in upper right +void put_pc_screen() +{ + char to_draw[256]; + + short i = 0,j; + RECT erase_rect = {2,17,270,99},to_draw_rect,from_rect; + RECT final_from_draw_rect = {0,0,271,116},final_to_draw_rect = {0,0,271,116}; + RECT small_erase_rects[3] = {{34,101,76,114},{106,101,147,114},{174,101,201,114}}; + RECT info_from = {1,0,13,12}; /**/ + + HDC hdc; + COLORREF colors[6] = {RGB(0,0,0),RGB(255,0,0),RGB(128,0,0),RGB(0,160,0),RGB(0,0,255),RGB(255,255,255)}; + HBITMAP store_bmp; + Boolean right_buttons_same = TRUE; + + for (i = 0; i < 6; i++) + if (((adven[i].main_status != MAIN_STATUS_ABSENT) && (pc_button_state[i] != 1)) || + ((adven[i].main_status == MAIN_STATUS_ABSENT) && (pc_button_state[i] != 0))) + right_buttons_same = FALSE; + + // First refresh gworld with the pc info + //rect_draw_some_item (orig_pc_info_screen_gworld, erase_rect, pc_info_screen_gworld, erase_rect, 0, 0); + // First clean up gworld with pretty patterns + // Will rewrite later + erase_rect.right -= 13; + from_rect = erase_rect; + OffsetRect(&from_rect,-1 * from_rect.left,-1 * from_rect.top); + rect_draw_some_item(status_pattern_gworld,from_rect, + pc_stats_gworld,(RECT16)erase_rect,0,0); + erase_rect.left = erase_rect.right; + erase_rect.right += 13; + from_rect = erase_rect; + OffsetRect(&from_rect,-1 * from_rect.left,-1 * from_rect.top); + rect_draw_some_item(status_pattern_gworld,(RECT16)from_rect, + pc_stats_gworld,(RECT16)erase_rect,0,0); + for (i = 0; i < 3; i++) { + from_rect = small_erase_rects[i]; + OffsetRect(&from_rect,-1 * from_rect.left + 208,-1 * from_rect.top + 136); + rect_draw_some_item(mixed_gworld,(RECT16)from_rect, + pc_stats_gworld,(RECT16)small_erase_rects[i],0,0); + } + + hdc = CreateCompatibleDC(main_dc); + SetBkMode(hdc,TRANSPARENT); + SelectObject(hdc,small_bold_font); + + store_bmp = (HBITMAP) SelectObject(hdc,pc_stats_gworld); + + // Put food, gold, day + SetTextColor(hdc,colors[5]); + sprintf((char *) to_draw, "%d", (short) party.gold); + win_draw_string(hdc,small_erase_rects[1], + to_draw,0,10); + sprintf((char *) to_draw, "%d", (short) party.food); + win_draw_string(hdc,small_erase_rects[0], + to_draw,0,10); + i = calc_day(); + sprintf((char *) to_draw, "%d", i); + win_draw_string(hdc,small_erase_rects[2], + to_draw,0,10); + SetTextColor(hdc,colors[0]); + + for (i = 0; i < 6; i++) { + if (adven[i].main_status != MAIN_STATUS_ABSENT) { + for (j = 0; j < 5; j++) + pc_area_button_active[i][j] = 1; + if (i == current_pc) { + SelectObject(hdc,italic_font); + SetTextColor(hdc,colors[4]); + } + + sprintf((char *) to_draw, "%d. %-20s ", i + 1, (char *) adven[i].name); + win_draw_string(hdc,pc_buttons[i][0], + to_draw,0,10); + SelectObject(hdc,small_bold_font); + SetTextColor(hdc,colors[0]); + + to_draw_rect = pc_buttons[i][1]; + to_draw_rect.right += 20; + switch (adven[i].main_status) { + case MAIN_STATUS_ALIVE: + if (adven[i].cur_health == adven[i].max_health) + SetTextColor(hdc,colors[3]); + else SetTextColor(hdc,colors[1]); + sprintf((char *) to_draw, "%-3d ",adven[i].cur_health); + win_draw_string(hdc,pc_buttons[i][1], + to_draw,0,10); + if (adven[i].cur_sp == adven[i].max_sp) + SetTextColor(hdc,colors[4]); + else SetTextColor(hdc,colors[2]); + sprintf((char *) to_draw, "%-3d ",adven[i].cur_sp); + win_draw_string(hdc,pc_buttons[i][2], + to_draw,0,10); + SetTextColor(hdc,colors[0]); + SelectObject(hdc,store_bmp); + draw_pc_effects(i,NULL); + SelectObject(hdc,pc_stats_gworld); + break; + case MAIN_STATUS_DEAD: + sprintf((char *) to_draw, "Dead"); + break; + case MAIN_STATUS_DUST: + sprintf((char *) to_draw, "Dust"); + break; + case MAIN_STATUS_STONE: + sprintf((char *) to_draw, "Stone"); + break; + case MAIN_STATUS_FLED: + sprintf((char *) to_draw, "Fled"); + break; + case MAIN_STATUS_SURFACE: + sprintf((char *) to_draw, "Surface"); + break; + case MAIN_STATUS_WON: + sprintf((char *) to_draw, "Won"); + break; + case MAIN_STATUS_ABSENT: + default: + sprintf((char *) to_draw, "Absent"); + break; + } + if (adven[i].isAlive() == false) + win_draw_string(hdc,to_draw_rect,to_draw,0,10); + + // Now put trade and info buttons + // do faster! + to_draw_rect = pc_buttons[i][3]; + to_draw_rect.right = pc_buttons[i][4].right + 1; + from_rect = info_from; + from_rect.right = from_rect.left + to_draw_rect.right - to_draw_rect.left; + + pc_button_state[i] = 1; + SelectObject(hdc,store_bmp); + rect_draw_some_item(mixed_gworld,(RECT16)from_rect,pc_stats_gworld,(RECT16)to_draw_rect,1,0); + SelectObject(hdc,pc_stats_gworld); + + } + else { + for (j = 0; j < 5; j++) + pc_area_button_active[i][j] = 0; + pc_button_state[i] = 0; + } + } + + // Now put text on window. + SelectObject(hdc,store_bmp); + if (!DeleteDC(hdc)) DebugQuit("Cannot release DC 5"); + + // Now put text on window. + OffsetRect(&final_to_draw_rect,PC_WIN_UL_X,PC_WIN_UL_Y); + rect_draw_some_item (pc_stats_gworld,(RECT16) final_from_draw_rect, pc_stats_gworld,(RECT16) final_to_draw_rect, 0, 1); + + // Sometimes this gets called when character is slain. when that happens, if items for + // that PC are up, switch item page. + if ((current_pc < 6) && (adven[current_pc].isAlive() == false) && (stat_window == current_pc)) { + set_stat_window(current_pc); + } +} + +// Draws item area in middle right +// Screen_num is what page is visible in the item menu. +// 0 - 5 pc inventory 6 - special item 7 - missions +// Stat_screen_mode ... 0 - normal, adventuring, all buttons vis +// 1 - in shop, item info only +// 2 - in shop, identifying, shop_identify_cost is cost +// 3 - in shop, selling weapons +// 4 - in shop, selling armor +// 5 - in shop, selling all +// 6 - in shop, augmenting weapon,shop_identify_cost is type +void put_item_screen(short screen_num,short suppress_buttons) +// if suppress_buttons > 0, save time by not redrawing buttons +{ + + char to_draw[256]; + short i_num,item_offset; + short i = 0,j,pc; + RECT erase_rect = {2,17,255,123},dest_rect,from_rect,to_rect; + RECT upper_frame_rect = {3,3,268,16}; + + RECT parts_of_area_to_draw[3] = {{0,0,271,17},{0,16,256,123},{0,123,271,144}}; /**/ + + HDC hdc; + COLORREF colors[6] = {RGB(0,0,0),RGB(255,0,0),RGB(128,0,0),RGB(0,160,0),RGB(0,0,255),RGB(255,255,255)}; + HBITMAP store_bmp; + + // First refresh gworld with the pc info + //rect_draw_some_item (orig_pc_info_screen_gworld, erase_rect, pc_info_screen_gworld, erase_rect, 0, 0); + // First clean up gworld with pretty patterns + // Will rewrite later + from_rect = erase_rect; + OffsetRect(&from_rect,-1 * from_rect.left,-1 * from_rect.top); + rect_draw_some_item(status_pattern_gworld,(RECT16)from_rect, + item_stats_gworld,(RECT16) erase_rect,0,0); + if (suppress_buttons == 0) + for (i = 0; i < 6; i++) + if ((adven[i].isAlive() == false) && (current_item_button[i] != -1)) { + current_item_button[i] = -1; + from_rect = item_screen_button_rects[i]; + OffsetRect(&from_rect,-1 * from_rect.left + 208,-1 * from_rect.top + 136); + rect_draw_some_item(mixed_gworld,(RECT16)from_rect, + item_stats_gworld,(RECT16)item_screen_button_rects[i],0,0); + } + to_rect = upper_frame_rect; + to_rect.right = to_rect.left + 96; + from_rect = to_rect; + OffsetRect(&from_rect,-1 * from_rect.left + 208,-1 * from_rect.top + 136); + rect_draw_some_item(mixed_gworld,from_rect, + item_stats_gworld,to_rect,0,0); + OffsetRect(&to_rect,96,0); + from_rect = to_rect; + OffsetRect(&from_rect,-1 * from_rect.left + 208,-1 * from_rect.top + 136); + rect_draw_some_item(mixed_gworld,from_rect, + item_stats_gworld,to_rect,0,0); + + + hdc = CreateCompatibleDC(main_dc); + SetBkMode(hdc,TRANSPARENT); + SelectObject(hdc,small_bold_font); + + store_bmp = (HBITMAP) SelectObject(hdc,item_stats_gworld); + + // Draw buttons at bottom + + item_offset = GetScrollPos(item_sbar,SB_CTL); + SetTextColor(hdc,colors[5]); + + for (i = 0; i < 8; i++) + for (j = 0; j < 6; j++) + item_area_button_active[i][j] = FALSE; + + switch (screen_num) { + case 6: // On special items page + SelectObject(hdc,bold_font); + sprintf((char *) to_draw, "Special items:"); + win_draw_string(hdc,upper_frame_rect, + to_draw,0,10); + SetTextColor(hdc,colors[0]); + for (i = 0; i < 8; i++) { + i_num = i + item_offset; + if (spec_item_array[i_num] >= 0){ + strcpy((char *) to_draw,data_store5->scen_strs[60 + spec_item_array[i_num] * 2]); + win_draw_string(hdc,item_buttons[i][0],to_draw,0,10); + + SelectObject(hdc,store_bmp); + place_item_button(3,i,4,0); + if ((scenario.special_items[spec_item_array[i_num]] % 10 == 1) + && (!(is_combat()))) + place_item_button(0,i,3,0); + SelectObject(hdc,item_stats_gworld); + } + } + break; + case 7: // On jobs page + break; + + default: // on an items page + pc = screen_num; + sprintf((char *) to_draw, "%s inventory:", + (char *) adven[pc].name); + win_draw_string(hdc,upper_frame_rect, + to_draw,0,10); + + SetTextColor(hdc,colors[0]); + for (i = 0; i < 8; i++) { + i_num = i + item_offset; + sprintf((char *) to_draw, "%d.",i_num + 1); + win_draw_string(hdc,item_buttons[i][0], + to_draw,0,10); + + dest_rect = item_buttons[i][0]; + dest_rect.left += 36; + + if (adven[pc].items[i_num].variety == 0) { + + } + else { + if (adven[pc].equip[i_num] == TRUE) { + SelectObject(hdc,italic_font); + if (adven[pc].items[i_num].variety < 3) + SetTextColor(hdc,colors[1]); + else if ((adven[pc].items[i_num].variety >= 12) && (adven[pc].items[i_num].variety <= 17)) + SetTextColor(hdc,colors[3]); + else SetTextColor(hdc,colors[4]); + } + else SetTextColor(hdc,colors[0]); + // Place object graphic here + if (adven[pc].items[i_num].isIdent() == false) + sprintf((char *) to_draw, "%s ",adven[pc].items[i_num].name); + else { /// Don't place # of charges when Sell button up and space tight + if ((adven[pc].items[i_num].charges > 0) && (adven[pc].items[i_num].type != 2) + && (stat_screen_mode <= 1)) + sprintf((char *) to_draw, "%s (%d)",adven[pc].items[i_num].full_name,adven[pc].items[i_num].charges); + else sprintf((char *) to_draw, "%s",adven[pc].items[i_num].full_name); + } + dest_rect.left -= 2; + win_draw_string(hdc,dest_rect,to_draw,0,10); + + SelectObject(hdc,small_bold_font); + SetTextColor(hdc,colors[0]); + + // this is kludgy, awkwark, and has redundant code. Done this way to + // make go faster, and I got lazy. + SelectObject(hdc,store_bmp); + if ((stat_screen_mode == 0) && + ((is_town()) || (is_out()) || ((is_combat()) && (pc == current_pc)))) { // place give and drop and use + place_item_button(0,i,0,adven[pc].items[i_num].graphic_num); // item_graphic + if (abil_chart[adven[pc].items[i_num].ability] != 4) // place use if can + place_item_button(10,i,1,0); + else place_item_button(11,i,1,0); + } + else { + place_item_button(0,i,0,adven[pc].items[i_num].graphic_num); // item_graphic + place_item_button(3,i,4,0); // info button + if ((stat_screen_mode == 0) && + ((is_town()) || (is_out()) || ((is_combat()) && (pc == current_pc)))) { // place give and drop and use + place_item_button(1,i,2,0); + place_item_button(2,i,3,0); + if (abil_chart[adven[pc].items[i_num].ability] != 4) // place use if can + place_item_button(0,i,1,0); + } + } + if (stat_screen_mode > 1) { + place_buy_button(i,pc,i_num,hdc); + + } + SelectObject(hdc,item_stats_gworld); + + } // end of if item is there + } // end of for (i = 0; i < 8; i++) + break; + } + + // Now put text on window. + SelectObject(hdc,store_bmp); + if (!DeleteDC(hdc)) DebugQuit("Cannot release DC 25"); + + place_item_bottom_buttons(); + + // Now put text on window. + for (i = 0; i < 3; i++) { + dest_rect = parts_of_area_to_draw[i]; + OffsetRect(&dest_rect,ITEM_WIN_UL_X,ITEM_WIN_UL_Y); + rect_draw_some_item (item_stats_gworld, parts_of_area_to_draw[i], + item_stats_gworld, dest_rect, 0, 1); + } +} + +void place_buy_button(short position,short pc_num,short item_num,HDC hdc) +{ + RECT dest_rect,source_rect; + RECT button_sources[3] = {{0,24,30,36},{30,24,60,36},{0,36,30,48}}; /**/ + short val_to_place; + short aug_cost[10] = {4,7,10,8, 15,15,10, 0,0,0}; + HBITMAP store_bmp; + + if (adven[pc_num].items[item_num].variety == 0) + return; + + dest_rect = item_buttons[position][5]; + + val_to_place = (adven[pc_num].items[item_num].charges > 0) ? + adven[pc_num].items[item_num].charges * adven[pc_num].items[item_num].value : + adven[pc_num].items[item_num].value; + val_to_place = val_to_place / 2; + + switch (stat_screen_mode) { + case 2: + if (adven[pc_num].items[item_num].isIdent() == false) { + item_area_button_active[position][5] = TRUE; + source_rect = button_sources[0]; + val_to_place = shop_identify_cost; + } + break; + case 3: // sell weapons + if (((adven[pc_num].items[item_num].variety < 7) || (adven[pc_num].items[item_num].variety == 23) || + (adven[pc_num].equip[item_num] == FALSE) && + (adven[pc_num].items[item_num].variety == 24)) && + (adven[pc_num].items[item_num].isIdent()) && (val_to_place > 0) && + (adven[pc_num].items[item_num].isCursed() == false)) + { + item_area_button_active[position][5] = TRUE; + source_rect = button_sources[1]; + } + break; + case 4: // sell armor + if ((adven[pc_num].items[item_num].variety >= 12) && + (adven[pc_num].items[item_num].variety <= 17) && + (adven[pc_num].equip[item_num] == FALSE) && + (adven[pc_num].items[item_num].isIdent() && (val_to_place > 0) && + (adven[pc_num].items[item_num].isCursed() == false))) { + item_area_button_active[position][5] = TRUE; + source_rect = button_sources[1]; + } + break; + case 5: // sell any + if ((val_to_place > 0) && (adven[pc_num].items[item_num].isIdent()) && + (adven[pc_num].equip[item_num] == FALSE) && + (adven[pc_num].items[item_num].isCursed() == false)) { + item_area_button_active[position][5] = TRUE; + source_rect = button_sources[1]; + } + break; + case 6: // augment weapons + if ((adven[pc_num].items[item_num].variety < 3) && + (adven[pc_num].items[item_num].isIdent()) && + (adven[pc_num].items[item_num].ability == 0) && + (adven[pc_num].items[item_num].isMagic() == false)) { + item_area_button_active[position][5] = TRUE; + source_rect = button_sources[2]; + val_to_place = max(aug_cost[shop_identify_cost] * 100,adven[pc_num].items[item_num].value * (5 + aug_cost[shop_identify_cost])); + } + break; + } + if (item_area_button_active[position][5] == TRUE) { + store_selling_values[position] = val_to_place; + dest_rect = item_buttons[position][5]; + dest_rect.right = dest_rect.left + 30; + rect_draw_some_item (mixed_gworld, source_rect, + item_stats_gworld, dest_rect, 1, 0); + sprintf((char *) store_string," %d",val_to_place); + store_bmp = (HBITMAP) SelectObject(hdc,item_stats_gworld); + char_win_draw_string(hdc,item_buttons[position][5], + store_string,2,10); + SelectObject(hdc,store_bmp); + } +} + + // name, use, give, drop, info, sell/id +// shortcuts - if which_button_to_put is 10, all 4 buttons now +// if which_button_to_put is 11, just right 2 +void place_item_button(short which_button_to_put,short which_slot,short which_button_position,short extra_val) +{ + RECT from_rect = {0,0,18,18},to_rect; + + if (which_button_position == 0) { // this means put little item graphic, extra val is which_graphic + item_area_button_active[which_slot][which_button_position] = TRUE; + OffsetRect(&from_rect,(extra_val % 10) * 18,(extra_val / 10) * 18); + to_rect = item_buttons[which_slot][0]; + to_rect.right = to_rect.left + (to_rect.bottom - to_rect.top); + InsetRect(&to_rect,-1,-1); + OffsetRect(&to_rect,20,1); + InsetRect(&from_rect,2,2); + if (extra_val >= 150) { + from_rect = get_custom_rect(extra_val - 150); + rect_draw_some_item (spec_scen_g, from_rect, + item_stats_gworld, to_rect, 1, 0); + } + else { + rect_draw_some_item (tiny_obj_gworld, from_rect, + item_stats_gworld, to_rect, 1, 0); + } + return; + } + if (which_button_to_put < 4) { // this means put a regular item button + item_area_button_active[which_slot][which_button_position] = TRUE; + rect_draw_some_item (mixed_gworld, item_buttons_from[which_button_to_put], + item_stats_gworld, item_buttons[which_slot][which_button_position], 1, 0); + } + if (which_button_to_put == 10) { // this means put all 4 + item_area_button_active[which_slot][1] = TRUE; + item_area_button_active[which_slot][2] = TRUE; + item_area_button_active[which_slot][3] = TRUE; + item_area_button_active[which_slot][4] = TRUE; + from_rect = item_buttons_from[0]; from_rect.right = item_buttons_from[3].right; + to_rect = item_buttons[which_slot][1]; + to_rect.right = to_rect.left + from_rect.right - from_rect.left; + rect_draw_some_item (mixed_gworld, from_rect, + item_stats_gworld, to_rect, 1, 0); + } + if (which_button_to_put == 11) { // this means put right 3 + item_area_button_active[which_slot][2] = TRUE; + item_area_button_active[which_slot][3] = TRUE; + item_area_button_active[which_slot][4] = TRUE; + from_rect = item_buttons_from[1]; from_rect.right = item_buttons_from[3].right; + to_rect = item_buttons[which_slot][2]; + to_rect.right = to_rect.left + from_rect.right - from_rect.left; + rect_draw_some_item (mixed_gworld, from_rect, + item_stats_gworld, to_rect, 1, 0); + } +} + +RECT get_custom_rect (short which_rect) //// +{ + RECT store_rect = {0,0,28,36}; + + OffsetRect(&store_rect,28 * (which_rect % 10),36 * (which_rect / 10)); + return store_rect; +} + +void place_item_bottom_buttons() +{ + RECT pc_from_rect = {0,0,28,36},but_from_rect = {36,85,54,101},to_rect; /**/ + short i; + + for (i = 0; i < 6; i++) { + if (adven[i].isAlive()) { + item_bottom_button_active[i] = TRUE; + to_rect = item_screen_button_rects[i]; + //if (current_item_button[i] != adven[i].which_graphic) { + current_item_button[i] = adven[i].which_graphic; + rect_draw_some_item (mixed_gworld, but_from_rect, item_stats_gworld, to_rect, 0, 0); + pc_from_rect = get_party_template_rect(i,0); + InsetRect(&to_rect,2,2); + rect_draw_some_item (party_template_gworld, pc_from_rect, item_stats_gworld, to_rect, 0, 0); + // } + + } + else item_bottom_button_active[i] = FALSE; + } +} + +RECT get_party_template_rect(short pc_num,short mode) +{ + RECT source_rect; + + source_rect.top = (pc_num % 3) * BITMAP_HEIGHT; + source_rect.bottom = 36 + (pc_num % 3) * BITMAP_HEIGHT; + source_rect.left = (pc_num / 3) * BITMAP_WIDTH * 2 + ((mode == 1) ? 28 : 0); + source_rect.right = source_rect.left + BITMAP_WIDTH; + + return source_rect; +} + + +void set_stat_window(short new_stat) +{ + short i,array_pos = 0; + + stat_window = new_stat; + if ((stat_window < 6) && (adven[stat_window].isAlive() == false)) + stat_window = first_active_pc(); + switch (stat_window) { + case 6: + for (i = 0; i < 60; i++) + spec_item_array[i] = -1; + for (i = 0; i < 50; i++) //// + if (party.spec_items[i] > 0) { + spec_item_array[array_pos] = i; + array_pos++; + } + array_pos = max(0,array_pos - 8); + SetScrollRange(item_sbar,SB_CTL,0,array_pos,FALSE); + break; + case 7: + SetScrollRange(item_sbar,SB_CTL,0,2,FALSE); + break; + default: + SetScrollRange(item_sbar,SB_CTL,0,16,FALSE); + break; + } + SetScrollPos(item_sbar,SB_CTL,0,TRUE); + put_item_screen(stat_window,0); + +} + +short first_active_pc() +{ + for (int i = 0; i < NUM_OF_PCS; i++) + if (adven[i].isAlive()) + return i; + + return INVALID_PC; +} + + +void refresh_stat_areas(short mode) +{ + short i,x; + RECT dest_rect,parts_of_area_to_draw[3] = {{0,0,271,17},{0,16,256,123},{0,123,271,144}};/**/ + RECT pc_stats_from = {0,0,271,116},text_area_from = {0,0,256,138}; + + x = mode * 10; + dest_rect = pc_stats_from; + OffsetRect(&dest_rect,PC_WIN_UL_X,PC_WIN_UL_Y); + rect_draw_some_item (pc_stats_gworld, pc_stats_from, pc_stats_gworld, dest_rect, x, 1); + for (i = 0; i < 3; i++) { + dest_rect = parts_of_area_to_draw[i]; + OffsetRect(&dest_rect,ITEM_WIN_UL_X,ITEM_WIN_UL_Y); + rect_draw_some_item (item_stats_gworld, parts_of_area_to_draw[i], + item_stats_gworld, dest_rect, x, 1); + } + dest_rect = text_area_from; + OffsetRect(&dest_rect,TEXT_WIN_UL_X,TEXT_WIN_UL_Y); + rect_draw_some_item (text_area_gworld, text_area_from, text_area_gworld, dest_rect, x, 1); + +} + + +short total_encumberance(short pc_num) +{ + short store = 0,i,what_val; + + for (i = 0; i < 24; i++) + if (adven[pc_num].equip[i] == TRUE) { + what_val = adven[pc_num].items[i].awkward; + store += what_val; + } + return store; +} + +short get_tnl(pc_record_type *pc) +{ + short tnl = 100,i,store_per = 100; + short rp[3] = {0,12,20}; + short ap[15] = {10,20,8,10,4, 6,10,7,12,15, -10,-8,-8,-20,-8}; + + tnl = (tnl * (100 + rp[pc->race])) / 100; + for (i = 0; i < 15; i++) + if (pc->traits[i] == TRUE) + store_per = store_per + ap[i]; + + tnl = (tnl * store_per) / 100; + + return tnl; +} + + + +void draw_pc_effects(short pc,HDC dest_dc) +//short pc; // 10 + x -> draw for pc x, but on spell dialog +{ + RECT source_rects[18] = {{55,0,67,12},{55,12,67,24},{55,24,67,36}, + {67,0,79,12},{67,12,79,24},{67,24,79,36}, + {79,0,91,12},{79,12,91,24},{79,24,91,36}, + {91,0,103,12},{91,12,103,24},{91,24,103,36}, + {103,0,115,12},{103,12,115,24},{103,24,115,36}, + {115,0,127,12},{115,12,127,24},{115,24,127,36}}; + RECT dest_rect = {18,15,30,27},dlog_dest_rect = {66,354,78,366};//rects altered below + + short right_limit = 250; + short dest = 0; // 0 - in gworld 2 - on dialog + short name_width,i,mode = 1; + HBITMAP dest_bmp; + + for (i = 0; i < 18; i++) + alter_rect(&source_rects[i]); + alter_rect(&dest_rect); + alter_rect(&dlog_dest_rect); + + if (pc >= 10) { + pc -= 10; + right_limit = 490; + dest_rect = dlog_dest_rect; + dest = 2; + mode = 0; + dest_rect.top += pc * 24 + 18; + dest_rect.bottom += pc * 24 + 18; + dest_bmp = (HBITMAP) dest_dc; + } + else { + name_width = string_length(adven[pc].name,main_dc); + right_limit = pc_buttons[0][1].left - 5; + //dest_rect.left = pc_buttons[i][1].left - 16; + dest_rect.left = name_width + 33; + dest_rect.right = dest_rect.left + 12; + dest_rect.top += pc * 13; + dest_rect.bottom += pc * 13; + dest_bmp = pc_stats_gworld; + } + + if (adven[pc].main_status % MAIN_STATUS_SPLIT != 1) // if PC is alive + return; + + if ((adven[pc].status[0] > 0) && (dest_rect.right < right_limit)) { + rect_draw_some_item (mixed_gworld,source_rects[4],dest_bmp,dest_rect,mode,dest); + dest_rect.left += 13; + dest_rect.right += 13; + } + if (adven[pc].status[1] > 0) { + rect_draw_some_item (mixed_gworld,source_rects[2],dest_bmp,dest_rect,mode,dest); + dest_rect.left += 13; + dest_rect.right += 13; + } + if (adven[pc].status[1] < 0) { + rect_draw_some_item (mixed_gworld,source_rects[3],dest_bmp,dest_rect,mode,dest); + dest_rect.left += 13; + dest_rect.right += 13; + } + if (adven[pc].status[2] > 0) { + rect_draw_some_item (mixed_gworld,source_rects[(adven[pc].status[2] > 4) ? 1 : 0],dest_bmp,dest_rect,mode,dest); + dest_rect.left += 13; + dest_rect.right += 13; + } + if (adven[pc].status[4] > 0) { + rect_draw_some_item (mixed_gworld,source_rects[5],dest_bmp,dest_rect,mode,dest); + dest_rect.left += 13; + dest_rect.right += 13; + } + if (adven[pc].status[3] > 0) { + rect_draw_some_item (mixed_gworld,source_rects[6],dest_bmp,dest_rect,mode,dest); + dest_rect.left += 13; + dest_rect.right += 13; + } + if (adven[pc].status[3] < 0) { + rect_draw_some_item (mixed_gworld,source_rects[8],dest_bmp,dest_rect,mode,dest); + dest_rect.left += 13; + dest_rect.right += 13; + } + if ((adven[pc].status[5] > 0) && (dest_rect.right < right_limit)) { + rect_draw_some_item (mixed_gworld,source_rects[9],dest_bmp,dest_rect,mode,dest); + dest_rect.left += 13; + dest_rect.right += 13; + } + if ((adven[pc].status[6] > 0) && (dest_rect.right < right_limit)) { + rect_draw_some_item (mixed_gworld,source_rects[10],dest_bmp,dest_rect,mode,dest); + dest_rect.left += 13; + dest_rect.right += 13; + } + if ((adven[pc].status[7] > 0) && (dest_rect.right < right_limit)){ + rect_draw_some_item (mixed_gworld,source_rects[11],dest_bmp,dest_rect,mode,dest); + dest_rect.left += 13; + dest_rect.right += 13; + } + if ((adven[pc].status[8] > 0) && (dest_rect.right < right_limit)){ + rect_draw_some_item (mixed_gworld,source_rects[12],dest_bmp,dest_rect,mode,dest); + dest_rect.left += 13; + dest_rect.right += 13; + } + if ((adven[pc].status[9] > 0) && (dest_rect.right < right_limit)){ + rect_draw_some_item (mixed_gworld,source_rects[13],dest_bmp,dest_rect,mode,dest); + dest_rect.left += 13; + dest_rect.right += 13; + } + if ((adven[pc].status[10] > 0) && (dest_rect.right < right_limit)){ + rect_draw_some_item (mixed_gworld,source_rects[14],dest_bmp,dest_rect,mode,dest); + dest_rect.left += 13; + dest_rect.right += 13; + } + if ((adven[pc].status[11] > 0) && (dest_rect.right < right_limit)){ + rect_draw_some_item (mixed_gworld,source_rects[15],dest_bmp,dest_rect,mode,dest); + dest_rect.left += 13; + dest_rect.right += 13; + } + if ((adven[pc].status[12] > 0) && (dest_rect.right < right_limit)){ + rect_draw_some_item (mixed_gworld,source_rects[16],dest_bmp,dest_rect,mode,dest); + dest_rect.left += 13; + dest_rect.right += 13; + } + if ((adven[pc].status[13] > 0) && (dest_rect.right < right_limit)){ + rect_draw_some_item (mixed_gworld,source_rects[17],dest_bmp,dest_rect,mode,dest); + dest_rect.left += 13; + dest_rect.right += 13; + } +} + + +void print_party_stats() { + add_string_to_buf("PARTY STATS:"); + sprintf((char *) store_string, " Number of kills: %ld ", party.total_m_killed); + add_string_to_buf((char *) store_string); + if ((is_town()) || ((is_combat()) && (which_combat_type == 1))) { + sprintf((char *) store_string, " Kills in this town: %d ", party.m_killed[c_town.town_num]); + add_string_to_buf((char *) store_string); + } + sprintf((char *) store_string, " Total experience: %ld ", party.total_xp_gained); + add_string_to_buf((char *) store_string); + sprintf((char *) store_string, " Total damage done: %ld ", party.total_dam_done); + add_string_to_buf((char *) store_string); + sprintf((char *) store_string, " Total damage taken: %ld ", party.total_dam_taken); + add_string_to_buf((char *) store_string); + print_buf(); +} + +short do_look(location space) +{ + short i,j,num_items = 0; + Boolean gold_here = FALSE, food_here = FALSE, is_lit = TRUE; + location from_where; + + from_where = get_cur_loc(); + is_lit = pt_in_light(from_where,space); + + if (((is_out()) && (same_point(space,party.p_loc) == TRUE)) || + ((is_town()) && (same_point(space,c_town.p_loc)))) + add_string_to_buf(" Your party"); + if (is_combat()) + for (i = 0; i < 6; i++) + if ((same_point(space,pc_pos[i]) == TRUE) && (adven[i].isAlive()) + && (is_lit == TRUE) && (can_see(pc_pos[current_pc],space,0) < 5)) { + sprintf((char *) store_string, " %s", (char *) adven[i].name); + add_string_to_buf((char *) store_string); + } + + if (is_out() == FALSE) { + for (i = 0; i < T_M; i++) + if ((c_town.monst.dudes[i].active != 0) && (is_lit == TRUE) + && (monst_on_space(space,i) == TRUE) && + ((is_town()) || (can_see(pc_pos[current_pc],space,0) < 5)) + && (c_town.monst.dudes[i].m_d.picture_num != 0)) { + + + get_m_name(store_string2,c_town.monst.dudes[i].number); + if (c_town.monst.dudes[i].m_d.health < c_town.monst.dudes[i].m_d.m_health) { + if (c_town.monst.dudes[i].attitude % 2 == 1) + sprintf((char *) store_string, " Wounded %s (H)", store_string2); + else sprintf((char *) store_string, " Wounded %s (F)", store_string2); + } + else { + if (c_town.monst.dudes[i].attitude % 2 == 1) + sprintf((char *) store_string, " %s (H)", (char *) store_string2); + else sprintf((char *) store_string, " %s (F)", (char *) store_string2); + } + + add_string_to_buf((char *) store_string); + + } + } + if (is_out()) { + for (i = 0; i < 10; i++) { + if ((party.out_c[i].exists == TRUE) + && (same_point(space,party.out_c[i].m_loc) == TRUE)) { + for (j = 0; j < 7; j++) + if (party.out_c[i].what_monst.monst[j] != 0) { + get_m_name(store_string2,party.out_c[i].what_monst.monst[j]); + sprintf((char *) store_string, " %s", store_string2); + add_string_to_buf((char *) store_string); + j = 7; + + } + + } + } + + if (out_boat_there(space) < 30) + add_string_to_buf(" Boat "); + if (out_horse_there(space) < 30) + add_string_to_buf(" Horse "); + } + + if (is_out() == FALSE) { + if (town_boat_there(space) < 30) + add_string_to_buf(" Boat "); + if (town_horse_there(space) < 30) + add_string_to_buf(" Horse "); + + if (is_web(space.x,space.y)) + add_string_to_buf(" Web "); + if (is_crate(space.x,space.y)) + add_string_to_buf(" Crate "); + if (is_barrel(space.x,space.y)) + add_string_to_buf(" Barrel "); + if (is_fire_barrier(space.x,space.y)) + add_string_to_buf(" Magic Barrier "); + if (is_force_barrier(space.x,space.y)) + add_string_to_buf(" Magic Barrier "); + if (is_quickfire(space.x,space.y)) + add_string_to_buf(" Quickfire "); + if (is_fire_wall(space.x,space.y)) + add_string_to_buf(" Wall of Fire "); + if (is_force_wall(space.x,space.y)) + add_string_to_buf(" Wall of Force "); + if (is_antimagic(space.x,space.y)) + add_string_to_buf(" Antimagic Field "); + if (is_scloud(space.x,space.y)) + add_string_to_buf(" Stinking Cloud "); + if (is_ice_wall(space.x,space.y)) + add_string_to_buf(" Ice Wall "); + if (is_blade_wall(space.x,space.y)) + add_string_to_buf(" Blade Wall "); + + if (is_small_blood(space.x,space.y)) + add_string_to_buf(" Blood stain "); + if (is_medium_blood(space.x,space.y)) + add_string_to_buf(" Blood stain "); + if (is_large_blood(space.x,space.y)) + add_string_to_buf(" Blood stain "); + if (is_small_slime(space.x,space.y)) + add_string_to_buf(" Smears of slime "); + if (is_big_slime(space.x,space.y)) + add_string_to_buf(" Smears of slime "); + if (is_ash(space.x,space.y)) + add_string_to_buf(" Ashes "); + if (is_bones(space.x,space.y)) + add_string_to_buf(" Bones "); + if (is_rubble(space.x,space.y)) + add_string_to_buf(" Rubble "); + + for (i = 0; i < NUM_TOWN_ITEMS; i++) { + if ((t_i.items[i].variety != 0) && (same_point(space,t_i.items[i].item_loc) == TRUE) + && (is_lit == TRUE)) { + if (t_i.items[i].variety == 3) + gold_here = TRUE; + else if (t_i.items[i].variety == 11) + food_here = TRUE; + else num_items++; + } + } + if (gold_here == TRUE) + add_string_to_buf(" Gold"); + if (food_here == TRUE) + add_string_to_buf(" Food"); + if (num_items > 8) + add_string_to_buf(" Many items"); + else for (i = 0; i < NUM_TOWN_ITEMS; i++) { + if ((t_i.items[i].variety != 0) && (t_i.items[i].variety != 3) &&(t_i.items[i].variety != 11) && + (same_point(space,t_i.items[i].item_loc) == TRUE) && (t_i.items[i].isContained() == false)) + { + if (t_i.items[i].isIdent()) + sprintf((char *) store_string, " %s",t_i.items[i].full_name); + else sprintf((char *) store_string, " %s",t_i.items[i].name); + add_string_to_buf((char *) store_string); + } + } + } + + if (is_lit == FALSE) { + add_string_to_buf(" Dark "); + return 0; + } + + return print_terrain(space); +} + +short town_boat_there(location where) +{ + short i; + + // Num boats stores highest # of boat in town + for (i = 0; i < 30; i++) + if ((party.boats[i].exists == TRUE) && (party.boats[i].which_town == c_town.town_num) + && (same_point(where,party.boats[i].boat_loc) == TRUE)) + return i; + return 30; +} +short out_boat_there(location where) +{ + short i; + + for (i = 0; i < 30; i++) + if ((party.boats[i].exists == TRUE) && (same_point(where,party.boats[i].boat_loc) == TRUE) + && (party.boats[i].which_town == 200)) + return i; + return 30; +} + +short town_horse_there(location where) +{ + short i; + + // Num boats stores highest # of boat in town + for (i = 0; i < 30; i++) + if ((party.horses[i].exists == TRUE) && (party.horses[i].which_town == c_town.town_num) + && (same_point(where,party.horses[i].horse_loc) == TRUE)) + return i; + return 30; +} +short out_horse_there(location where) +{ + short i; + + for (i = 0; i < 30; i++) + if ((party.horses[i].exists == TRUE) && (same_point(where,party.horses[i].horse_loc) == TRUE) + && (party.horses[i].which_town == 200)) + return i; + return 30; +} +void notify_out_combat_began(out_wandering_type encounter,short *nums) +{ + short i; + + sprintf((char *) store_string, "COMBAT! "); + add_string_to_buf((char *) store_string); + + for (i = 0; i < 6; i++) + if (encounter.monst[i] != 0) { + switch (encounter.monst[i]) { + //// + + default: + get_m_name(store_string2,encounter.monst[i]); + sprintf((char *) store_string, " %d x %s ",nums[i],store_string2); + break; + } + add_string_to_buf((char *) store_string); + } + if (encounter.monst[6] != 0) { + get_m_name(store_string2,encounter.monst[6]); + sprintf((char *) store_string, " %s ",store_string2); + add_string_to_buf((char *) store_string); + } +} + +void get_m_name(char *str,unsigned char num) +{ + strcpy((char *) str,(char *) data_store2->scen_item_list.monst_names[num]); +} +void get_ter_name(char *str,unsigned char num) +{ + char store_name[256]; + + //// + if ((num == 90) && ((is_out()) || (is_town()) || ((is_combat()) && (which_combat_type == 1)))) + sprintf((char *) store_name,"Pit"); + else { + strcpy((char *) store_name,(char *) data_store2->scen_item_list.ter_names[num]); + } + strcpy((char *) str,(char *) store_name); +} + +void print_monst_name(unsigned char m_type) +{ + get_m_name(store_string2,m_type); + sprintf ((char *) store_string, "%s:",store_string2); + add_string_to_buf((char *) store_string); +} + +void print_monst_attacks(unsigned char m_type,short target) +//short target; // < 100 - pc >= 100 monst +{ + char store_string3[60]; + + get_m_name(store_string2,m_type); + if (target < 100) + sprintf ((char *) store_string, "%s attacks %s", + store_string2,(char *) adven[target].name); + else { + get_m_name(store_string3,c_town.monst.dudes[target - 100].number); + sprintf ((char *) store_string, "%s attacks %s", + store_string2,store_string3); + } + add_string_to_buf((char *) store_string); +} + +void damaged_message(short damage,short type) +{ + char str[256]; + + GetIndString(str,20,130 + type); + sprintf ((char *) store_string, " %s for %d", + (char *) str,damage); + add_string_to_buf((char *) store_string); +} + +// This prepares the monster's string for the text bar +void print_monster_going(char *combat_str,unsigned char m_num,short ap) +{ + get_m_name(store_string2,m_num); + sprintf ((char *) combat_str, "%s (ap: %d)", + store_string2,ap); +} + +void monst_spell_note(unsigned char number,short which_mess) +{ + get_m_name(store_string2,number); + switch (which_mess) { + case 1: sprintf ((char *) store_string, " %s scared. ",store_string2);break; + case 2: sprintf ((char *) store_string, " %s slowed. ",store_string2);break; + case 3: sprintf ((char *) store_string, " %s weakened.",store_string2);break; + case 4: sprintf ((char *) store_string, " %s poisoned.",store_string2);break; + case 5: sprintf ((char *) store_string, " %s cursed.",store_string2);break; + case 6: sprintf ((char *) store_string, " %s ravaged.",store_string2);break; + case 7: sprintf ((char *) store_string, " %s undamaged.",store_string2);break; + case 8: sprintf ((char *) store_string, " %s is stoned.",store_string2);break; + case 9: sprintf ((char *) store_string, " Gazes at %s.",store_string2);break; + case 10: sprintf ((char *) store_string, " %s resists.",store_string2);break; + case 11: sprintf ((char *) store_string, " Drains %s.",store_string2);break; + case 12: sprintf ((char *) store_string, " Shoots at %s.",store_string2);break; + case 13: sprintf ((char *) store_string, " Throws spear at %s.", store_string2); break; + case 14: sprintf ((char *) store_string, " Throws rock at %s.", store_string2); break; + case 15: sprintf ((char *) store_string, " Throws razordisk at %s.", store_string2); break; + case 16: sprintf ((char *) store_string, " Hits %s.", store_string2); break; + case 17: sprintf ((char *) store_string, "%s disappears.", store_string2);break; + case 18: sprintf ((char *) store_string, " Misses %s.", store_string2); break; + case 19: sprintf ((char *) store_string, " %s is webbed.",store_string2);break; + case 20: sprintf ((char *) store_string, " %s chokes.",store_string2);break; + case 21: sprintf ((char *) store_string, " %s summoned.",store_string2);break; + case 22: sprintf ((char *) store_string, " %s is dumbfounded.",store_string2);break; + case 23: sprintf ((char *) store_string, " %s is charmed.",store_string2);break; + case 24: sprintf ((char *) store_string, " %s is recorded.",store_string2);break; + case 25: sprintf ((char *) store_string, " %s is diseased.",store_string2);break; + case 26: sprintf ((char *) store_string, " %s is an avatar!",store_string2);break; + case 27: sprintf ((char *) store_string, " %s splits!",store_string2);break; + case 28: sprintf ((char *) store_string, " %s falls asleep.",store_string2);break; + case 29: sprintf ((char *) store_string, " %s wakes up.",store_string2);break; + case 30: sprintf ((char *) store_string, " %s paralyzed.",store_string2);break; + case 31: sprintf ((char *) store_string, " %s covered with acid.",store_string2);break; + case 32: sprintf ((char *) store_string, " Fires spines at %s.",store_string2);break; + } + + if (which_mess > 0) + add_string_to_buf((char *) store_string); +} + +void monst_cast_spell_note(unsigned char number,short spell,short type) +//short type; // 0 - mage 1- priest +{ + get_m_name(store_string2,number); + sprintf ((char *) store_string, "%s casts:", + (char *) store_string2); + add_string_to_buf((char *) store_string); + sprintf ((char *) store_string, " %s", + (type == 1) ? (char *) m_priest_sp[spell - 1] : (char *) m_mage_sp[spell - 1]); + add_string_to_buf((char *) store_string); +} + +void monst_breathe_note(unsigned char number) +{ + get_m_name(store_string2,number); + sprintf ((char *) store_string, "%s breathes.", + (char *) store_string2); + add_string_to_buf((char *) store_string); +} + +void monst_damaged_mes(short which_m,short how_much,short how_much_spec) +{ + get_m_name(store_string2,c_town.monst.dudes[which_m].number); + if (how_much_spec > 0) + sprintf ((char *) store_string, " %s takes %d+%d", + store_string2, how_much,how_much_spec); + else sprintf ((char *) store_string, " %s takes %d", + store_string2, how_much); + + add_string_to_buf((char *) store_string); +} + +void monst_killed_mes(short which_m) +{ + get_m_name(store_string2,c_town.monst.dudes[which_m].number); + sprintf ((char *) store_string, " %s dies.", + (char *) store_string2); + add_string_to_buf((char *) store_string); +} + +void print_nums(short a,short b,short c) +{ + sprintf((char *) store_string, "debug: %d %d %d", a,b,c); + add_string_to_buf((char *) store_string); +} + +short print_terrain(location space) +{ + unsigned char which_terrain; + + if (is_out()) which_terrain = out[space.x][space.y]; + if (is_town()) which_terrain = t_d.terrain[space.x][space.y]; + if (is_combat()) which_terrain = combat_terrain[space.x][space.y]; + get_ter_name(store_string2,which_terrain); + sprintf((char *) store_string, " %s", store_string2); + add_string_to_buf((char *) store_string); + + return (short) which_terrain; +} + + +void add_string_to_buf(char *string) +{ + SetScrollPos(text_sbar,SB_CTL,58,TRUE); + string_added = TRUE; + if (buf_pointer == mark_where_printing_long) { + printing_long = TRUE; + print_buf(); + through_sending(); + } + sprintf((char *)text_buffer[buf_pointer].line, "%-49.49s", string); + text_buffer[buf_pointer].line[49] = 0; + if (buf_pointer == (TEXT_BUF_LEN - 1)) + buf_pointer = 0; + else buf_pointer++; +} + +void print_buf () +{ + short num_lines_printed = 0,ctrl_val; + short line_to_print; + short start_print_point; + Boolean end_loop = FALSE; + RECT store_text_rect = {0,0,256,138},dest_rect,erase_rect = {1,1,255,137}; /**/ + RECT from_rect,to_rect; + HDC hdc; + HBITMAP store_bmp; + + if (string_added == TRUE) { + // First clean up gworld with pretty patterns + //FillCRECT(&erase_rect,bg[6]); + InsetRect(&erase_rect,1,1); //// + erase_rect.right++; + to_rect = erase_rect; + to_rect.bottom = to_rect.top + 128; + from_rect = to_rect; + OffsetRect(&from_rect,-1 * from_rect.left,-1 * from_rect.top); + rect_draw_some_item(status_pattern_gworld,from_rect, + text_area_gworld,to_rect,0,0); + to_rect = erase_rect; + to_rect.top = to_rect.bottom - 8; + from_rect = to_rect; + OffsetRect(&from_rect,-1 * from_rect.left,-1 * from_rect.top); + rect_draw_some_item(status_pattern_gworld,from_rect, + text_area_gworld,to_rect,0,0); + + + hdc = CreateCompatibleDC(main_dc); + //store_text_hdc = hdc; + SetBkMode(hdc,TRANSPARENT); + SelectObject(hdc,small_bold_font); + + store_bmp = (HBITMAP)SelectObject(hdc,text_area_gworld); + + ctrl_val = 58 - GetScrollPos(text_sbar,SB_CTL); + start_print_point = buf_pointer - LINES_IN_TEXT_WIN - ctrl_val; + if (start_print_point< 0) + start_print_point= TEXT_BUF_LEN + start_print_point; + line_to_print= start_print_point; + + while ((line_to_print!= buf_pointer) && (num_lines_printed < LINES_IN_TEXT_WIN)) { + DrawString((char *) text_buffer[line_to_print].line,4, + 2 + 12 * num_lines_printed,hdc); + num_lines_printed++; + line_to_print++; + if (line_to_print== TEXT_BUF_LEN) { + line_to_print= 0; + } + + if ((num_lines_printed == LINES_IN_TEXT_WIN - 1) && (printing_long == TRUE)) { + end_loop = FALSE; + line_to_print= buf_pointer; + } + + } + + + // Now put text on window. + SelectObject(hdc,store_bmp); + if (!DeleteDC(hdc)) DebugQuit("Cannot release DC 26"); + } + + dest_rect = store_text_rect; + + OffsetRect(&dest_rect,TEXT_WIN_UL_X,TEXT_WIN_UL_Y); + // Now put text on window. + rect_draw_some_item (text_area_gworld, store_text_rect, text_area_gworld, dest_rect, 0, 1); + string_added = FALSE; +} + +void through_sending() +{ + mark_where_printing_long = buf_pointer + LINES_IN_TEXT_WIN - 1; + if (mark_where_printing_long > TEXT_BUF_LEN - 1) + mark_where_printing_long -= TEXT_BUF_LEN; + printing_long = FALSE; +} + +/* Draw a bitmap in the world window. hor in 0 .. 8, vert in 0 .. 8, + object is ptr. to bitmap to be drawn, and masking is for Copybits. */ +void Draw_Some_Item (HBITMAP src_gworld, RECT src_rect, HBITMAP targ_gworld, +location target, char masked, short main_win) +{ + RECT destrec = {0,0,28,36}; + + if ((target.x < 0) || (target.y < 0) || (target.x > 8) || (target.y > 8)) + return; + if (src_gworld == NULL) + return; + if ((supressing_some_spaces == TRUE) && + (same_point(target,ok_space[0]) == FALSE) && + (same_point(target,ok_space[1]) == FALSE) && + (same_point(target,ok_space[2]) == FALSE) && + (same_point(target,ok_space[3]) == FALSE)) + return; + terrain_there[target.x][target.y] = -1; + + destrec = coord_to_rect(target.x,target.y); + rect_draw_some_item ( src_gworld, src_rect, targ_gworld, + destrec, masked, main_win); + +} + +RECT coord_to_rect(short i, short j) +{ + RECT to_return; + + to_return.left = 13 + BITMAP_WIDTH * i; + to_return.right = to_return.left + BITMAP_WIDTH; + to_return.top = 13 + BITMAP_HEIGHT * j; + to_return.bottom = to_return.top + BITMAP_HEIGHT; + + return to_return; +} + +short string_length(char *str,HDC hdc) +{ + short text_len[257]; + short total_width = 0,i,len; + char p_str[256]; + + for (i = 0; i < 257; i++) + text_len[i]= 0; + + strcpy((char *) p_str,str); + MeasureText(256,p_str,text_len,hdc); + len = strlen((char *)str); + + for (i = 0; i < 257; i++) + if ((text_len[i] > total_width) && (i <= len)) + total_width = text_len[i]; + return total_width; +} + + +void char_win_draw_string(HDC dest_window,RECT dest_rect,char *str,short mode,short line_height) +{ + char store_s[256]; + + strcpy((char *) store_s,str); + win_draw_string( dest_window, dest_rect,store_s, mode, line_height); +} + +// mode: 0 - align up and left, 1 - center on one line +// str is a c string, 256 characters +// uses current font +void win_draw_string(HDC dest_hdc,RECT dest_rect,char *str,short mode, short) +{ + short i; + + // this will need formatting for '|' line breaks + for (i = 0; i < 256; i++) + { + if (str[i] == 0) i = 256; + else + { + if (str[i] == '|') str[i] = 13; + if (str[i] == '_') str[i] = 34; + } + } + + // if dest is main window, add ulx, uly + if (dest_hdc == main_dc) OffsetRect(&dest_rect,ulx,uly); + + switch (mode) + { + case 0: + dest_rect.bottom += 6; + DrawText(dest_hdc,str,strlen((char *)str),&dest_rect,DT_LEFT | DT_NOPREFIX | DT_WORDBREAK); break; + case 1: + dest_rect.bottom += 6; dest_rect.top -= 6; + DrawText(dest_hdc,str,strlen((char *)str),&dest_rect, + DT_CENTER | DT_NOPREFIX | DT_VCENTER | DT_NOCLIP | DT_SINGLELINE); break; + case 2: case 3: + dest_rect.bottom += 6; dest_rect.top -= 6; + DrawText(dest_hdc,str,strlen((char *)str),&dest_rect, + DT_LEFT | DT_NOPREFIX | DT_VCENTER | DT_NOCLIP | DT_SINGLELINE); break; + } + // not yet done adjusts for 1, 2, 3 +} + +short calc_day() +{ + return (short) ((party.age) / 3700) + 1; +} + +Boolean day_reached(unsigned char which_day, unsigned char which_event) +// which_day is day event should happen +// which_event is the party.key_times value to cross reference with. +// if the key_time is reached before which_day, event won't happen +// if it's 8, event always happens +// which_day gets an extra 20 days to give party bonus time +{ + short what_day; + if(party.stuff_done[309][0]==1) + what_day = (short) (which_day) + 20; + else + what_day = (short) (which_day); + + if (which_event > 10) + return FALSE; + if ((which_event > 0) && (party.key_times[which_event] < what_day)) + return FALSE; + if (calc_day() >= what_day) + return TRUE; + else return FALSE; + +} + +// BEGIN EXTRA WINDOWS STUFF + +void WinDrawString(char *string,short x,short y) +{ + HDC hdc; + + hdc = GetDC(mainPtr); + SetViewportOrgEx(hdc,ulx,uly, NULL); + SelectObject(hdc,small_bold_font); + SetBkMode(hdc,TRANSPARENT); + SetTextColor(hdc,RGB(255,255,255)); + DrawString(string,x,y,hdc); + fry_dc(mainPtr,hdc); +} + +void WinBlackDrawString(char *string,short x,short y) +{ + HDC hdc; + + hdc = GetDC(mainPtr); + SetViewportOrgEx(hdc,ulx,uly, NULL); + SelectObject(hdc,small_bold_font); + SetBkMode(hdc,TRANSPARENT); + DrawString(string,x,y,hdc); + fry_dc(mainPtr,hdc); +} + + +void DrawString(char *string,short x,short y,HDC hdc) +{ + RECT text_r = {0,0,450,20}; + + OffsetRect(&text_r,x,y); + DrawText(hdc,string,-1,&text_r,DT_LEFT | DT_SINGLELINE | DT_TOP | DT_NOCLIP); +} + +void FlushEvents(short mode) +// mode... 0 - keystrokes 1 - mouse presses 2 - both +{ + MSG msg; + + if ((mode == 0) || (mode == 2)) { + while ((PeekMessage(&msg, mainPtr, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE)) != 0) + ; + } + if ((mode == 1) || (mode == 2)) { + while ((PeekMessage(&msg, mainPtr, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE)) != 0) + ; + } + +} + +void undo_clip() +{ + HRGN rgn; + + rgn = CreateRectRgn(0,0,5000,5000); + SelectClipRgn(main_dc,rgn); + DeleteObject(rgn); +} + +void ClipRect(RECT *rect) +{ + HRGN rgn; + + RECT rect2 = *rect; + OffsetRect(&rect2,ulx,uly); + + rgn = CreateRectRgn(rect2.left,rect2.top,rect2.right,rect2.bottom); + SelectClipRgn(main_dc,rgn); + DeleteObject(rgn); +} + +void beep() +{ + long dummy; + + MessageBeep(MB_OK); + Delay(30,&dummy); +} + +void GetIndString(char *str,short i, short j) { + UINT resnum = 0,len; + short k; + + resnum = i * 300 + j; + + len = LoadString(store_hInstance,resnum,str,256); + if (len == 0) { + sprintf(str,""); + return; + } + for (k = 0; k < 256; k++) { + if (str[k] == '|') + str[k] = 13; + if (str[k] == '_') + str[k] = 34; + } +} + +void InsetRect(RECT *rect,short x, short y) +{ + InflateRect(rect,-1 * x, -1 * y); +} + +// Note ... this expects a str len of at most 256 and +// len_array pointing to a 256 long array of shorts +void MeasureText(short str_len,char *str, short *len_array,HDC hdc) +{ + short text_len[257]; + short i; + char p_str[257]; + SIZE val_returned; + char *store_array; + short *store2; + + store_array = (char *) len_array; + for (i = 0; i < 256; i++) + text_len[i] = 0; + for (i = 1; i < str_len; i++) { + strncpy(p_str,str,i); + p_str[i] = 0; + GetTextExtentPoint32(hdc,p_str,i, (LPSIZE) &val_returned); + text_len[i] = val_returned.cx; + } + for (i = 0; i < 256; i++) { + store2 = (short *) store_array; + *store2 = text_len[i]; + store_array += 2; + } + } diff --git a/Win32/Blades of Exile/TEXT.H b/Win32/Blades of Exile/TEXT.H new file mode 100644 index 00000000..1ceea15c --- /dev/null +++ b/Win32/Blades of Exile/TEXT.H @@ -0,0 +1,68 @@ +#ifndef _TEXT_H + #define _TEXT_H + +#include // RECT, HDC etc. +#include "location.h" // location +#include "pc.h" // pc_record_type + +#include "global.h" // structs + +short text_pc_has_abil_equip(short pc_num,short abil); +void put_pc_screen(); +void place_buy_button(short position,short pc_num,short item_num,HDC hdc); +void put_item_screen(short screen_num,short suppress_buttons); +void place_item_bottom_buttons(); +RECT get_party_template_rect(short pc_num,short mode); +void set_stat_window(short new_stat); +void place_item_button(short which_button_to_put,short which_slot,short which_button_position,short extraVal); +short first_active_pc(); +void refresh_stat_areas(short mode); +short total_encumberance(short pc_num); +short get_tnl(pc_record_type *pc); +void draw_pc_effects(short pc,HDC dest_dc); +void print_party_stats() ; +short do_look(location space); +short town_boat_there(location where); +short out_boat_there(location where); +short town_horse_there(location where); +short out_horse_there(location where); +void notify_out_combat_began(out_wandering_type encounter,short *nums); +void get_m_name(char *str,unsigned char num); +void get_ter_name(char *str,unsigned char num); +void print_monst_name(unsigned char m_type); +void print_monst_attacks(unsigned char m_type,short target); +void damaged_message(short damage,short type); +void print_monster_going(char *combat_str,unsigned char m_num,short ap); +void monst_spell_note(unsigned char number,short which_mess); +void monst_cast_spell_note(unsigned char number,short spell,short type); +void monst_breathe_note(unsigned char number); +void monst_damaged_mes(short which_m,short how_much,short how_much_spec); +void monst_killed_mes(short which_m); +void print_nums(short a,short b,short c); +short print_terrain(location space); +void add_string_to_buf(char *string); +void print_buf () ; +void through_sending(); +void Display_String(char *str); +RECT coord_to_rect(short i,short j); +void c2p(char *str) ; +void p2c(char *str); +short string_length(char *str,HDC hdc); +void char_win_draw_string(HDC dest_window,RECT dest_rect,char *str,short mode,short line_height); +void win_draw_string(HDC dest_window,RECT dest_rect,char *str,short mode,short line_height); +short calc_day(); +Boolean day_reached(unsigned char which_day, unsigned char which_event); +void display_string(char *str); +void Draw_Some_Item (HBITMAP src_gworld, RECT src_rect, HBITMAP targ_gworld, location target, char masked, short main_win); +void WinBlackDrawString(char *string,short x,short y); +void WinDrawString(char *string,short x,short y); +void DrawString(char *string,short x,short y,HDC hdc); +void FlushEvents(short mode); +void undo_clip(); +void ClipRect(RECT *rect); +void beep(); +void GetIndString(char *str,short i, short j) ; +void MeasureText(short str_len,char *str, short *len_array,HDC hdc); +RECT get_custom_rect (short which_rect); + +#endif diff --git a/Win32/Blades of Exile/TOWN.CPP b/Win32/Blades of Exile/TOWN.CPP new file mode 100644 index 00000000..ccb2deb5 --- /dev/null +++ b/Win32/Blades of Exile/TOWN.CPP @@ -0,0 +1,1653 @@ +#include +#include "stdio.h" +#include "global.h" +#include "gutils.h" +#include "graphics.h" +#include "newgraph.h" +#include "fileio.h" +#include "items.h" +#include "itemdata.h" +#include "monster.h" +#include "town.h" +#include "combat.h" +#include "party.h" +#include "text.h" +#include "exlsound.h" +#include "fields.h" +#include "locutils.h" +#include "dlogtool.h" +#include "infodlgs.h" +#include "graphutl.h" + +#include "globvar.h" + +void force_town_enter(short which_town,location where_start) +{ + town_force = which_town; + town_force_loc = where_start; +} + +void start_town_mode(short which_town, short entry_dir) +//short entry_dir; // if 9, go to forced +{ + short i,m,n; + + char message[60]; + short j,k,town_number; + short at_which_save_slot,former_town; + location loc; + unsigned char temp; + Boolean monsters_loaded = FALSE, town_toast = FALSE; + Boolean play_town_sound = FALSE; + + if (town_force < INVALID_TOWN) which_town = town_force; + else play_town_sound = TRUE; + + former_town = town_number = which_town; + + if ((town_number < 0) || (town_number >= scenario.num_towns)) + { + char text[256]; + wsprintf(text, "town number = %i, max = %i, %i, %i", town_number, + scenario.num_towns, sizeof(short), sizeof(WORD)); + give_error("The scenario tried to put you into a town that doesn't exist.",text,0); + return; + } + + // Now adjust town number as necessary. + for (i = 0; i < 10; i++) + if ((scenario.town_to_add_to[i] >= 0) && (scenario.town_to_add_to[i] < 200) && + (town_number == scenario.town_to_add_to[i]) && + (sd_legit(scenario.flag_to_add_to_town[i][0],scenario.flag_to_add_to_town[i][1]) == TRUE)) + { + former_town = town_number; + town_number += PSD[scenario.flag_to_add_to_town[i][0]][scenario.flag_to_add_to_town[i][1]]; + + // Now update horses & boats + for (i = 0; i < 30; i++) + if ((party.horses[i].exists == TRUE) && (party.horses[i].which_town == former_town)) + party.horses[i].which_town = town_number; + + for (i = 0; i < 30; i++) + if ((party.boats[i].exists == TRUE) && (party.boats[i].which_town == former_town)) + party.boats[i].which_town = town_number; + } + + if ((town_number < 0) || (town_number >= scenario.num_towns)) + { + give_error("The scenario tried to put you into a town that doesn't exist.","2",0); + return; + } + + overall_mode = MODE_TOWN; + + load_town(town_number,0,0,NULL); + + c_town.town_num = town_number; + + if (play_town_sound == TRUE) + { + if (c_town.town.lighting > 0) play_sound(95); + else play_sound(16); + } + + belt_present = FALSE; + // Set up map, using stored map + for (i = 0; i < town_size[town_type]; i++) + for (j = 0; j < town_size[town_type]; j++) { + c_town.explored[i][j] = 0; + if (town_maps.town_maps[c_town.town_num][i / 8][j] & (char)(s_pow(2,i % 8))) + make_explored(i,j); + + if (t_d.terrain[i][j] == 0) current_ground = 0; + else if (t_d.terrain[i][j] == 2) current_ground = 2; + + if ((scenario.ter_types[t_d.terrain[i][j]].special >= 16) && + (scenario.ter_types[t_d.terrain[i][j]].special <= 19)) + belt_present = TRUE; + } + c_town.hostile = 0; + c_town.monst.which_town = town_number; + c_town.monst.friendly = 0; + + at_which_save_slot = party.at_which_save_slot; + + for (i = 0; i < 4; i++) + if (town_number == party.creature_save[i].which_town) { + c_town.monst = party.creature_save[i]; + monsters_loaded = TRUE; + + for (j = 0; j < T_M; j++) { + if (loc_off_act_area(c_town.monst.dudes[j].m_loc) == TRUE) + c_town.monst.dudes[j].active = 0; + if (c_town.monst.dudes[j].active == 2) + c_town.monst.dudes[j].active = 1; + c_town.monst.dudes[j].m_loc = t_d.creatures[j].start_loc; + c_town.monst.dudes[j].m_d.health = c_town.monst.dudes[j].m_d.m_health; + c_town.monst.dudes[j].m_d.mp = c_town.monst.dudes[j].m_d.max_mp; + c_town.monst.dudes[j].m_d.morale = c_town.monst.dudes[j].m_d.m_morale; + for (k = 0; k < 15; k++) + c_town.monst.dudes[j].m_d.status[k] = 0; + if (c_town.monst.dudes[j].summoned > 0) + c_town.monst.dudes[j].active = 0; + monst_target[j] = 6; + } + + // Now, travelling NPCs might have arrived. Go through and put them in. + // These should have protected status (i.e. spec1 >= 200, spec1 <= 204) + for (j = 0; j < T_M; j++) { + switch (c_town.monst.dudes[j].monst_start.time_flag){ + case 4: case 5 : case 6: + if ((((short) (party.age / 1000) % 3) + 4) != c_town.monst.dudes[j].monst_start.time_flag) + c_town.monst.dudes[j].active = 0; + else { + c_town.monst.dudes[j].active = 1; + c_town.monst.dudes[j].monst_start.spec_enc_code = 0; + // Now remove time flag so it doesn't get reappearing + c_town.monst.dudes[j].monst_start.time_flag = 0; + c_town.monst.dudes[j].m_loc = t_d.creatures[j].start_loc; + c_town.monst.dudes[j].m_d.health = c_town.monst.dudes[j].m_d.m_health; + } + break ; + + // Now, appearing/disappearing monsters might have arrived/disappeared. + case 1: + if (day_reached(c_town.monst.dudes[j].monst_start.monster_time, c_town.monst.dudes[j].monst_start.time_code) == TRUE) + { + c_town.monst.dudes[j].active = 1; + c_town.monst.dudes[j].monst_start.time_flag=0; // Now remove time flag so it doesn't get reappearing + } + break; + case 2: + if (day_reached(c_town.monst.dudes[j].monst_start.monster_time, c_town.monst.dudes[j].monst_start.time_code) == TRUE) + { + c_town.monst.dudes[j].active = 0; + c_town.monst.dudes[j].monst_start.time_flag=0; // Now remove time flag so it doesn't get disappearing again + } + break; + case 7: + if (calc_day() >= party.key_times[c_town.monst.dudes[j].monst_start.time_code]){ //calc_day is used because of the "definition" of party.key_times + c_town.monst.dudes[j].active = 1; + c_town.monst.dudes[j].monst_start.time_flag=0; // Now remove time flag so it doesn't get reappearing + } + break; + + case 8: + if (calc_day() >= party.key_times[c_town.monst.dudes[j].monst_start.time_code]){ + c_town.monst.dudes[j].active = 0; + c_town.monst.dudes[j].monst_start.time_flag=0; // Now remove time flag so it doesn't get disappearing again + } + break; + case 0: + break; + default: + break; + } +} + + for (j = 0; j < town_size[town_type]; j++) + for (k = 0; k < town_size[town_type]; k++) { // now load in saved setup, + // except that barrels and crates restore to orig locs + temp = setup_save.setup[i][j][k] & 231; + + misc_i[j][k] = (misc_i[j][k] & 24) | temp;//setup_save.setup[i][j][k]; + } + } + + if (monsters_loaded == FALSE) { + for (i = 0; i < T_M; i++) + if (t_d.creatures[i].number == 0) { + c_town.monst.dudes[i].active = 0; + c_town.monst.dudes[i].number = 0; + c_town.monst.dudes[i].monst_start.time_flag = 0; + c_town.monst.dudes[i].m_loc.x = 80; + } + else { + // First set up the values. + monst_target[i] = 6; + c_town.monst.dudes[i].active = 1; + c_town.monst.dudes[i].number = t_d.creatures[i].number; + c_town.monst.dudes[i].attitude = t_d.creatures[i].start_attitude; + c_town.monst.dudes[i].m_loc = t_d.creatures[i].start_loc; + c_town.monst.dudes[i].mobile = t_d.creatures[i].mobile; + c_town.monst.dudes[i].m_d = return_monster_template(c_town.monst.dudes[i].number); + + c_town.monst.dudes[i].summoned = 0; + c_town.monst.dudes[i].monst_start = t_d.creatures[i]; + + if (c_town.monst.dudes[i].monst_start.spec_enc_code > 0) + c_town.monst.dudes[i].active = 0; + + // Now, if necessary, fry the monster. + switch (c_town.monst.dudes[i].monst_start.time_flag) { + case 1: + if (day_reached(c_town.monst.dudes[i].monst_start.monster_time, + c_town.monst.dudes[i].monst_start.time_code) == FALSE) + c_town.monst.dudes[i].active = 0; + break; + case 2: + if (day_reached(c_town.monst.dudes[i].monst_start.monster_time, + c_town.monst.dudes[i].monst_start.time_code) == TRUE) + c_town.monst.dudes[i].active = 0; + break; + case 3: + // unused + break; + case 4: case 5: case 6: + if ((((short) (party.age / 1000) % 3) + 4) != c_town.monst.dudes[i].monst_start.time_flag) { + c_town.monst.dudes[i].active = 0; + c_town.monst.dudes[i].monst_start.spec_enc_code = 50; + } + else { + c_town.monst.dudes[i].active = 1; + // Now remove time flag so it doesn't keep reappearing + c_town.monst.dudes[i].monst_start.time_flag = 0; + } + break; + case 7: + if (calc_day() < party.key_times[c_town.monst.dudes[i].monst_start.time_code]) + c_town.monst.dudes[i].active = 0; + break; + + case 8: + if (calc_day() >= party.key_times[c_town.monst.dudes[i].monst_start.time_code]) + c_town.monst.dudes[i].active = 0; + break; + case 9: + if (c_town.town.town_chop_time > 0) + if (day_reached(c_town.town.town_chop_time,c_town.town.town_chop_key) == TRUE) { + c_town.monst.dudes[i].active += 10; + break; + } + c_town.monst.dudes[i].active = 0; + break; + case 0: + break; + default: + break; } + } + } + + // Now munch all large monsters that are misplaced + // only large monsters, as some smaller monsters are intentionally placed + // where they cannot be + for (i = 0; i < T_M; i++) { + if (c_town.monst.dudes[i].active > 0) + if (((c_town.monst.dudes[i].m_d.x_width > 1) || (c_town.monst.dudes[i].m_d.y_width > 1)) && + (monst_can_be_there(c_town.monst.dudes[i].m_loc,i) == FALSE)) + c_town.monst.dudes[i].active = 0; + } + // Thrash town? + if (party.m_killed[c_town.town_num] > c_town.town.max_num_monst) { + town_toast = TRUE; + add_string_to_buf("Area has been cleaned out."); + } + if (c_town.town.town_chop_time > 0) { + if (day_reached(c_town.town.town_chop_time,c_town.town.town_chop_key) == TRUE){ + //add_string_to_buf("Area has been abandoned."); + for (i = 0; i < T_M; i++) + if ((c_town.monst.dudes[i].active > 0) && (c_town.monst.dudes[i].active < 10) && + (c_town.monst.dudes[i].attitude % 2 == 1)) + c_town.monst.dudes[i].active += 10; + town_toast = TRUE; + } + } + if (town_toast == TRUE) { + for (i = 0; i < T_M; i++) + if (c_town.monst.dudes[i].active >= 10) + c_town.monst.dudes[i].active -= 10; + else c_town.monst.dudes[i].active = 0; + } + if ((short) town_toast > 0) + special_queue[0] = c_town.town.spec_on_entry_if_dead; + else special_queue[0] = c_town.town.spec_on_entry; + // Flush excess doomguards and viscous goos + for (i = 0; i < T_M; i++) + if ((c_town.monst.dudes[i].m_d.spec_skill == 12) && + (c_town.monst.dudes[i].number != t_d.creatures[i].number)) + c_town.monst.dudes[i].active = 0; + + quickfire = FALSE; + crate = FALSE; + barrel = FALSE; + web = FALSE; + fire_barrier = FALSE; + force_barrier = FALSE; + // Set up field booleans, correct for doors + for (j = 0; j < town_size[town_type]; j++) + for (k = 0; k < town_size[town_type]; k++) { + loc.x = j; loc.y = k; + if (loc.isDoor()) misc_i[j][k] = misc_i[j][k] & 3; + + // Set up field booleans + if (is_web(j,k) == TRUE) web = TRUE; + if (is_crate(j,k) == TRUE) crate = TRUE; + if (is_barrel(j,k) == TRUE) barrel = TRUE; + if (is_fire_barrier(j,k) == TRUE) fire_barrier = TRUE; + if (is_force_barrier(j,k) == TRUE) force_barrier = TRUE; + if (is_quickfire(j,k) == TRUE) quickfire = TRUE; + } + + // Set up items, maybe place items already there + for (i = 0; i < NUM_TOWN_ITEMS; i++) + t_i.items[i] = return_dummy_item(); + + for (j = 0; j < 3; j++) + if (scenario.store_item_towns[j] == town_number) { + for (i = 0; i < NUM_TOWN_ITEMS; i++) + t_i.items[i] = stored_items[j].items[i]; + } + + for (i = 0; i < 64; i++) + if ((c_town.town.preset_items[i].item_code >= 0) + && (((party.item_taken[c_town.town_num][i / 8] & s_pow(2,i % 8)) == 0) || + (c_town.town.preset_items[i].always_there == TRUE))) { + for (j = 0; j < NUM_TOWN_ITEMS; j++) + + // place the preset item, if party hasn't gotten it already + if (t_i.items[j].variety == 0) { + t_i.items[j] = get_stored_item(c_town.town.preset_items[i].item_code); + t_i.items[j].item_loc = c_town.town.preset_items[i].item_loc; + + // Not use the items data flags, starting with forcing an ability + if (c_town.town.preset_items[i].ability >= 0) { + switch (t_i.items[j].variety) { + case 3: case 11: // If gold or food, this value is amount + if (c_town.town.preset_items[i].ability > 0) + t_i.items[j].item_level = c_town.town.preset_items[i].ability; + break; + } + } + + if (c_town.town.preset_items[i].property == TRUE) + t_i.items[j].item_properties = t_i.items[j].item_properties | 2; + if (town_toast == TRUE) + t_i.items[j].item_properties = t_i.items[j].item_properties & 253; + if (c_town.town.preset_items[i].contained == TRUE) + t_i.items[j].item_properties = t_i.items[j].item_properties | 8; + t_i.items[j].is_special = i + 1; + + j = NUM_TOWN_ITEMS; + } + } + + + for (i = 0; i < T_M; i++) + if (loc_off_act_area(c_town.monst.dudes[i].m_loc) == TRUE) + c_town.monst.dudes[i].active = 0; + for (i = 0; i < NUM_TOWN_ITEMS; i++) + if (loc_off_act_area(t_i.items[i].item_loc) == TRUE) + t_i.items[i].variety = 0; + + // Clean out unwanted monsters + for (i = 0; i < T_M; i++) + if (sd_legit(c_town.monst.dudes[i].monst_start.spec1,c_town.monst.dudes[i].monst_start.spec2) == TRUE) { + if (party.stuff_done[c_town.monst.dudes[i].monst_start.spec1][c_town.monst.dudes[i].monst_start.spec2] > 0) + c_town.monst.dudes[i].active = 0; + } + + erase_specials(); + make_town_trim(0); + + load_area_graphics(); + + c_town.p_loc = (entry_dir < 9) ? c_town.town.start_locs[entry_dir] : town_force_loc; + center = c_town.p_loc; + if (party.in_boat >= 0) { + party.boats[party.in_boat].which_town = which_town; + party.boats[party.in_boat].boat_loc = c_town.p_loc; + } + if (party.in_horse >= 0) { + party.horses[party.in_horse].which_town = which_town; + party.horses[party.in_horse].horse_loc = c_town.p_loc; + } + + // End flying + if (party.stuff_done[305][1] > 0) + { + party.stuff_done[305][1] = 0; + add_string_to_buf("You land, and enter. "); + } + + // No hostile monsters present. + party.stuff_done[305][9] = 0; + + add_string_to_buf("Now entering:"); + sprintf ((char *) message, " %-30.30s ",data_store->town_strs[0]); + add_string_to_buf((char *) message); + + // clear entry space, and check exploration + misc_i[c_town.p_loc.x][c_town.p_loc.y] = misc_i[c_town.p_loc.x][c_town.p_loc.y] & 3; + update_explored(c_town.p_loc); + + // If a PC dead, drop his items + for (m = 0; m < 6; m++) + for (n = 0; n < 24; n++) + if ((adven[m].isAlive() == false) && (adven[m].items[n].variety != 0)) { + place_item(adven[m].items[n],c_town.p_loc,TRUE); + adven[m].items[n].variety = 0; + } + + for (i = 0; i < T_M; i++) + {monster_targs[i].x = 0; monster_targs[i].y = 0;} + + //// check horses + for (i = 0; i < 30; i++) { + if ((scenario.scen_boats[i].which_town >= 0) && (scenario.scen_boats[i].boat_loc.x >= 0)) { + if (party.boats[i].exists == FALSE) { + party.boats[i] = scenario.scen_boats[i]; + party.boats[i].exists = TRUE; + } + } + if ((scenario.scen_horses[i].which_town >= 0) && (scenario.scen_horses[i].horse_loc.x >= 0)) { + if (party.horses[i].exists == FALSE) { + party.horses[i] = scenario.scen_horses[i]; + party.horses[i].exists = TRUE; + } + } + } + + // Place correct graphics + redraw_screen(0); + + clear_map(); + reset_item_max(); + town_force = INVALID_TOWN; +} + +location end_town_mode(short switching_level,location destination) // returns new party location +{ + location to_return; + short i,j,k; + Boolean data_saved = FALSE,combat_end = FALSE; + + if (is_combat()) combat_end = TRUE; + + if (overall_mode == 1) { + for (i = 0; i < 4; i++) + if (party.creature_save[i].which_town == c_town.town_num) { + party.creature_save[i] = c_town.monst; + for (j = 0; j < town_size[town_type]; j++) + for (k = 0; k < town_size[town_type]; k++) + setup_save.setup[i][j][k] = misc_i[j][k]; + data_saved = TRUE; + } + if (data_saved == FALSE) { + party.creature_save[party.at_which_save_slot] = c_town.monst; + for (j = 0; j < town_size[town_type]; j++) + for (k = 0; k < town_size[town_type]; k++) + setup_save.setup[party.at_which_save_slot][j][k] = misc_i[j][k]; + party.at_which_save_slot = (party.at_which_save_slot == 3) ? 0 : party.at_which_save_slot + 1; + } + + // Store items, if necessary + for (j = 0; j < 3; j++) + if (scenario.store_item_towns[j] == c_town.town_num) { + for (i = 0; i < NUM_TOWN_ITEMS; i++) + if ((t_i.items[i].variety != 0) && (t_i.items[i].is_special == 0) && + ((t_i.items[i].item_loc.x >= scenario.store_item_rects[j].left) && + (t_i.items[i].item_loc.x <= scenario.store_item_rects[j].right) && + (t_i.items[i].item_loc.y >= scenario.store_item_rects[j].top) && + (t_i.items[i].item_loc.y <= scenario.store_item_rects[j].bottom)) ) { + stored_items[j].items[i] = t_i.items[i]; + } + else stored_items[j].items[i].variety = 0; + } + + // Clean up special data, just in case + for (i = 0; i < T_M; i++) { + c_town.monst.dudes[i].monst_start.spec1 = 0; + c_town.monst.dudes[i].monst_start.spec2 = 0; + } + + // Now store map + for (i = 0; i < town_size[town_type]; i++) + for (j = 0; j < town_size[town_type]; j++) + if (is_explored(i,j) > 0) { + town_maps.town_maps[c_town.town_num][i / 8][j] = town_maps.town_maps[c_town.town_num][i / 8][j] | + (char) (s_pow(2,i % 8)); + + } + + to_return = party.p_loc; + + for (i = 0; i < 30; i++) + if ((party.party_event_timers[i] > 0) && (party.global_or_town[i] == 1)) + party.party_event_timers[i] = 0; + } + + + // Check for exit specials, if leaving town + if (switching_level == 0) { + to_return = party.p_loc; + + if (is_town()) { + if (destination.x <= c_town.town.in_town_rect.left) { + if (c_town.town.exit_locs[1].x > 0) + to_return = c_town.town.exit_locs[1].toGlobal(); + else to_return.x--; + party.p_loc = to_return; party.p_loc.x++; + special_queue[1] = c_town.town.exit_specs[1]; + } + else if (destination.x >= c_town.town.in_town_rect.right) { + if (c_town.town.exit_locs[3].x > 0) + to_return = c_town.town.exit_locs[3].toGlobal(); + else to_return.x++; + party.p_loc = to_return; party.p_loc.x--; + special_queue[1] = c_town.town.exit_specs[3]; + } + else if (destination.y <= c_town.town.in_town_rect.top) { + if (c_town.town.exit_locs[0].x > 0) + to_return = c_town.town.exit_locs[0].toGlobal(); + else to_return.y--; + party.p_loc = to_return; party.p_loc.y++; + special_queue[1] = c_town.town.exit_specs[0]; + } + else if (destination.y >= c_town.town.in_town_rect.bottom) { + if (c_town.town.exit_locs[2].x > 0) + to_return = c_town.town.exit_locs[2].toGlobal(); + else to_return.y++; + party.p_loc = to_return; party.p_loc.y--; + special_queue[1] = c_town.town.exit_specs[2]; + } + + } + } + + if (switching_level == 0) + { + fix_boats(); + overall_mode = 0; + + erase_out_specials(); + + load_area_graphics(); + + party.stuff_done[305][0] = 0; + for (i = 0; i < 6; i++) + for (j = 0; j < 15; j++) + if ((j != 2) && (j != 7) && (j != 9)) + adven[i].status[j] = 0; + + update_explored(to_return); + redraw_screen(0); + } + + if (combat_end == FALSE) clear_map(); + + return to_return; +} + +void start_town_combat(short direction) +{ + short i; + + create_town_combat_terrain(); + + place_party(direction); + + if (current_pc == 6) { + for (i = 0; i < 6; i++) + if (adven[i].isAlive()) { + current_pc = i; + i = 6; + } + } + center = pc_pos[current_pc]; + + which_combat_type = 1; + overall_mode = MODE_COMBAT; + + combat_active_pc = 6; + for (i = 0; i < T_M; i++) + monst_target[i] = 6; + + for (i = 0; i < 6; i++) { + last_attacked[i] = T_M + 10; + pc_parry[i] = 0; + pc_dir[i] = direction; + adven[current_pc].direction = direction; + if (adven[i].isAlive()) + update_explored(pc_pos[i]); + } + + store_current_pc = current_pc; + current_pc = 0; + set_pc_moves(); + pick_next_pc(); + center = pc_pos[current_pc]; + draw_buttons(0); + put_pc_screen(); + set_stat_window(current_pc); + give_help(48,49,0); + +} + +short end_town_combat() +{ + short num_tries = 0,r1,i; + + r1 = get_ran(1,0,5); + while ((adven[r1].isAlive() == false) && (num_tries++ < 1000)) + r1 = get_ran(1,0,5); + c_town.p_loc = pc_pos[r1]; + overall_mode = 1; + current_pc = store_current_pc; + if (adven[current_pc].isAlive() == false) + current_pc = first_active_pc(); + for (i = 0; i < 6; i++) + pc_parry[i] = 0; + return pc_dir[r1]; +} + +void place_party(short direction) +{ + Boolean spot_ok[14] = {TRUE,TRUE,TRUE,TRUE,TRUE,TRUE,TRUE, + TRUE,TRUE,TRUE,TRUE,TRUE,TRUE,TRUE}; + location pos_locs[14]; + location check_loc; + short x_adj,y_adj,how_many_ok = 1,where_in_a = 0,i; + + for (i = 0; i < 14; i++) { + check_loc = c_town.p_loc; + if (direction % 4 < 2) + x_adj = ((direction % 2 == 0) ? hor_vert_place[i].x : diag_place[i].x); + else x_adj = ((direction % 2 == 0) ? hor_vert_place[i].y : diag_place[i].y); + if (direction % 2 == 0) + x_adj = (direction < 4) ? x_adj : -1 * x_adj; + else x_adj = ((direction == 1) || (direction == 7)) ? -1 * x_adj : x_adj; + check_loc.x -= x_adj; + if (direction % 4 < 2) + y_adj = ((direction % 2 == 0) ? hor_vert_place[i].y : diag_place[i].y); + else y_adj = ((direction % 2 == 0) ? hor_vert_place[i].x : diag_place[i].x); + if (direction % 2 == 0) + y_adj = ((direction > 1) && (direction < 6)) ? y_adj : -1 * y_adj; + else y_adj = ((direction == 3) || (direction == 1)) ? -1 * y_adj : y_adj; + + check_loc.y -= y_adj; + pos_locs[i] = check_loc; + if ((loc_off_act_area(check_loc) == FALSE) && + (is_blocked(check_loc) == FALSE) && (is_special(check_loc) == FALSE) && (get_obscurity(check_loc.x,check_loc.y) == 0) + && (can_see(c_town.p_loc,check_loc,1) < 1)) { + spot_ok[i] = TRUE; + how_many_ok += (i > 1) ? 1 : 0; + } + else spot_ok[i] = FALSE; + + if (i == 0) + spot_ok[i] = TRUE; + } + i = 0; + while (i < 6) { + if (adven[i].isAlive()) { + if (how_many_ok == 1) + pc_pos[i] = pos_locs[where_in_a]; + else { + pc_pos[i] = pos_locs[where_in_a]; + if (how_many_ok > 1) + where_in_a++; + how_many_ok--; + while (spot_ok[where_in_a] == FALSE) + where_in_a++; + } + } + i++; + } +} + + + +void create_town_combat_terrain() +{ + location where; + + for (where.x = 0; where.x < town_size[town_type]; where.x++) + for (where.y = 0; where.y < town_size[town_type]; where.y++) + combat_terrain[where.x][where.y] = t_d.terrain[where.x][where.y]; +} + +void create_out_combat_terrain(short type,short num_walls) +// spec_code is encounter's spec_code +{ + short i,j,k,r1,ter_type; +// 0 grass 1 cave 2 mntn 3 bridge 4 cave bridge 5 rubble cave 6 cave tree 7 cave mush +// 8 cave swamp 9 surface rocks 10 surf swamp 11 surface woods 12 s. shrub 13 stalags +short general_types[260] = {1,1,0,0,0,1,1,1,1,1, +1,1,1,1,1,1,1,1,2,2, +2,2,2,2,2,2,2,2,2,2, +2,2,2,2,2,2,2,2,2,2, +2,2,2,2,2,2,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,// 50 +0,3,3,3,3,3,3,5,5,5, +6,6,7,7,1,1,8,9,10,11, +10,11,12,13,13,9,9,9,1,1, +1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,// 100 +1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,// 150 +1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1, +1,0,1,1,1,1,1,1,1,0, +0,0,0,0,1,0,0,0,0,0, +0,0,1,0,2,0,0,1,1,1,// 200 +1,0,2,1,1,0,1,1,1,1, +1,1,0,0,0,0,1,0,1,1, +1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1};// 250 +short ter_base[14] = {2,0,36,50,71, 0,0,0,0,2, 2,2,2,0}; +short ground_type[14] = {2,0,36,50,71, 0,0,0,0,2, 2,2,2,0}; + +location special_ter_locs[15] = + { + location(11,10),location(11,14),location(10,20),location(11,26),location(9,30), + location(15,19),location(23,19),location(19,29),location(20,11),location(28,16), + location(28,24),location(27,19),location(27,29),location(15,28),location(19,19) + }; +unsigned char cave_pillar[4][4] = {{0,14,11,1},{14,19,20,11},{17,18,21,8},{1,17,8,0}}; +unsigned char mntn_pillar[4][4] = {{37,29,27,36},{29,33,34,27},{31,32,35,25},{36,31,25,37}}; +unsigned char surf_lake[4][4] = {{56,55,54,3},{57,50,61,54},{58,51,59,53},{3,4,58,52}}; +unsigned char cave_lake[4][4] = {{93,96,71,71},{96,71,71,71},{71,71,71,96},{71,71,71,96}}; +location stuff_ul; +short terrain_odds[14][10] = {{3,80,4,40,115,20,114,10,112,1}, + {1,50,93,25,94,5,98,10,95,1}, + {37,20,0,0,0,0,0,0,0,0}, + {64,3,63,1,0,0,0,0,0,0}, + {74,1,0,0,0,0,0,0,0,0}, + {84,700,97,30,98,20,92,4,95,1}, + {93,280,91,300,92,270,95,7,98,10}, + {1,800,93,600,94,10,92,10,95,4}, + {1,700,96,200,95,100,92,10,112,5}, + {3,600,87,90,110,20,114,6,113,2}, + {3,200,4,400,111,250,0,0,0,0}, + {3,200,4,300,112,50,113,60,114,100}, + {3,100,4,250,115,120,114,30,112,2}, + {1,25,84,15,98,300,97,280,0,0}}; // ter then odds then ter then odds ... + + + ter_type = scenario.ter_types[type].picture; + if (ter_type > 260) + ter_type = 1; + else ter_type = general_types[ter_type]; + + for (i = 0; i < 48; i++) + for (j = 0; j < 48; j++) { + c_town.explored[i][j] = 0; + misc_i[i][j] = 0; + sfx[i][j] = 0; + if ((j <= 8) || (j >= 35) || (i <= 8) || (i >= 35)) + t_d.terrain[i][j] = 90; + else t_d.terrain[i][j] = ter_base[ter_type]; + } + for (i = 0; i < 48; i++) + for (j = 0; j < 48; j++) + for (k = 0; k < 5; k++) + if ((t_d.terrain[i][j] != 90) && (get_ran(1,1,1000) < terrain_odds[ter_type][k * 2 + 1])) + t_d.terrain[i][j] = terrain_odds[ter_type][k * 2]; + + t_d.terrain[0][0] = ter_base[ter_type]; + + if ((ter_type == 3) || (ter_type == 4) ) { + t_d.terrain[0][0] = 83; + for (i = 15; i < 26; i++) + for (j = 9; j < 35; j++) + t_d.terrain[i][j] = 83; + } + if ((type >= 79) && (type <= 81)) { + t_d.terrain[0][0] = 82; + for (i = 19; i < 23; i++) + for (j = 9; j < 35; j++) + t_d.terrain[i][j] = 82; + } + + + // Now place special lakes, etc. + if (ter_type == 2) + for (i = 0; i < 15; i++) + if (get_ran(1,0,5) == 1) { + stuff_ul = special_ter_locs[i]; + for (j = 0; j < 4; j++) + for (k = 0; k < 4; k++) + t_d.terrain[stuff_ul.x + j][stuff_ul.y + k] = mntn_pillar[k][j]; + } + if (t_d.terrain[0][0] == 0) + for (i = 0; i < 15; i++) + if (get_ran(1,0,25) == 1) { + stuff_ul = special_ter_locs[i]; + for (j = 0; j < 4; j++) + for (k = 0; k < 4; k++) + t_d.terrain[stuff_ul.x + j][stuff_ul.y + k] = cave_pillar[k][j]; + } + if (t_d.terrain[0][0] == 0) + for (i = 0; i < 15; i++) + if (get_ran(1,0,40) == 1) { + stuff_ul = special_ter_locs[i]; + for (j = 0; j < 4; j++) + for (k = 0; k < 4; k++) + t_d.terrain[stuff_ul.x + j][stuff_ul.y + k] = cave_lake[k][j]; + } + if (t_d.terrain[0][0] == 2) + for (i = 0; i < 15; i++) + if (get_ran(1,0,40) == 1) { + stuff_ul = special_ter_locs[i]; + for (j = 0; j < 4; j++) + for (k = 0; k < 4; k++) + t_d.terrain[stuff_ul.x + j][stuff_ul.y + k] = surf_lake[k][j]; + } + + + if (ground_type[ter_type] == 0) { + for (i = 0; i < num_walls; i++) { + r1 = get_ran(1,0,3); + for (j = 9; j < 35; j++) + switch (r1) { + case 0: + t_d.terrain[j][8] = 6; + break; + case 1: + t_d.terrain[8][j] = 9; + break; + case 2: + t_d.terrain[j][35] = 12; + break; + case 3: + t_d.terrain[32][j] = 15; + break; + } + } + if ((t_d.terrain[17][8] == 6) && (t_d.terrain[8][20] == 9)) + t_d.terrain[8][8] = 21; + if ((t_d.terrain[32][20] == 15) && (t_d.terrain[17][35] == 12)) + t_d.terrain[32][35] = 19; + if ((t_d.terrain[17][8] == 6) && (t_d.terrain[32][20] == 15)) + t_d.terrain[32][8] = 32; + if ((t_d.terrain[8][20] == 9) && (t_d.terrain[17][35] == 12)) + t_d.terrain[8][35] = 20; + } + if (ground_type[ter_type] == 36) { + for (i = 0; i < num_walls; i++) { + r1 = get_ran(1,0,3); + for (j = 9; j < 35; j++) + switch (r1) { + case 0: + t_d.terrain[j][8] = 24; + break; + case 1: + t_d.terrain[8][j] = 26; + break; + case 2: + t_d.terrain[j][35] = 28; + break; + case 3: + t_d.terrain[32][j] = 30; + break; + } + } + if ((t_d.terrain[17][8] == 6) && (t_d.terrain[8][20] == 9)) + t_d.terrain[8][8] = 35; + if ((t_d.terrain[32][20] == 15) && (t_d.terrain[17][35] == 12)) + t_d.terrain[32][35] = 33; + if ((t_d.terrain[17][8] == 6) && (t_d.terrain[32][20] == 15)) + t_d.terrain[32][8] = 32; + if ((t_d.terrain[8][20] == 9) && (t_d.terrain[17][35] == 12)) + t_d.terrain[8][35] = 34; + } + + for (i = 0; i < 48; i++) + for (j = 0; j < 48; j++) + combat_terrain[i][j] = t_d.terrain[i][j]; + + make_town_trim(1); +} + + +/*void elim_monst(unsigned char which,short spec_a,short spec_b) +{ + short i; + + if (party.stuff_done[spec_a][spec_b] > 0) { + for (i = 0; i < T_M; i++) + if (c_town.monst.dudes[i].number == which) { + c_town.monst.dudes[i].active = 0; + } + } +}*/ + + + +void dump_gold(short print_mes) +//short print_mes; // 0 - no 1 - yes +{ + // Mildly kludgy gold check + if (party.gold > 30000) { + party.gold = 30000; + if (print_mes == 1) { + put_pc_screen(); + add_string_to_buf("Excess gold dropped. "); + print_buf(); + } + } + if (party.food > 25000) { + party.food = 25000; + if (print_mes == 1) { + put_pc_screen(); + add_string_to_buf("Excess food dropped. "); + print_buf(); + } + } +} + +void erase_specials() +{ + location where; + short k,sd1,sd2; + + special_node_type sn; + + if ((is_combat()) && (which_combat_type == 0)) + return; + if ((is_town() == FALSE) && (is_combat() == FALSE)) + return; + for (k = 0; k < 50; k++) { + //GK if (c_town.town.spec_id[k] >= 0) + { + sn = c_town.town.specials[c_town.town.spec_id[k]]; + sd1 = sn.sd1; sd2 = sn.sd2; + if ((sd_legit(sd1,sd2) == TRUE) && (PSD[sd1][sd2] == 250)) { + where = c_town.town.special_locs[k]; + if ((where.x != 100) && ((where.x > town_size[town_type]) || (where.y > town_size[town_type]) + || (where.x < 0) || (where.y < 0))) { + MessageBeep(MB_OK); + add_string_to_buf("Town corrupt. Problem fixed."); + print_nums(where.x,where.y,k); + c_town.town.special_locs[k].x = 0; + } + + if (where.x != 100) { + switch (scenario.ter_types[t_d.terrain[where.x][where.y]].picture) { + case 207: t_d.terrain[where.x][where.y] = 0; break; + case 208: t_d.terrain[where.x][where.y] = 170; break; + case 209: t_d.terrain[where.x][where.y] = 210; break; + case 210: t_d.terrain[where.x][where.y] = 217; break; + case 211: t_d.terrain[where.x][where.y] = 2; break; + case 212: t_d.terrain[where.x][where.y] = 36; break; + } + take_special(where.x,where.y); + } + } + + + } + } +} + +void erase_out_specials() +{ + short i,j,k,l,m,out_num; + + special_node_type sn; + short sd1,sd2; + shortloc where; + + for (k = 0; k < 2; k++) + { + for (l = 0; l < 2; l++) + { + if (quadrant_legal(k,l) == TRUE) + { + for (m = 0; m < 8; m++) + { + if ((outdoors[k][l].exit_dests[m] >= 0) && + (outdoors[k][l].exit_locs[m].x == minmax(0,47,(int)outdoors[k][l].exit_locs[m].x)) && + (outdoors[k][l].exit_locs[m].y == minmax(0,47,(int)outdoors[k][l].exit_locs[m].y))) + { + if (party.can_find_town[outdoors[k][l].exit_dests[m]] == 0) + { + out[48 * k + outdoors[k][l].exit_locs[m].x][48 * l + outdoors[k][l].exit_locs[m].y] = + scenario.ter_types[outdoors[k][l].terrain[outdoors[k][l].exit_locs[m].x][outdoors[k][l].exit_locs[m].y]].flag1; + } + else if (party.can_find_town[outdoors[k][l].exit_dests[m]] > 0) + { + out[48 * k + outdoors[k][l].exit_locs[m].x][48 * l + outdoors[k][l].exit_locs[m].y] = + outdoors[k][l].terrain[outdoors[k][l].exit_locs[m].x][outdoors[k][l].exit_locs[m].y]; + } + } + } + } + } + } + + for (i = 0; i < 2; i++) + for (j = 0; j < 2; j++) + if (quadrant_legal(i,j) == TRUE) { + for (k = 0; k < 18; k++) + //GK if (outdoors[i][j].special_id[k] >= 0) + { + out_num = scenario.out_width * (party.outdoor_corner.y + j) + party.outdoor_corner.x + i; + + sn = outdoors[i][j].specials[outdoors[i][j].special_id[k]]; + sd1 = sn.sd1; sd2 = sn.sd2; + if ((sd_legit(sd1,sd2) == TRUE) && (PSD[sd1][sd2] == 250)) { + where.x = outdoors[i][j].special_locs[k].x; + where.y = outdoors[i][j].special_locs[k].y; + if (where.x != 100) { + if ((where.x > 48) || (where.y > 48) + || (where.x < 0) || (where.y < 0)) { + MessageBeep(MB_OK); + add_string_to_buf("Outdoor section corrupt. Problem fixed."); + //GK outdoors[i][j].special_id[k] = -1; + outdoors[i][j].special_id[k] = 0xFF; + } + + switch (scenario.ter_types[outdoors[i][j].terrain[where.x][where.y]].picture) { + case 207: out[48 * i + where.x][48 * j + where.y] = 0; break; + case 208: out[48 * i + where.x][48 * j + where.y] = 170; break; + case 209: out[48 * i + where.x][48 * j + where.y] = 210; break; + case 210: out[48 * i + where.x][48 * j + where.y] = 217; break; + case 211: out[48 * i + where.x][48 * j + where.y] = 2; break; + case 212: out[48 * i + where.x][48 * j + where.y] = 36; break; + } + } + } + + + } + } +} + +void clear_map() +{ + RECT map_world_rect = {0,0,384,384}; + HBITMAP old_bmp; + HDC hdc; + HBRUSH oldb; + HPEN oldp; + + hdc = CreateCompatibleDC(main_dc); + old_bmp = (HBITMAP) SelectObject(hdc, map_gworld); + + oldp = (HPEN) SelectObject(hdc,GetStockObject(BLACK_PEN)); + oldb = (HBRUSH) SelectObject(hdc,GetStockObject(BLACK_BRUSH)); + Rectangle(hdc, map_world_rect.left,map_world_rect.top,map_world_rect.right,map_world_rect.bottom); + SelectObject(hdc,oldp); + SelectObject(hdc,oldb); + SelectObject(hdc, old_bmp); + DeleteDC(hdc); + + draw_map(modeless_dialogs[5],10); +} + + +void draw_map_rect (HWND the_dialog, short ul_x, short ul_y, short lr_x, short lr_y) //to clean +//ul = upper left +//lr = lower right + +{ + + location map_adj; + location where; + location kludge; + RECT area_to_put_on_map_rect; + RECT draw_rect; + RECT custom_from; + RECT ter_temp_from,orig_draw_rect = {0,0,6,6}; + RECT redraw_rect = {0,0,48,48}; // RECTangle visible in view screen + COLORREF map_colors[6] = {RGB(0,0,0),RGB(63,223,95),RGB(0,0,255),RGB(191,0,191),RGB(255,0,0),RGB(204,204,204)}; + HDC hdc = NULL; + HBITMAP old_bmp; + HBRUSH old_brush; + HPEN old_pen; + short i,pic,pic2; + Boolean expl,expl2; + short small_adj = 0; + unsigned char what_ter,what_ter2; + Boolean out_mode; + + // make map pens + if (hbrush[0] == NULL) { + for (i = 0; i < 6; i++) { + hbrush[i] = CreateSolidBrush(map_colors[i]); + hpen[i] = CreatePen(PS_SOLID,1,map_colors[i]); + } + } + + hdc = CreateCompatibleDC(main_dc); + old_bmp = (HBITMAP) SelectObject(hdc, map_gworld); + old_brush = (HBRUSH) SelectObject(hdc,map_brush[0]); + old_pen = (HPEN) SelectObject(hdc,GetStockObject(NULL_PEN)); + + + if (is_out()) { // for outside map, adjust for where in outdoors is being mapped + if (party.i_w_c.x == 1) + map_adj.x += 48; + if (party.i_w_c.y == 1) + map_adj.y += 48; + } + + // Now, if shopping or talking, just don't touch anything. + if ((overall_mode == 21) || (overall_mode == 20)) + redraw_rect.right = -1; + + if ((is_out()) || + ((is_combat()) && (which_combat_type == 0)) || + ((overall_mode == 20) && (store_pre_talk_mode == 0)) || + ((overall_mode == 21) && (store_pre_shop_mode == 0))) + out_mode = TRUE; + else out_mode = FALSE; + + area_to_put_on_map_rect = redraw_rect; + + for (where.x= ul_x; where.x <= lr_x; where.x++) + for (where.y= ul_y; where.y <= lr_y; where.y++){ + draw_rect = orig_draw_rect; + OffsetRect(&draw_rect,6 * where.x + small_adj, 6 * where.y + small_adj); + + if (out_mode == TRUE) + what_ter = out[where.x + 48 * party.i_w_c.x][where.y + 48 * party.i_w_c.y]; + else what_ter = t_d.terrain[where.x][where.y]; + + ter_temp_from = orig_draw_rect; + + if (out_mode == TRUE) + expl = out_e[where.x + 48 * party.i_w_c.x][where.y + 48 * party.i_w_c.y]; + else expl = is_explored(where.x,where.y); + + if (expl != 0) { + map_graphic_placed[where.x / 8][where.y] = + map_graphic_placed[where.x / 8][where.y] | (unsigned char)(s_pow(2,where.x % 8)); + pic = scenario.ter_types[what_ter].picture; + if (pic >= 1000) { + + if (spec_scen_g != NULL) { + + pic = pic % 1000; + custom_from = coord_to_rect(pic % 10, pic / 10); + OffsetRect(&custom_from,-13,-13); + SelectObject(hdc,old_bmp); + rect_draw_some_item(spec_scen_g,custom_from,map_gworld,draw_rect,0,0); + SelectObject(hdc,map_gworld); + } + } + else switch ((pic >= 400) ? anim_map_pats[pic - 400] : map_pats[pic]) { + case 0: case 10: case 11: + if (terrain_pic[what_ter] < 400) + OffsetRect(&ter_temp_from, + 6 * (terrain_pic[what_ter] % 10) + 312,6 * (terrain_pic[what_ter] / 10)); + else OffsetRect(&ter_temp_from, + 24 * ((terrain_pic[what_ter] - 400) / 5) + 312,6 * ((terrain_pic[what_ter] - 400) % 5) + 163); + SelectObject(hdc,old_bmp); + rect_draw_some_item(mixed_gworld,ter_temp_from, + map_gworld,draw_rect,0,0); + SelectObject(hdc,map_gworld); + break; + + default: + if (((pic >= 400) ? anim_map_pats[pic - 400] : map_pats[pic]) < 30) { + // Try a little optimization + if ((pic < 400) && (where.x < area_to_put_on_map_rect.right - 1)) { + if (out_mode == TRUE) + what_ter2 = out[(where.x + 1)+ 48 * party.i_w_c.x][where.y + 48 * party.i_w_c.y]; + else what_ter2 = t_d.terrain[where.x + 1][where.y]; + if (out_mode == TRUE) + expl2 = out_e[(where.x + 1) + 48 * party.i_w_c.x][where.y + 48 * party.i_w_c.y]; + else expl2 = is_explored(where.x + 1,where.y); + pic2 = scenario.ter_types[what_ter2].picture; + if (pic2 < 400 && (map_pats[pic] == map_pats[pic2]) && (expl2 != 0)) { + draw_rect.right += 6; + map_graphic_placed[(where.x + 1)/ 8][where.y] = + map_graphic_placed[(where.x + 1)/ 8][where.y] | (unsigned char)(s_pow(2,(where.x + 1)% 8)); + } + } + SelectObject(hdc,map_brush[((pic >= 400) ? anim_map_pats[pic - 400] : map_pats[pic]) - 1]); + Rectangle(hdc,draw_rect.left, draw_rect.top,draw_rect.right + 1,draw_rect.bottom + 1); + break; + } +/* OffsetRect(&ter_temp_from, + 312 + 24 * ((map_pats[what_ter] - 30) / 5), + 138 + 6 * ((map_pats[what_ter] - 30) % 5)); + SelectObject(hdc,old_bmp); + rect_draw_some_item(mixed_gworld,ter_temp_from, + map_gworld,draw_rect,0,0); + SelectObject(hdc,map_gworld);*/ + break; + } + } + + + } + + SelectObject(hdc,old_brush); + SelectObject(hdc,old_pen); + SelectObject(hdc,old_bmp); + DeleteDC(hdc); + +} + +void draw_map (HWND the_dialog, short the_item) +//short the_item; // Being sneaky - if this gets value of 5, this is not a full restore - + // just update near party, if it gets 11, blank out middle and leave + // No redrawing in gworld + // If a 10, do a regular full restore + // Also, can get a 5 even when the window is not up, so have to make + // sure dialog exists before accessing it. +{ + RECT map_world_rect = {0,0,321,321}; + RECT whole_map_win_rect = {0,0,400,400}; + + location map_adj; + location where; + location kludge; + RECT area_to_draw_from,area_to_draw_on = {47,29,287,269}; + RECT area_to_put_on_map_rect; + RECT draw_rect; + RECT custom_from; + RECT ter_temp_from,dlogpicrect = {6,6,42,42},orig_draw_rect = {0,0,6,6}; + RECT view_rect= {0,0,48,48},tiny_rect = {0,0,32,32}, + redraw_rect = {0,0,48,48},big_rect = {0,0,64,64}; // RECTangle visible in view screen + COLORREF map_colors[6] = {RGB(0,0,0),RGB(63,223,95),RGB(0,0,255),RGB(191,0,191),RGB(255,0,0),RGB(204,204,204)}; + HDC hdc = NULL,hdc2; + HBITMAP old_bmp; + HBRUSH old_brush; + HPEN old_pen; + short i,j,pic,pic2; + Boolean draw_surroundings = FALSE,expl,expl2; + Boolean draw_pcs = TRUE; + short total_size = 48; // if full redraw, use this to figure out everything + short small_adj = 0; + unsigned char what_ter,what_ter2; + Boolean out_mode; +// UINT c; + +if(party.stuff_done[308][0] > 0 ){//map not available ; (temporary ?) assigned to SDF[308][0] + +if (modeless_exists[5] == TRUE){ +// RECT text_rect = {30,265,230,275}; // legacy text position (lower left corner) + RECT text_rect = {0,0,300,290}; + hdc2 = GetDC(the_dialog); + paint_pattern((HBITMAP) hdc2,2,map_world_rect,0); + SetBkMode(hdc2,TRANSPARENT); + SelectObject(hdc2,bold_font); + SetTextColor(hdc2,RGB(255,255,255)); + char_win_draw_string(hdc2,text_rect,"Map unavailable.",1,10); + GetClientRect(GetDlgItem(the_dialog,1),&draw_rect); + InvalidateRect(GetDlgItem(the_dialog,1),&draw_rect,FALSE); + fry_dc(the_dialog,hdc2); +} + return; +} + if (the_item == 4) { + draw_surroundings = TRUE; + the_item = 5; + } + if (kludge_force_full_refresh == TRUE) + draw_surroundings = TRUE; + if ((modeless_exists[5] == FALSE) && (the_item == 5) && (need_map_full_refresh == TRUE)) + return; + if ((modeless_exists[5] == FALSE) && (the_item == 10)) { + need_map_full_refresh = TRUE; + return; + } + if ((modeless_exists[5] == TRUE) && (the_item != 11) && (need_map_full_refresh == TRUE)) { + need_map_full_refresh = FALSE; + the_item = 10; + } + + OffsetRect(&area_to_draw_on,0,-23); + + if (the_item == 10) { + for (i = 0; i < 8; i++) + for (j = 0; j < 64; j++) + map_graphic_placed[i][j] = 0; + } + + town_map_adj.x = 0; + town_map_adj.y = 0; + // view rect is rect that is visible, redraw rect is area to redraw now + // area_to_draw_from is final draw from rect + // area_to_draw_on is final draw to rect + if ((is_out()) || ((is_combat()) && (which_combat_type == 0)) || + ((overall_mode == 20) && (store_pre_talk_mode == 0)) || + ((overall_mode == 21) && (store_pre_shop_mode == 0))) { + view_rect.left = minmax(0,8,party.loc_in_sec.x - 20); + view_rect.right = view_rect.left + 40; + view_rect.top = minmax(0,8,party.loc_in_sec.y - 20); + view_rect.bottom = view_rect.top + 40; + redraw_rect = view_rect; + } + else { + switch (town_type) { + case 0: + view_rect.left = minmax(0,24,c_town.p_loc.x - 20); + view_rect.right = view_rect.left + 40; + view_rect.top = minmax(0,24,c_town.p_loc.y - 20); + view_rect.bottom = view_rect.top + 40; + if (the_item == 5) + redraw_rect = view_rect; + else redraw_rect = big_rect; + total_size = 64; + break; + case 1: + view_rect.left = minmax(0,8,c_town.p_loc.x - 20); + view_rect.right = view_rect.left + 40; + view_rect.top = minmax(0,8,c_town.p_loc.y - 20); + view_rect.bottom = view_rect.top + 40; + redraw_rect = view_rect; + break; + case 2: + view_rect = tiny_rect; + redraw_rect = view_rect; + total_size = 32; + break; + } + } + if ((is_out()) || ((is_combat()) && (which_combat_type == 0)) || + ((overall_mode == 20) && (store_pre_talk_mode == 0)) || + ((overall_mode == 21) && (store_pre_shop_mode == 0)) || + (((is_town()) || (is_combat())) && (town_type != 2))) { + area_to_draw_from = view_rect; + area_to_draw_from.left *= 6; + area_to_draw_from.right *= 6; + area_to_draw_from.top *= 6; + area_to_draw_from.bottom *= 6; + } + else { + area_to_draw_from = area_to_draw_on; + OffsetRect(&area_to_draw_from,-1 * area_to_draw_from.left,-1 * area_to_draw_from.top); + small_adj = 0; + } + + if (is_combat()) + draw_pcs = FALSE; + + // make map pens + if (hbrush[0] == NULL) { + for (i = 0; i < 6; i++) { + hbrush[i] = CreateSolidBrush(map_colors[i]); + hpen[i] = CreatePen(PS_SOLID,1,map_colors[i]); + } + } + + hdc = CreateCompatibleDC(main_dc); + old_bmp = (HBITMAP) SelectObject(hdc, map_gworld); + old_brush = (HBRUSH) SelectObject(hdc,map_brush[0]); + old_pen = (HPEN) SelectObject(hdc,GetStockObject(NULL_PEN)); + + if (the_item == 11) { + SelectObject(hdc,GetStockObject(WHITE_BRUSH)); + Rectangle(hdc, map_world_rect.left,map_world_rect.top,map_world_rect.right,map_world_rect.bottom); + draw_pcs = FALSE; + } + else { + if (modeless_exists[5] == TRUE) { + SetDlgItemText(the_dialog,3,""); + } + + if (is_out()) { // for outside map, adjust for where in outdoors is being mapped + if (party.i_w_c.x == 1) + map_adj.x += 48; + if (party.i_w_c.y == 1) + map_adj.y += 48; + } + + // Now, if doing just partial restore, crop redraw_rect to save time. + if (the_item == 5) { + if ((is_out()) || ((is_combat()) && (which_combat_type == 0)) || + ((overall_mode == 20) && (store_pre_talk_mode == 0)) || + ((overall_mode == 21) && (store_pre_shop_mode == 0))) + kludge = party.p_loc.toLocal(); + else if (is_combat()) + kludge = pc_pos[current_pc]; + else kludge = c_town.p_loc; + redraw_rect.left = max(0,kludge.x - 4); + redraw_rect.right = min(view_rect.right,kludge.x + 5); + redraw_rect.top = max(0,kludge.y - 4); + redraw_rect.bottom = min(view_rect.bottom,kludge.y + 5); + } + + // Now, if shopping or talking, just don't touch anything. + if ((overall_mode == 21) || (overall_mode == 20)) + redraw_rect.right = -1; + + if ((is_out()) || + ((is_combat()) && (which_combat_type == 0)) || + ((overall_mode == 20) && (store_pre_talk_mode == 0)) || + ((overall_mode == 21) && (store_pre_shop_mode == 0))) + out_mode = TRUE; + else out_mode = FALSE; + + area_to_put_on_map_rect = redraw_rect; + if (the_item == 10) { + area_to_put_on_map_rect.top = area_to_put_on_map_rect.left = 0; + area_to_put_on_map_rect.right = area_to_put_on_map_rect.bottom = total_size; + } + + for (where.x= area_to_put_on_map_rect.left; where.x < area_to_put_on_map_rect.right; where.x++) + for (where.y= area_to_put_on_map_rect.top; where.y < area_to_put_on_map_rect.bottom; where.y++) + if ((map_graphic_placed[where.x / 8][where.y] & (unsigned char)(s_pow(2,where.x % 8))) == 0) + { + draw_rect = orig_draw_rect; + OffsetRect(&draw_rect,6 * where.x + small_adj, 6 * where.y + small_adj); + + if (out_mode == TRUE) + what_ter = out[where.x + 48 * party.i_w_c.x][where.y + 48 * party.i_w_c.y]; + else what_ter = t_d.terrain[where.x][where.y]; + + ter_temp_from = orig_draw_rect; + + if (out_mode == TRUE) + expl = out_e[where.x + 48 * party.i_w_c.x][where.y + 48 * party.i_w_c.y]; + else expl = is_explored(where.x,where.y); + + if (expl != 0) { + map_graphic_placed[where.x / 8][where.y] = + map_graphic_placed[where.x / 8][where.y] | (unsigned char)(s_pow(2,where.x % 8)); + pic = scenario.ter_types[what_ter].picture; + if (pic >= 1000) { + + if (spec_scen_g != NULL) { + + pic = pic % 1000; + custom_from = coord_to_rect(pic % 10, pic / 10); + OffsetRect(&custom_from,-13,-13); + SelectObject(hdc,old_bmp); + rect_draw_some_item(spec_scen_g,custom_from,map_gworld,draw_rect,0,0); + SelectObject(hdc,map_gworld); + } + } + else switch ((pic >= 400) ? anim_map_pats[pic - 400] : map_pats[pic]) { + case 0: case 10: case 11: + if (terrain_pic[what_ter] < 400) + OffsetRect(&ter_temp_from, + 6 * (terrain_pic[what_ter] % 10) + 312,6 * (terrain_pic[what_ter] / 10)); + else OffsetRect(&ter_temp_from, + 24 * ((terrain_pic[what_ter] - 400) / 5) + 312,6 * ((terrain_pic[what_ter] - 400) % 5) + 163); + SelectObject(hdc,old_bmp); + rect_draw_some_item(mixed_gworld,ter_temp_from, + map_gworld,draw_rect,0,0); + SelectObject(hdc,map_gworld); + break; + + default: + if (((pic >= 400) ? anim_map_pats[pic - 400] : map_pats[pic]) < 30) {//always true ?!? + // Try a little optimization + if ((pic < 400) && (where.x < area_to_put_on_map_rect.right - 1)) { + if (out_mode == TRUE) + what_ter2 = out[(where.x + 1)+ 48 * party.i_w_c.x][where.y + 48 * party.i_w_c.y]; + else what_ter2 = t_d.terrain[where.x + 1][where.y]; + if (out_mode == TRUE) + expl2 = out_e[(where.x + 1) + 48 * party.i_w_c.x][where.y + 48 * party.i_w_c.y]; + else expl2 = is_explored(where.x + 1,where.y); + pic2 = scenario.ter_types[what_ter2].picture; + if (pic2 < 400 && (map_pats[pic] == map_pats[pic2]) && (expl2 != 0)) { + draw_rect.right += 6; + map_graphic_placed[(where.x + 1)/ 8][where.y] = + map_graphic_placed[(where.x + 1)/ 8][where.y] | (unsigned char)(s_pow(2,(where.x + 1)% 8)); + } + } + SelectObject(hdc,map_brush[((pic >= 400) ? anim_map_pats[pic - 400] : map_pats[pic]) - 1]); + Rectangle(hdc,draw_rect.left, draw_rect.top,draw_rect.right + 1,draw_rect.bottom + 1); + break; + } +/* OffsetRect(&ter_temp_from, + 312 + 24 * ((map_pats[what_ter] - 30) / 5), + 138 + 6 * ((map_pats[what_ter] - 30) % 5));//138 ??? <= nevermind cause never called ... + SelectObject(hdc,old_bmp); + rect_draw_some_item(mixed_gworld,ter_temp_from, + map_gworld,draw_rect,0,0); + SelectObject(hdc,map_gworld);*/ + break; + } + } + } + + } + + SelectObject(hdc,old_brush); + SelectObject(hdc,old_pen); + SelectObject(hdc,old_bmp); + DeleteDC(hdc); + + // Now place terrain map gworld + if (modeless_exists[5] == TRUE) { + + // graphics goes here + hdc2 = GetDC(the_dialog); + if ((draw_surroundings == TRUE) || (the_item != 5)) { // redraw much stuff + paint_pattern((HBITMAP) hdc2,2,whole_map_win_rect,0); + SetBkMode(hdc2,TRANSPARENT); + SelectObject(hdc2,small_bold_font); + GetClientRect(GetDlgItem(the_dialog,1),&draw_rect); + InvalidateRect(GetDlgItem(the_dialog,1),&draw_rect,FALSE); + } + + rect_draw_some_item(map_gworld,area_to_draw_from,(HBITMAP) hdc2,area_to_draw_on,0,2); + } + + // Now place PCs and monsters + if ((draw_pcs == TRUE) && (modeless_exists[5] == TRUE)) { + if ((is_town()) && (party.stuff_done[305][2] > 0)) + for (i = 0; i < T_M; i++) + if (c_town.monst.dudes[i].active > 0) { + where = c_town.monst.dudes[i].m_loc; + if ((is_explored(where.x,where.y)) && + ((where.x >= view_rect.left) && (where.x <= view_rect.right) + && (where.y >= view_rect.top) && (where.x <= view_rect.bottom))){ + + draw_rect.left = area_to_draw_on.left + 6 * (where.x - view_rect.left); + draw_rect.top = area_to_draw_on.top + 6 * (where.y - view_rect.top); + draw_rect.right = draw_rect.left + 6; + draw_rect.bottom = draw_rect.top + 6; + + map_graphic_placed[where.x / 8][where.y] = + map_graphic_placed[where.x / 8][where.y] & ~((unsigned char)(s_pow(2,where.x % 8))); + SelectObject(hdc2,hpen[0]); + SelectObject(hdc2,hbrush[0]); + Rectangle(hdc2, draw_rect.left,draw_rect.top,draw_rect.right,draw_rect.bottom); + SelectObject(hdc2,hpen[4]); + SelectObject(hdc2,hbrush[5]); + Ellipse(hdc2, draw_rect.left,draw_rect.top,draw_rect.right,draw_rect.bottom); + } + } + + if ((overall_mode != 21) && (overall_mode != 20)) { + where = (is_town()) ? c_town.p_loc : party.p_loc.toLocal(); + + draw_rect.left = area_to_draw_on.left + 6 * (where.x - view_rect.left); + draw_rect.top = area_to_draw_on.top + 6 * (where.y - view_rect.top); + draw_rect.right = draw_rect.left + 6; + draw_rect.bottom = draw_rect.top + 6; + if ((where.x >= 0) && (where.x < 64) && + (where.y >= 0) && (where.y < 64)) { + map_graphic_placed[where.x / 8][where.y] = /* Crash! vvv */ + map_graphic_placed[where.x / 8][where.y] & ~((unsigned char)(s_pow(2,where.x % 8))); + + SelectObject(hdc2,hpen[0]); + SelectObject(hdc2,hbrush[0]); + Rectangle(hdc2, draw_rect.left,draw_rect.top,draw_rect.right,draw_rect.bottom); + SelectObject(hdc2,hpen[3]); + SelectObject(hdc2,hbrush[3]); + Ellipse(hdc2, draw_rect.left,draw_rect.top,draw_rect.right,draw_rect.bottom); + } + } + } + + // Now exit gracefully + + if (modeless_exists[5] == TRUE) { + + // graphics goes here + fry_dc(the_dialog,hdc2); + if ((draw_surroundings == TRUE) || (the_item != 5)) { // redraw much stuff + draw_dialog_graphic(the_dialog, dlogpicrect, + 721, FALSE,0); // draw the map graphic + } + } +} + +BOOL CALLBACK map_dialog_proc(HWND hDlg, UINT message, WPARAM wParam, LPARAM) +{ + switch (message) { + case WM_INITDIALOG: + if (store_map_window_rect.right > 0) + MoveWindow(hDlg,store_map_window_rect.left,store_map_window_rect.top, + store_map_window_rect.right - store_map_window_rect.left, + store_map_window_rect.bottom - store_map_window_rect.top,FALSE); + else { + GetWindowRect(hDlg,&store_map_window_rect); + MoveWindow(hDlg,294 + ulx, 47 + uly, + store_map_window_rect.right - store_map_window_rect.left, + store_map_window_rect.bottom - store_map_window_rect.top,FALSE); + + } + kludge_force_full_refresh = TRUE; + draw_map(hDlg,10); + kludge_force_full_refresh = FALSE; + SetFocus(mainPtr); + break; + case WM_ERASEBKGND: + return 1; + + case WM_PAINT: + kludge_force_full_refresh = TRUE; + draw_map(hDlg,5); + kludge_force_full_refresh = FALSE; + return FALSE; + + case WM_KEYDOWN: + if (wParam != VK_RETURN) + return 0; + case WM_COMMAND: + modeless_exists[5] = FALSE; + GetWindowRect(hDlg,&store_map_window_rect); + DestroyWindow(hDlg); + return TRUE; + case WM_DESTROY: + modeless_exists[5] = FALSE; + return 0; + } + return FALSE; +} + + +void display_map() +{ + if ( modeless_exists[5] == TRUE) + return; + + modeless_exists[5] = TRUE; + + modeless_dialogs[5] = CreateDialog(store_hInstance, + MAKEINTRESOURCE(1046),mainPtr,(DLGPROC) map_dialog_proc); +} + +Boolean quadrant_legal(short i, short j) +{ + if (party.outdoor_corner.x + i >= scenario.out_width) return FALSE; + if (party.outdoor_corner.y + j >= scenario.out_height) return FALSE; + if (party.outdoor_corner.x + i < 0) return FALSE; + if (party.outdoor_corner.y + j < 0) return FALSE; + return TRUE; +} diff --git a/Win32/Blades of Exile/TOWN.H b/Win32/Blades of Exile/TOWN.H new file mode 100644 index 00000000..f61e9c8f --- /dev/null +++ b/Win32/Blades of Exile/TOWN.H @@ -0,0 +1,24 @@ +void force_town_enter(short which_town,location where_start); +void start_town_mode(short which_town, short entry_dir); +location end_town_mode(short switching_level,location destination); // returns new party location +void handle_leave_town_specials(short town_number, short which_spec,location start_loc) ; +void handle_town_specials(short town_number, short entry_dir,location start_loc) ; +void start_town_combat(short direction); +short end_town_combat(); +void place_party(short direction); +void create_town_combat_terrain(); +void create_out_combat_terrain(short type,short num_walls); +//void elim_monst(unsigned char which,short spec_a,short spec_b); +void do_shop(short which,short min,short max,char *store_name); +void buy_food(short cost,short per,char *food_name); +void healing_shop(); +void do_sell(short which); +void dump_gold(short print_mes); +void erase_specials(); +void erase_out_specials(); +void clear_map(); +void draw_map (HWND the_dialog, short the_item); +void draw_map_rect (HWND the_dialog, short ul_x, short ul_y, short lr_x, short lr_y); +void display_map(); +void check_done(); +Boolean quadrant_legal(short i, short j) ; diff --git a/Win32/Scenarios Editor/1.cur b/Win32/Scenarios Editor/1.cur new file mode 100644 index 00000000..66301fb0 Binary files /dev/null and b/Win32/Scenarios Editor/1.cur differ diff --git a/Win32/Scenarios Editor/2.cur b/Win32/Scenarios Editor/2.cur new file mode 100644 index 00000000..7175d3da Binary files /dev/null and b/Win32/Scenarios Editor/2.cur differ diff --git a/Win32/Scenarios Editor/3.cur b/Win32/Scenarios Editor/3.cur new file mode 100644 index 00000000..db318852 Binary files /dev/null and b/Win32/Scenarios Editor/3.cur differ diff --git a/Win32/Scenarios Editor/4.cur b/Win32/Scenarios Editor/4.cur new file mode 100644 index 00000000..17ed3b83 Binary files /dev/null and b/Win32/Scenarios Editor/4.cur differ diff --git a/Win32/Scenarios Editor/5.cur b/Win32/Scenarios Editor/5.cur new file mode 100644 index 00000000..56d035e7 Binary files /dev/null and b/Win32/Scenarios Editor/5.cur differ diff --git a/Win32/Scenarios Editor/6.cur b/Win32/Scenarios Editor/6.cur new file mode 100644 index 00000000..0110f7aa Binary files /dev/null and b/Win32/Scenarios Editor/6.cur differ diff --git a/Win32/Scenarios Editor/7.cur b/Win32/Scenarios Editor/7.cur new file mode 100644 index 00000000..c82b8a8b Binary files /dev/null and b/Win32/Scenarios Editor/7.cur differ diff --git a/Win32/Scenarios Editor/8.cur b/Win32/Scenarios Editor/8.cur new file mode 100644 index 00000000..268057d3 Binary files /dev/null and b/Win32/Scenarios Editor/8.cur differ diff --git a/Win32/Scenarios Editor/BLSCENED.CPP b/Win32/Scenarios Editor/BLSCENED.CPP new file mode 100644 index 00000000..ea534fd3 --- /dev/null +++ b/Win32/Scenarios Editor/BLSCENED.CPP @@ -0,0 +1,1013 @@ +// Blades of Exile Scenario Editor + +#include + +#include "stdlib.h" +#include "string.h" +#include "stdio.h" +#include "math.h" + + +#include "Global.h" +#include "graphics.h" +#include "tactions.h" +#include "tfileio.h" +#include "dlogtool.h" +#include "buttonmg.h" +#include "edsound.h" +#include "townout.h" +#include "scenario.h" +#include "keydlgs.h" +#include "graphutl.h" + +void check_game_done(); + +void check_colors(); +bool need_redraw = FALSE; +void cursor_stay(); +Boolean verify_restore_quit(short mode); +void max_window(HWND window); +short check_cd_event(HWND hwnd,UINT message,WPARAM wparam, LPARAM lparam); +short cur_viewing_mode = 0; +extern unsigned long anim_ticks; +extern terrain_type_type store_ter; +extern BOOL do_choose_anim; +extern BOOL custom_pic; +extern BOOL play_anim; + +/* Mac stuff globals */ +Boolean All_Done = FALSE; +Boolean in_startup_mode = TRUE,mouse_button_held = FALSE; +Boolean play_sounds = TRUE; +Boolean palette_suspect = FALSE,window_in_front = TRUE; +Boolean change_made = FALSE; + +HWND right_sbar; + +short cur_town; +location cur_out; +short mode_count = 0; + +/* Display globals */ +short give_delays = 0; +Boolean dialog_not_toast = TRUE; +short dialog_answer; +char file_path_name[256]; + +/* Windoze stuff globals */ +Boolean cursor_shown = TRUE; + +short ulx = 0, uly = 0; + +HWND mainPtr; +HFONT font,small_bold_font,italic_font,underline_font,bold_font,tiny_font; + +HDC main_dc,main_dc2,main_dc3; +HINSTANCE store_hInstance; +HACCEL accel; +BOOL event_handled; + +scenario_data_type scenario; +piles_of_stuff_dumping_type *data_store; +RECT right_sbar_rect; +town_record_type town; +big_tr_type t_d; +outdoor_record_type current_terrain; +talking_record_type talking; +short overall_mode = 61; +scen_item_data_type scen_item_list; +char scen_strs[160][256]; +char scen_strs2[110][256]; +char talk_strs[170][256]; +char town_strs[180][256]; +unsigned char borders[4][50]; +short max_dim[3] = {64,48,32}; +short cen_x, cen_y; +Boolean editing_town = FALSE; +short town_type = 0; // 0 - big 1 - ave 2 - small +char szWinName[] = "BoE for Win32 dialogs"; +char szAppName[] = "Classic BoE Scenario Editor"; + +char szBladBase[128]; + +void loadSettingsFromFile() +{ + const int BUFFER_LEN = 64; + char buffer[BUFFER_LEN]; + + const char * iniFile = "./blades.ini"; + const char * section = "Scenario Editor"; + + GetPrivateProfileString(section, "bladbase.exs", "bladbase.exs", + szBladBase, 126, iniFile); + szBladBase[127] = 0; + GetPrivateProfileString(section, "play_sounds", "1", buffer, BUFFER_LEN, iniFile); + play_sounds = (atoi(buffer))? TRUE : FALSE; + GetPrivateProfileString(section, "play_animations", "1", buffer, BUFFER_LEN, iniFile); + play_anim = (atoi(buffer))? TRUE : FALSE; + if(play_anim == TRUE){//if option is active, check the menu item + HMENU menu,big_menu; + big_menu = GetMenu(mainPtr); + menu = GetSubMenu(big_menu,4); + CheckMenuItem(menu,411,MF_BYCOMMAND | MF_CHECKED); + } +} + +void saveSettingsToFile() +{ + char tmp[] = "?"; + const char * iniFile = "./blades.ini"; + const char * section = "Scenario Editor"; + + WritePrivateProfileString(section, "bladbase.exs", szBladBase, iniFile); + WritePrivateProfileString(section, "play_sounds", (play_sounds)? "1" : "0", iniFile); + WritePrivateProfileString(section, "play_animations", (play_anim) ? "1" : "0", iniFile); +} + +Boolean block_erase = FALSE; + +RECT windRect; + +long CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM); +Boolean handle_menu (short, HMENU); + +int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR, int nCmdShow) +{ + + MSG msg; + WNDCLASS wndclass,wndclass2; + short i,seed; + + if (!hPrevInstance) { + wndclass.style = CS_HREDRAW | CS_VREDRAW | CS_BYTEALIGNWINDOW; + wndclass.lpfnWndProc = WndProc; + wndclass.cbClsExtra = 0; + wndclass.cbWndExtra = 0; + wndclass.hInstance = hInstance; + wndclass.hIcon = LoadIcon(hInstance,MAKEINTRESOURCE(10)); + wndclass.hCursor = NULL; + wndclass.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH); + wndclass.lpszMenuName = MAKEINTRESOURCE(1); + wndclass.lpszClassName = szAppName; + + RegisterClass(&wndclass); + + wndclass2.style = CS_HREDRAW | CS_VREDRAW | CS_BYTEALIGNWINDOW; + wndclass2.lpfnWndProc = WndProc; + wndclass2.cbClsExtra = 0; + wndclass2.cbWndExtra = 0; + wndclass2.hInstance = hInstance; + wndclass2.hIcon = LoadIcon(hInstance,MAKEINTRESOURCE(10)); + wndclass2.hCursor = NULL; + wndclass2.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH); + wndclass2.lpszMenuName = NULL; + wndclass2.lpszClassName = szWinName; + + RegisterClass(&wndclass2); + } + + mainPtr = CreateWindow (szAppName, + "Classic BoE Scenario Editor Beta 1", + WS_OVERLAPPEDWINDOW, + 0, + 0, + 536, + 478, + NULL, + NULL, + hInstance, + NULL); + + + if (!hPrevInstance) { // initialize + //center_window(mainPtr); + Get_Path(file_path_name); + store_hInstance = hInstance; + accel = LoadAccelerators(hInstance, MAKEINTRESOURCE(1)); + loadSettingsFromFile(); + + seed = (short) GetCurrentTime(); + srand(seed); + + data_store = new piles_of_stuff_dumping_type; + + max_window(mainPtr); + GetWindowRect(mainPtr,&windRect); + SetTimer(mainPtr,1,20,NULL); + + ShowWindow(mainPtr,nCmdShow); + Set_up_win (); + init_lb(); + init_rb(); + init_town(1); + init_out(); + + init_scenario(); + + font = CreateFont(12,0,0,0,0, 0,0,0, 0,0, + 0,0,0,"MS Sans Serif"); + small_bold_font = CreateFont(12,0,0,0,700, 0,0,0, 0,0, + 0,0,0,"MS Sans Serif"); + italic_font = CreateFont(12,0,0,0,0, 1,0,0, 0,0, + 0,0,0,"MS Sans Serif"); + underline_font = CreateFont(12,0,0,0,0, 0,1,0, 0,0, + 0,0,0,"MS Sans Serif"); + bold_font = CreateFont(14,0,0,0,700, 0,0,0, 0,0, + 0,0,0,"MS Sans Serif"); + tiny_font = font; + load_sounds(); + + right_sbar_rect.top = RIGHT_AREA_UL_Y; + right_sbar_rect.left = RIGHT_AREA_UL_X + RIGHT_AREA_WIDTH - 1 - 16; + right_sbar_rect.bottom = RIGHT_AREA_UL_Y + RIGHT_AREA_HEIGHT; + right_sbar_rect.right = RIGHT_AREA_UL_X + RIGHT_AREA_WIDTH - 1; + right_sbar = CreateWindow("scrollbar",NULL, + WS_CHILD | WS_TABSTOP | SBS_VERT, right_sbar_rect.left + ulx,right_sbar_rect.top + uly, + right_sbar_rect.right - right_sbar_rect.left, + right_sbar_rect.bottom - right_sbar_rect.top, + mainPtr,(HMENU) 1,store_hInstance,NULL); + + init_screen_locs(); + set_up_start_screen(); + + file_initialize(); + check_colors(); + cursor_stay(); + update_item_menu(); + shut_down_menus(0); + + cd_init_dialogs(); + + } + + event_handled = FALSE; + while(GetMessage(&msg,NULL,0,0)) { + if (event_handled == FALSE) { + if (!TranslateAccelerator(mainPtr, accel, &msg)) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + } + + delete data_store; + saveSettingsToFile(); + + return msg.wParam; +} + +long CALLBACK WndProc (HWND hwnd, UINT message,WPARAM wParam, LPARAM lParam) +{ +HDC hdc; +PAINTSTRUCT ps; +RECT rect; +//RECT s_rect = {0,0,30,30},d_rect = {0,0,30,30},d2 = {0,0,420,216},s2 = {0,0,420,216}; +POINT press; +short handled = 0,sbar_pos = 0,old_setting; +long which_sbar; +int min = 0, max = 0; +HMENU menu; +RECT wind_rect; +POINT p; +RECT r; + + switch (message) { + case WM_KEYDOWN: + if (hwnd != mainPtr) { + check_cd_event(hwnd,message,wParam,lParam); + } + else { + All_Done = handle_syskeystroke(wParam,lParam,&handled); + } + return 0; + break; + + case WM_CHAR: + if (hwnd != mainPtr) + check_cd_event(hwnd,message,wParam,lParam); + else { + All_Done = handle_keystroke(wParam,lParam); + } + return 0; + break; + + case WM_LBUTTONDOWN: + cursor_stay(); + if (hwnd != mainPtr) + check_cd_event(hwnd,message,wParam,lParam); + else { + SetFocus(hwnd); + press = MAKEPOINT(lParam); + + All_Done = handle_action(press, wParam,lParam); + check_game_done(); + } + return 0; + break; + + case WM_LBUTTONUP: + mouse_button_held = FALSE; + break; + + case WM_RBUTTONDOWN: + mouse_button_held = FALSE; + cursor_stay(); + if (hwnd != mainPtr) + check_cd_event(hwnd,message,wParam,lParam); + else { + SetFocus(hwnd); + press = MAKEPOINT(lParam); + + All_Done = handle_action(press, wParam,-2); + check_game_done(); + } + return 0; + break; + + case WM_TIMER: + // first, mouse held? + if ((wParam == 1) && (mouse_button_held == TRUE)) { + GetCursorPos(&p); + ScreenToClient(mainPtr,&p); + All_Done = handle_action(p, 0,0); + } + // second, refresh cursor? + if ((wParam == 1) && (overall_mode < 60) && (GetFocus() == mainPtr)) { + GetCursorPos(&p); + ScreenToClient(mainPtr,&p); + GetClientRect(mainPtr,&r); + if (PtInRect(&r,p)) + restore_cursor(); + } + + if(play_anim == TRUE){ + anim_ticks++; + if(overall_mode < 60){ + draw_terrain(); + } + if(overall_mode == 62){ + if(store_ter.picture >= 2000){ + custom_pic = 5; + csp(813,14,store_ter.picture - 2000); + } + else if (store_ter.picture >= 400 && store_ter.picture < 1000){ + csp(813,14,store_ter.picture - 100); + } + if(do_choose_anim == TRUE){ + put_choice_pics(); + } + } + } + break; + + case WM_PALETTECHANGED: + palette_suspect = TRUE; + return 0; + + case WM_ACTIVATE: + if (hwnd == mainPtr) { + if (((wParam == WA_ACTIVE) ||(wParam == WA_CLICKACTIVE)) && + (palette_suspect == TRUE)) { + palette_suspect = FALSE; + } + if ((wParam == WA_ACTIVE) ||(wParam == WA_CLICKACTIVE)) { + window_in_front = TRUE; + } + if (wParam == WA_INACTIVE) { + window_in_front = FALSE; + } + } + return 0; + + + case WM_MOUSEMOVE: + if ((mouse_button_held == TRUE) && (hwnd == mainPtr)) { + press = MAKEPOINT(lParam); + All_Done = handle_action(press, wParam,lParam); + } + restore_cursor(); + return 0; + + case WM_PAINT: + hdc = BeginPaint(hwnd,&ps); + EndPaint(hwnd,&ps); + if (hwnd != mainPtr) + check_cd_event(hwnd,message,wParam,lParam); + else redraw_screen(); + return 0; + + case WM_VSCROLL: + which_sbar = GetWindowLong((HWND) lParam, GWL_ID); + switch (which_sbar) { + case 1: + sbar_pos = GetScrollPos(right_sbar,SB_CTL); + old_setting = sbar_pos; + GetScrollRange(right_sbar,SB_CTL,&min,&max); + switch (LOWORD(wParam)) { + case SB_PAGEDOWN: sbar_pos += NRSONPAGE - 1; break; + case SB_LINEDOWN: sbar_pos++; break; + case SB_PAGEUP: sbar_pos -= NRSONPAGE - 1; break; + case SB_LINEUP: sbar_pos--; break; + case SB_TOP: sbar_pos = 0; break; + case SB_BOTTOM: sbar_pos = max; break; + case SB_THUMBPOSITION: + case SB_THUMBTRACK: + sbar_pos = HIWORD(wParam); + break; + } + if (sbar_pos < 0) + sbar_pos = 0; + if (sbar_pos > max) + sbar_pos = max; + SetScrollPos(right_sbar,SB_CTL,sbar_pos,TRUE); + if (sbar_pos != old_setting) + draw_rb(); + break; + } + SetFocus(mainPtr); + return 0; + + case WM_COMMAND: + if (hwnd == mainPtr) { + + menu = GetMenu(mainPtr); + handle_menu((short) wParam, menu); + check_game_done(); + } + else { + check_cd_event(hwnd,message,wParam,lParam); + } + return 0; + + + case WM_DESTROY: + case WM_CLOSE: + if (hwnd == mainPtr) { + discard_graphics(); + PostQuitMessage(0); + } + return 0; + case WM_QUIT: + if (hwnd == mainPtr) + discard_graphics(); + break; + + + } + +return DefWindowProc(hwnd,message,wParam,lParam); +} + +void check_game_done() +{ + if (All_Done == TRUE) { + discard_graphics(); + PostQuitMessage(0); + } +} + +Boolean handle_menu (short item, HMENU menu) +{ + short i,j; + Boolean to_return = FALSE; + short item_hit; + Boolean need_redraw = FALSE; + item_hit = item; + + switch (item) { + case -1: break; + case 1: // open + load_scenario(); + if (overall_mode == 60) { + update_item_menu(); + set_up_main_screen(); + } + break; + case 2: // save + modify_lists(); + save_scenario(); + break; + case 3: // new scen + build_scenario(); + if (overall_mode == 60) + set_up_main_screen(); + break; + + case 5: // quit + if (save_check(869) == FALSE) + break; + discard_graphics(); + PostQuitMessage(0); + break; + + // Scenario Menu + + case 101: + if (change_made == TRUE) { + give_error("You need to save the changes made to your scenario before you can add a new town.", + "",0); + return to_return; + } + if (scenario.num_towns >= 200) { + give_error("You have reached the limit of 200 towns you can have in one scenario.", + "",0); + return to_return; + } + if (new_town(scenario.num_towns) == TRUE) + set_up_main_screen(); + break; + case 103: + edit_scen_details(); + break; + case 104: + edit_scen_intro(); + break; + case 105: + set_starting_loc(); + break; + case 106: overall_mode = 47; + set_string("Select party starting location.",""); + break; + case 109: SetScrollPos(right_sbar,SB_CTL,0,TRUE); start_special_editing(0,0); break; + case 110: + SetScrollPos(right_sbar,SB_CTL,0,TRUE); start_string_editing(0,0); + break; + case 111: + if (change_made == TRUE) { + give_error("You need to save the changes made to your scenario before you can add a new town.", + "",0); + return to_return; + } + i = pick_import_town(841,0); + if (i >= 0) { + import_town(i); + change_made = TRUE; + redraw_screen(); + } + break; + case 112: + edit_save_rects(); + break; + case 113: + edit_horses(); + break; + case 114: + edit_boats(); + break; + case 115: + edit_add_town(); + break; + case 116: + edit_scenario_events(); + break; + case 117: + edit_item_placement(); + break; + case 118: + if (change_made == TRUE) { + give_error("You need to save the changes made to your scenario before you can delete a town.", + "",0); + return to_return; + } + if (scenario.num_towns == 1) { + give_error("You can't delete the last town in a scenario. All scenarios must have at least 1 town.", + "",0); + return to_return; + } + if (scenario.num_towns - 1 == cur_town) { + give_error("You can't delete the last town in a scenario while you're working on it. Load a different town, and try this again.", + "",0); + return to_return; + } + if (scenario.num_towns - 1 == scenario.which_town_start) { + give_error("You can't delete the last town in a scenario while it's the town the party starts the scenario in. Change the parties starting point and try this again.", + "",0); + return to_return; + } + if (fancy_choice_dialog(865,0) == 1) + delete_last_town(); + break; + case 119: + if (fancy_choice_dialog(866,0) == 1) + start_data_dump(); + break; + case 120: + if (change_made == TRUE) { + give_error("You need to save the changes made to your scenario before you can delete a town.", + "",0); + return to_return; + } + if (fancy_choice_dialog(871,0) == 1) + scen_text_dump(); + redraw_screen(); + break; + + case 121: + if (fancy_choice_dialog(868,0) == 1) + start_shopping_data_dump(); + break; + + // Town Menu + case 201: edit_town_details(); break; + case 202: edit_town_wand(); break; + case 203: overall_mode = 9; + mode_count = 2; + set_cursor(5); + set_string("Set town boundary","Select upper left corner"); + break; + case 204: frill_up_terrain(); break; + case 205: unfrill_terrain(); break; + case 206: edit_town_strs(); break; + case 208: if (fancy_choice_dialog(863,0) == 2) // add random + break; + place_items_in_town(); + break; + case 209: for (i = 0; i < 64; i++) // set not prop + town.preset_items[i].property = 0; + fancy_choice_dialog(861,0); + draw_terrain(); + break; + case 210: if (fancy_choice_dialog(862,0) == 2) // clear all items + break; + for (i = 0; i < 64; i++) + town.preset_items[i].item_code = -1; + draw_terrain(); + break; + case 213: SetScrollPos(right_sbar,SB_CTL,0,TRUE); start_special_editing(2,0); break; + case 214: SetScrollPos(right_sbar,SB_CTL,0,TRUE); start_string_editing(2,0); break; + case 215: edit_advanced_town(); break; + case 216: edit_town_events(); break; + case 217: if (fancy_choice_dialog(872,0) == 2) // clear all monsters + break; + for (i = 0; i < 60; i++) { + t_d.creatures[i].number = 0; + t_d.creatures[i].start_loc.x = 0; + t_d.creatures[i].start_loc.y = 0; + } + break; + case 218: if (fancy_choice_dialog(873,0) == 2) // clear all special encounters + break; + for (i = 0; i < 50; i++) { + town.special_locs[i].x = 100; + town.special_locs[i].y = 0; + town.spec_id[i] = 255; + } + break; + case 219: if (fancy_choice_dialog(874,0) == 2) // clear all fields + break; + for (i = 0; i < 50; i++) + if ((town.preset_fields[i].field_type >= 0) && (town.preset_fields[i].field_type < 9)) { + town.preset_fields[i].field_type = 0; + town.preset_fields[i].field_loc.x = 0; + town.preset_fields[i].field_loc.y = 0; + } + break; + + case 220: if (fancy_choice_dialog(876,0) == 2) // clear all stains + break; + for (i = 0; i < 50; i++) + if ((town.preset_fields[i].field_type > 13) && (town.preset_fields[i].field_type < 22)) { + town.preset_fields[i].field_type = 0; + town.preset_fields[i].field_loc.x = 0; + town.preset_fields[i].field_loc.y = 0; + } + break; + + // Outdoor Menu + case 301: outdoor_details(); break; + case 302: edit_out_wand(0); break; + case 303: edit_out_wand(1); break; + case 304: frill_up_terrain(); break; + case 305: unfrill_terrain(); break; + case 306: edit_out_strs(); break; + case 311: SetScrollPos(right_sbar,SB_CTL,0,TRUE); start_special_editing(1,0); break; + case 312: SetScrollPos(right_sbar,SB_CTL,0,TRUE); start_string_editing(1,0); break; + case 313: if (fancy_choice_dialog(875,0) == 2) // clear all special encounters + break; + for (i = 0; i < 18; i++) { + current_terrain.special_locs[i].x = 100; + current_terrain.special_locs[i].y = 0; + current_terrain.special_id[i] = 255; + } + break; + + case 401: + start_town_edit(); + break; + case 402: + start_out_edit(); + break; + case 403: + short x, y; + location spot_hit; + + if (editing_town == false) { + + if (change_made == TRUE) { + if (save_check(859) == FALSE) + break; + } + x = pick_out(cur_out); + if (x >= 0) { + spot_hit.x = x / 100; + spot_hit.y = x % 100; + load_outdoors(spot_hit,0); + augment_terrain(spot_hit); + start_out_edit(); + } + + } + else { + if (change_made == TRUE) { + if (save_check(859) == FALSE) + break; + } + x = pick_town_num(855,cur_town); + if (x >= 0) { + load_town(x); + start_town_edit(); + } + } + break; + case 404: + set_up_main_screen(); + start_terrain_editing(); + break; + case 405: + set_up_main_screen(); + start_monster_editing(0); + break; + case 406: + start_item_editing(0); + break; + case 407: + set_up_main_screen(); + break; + + case 408: // switch view + cur_viewing_mode = 1 - cur_viewing_mode; + need_redraw = TRUE; + draw_main_screen(); + draw_terrain(); + break; + + case 409: // load previous town/outdoor zone + if (editing_town == true) { + if (cur_town == 0) + load_town(scenario.num_towns - 1); + else load_town(cur_town - 1); + start_town_edit(); + } + else { + if (cur_out.x > 0) { + x = cur_out.x - 1; + y = cur_out.y; + } + if ((cur_out.x == 0) && (cur_out.y > 0)) { + x = scenario.out_width - 1; + y = cur_out.y - 1; + } + if ((cur_out.x == 0) && (cur_out.y == 0)) { + x = scenario.out_width - 1; + y = scenario.out_height - 1; + } + spot_hit.x = x; + spot_hit.y = y; + load_outdoors(spot_hit,0); + augment_terrain(spot_hit); + start_out_edit(); + } + break; + + case 410: // load next town/outdoor zone + if (editing_town == true) { + if (cur_town + 1 == scenario.num_towns) + load_town(0); + else load_town(cur_town + 1); + start_town_edit(); + } + else { + if ((cur_out.x < (scenario.out_width - 1)) && (cur_out.y <= (scenario.out_height - 1))) { + x = cur_out.x + 1; + y = cur_out.y; + } + if ((cur_out.x == (scenario.out_width - 1)) && (cur_out.y < (scenario.out_height - 1))) { + x = 0; + y = cur_out.y + 1; + } + if ((cur_out.x == (scenario.out_width - 1)) && (cur_out.y == (scenario.out_height - 1))) { + x = 0; + y = 0; + } + spot_hit.x = x; + spot_hit.y = y; + load_outdoors(spot_hit,0); + augment_terrain(spot_hit); + start_out_edit(); + } + break; + + case 411: + + HMENU menu,big_menu; + big_menu = GetMenu(mainPtr); + menu = GetSubMenu(big_menu,4); + + if(play_anim == FALSE){ + play_anim = TRUE; + CheckMenuItem(menu,411,MF_BYCOMMAND | MF_CHECKED); + } + else{ + play_anim = FALSE; + CheckMenuItem(menu,411,MF_BYCOMMAND | MF_UNCHECKED); + } + break; + + // Extra Help + case 801: // help file + WinHelp(mainPtr,"Scenario Editor.hlp",HELP_CONTENTS,0L); + break; + case 802: fancy_choice_dialog(986,0); break; // started + case 803: fancy_choice_dialog(1000,0); break; // testing + case 804: fancy_choice_dialog(1001,0); break; // distributing + case 805: + fancy_choice_dialog(1062,0); + break; + + default: + if ((overall_mode >= 60) || (editing_town == FALSE)) { + give_error("You can only place items and individual monsters in town sections, not outdoors.","",0); + break; + } + if ((item_hit >= 600) && (item_hit < 1000)) { + item_hit -= 600; + if (scen_item_list.scen_items[item_hit].variety == 0) { + give_error("This item has its Variety set to No Item. You can only place items with a Variety set to an actual item type.","",0); + return to_return; + } + overall_mode = 4; + set_string("Place the item.","Select item location"); + mode_count = item_hit; + } +// skip the type 0 monster, it is non-existent + if ((item_hit >= 1001) && (item_hit <= 1255)) { // 1,255? + overall_mode = 28; + item_hit -= 1000; + set_string("Place the monster.","Select monster location"); + mode_count = item_hit; + } +/* + if ((item_hit >= 1256) && (item_hit <= 1455)) { + item_hit -= 1256; + mode_count = item_hit; + load_town(item_hit); + start_town_edit(); +// set_string("Loading the indicated town."," "); + + } +*/ + break; + + } + if ((item >= 100) && (item < 200) && (item != 118) && (item != 119)) + change_made = TRUE; + + return to_return; +} + + +void check_colors() +{ + short a,b; + + a = GetDeviceCaps(main_dc,BITSPIXEL); + b = GetDeviceCaps(main_dc,PLANES); + if (a * b < 8) { + MessageBox(mainPtr,"The Blades of Exile editor is designed for 256 colors. The current graphics device is set for less. Exile is playable with less colors, but will look somewhat odd." , + "Not 256 colors!",MB_OK | MB_ICONEXCLAMATION); + MessageBox(mainPtr,"For tips on how to get 256 colors, hit F1 for help, and then select 'Getting 256 Colors' from the table of contents." , + "Not 256 colors!",MB_OK | MB_ICONEXCLAMATION); + } +} + +void cursor_stay() +{ + if ((cursor_shown == FALSE) || (in_startup_mode == TRUE)) { + cursor_shown = TRUE; + showcursor(TRUE); + } +} + +void max_window(HWND window) +{ + RECT main_rect,wind_rect; + short width,height; + + cursor_shown = TRUE; + showcursor(TRUE); + + GetWindowRect(GetDesktopWindow(),&main_rect); + GetWindowRect(window,&wind_rect); + width = main_rect.right - main_rect.left; + height = main_rect.bottom - main_rect.top; + MoveWindow(window,0,0,width,height,TRUE); + +} + +short check_cd_event(HWND hwnd, UINT message, WPARAM wparam,LPARAM lparam) +{ + POINT press; + short wind_hit = -1,item_hit = -1; + + switch (message) { + case WM_COMMAND: + if ((LOWORD(wparam) >= 150) && (LOWORD(wparam) <= 250)) { + + if (HIWORD(wparam) == EN_ERRSPACE) + play_sound(0); + + return 0; + } + cd_find_dlog(hwnd,&wind_hit,&item_hit); // item_hit is dummy + item_hit = (short) wparam; + break; + case WM_KEYDOWN: + if ((wparam >= 150) && (wparam <= 250)) { + return -1; + } + wind_hit = cd_process_syskeystroke(hwnd, wparam, lparam,&item_hit); + break; + + case WM_CHAR: + wind_hit = cd_process_keystroke(hwnd, wparam, lparam,&item_hit); + break; + + case WM_LBUTTONDOWN: + press = MAKEPOINT(lparam); + wind_hit = cd_process_click(hwnd,press, wparam, lparam,&item_hit); + break; + case WM_RBUTTONDOWN: + press = MAKEPOINT(lparam); + wparam = wparam | MK_CONTROL; + wind_hit = cd_process_click(hwnd,press, wparam, lparam,&item_hit); + break; + case WM_MOUSEMOVE: + restore_cursor(); + break; + case WM_PAINT: + cd_redraw(hwnd); + break; + } + if (wind_hit < 0) + return 0; + switch (wind_hit) { + case -1: break; + case 970: case 971: case 972: case 973: display_strings_event_filter(item_hit); break; + case 800: edit_make_scen_1_event_filter(item_hit); break; + case 801: edit_make_scen_2_event_filter(item_hit); break; + case 803: edit_scen_details_event_filter(item_hit); break; + case 804: edit_scen_intro_event_filter(item_hit); break; + case 805: set_starting_loc_filter(item_hit); break; + case 806: edit_spec_item_event_filter(item_hit); break; + case 807: edit_save_rects_event_filter(item_hit); break; + case 808: edit_horses_event_filter(item_hit); break; + case 809: edit_boats_event_filter(item_hit); break; + case 810: edit_add_town_event_filter(item_hit); break; + case 811: edit_scenario_events_event_filter(item_hit); break; + case 812: edit_item_placement_event_filter(item_hit); break; + case 813: edit_ter_type_event_filter(item_hit); break; + case 814: edit_monst_type_event_filter(item_hit); break; + case 815: edit_monst_abil_event_filter(item_hit); break; + case 816: edit_text_event_filter(item_hit); break; + case 817: edit_talk_node_event_filter(item_hit); break; + case 818: edit_item_type_event_filter(item_hit); break; + case 819: choose_graphic_event_filter(item_hit); break; + case 820: choose_text_res_event_filter(item_hit); break; + case 821: edit_basic_dlog_event_filter(item_hit); break; + case 822: edit_spec_enc_event_filter(item_hit); break; + case 824: edit_item_abil_event_filter(item_hit); break; + case 825: edit_special_num_event_filter(item_hit); break; + case 826: edit_spec_text_event_filter(item_hit); break; + case 830: new_town_event_filter(item_hit); break; + case 831: edit_sign_event_filter(item_hit); break; + case 832: edit_town_details_event_filter(item_hit); break; + case 833: edit_town_events_event_filter(item_hit); break; + case 834: edit_advanced_town_event_filter(item_hit); break; + case 835: edit_town_wand_event_filter(item_hit); break; + case 836: edit_placed_item_event_filter(item_hit); break; + case 837: edit_placed_monst_event_filter(item_hit); break; + case 838: edit_placed_monst_adv_event_filter(item_hit); break; + case 839: edit_town_strs_event_filter(item_hit); break; + case 840: edit_area_rect_event_filter(item_hit); break; + case 841: pick_import_town_event_filter(item_hit); break; + case 842: edit_dialog_text_event_filter(item_hit); break; + case 850: edit_out_strs_event_filter(item_hit); break; + case 851: outdoor_details_event_filter(item_hit); break; + case 852: edit_out_wand_event_filter(item_hit); break; + case 854: pick_out_event_filter(item_hit); break; + case 855: case 856: pick_town_num_event_filter(item_hit); break; + case 857: change_ter_event_filter(item_hit); break; + default: fancy_choice_dialog_event_filter (item_hit); break; + } + return 0; +} diff --git a/Win32/Scenarios Editor/BLSCENED.ICO b/Win32/Scenarios Editor/BLSCENED.ICO new file mode 100644 index 00000000..218c7a33 Binary files /dev/null and b/Win32/Scenarios Editor/BLSCENED.ICO differ diff --git a/Win32/Scenarios Editor/BLSCENED.RC b/Win32/Scenarios Editor/BLSCENED.RC new file mode 100644 index 00000000..716575e6 --- /dev/null +++ b/Win32/Scenarios Editor/BLSCENED.RC @@ -0,0 +1,242 @@ + +#include +#define Exile 1 +#define MENU_1 1 +#define MENU_2 2 +#define ACCELERATORS_1 1 +#define DIALOG_1 1 +#define DIALOG_2 2 +#define DIALOG_3 3 +#define WAVE 100 +#define CURSOR_1 1 +#define CURSOR_2 2 +#define CURSOR_3 3 +#define CURSOR_4 4 +#define CURSOR_5 5 +#define CURSOR_6 6 +#define CURSOR_7 7 +#define CURSOR_8 8 +#define ICON_1 1 + + +Exile MENU +{ + POPUP "&File" + { + MENUITEM "&Open Scenario\tCtrl+O", 1 + MENUITEM "&Save Scenario\tCtrl+S", 2 + MENUITEM "New Scenario\tCtrl+N", 3 + MENUITEM SEPARATOR + MENUITEM "&Quit\tCtrl+Q", 5 + } + + POPUP "&Scenario" + { + MENUITEM "Create New Town", 101 + MENUITEM SEPARATOR + MENUITEM "Scenario Details", 103 + MENUITEM "Scenario Intro Text", 104 + MENUITEM "Set Starting Location: Town", 105 + MENUITEM "Set Starting Location: Outdoors", 106 + MENUITEM SEPARATOR + MENUITEM "Advanced:", 107 + MENUITEM " Edit Special Nodes", 109 + MENUITEM " Edit Scenario Text", 110 + MENUITEM " Import Town", 111 + MENUITEM " Edit Saved Item Rectangles", 112 + MENUITEM " Edit Horses", 113 + MENUITEM " Edit Boats", 114 + MENUITEM " Set Variable Town Entry", 115 + MENUITEM " Set Scenario Event Timers", 116 + MENUITEM " Edit Item Placement Shortcuts", 117 + MENUITEM " Delete Last Town", 118 + MENUITEM " Write Data To Text File", 119 + MENUITEM " Do Full Text Dump", 120 + MENUITEM " Scenario Shopping Text Dump", 121 + } + + POPUP "&Town" + { + MENUITEM "Town Details\tCtrl+D", 201 + MENUITEM "Town Wandering Monsters", 202 + MENUITEM "Set Town Boundaries", 203 + MENUITEM "Frill Up Terrain", 204 + MENUITEM "Remove Terrain Frills", 205 + MENUITEM "Edit Area Descriptions", 206 + MENUITEM SEPARATOR + MENUITEM "Add Random Items", 208 + MENUITEM "Set All Items Not Property", 209 + MENUITEM "Clear All Items", 210 + MENUITEM SEPARATOR + MENUITEM "Advanced:", 212 + MENUITEM " Edit Special Nodes\tCtrl+A", 213 + MENUITEM " Edit Town Text\tCtrl+B", 214 + MENUITEM " Advanced Town Details\tCtrl+C", 215 + MENUITEM " Set Town Event Timers", 216 + MENUITEM SEPARATOR + MENUITEM " Clear All Monsters", 217 + MENUITEM " Clear All Placed Specials", 218 + MENUITEM " Clear All Preset Fields", 219 + MENUITEM " Clear All Stains", 220 + } + + POPUP "&Outdoors" + { + MENUITEM "Outdoor Details\tCtrl+D", 301 + MENUITEM "Outdoor Wandering Monsters", 302 + MENUITEM "Outdoor Special Encounters", 303 + MENUITEM "Frill Up Terrain", 304 + MENUITEM "Remove Terrain Frills", 305 + MENUITEM "Edit Area Descriptions", 306 + MENUITEM SEPARATOR + MENUITEM "Advanced:", 310 + MENUITEM " Edit Special Nodes\tCtrl+U", 311 + MENUITEM " Edit Outdoor Text\tCtrl+V", 312 + MENUITEM " Delete All Placed Specials", 313 + } + + POPUP "&Additional Features" + { + MENUITEM "Terrain Animations Play", 411 + MENUITEM SEPARATOR + MENUITEM "Edit Town\tCtrl+T", 401 + MENUITEM "Edit Outdoor\tCtrl+R", 402 + MENUITEM "Load Another Outdoor Zone/Town\tCtrl+L", 403 + MENUITEM SEPARATOR + MENUITEM "Edit Terrain Types\tCtrl+E", 404 + MENUITEM "Edit Monsters\tCtrl+F", 405 + MENUITEM "Edit Items\tCtrl+G", 406 + MENUITEM SEPARATOR + MENUITEM "Return to Main Screen\tCtrl+M", 407 + MENUITEM "Switch Viewing Mode\tCtrl+I", 408 + MENUITEM "Load Previous Outdoor Zone/Town\tCtrl+J", 409 + MENUITEM "Load Next Outdoor Zone/Town\tCtrl+K", 410 + + } + +POPUP "&I1" + { + MENUITEM "Dummy", 600 + } + POPUP "&I2" + { + MENUITEM "Dummy", 601 + } + POPUP "&I3" + { + MENUITEM "Dummy", 602 + } + POPUP "&I4" + { + MENUITEM "Dummy", 603 + } + POPUP "&I5" + { + MENUITEM "Dummy", 604 + } + POPUP "&I6" + { + MENUITEM "Dummy", 605 + } + POPUP "&I7" + { + MENUITEM "Dummy", 606 + } + POPUP "&I8" + { + MENUITEM "Dummy", 607 + } + POPUP "&M1" + { + MENUITEM "Dummy", 608 + } + POPUP "&M2" + { + MENUITEM "Dummy", 609 + } + POPUP "&M3" + { + MENUITEM "Dummy", 610 + } + POPUP "&M4" + { + MENUITEM "Dummy", 611 + } + POPUP "&M5" + { + MENUITEM "Dummy", 612 + } +/* + POPUP "&T1" + { + MENUITEM "Dummy", 613 + } + POPUP "&T2" + { + MENUITEM "Dummy", 614 + } + POPUP "&T3" + { + MENUITEM "Dummy", 615 + } + POPUP "&T4" + { + MENUITEM "Dummy", 616 + } +*/ + POPUP "&Help" + { + MENUITEM "Index\tF1", 801 + MENUITEM SEPARATOR + MENUITEM "Getting Started", 802 + MENUITEM "Testing Your Scenario", 803 + MENUITEM "Distributing Your Scenario", 804 + MENUITEM SEPARATOR + MENUITEM "About Blades Scenario Editor", 805 + } + + +} + +ACCELERATORS_1 ACCELERATORS +{ + VK_F1, 801, VIRTKEY + "^O", 1, ASCII + "^S", 2, ASCII + "^N", 3, ASCII + "^Q", 5, ASCII + "^A", 213, ASCII + "^B", 214, ASCII + "^C", 215, ASCII + "^U", 311, ASCII + "^V", 312, ASCII + "^T", 401, ASCII + "^R", 402, ASCII + "^L", 403, ASCII + "^E", 404, ASCII + "^F", 405, ASCII + "^G", 406, ASCII + "^M", 407, ASCII + "^I", 408, ASCII + "^J", 409, ASCII + "^K", 410, ASCII +} + +1 WAVE "snd0.wav" +2 WAVE "snd1.wav" +35 WAVE "snd34.wav" +38 WAVE "snd37.wav" +96 WAVE "snd95.wav" + +130 CURSOR "1.cur" +131 CURSOR "2.cur" +132 CURSOR "3.cur" +133 CURSOR "4.cur" +134 CURSOR "5.cur" +135 CURSOR "6.cur" +136 CURSOR "7.cur" +137 CURSOR "8.cur" + + +10 ICON "blscened.ico" + diff --git a/Win32/Scenarios Editor/BUTTONMG.CPP b/Win32/Scenarios Editor/BUTTONMG.CPP new file mode 100644 index 00000000..5d554298 --- /dev/null +++ b/Win32/Scenarios Editor/BUTTONMG.CPP @@ -0,0 +1,123 @@ +#include +#include "string.h" +#include "stdio.h" + +#include "global.h" +#include "graphics.h" +#include "math.h" +#include "buttonmg.h" + +extern piles_of_stuff_dumping_type *data_store; +extern RECT right_sbar_rect; +extern RECT right_buttons[NRSONPAGE]; +extern short current_rs_top; +extern short left_button_status[NLS]; // 0 - clear, 1 - text, 2 - title text, 3 - tabbed text, +10 - button +extern short right_button_status[NRS]; +extern HWND right_sbar; +// 0 - clear +// 1000 + x - terrain type x +// 2000 + x - monster type x +// 3000 + x - item type x +// 4000 + x - global special node +// 5000 + x - out special node +// 6000 + x - town special node +// 7000 + x - global string x +// 8000 + x - out string x +// 9000 + x - town string x +// 10000 + x - scen. special item x +// 11000 + x - charter intro c +// 12000 + x - dialogue node x +// 13000 + x - basic dialogue node x + + +// for following, lb stands for left button(s) + +void init_lb() { + short i; + for (i = 0; i < NLS; i++) { + left_button_status[i] = 0; + sprintf((char *) data_store->strings_ls[i], ""); + } +} + +void reset_lb() { + short i; + for (i = 0; i < NLS; i++) { + left_button_status[i] = 0; + draw_lb_slot(i,0); + } +} + +// is slot >= 0, force that slot +// if -1, use 1st free slot +void set_lb(short slot, short mode, char *label, short do_draw) +{ + short i; + + if (slot < 0) { + for (i = 0; i < NLS; i++) + if (left_button_status[i] == 0) { + slot = i; + i = NLS + 5000; + } + if (i < NLS + 5000) + return; + } + left_button_status[slot] = mode; + sprintf((char *)data_store->strings_ls[slot], "%-39.39s", label); + data_store->strings_ls[slot][39] = 0; + if (do_draw > 0) + draw_lb_slot(slot,0); + +} + + + +void init_rb() +{ + short i; + + SetScrollPos(right_sbar,SB_CTL,0,FALSE); + SetScrollRange(right_sbar,SB_CTL,0,0,TRUE); + for (i = 0; i < NRS; i++) { + right_button_status[i] = 0; + sprintf((char *) data_store->strings_rs[i], ""); + } +} + +void reset_rb() +{ + short i; + + for (i = 0; i < NRS; i++) { + right_button_status[i] = 0; + } + draw_rb(); + SetScrollPos(right_sbar,SB_CTL,0,FALSE); +} + +// is slot >= 0, force that slot +// if -1, use 1st free slot +void set_rb(short slot, short mode, char *label, short do_draw) +{ + short i; + + if (slot < 0) { + for (i = 0; i < NRS; i++) + if (right_button_status[i] == 0) { + slot = i; + i = NRS + 5000; + } + if (i < NRS + 5000) + return; + } + right_button_status[slot] = mode; + sprintf((char *)data_store->strings_rs[slot], "%s", label); + data_store->strings_rs[slot][39] = 0; + for (i = 0; i < 39; i++) + if (data_store->strings_rs[slot][i] == '|') + data_store->strings_rs[slot][i] = ' '; + if (do_draw > 0) + draw_rb_slot(slot,0); + +} diff --git a/Win32/Scenarios Editor/BUTTONMG.H b/Win32/Scenarios Editor/BUTTONMG.H new file mode 100644 index 00000000..2835bd29 --- /dev/null +++ b/Win32/Scenarios Editor/BUTTONMG.H @@ -0,0 +1,6 @@ +void init_lb(); +void reset_lb(); +void set_lb(short slot, short mode, char *label, short do_draw) ; +void init_rb() ; +void reset_rb() ; +void set_rb(short slot, short mode, char *label, short do_draw) ; diff --git a/Win32/Scenarios Editor/Blades of Exile Scenario Editor.dev b/Win32/Scenarios Editor/Blades of Exile Scenario Editor.dev new file mode 100644 index 00000000..15d88da0 --- /dev/null +++ b/Win32/Scenarios Editor/Blades of Exile Scenario Editor.dev @@ -0,0 +1,309 @@ +[Project] +FileName=Blades of Exile Scenario Editor.dev +Name=Blades of Exile Scenario Editor +UnitCount=26 +Type=0 +Ver=1 +ObjFiles= +Includes= +Libs= +PrivateResource=Blades_of_Exile_Scenario_Editor_private.rc +ResourceIncludes= +MakeIncludes= +Compiler= +CppCompiler=-fno-exceptions_@@_-fno-rtti_@@_ +Linker=-lwinmm_@@_--strip-all_@@_ +IsCpp=1 +Icon= +ExeOutput= +ObjectOutput= +OverrideOutput=1 +OverrideOutputName=Blades of Exile Scenario Editor.exe +HostApplication= +Folders= +CommandLine= +UseCustomMakefile=0 +CustomMakefile= +IncludeVersionInfo=0 +SupportXPThemes=0 +CompilerSet=0 +CompilerSettings=0000000000000000000000 + +[Unit3] +FileName=DLOGTOOL.CPP +CompileCpp=1 +Folder=Blades of Exile Scenario Editor +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit4] +FileName=DLOGTOOL.H +CompileCpp=1 +Folder=Blades of Exile Scenario Editor +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit5] +FileName=GLOBAL.CPP +CompileCpp=1 +Folder=Blades of Exile Scenario Editor +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit6] +FileName=GLOBAL.H +CompileCpp=1 +Folder=Blades of Exile Scenario Editor +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit9] +FileName=GRAPHUTL.H +Folder=Blades of Exile Scenario Editor +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= +CompileCpp=1 + +[Unit11] +FileName=KEYDLGS.H +CompileCpp=1 +Folder=Blades of Exile Scenario Editor +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit12] +FileName=SCENARIO.H +CompileCpp=1 +Folder=Blades of Exile Scenario Editor +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit13] +FileName=TACTIONS.H +CompileCpp=1 +Folder=Blades of Exile Scenario Editor +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit16] +FileName=townout.cpp +CompileCpp=1 +Folder=Blades of Exile Scenario Editor +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit17] +FileName=townout.h +CompileCpp=1 +Folder=Blades of Exile Scenario Editor +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit18] +FileName=EDSOUND.CPP +CompileCpp=1 +Folder=Blades of Exile Scenario Editor +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit19] +FileName=EDSOUND.H +CompileCpp=1 +Folder=Blades of Exile Scenario Editor +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit20] +FileName=GRAPHICS.CPP +Folder=Blades of Exile Scenario Editor +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= +CompileCpp=1 + +[Unit21] +FileName=SCENARIO.CPP +CompileCpp=1 +Folder=Blades of Exile Scenario Editor +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit22] +FileName=STRINGS.RC +CompileCpp=1 +Folder=Blades of Exile Scenario Editor +Compile=1 +Link=0 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit23] +FileName=BLSCENED.RC +CompileCpp=1 +Folder=Blades of Exile Scenario Editor +Compile=1 +Link=0 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[VersionInfo] +Major=0 +Minor=1 +Release=1 +Build=1 +LanguageID=1033 +CharsetID=1252 +CompanyName= +FileVersion= +FileDescription=Developed using the Dev-C++ IDE +InternalName= +LegalCopyright= +LegalTrademarks= +OriginalFilename= +ProductName= +ProductVersion= +AutoIncBuildNr=0 + +[Unit8] +FileName=GRAPHUTL.CPP +CompileCpp=1 +Folder=Blades of Exile Scenario Editor +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit10] +FileName=KEYDLGS.CPP +CompileCpp=1 +Folder=Blades of Exile Scenario Editor +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit26] +FileName=GAMEDLOG.RC +CompileCpp=1 +Folder=Blades of Exile Scenario Editor +Compile=1 +Link=0 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit7] +FileName=GRAPHICS.H +CompileCpp=1 +Folder=Blades of Exile Scenario Editor +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit15] +FileName=TFILEIO.H +CompileCpp=1 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit2] +FileName=BUTTONMG.H +CompileCpp=1 +Folder=Blades of Exile Scenario Editor +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit25] +FileName=TACTIONS.CPP +Folder=Blades of Exile Scenario Editor +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= +CompileCpp=1 + +[Unit1] +FileName=BUTTONMG.CPP +CompileCpp=1 +Folder=Blades of Exile Scenario Editor +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit14] +FileName=TFILEIO.CPP +CompileCpp=1 +Folder=Blades of Exile Scenario Editor +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit24] +FileName=BLSCENED.CPP +CompileCpp=1 +Folder=Blades of Exile Scenario Editor +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + diff --git a/Win32/Scenarios Editor/Blades_of_Exile_Scenario_Editor_private.h b/Win32/Scenarios Editor/Blades_of_Exile_Scenario_Editor_private.h new file mode 100644 index 00000000..9e25bc03 --- /dev/null +++ b/Win32/Scenarios Editor/Blades_of_Exile_Scenario_Editor_private.h @@ -0,0 +1,23 @@ +/* THIS FILE WILL BE OVERWRITTEN BY DEV-C++ */ +/* DO NOT EDIT ! */ + +#ifndef BLADES_OF_EXILE_SCENARIO_EDITOR_PRIVATE_H +#define BLADES_OF_EXILE_SCENARIO_EDITOR_PRIVATE_H + +/* VERSION DEFINITIONS */ +#define VER_STRING "0.1.1.1" +#define VER_MAJOR 0 +#define VER_MINOR 1 +#define VER_RELEASE 1 +#define VER_BUILD 1 +#define COMPANY_NAME "" +#define FILE_VERSION "" +#define FILE_DESCRIPTION "Developed using the Dev-C++ IDE" +#define INTERNAL_NAME "" +#define LEGAL_COPYRIGHT "" +#define LEGAL_TRADEMARKS "" +#define ORIGINAL_FILENAME "" +#define PRODUCT_NAME "" +#define PRODUCT_VERSION "" + +#endif /*BLADES_OF_EXILE_SCENARIO_EDITOR_PRIVATE_H*/ diff --git a/Win32/Scenarios Editor/DLOGTOOL.CPP b/Win32/Scenarios Editor/DLOGTOOL.CPP new file mode 100644 index 00000000..9be0077b --- /dev/null +++ b/Win32/Scenarios Editor/DLOGTOOL.CPP @@ -0,0 +1,1982 @@ + +#include + +#define ND 15 +#define NI 500 +#define NL 100 + +#include "string.h" + +#include "global.h" +#include "graphutl.h" +#include "stdio.h" +#include "graphics.h" +#include "edsound.h" +#include "dlogtool.h" +#include "keydlgs.h" + +extern Boolean play_sounds,cursor_shown,dialog_not_toast,block_erase,mouse_button_held; +extern HBITMAP title_gworld,dlogpics_gworld,items_gworld,tiny_obj_gworld; +extern HBITMAP dlg_buttons_gworld,mixed_gworld,monst_gworld[10],talkfaces_gworld; +extern HFONT font,italic_font,underline_font,bold_font,tiny_font,small_bold_font; +extern HWND mainPtr; +extern HDC main_dc; +extern HINSTANCE store_hInstance; +long CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM); + + +extern short terrain_pic[256]; +extern unsigned char m_pic_index[200]; +extern unsigned char m_pic_index_x[200]; +extern unsigned char m_pic_index_y[200]; +extern unsigned long anim_ticks; +extern terrain_type_type store_ter; +extern short custom_pic; +extern HBITMAP spec_scen_g; + +extern HACCEL accel; + +short current_key = 0; +short dlg_keys[ND]; +short dlg_types[ND]; +HWND dlgs[ND]; +HWND dlg_parent[ND]; +short dlg_highest_item[ND]; +Boolean dlg_draw_ready[ND]; + +short item_dlg[NI]; +short item_number[NI]; +char item_type[NI]; +RECT item_rect[NI]; +short item_flag[NI]; +char item_active[NI]; +char item_key[NI]; +short item_label[NI]; +short item_label_loc[NI]; + +char text_long_str[10][256]; +char text_short_str[140][40]; +char labels[NL][25]; +Boolean label_taken[NL]; + +HWND edit_box[80]; +HWND store_edit_parent[80]; +short store_edit_parent_num[80]; +short store_edit_item[80]; // kludgy +FARPROC edit_proc,old_edit_proc[80]; + +HDC dlg_force_dc = NULL; // save HDCs when dealing with dlogs + +short store_free_slot,store_dlog_num; +HWND store_parent; + +short available_dlog_buttons[NUM_DLOG_B] = {0,63,64,65,1,4,5,8, + 128, + 9,10,11,12,13, + 14,15,16,17,29, 51,60,61,62, + 66,69,70, 71,72,73,74,79, + 80,83,86,87,88, 91,92,93,99,100, + 101,102,104, 129,130,131,132,133, + 134,135,136,137}; +short button_type[140] = {1,1,4,5,1,1,0,0,1,1, + 1,1,1,1,1,1,1,1,8,8, + 9,9,9,1,1,2,1,6,7,1, + 1,12,1,1,2,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0, + 0,1,1,1,2,1,1,1,2,2, // 50 + 1,1,1,1,1,1,2,3,1,1, + 1,1,1,1,2,2,2,2,2,1, + 1,1,1,1,2,2,1,1,1,2, + 0,1,1,1,14,13,12,12,12,1, + 1,1,1,2,1,2,2,2,2,1, // 100 + 2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,0,0, + 1,1,1,1,1,1,0,0,0,0}; +char *button_strs[140] = {"Done ","Ask"," "," ","Keep", "Cancel","+","-","Buy","Leave", + "Get","1","2","3","4","5","6","Cast"," "," ", + " "," "," ","Buy","Sell","Other Spells","Buy x10"," "," ","Save", + "Race","Train","Items","Spells","Heal Party","1","2","3","4","5", + "6","7","8","9","10","11","12","13","14","15", + /*50*/ "16","Take","Create","Delete","Race/Special","Skill","Name","Graphic","Bash Door","Pick Lock", + "Leave","Steal","Attack","OK","Yes","No","Step In"," ","Record","Climb", + "Flee","Onward","Answer","Drink","Approach","Mage Spells","Priest Spells","Advantages","New Game","Land", + "Under","Restore","Restart","Quit","Save First","Just Quit","Rest","Read","Pull","Alchemy", + "17","Push","Pray","Wait","","","Delete","Graphic","Create","Give", + /*100*/ "Destroy","Pay","Free","Next Tip","Touch", "Select Icon","Create/Edit","Clear Special","Edit Abilities","Choose", + "Go Back","Create New","General","One Shots","Affect PCs","If-Thens","Town Specs","Out Specs","Advanced","Weapon Abil", + "General Abil.","NonSpell Use","Spell Usable","Reagents","Missiles","Abilities","Pick Picture","Animated","Enter","Burn", + "Insert","Remove","Accept","Refuse","Open","Close","Sit","Stand","",""}; +short button_left_adj[140] = {0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0, // 50 + 0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0, // 100 + 0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0, + }; +char button_def_key[140] = {0,0,20,21,'k', 24,0,0,0,0, + 'g','1','2','3','4', '5','6',0,0,0, + 0,0,0,0,0,' ',0,22,23,0, + 0,0,0,0,0,'1','2','3','4','5', + '6','7','8','9','a', 'b','c','d','e','f', + 'g',0,0,0,0,0,0,0,0,0, + 0,0,0,0,'y','n',0,'?','r',0, + 0,0,0,0,0,0,0,0,0, 0, + 0,0,0,0,0,0,0,0,0,0, + 'g',0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,'o',0,0,0,0,0 + }; + // specials ... 20 - <- 21 - -> 22 up 23 down 24 esc + // 25-30 ctrl 1-6 31 - return\ + +short button_ul_x[15] = {0,46,0,126,0, 0,126,126,126,138, 166,0,0,126,172}; +short button_ul_y[15] = {0,0,132,23,46, 69,46,69,36,36, 36,23,92,92,0}; +short button_width[15] = {23,63,102,16,63, 63,63,63,6,14, 14,63,63,63,30}; +short button_height[15] = {23,23,23,13,23, 23,23,23,6,10,10,23,40,40,30}; + +BOOL CALLBACK dummy_dialog_proc (HWND hDlg, UINT message, WPARAM wparam, LPARAM lparam); +long CALLBACK fresh_edit_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam); + +FARPROC d_proc; + +extern char szAppName[]; +extern char szWinName[]; + +void cd_init_dialogs() +{ + short i; + + for (i = 0; i < ND; i++) { + dlg_keys[i] = -1; + dlg_types[i] = 0; + dlgs[i] = NULL; + dlg_highest_item[i] = 0; + } + for (i = 0; i < NI; i++) { + item_dlg[i] = -1; + } + for (i = 0; i < NL; i++) { + label_taken[i] = FALSE; + } + for (i = 0; i < 80; i++) { + edit_box[i] = NULL; + store_edit_parent[i] = NULL; + store_edit_parent_num[i] = -1; + store_edit_item[i] = -1 ; + } + d_proc = (FARPROC) dummy_dialog_proc; + edit_proc = (FARPROC) fresh_edit_proc; +} + +long CALLBACK fresh_edit_proc(HWND hwnd, UINT message, UINT wParam, LONG lParam) +{ + short i,cur_box = -1,cur_item_num,item_for_focus = -1,first_edit_box = -1; + + + for (i = 0; i < 80; i++) + if (edit_box[i] == hwnd) { + cur_box = i; + cur_item_num = store_edit_item[i]; + } + if (cur_box >= 0) { + switch (message) { + + case WM_CHAR: + if ((char) (wParam) == 9) { + return TRUE; + } + break; + case WM_KEYDOWN: + if (wParam == VK_RETURN) + SendMessage(store_edit_parent[cur_box],WM_KEYDOWN,wParam,lParam); + if (wParam == VK_ESCAPE) + SendMessage(store_edit_parent[cur_box],WM_KEYDOWN,wParam,lParam); + + if (wParam == VK_TAB) { + //play_sound(1); + for (i = 0; i < 80; i++) { + if ((store_edit_parent[i] == store_edit_parent[cur_box]) && + (store_edit_item[i] == cur_item_num + 1)) + item_for_focus = i; + if ((store_edit_parent[i] == store_edit_parent[cur_box]) && + (store_edit_item[i] == 2)) + first_edit_box = i; + } + + if (item_for_focus >= 0) + SetFocus(edit_box[item_for_focus]); + else if (first_edit_box >= 0) + SetFocus(edit_box[first_edit_box]); + return TRUE; + } + break; + } + + return CallWindowProc((WNDPROC) old_edit_proc[cur_box],hwnd,message,wParam,lParam); + } + return 0; + } + +short cd_create_dialog_parent_num(short dlog_num,short parent) +{ + short i; + + if ((parent == 0) || (parent == 1)) + return cd_create_dialog(dlog_num,mainPtr); + i = cd_get_dlg_index(parent); + if (i < 0) + return -1; + return cd_create_dialog(dlog_num,dlgs[i]); + +} + +short cd_create_dialog(short dlog_num,HWND parent) +{ + short i,j,free_slot = -1,free_item = -1; + HWND dlg; + + char item_str[256]; + short type,flag; + HDC win_dc; + + if (parent != NULL) { + if (IsWindowEnabled(parent) == 0) + return -1; + } + mouse_button_held = FALSE; + store_dlog_num = dlog_num; + store_parent = parent; + + for (i = 0; i < ND; i++) { + if ((dlg_keys[i] >= 0) && (dlg_types[i] == dlog_num)) + return -1; + } + for (i = 0; i < ND; i++) { + if (dlg_keys[i] < 0) { + free_slot = i; + i = 500; + } + } + if (free_slot < 0) + return -2; + current_key++; + dlg_keys[free_slot] = current_key; + dlg_types[free_slot] = dlog_num; + dlg_highest_item[free_slot] = 1; + dlg_draw_ready[free_slot] = FALSE; + dlgs[free_slot] = NULL; + + // first, create dummy dlog + store_free_slot = free_slot; + dlg = CreateDialog(store_hInstance,MAKEINTRESOURCE(dlog_num),0,(DLGPROC)d_proc); + + if (dlgs[free_slot] == NULL) { + play_sound(3); + return -3; + } + center_window(dlgs[free_slot]); + + dlg_parent[free_slot] = parent; + + SetWindowText(dlgs[free_slot],"Blades of Exile Scenario Editor"); + + ShowWindow(dlgs[free_slot],SW_SHOW); + DestroyWindow(dlg); //Necesary? Dunno. + + if (dlg_parent[free_slot] != NULL) { + EnableWindow(dlg_parent[free_slot],FALSE); + } + dialog_not_toast = TRUE; + set_cursor(0); + return 0; +} + +BOOL CALLBACK dummy_dialog_proc (HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + short i,j,k,l,free_slot = -1,free_item = -1,type,flag; + char item_str[256]; + Boolean str_stored = FALSE,focus_set = FALSE; + RECT dlg_rect; + short win_height = 0, win_width = 0, num_text_boxes = 0; + short str_offset = 1; + + free_slot = store_free_slot; + + switch (message) + { + case WM_INITDIALOG: + + // now, make a window, matching dialog + GetWindowRect(hDlg,&dlg_rect); + dlgs[store_free_slot] = CreateWindow (szWinName, + "BoE for Win32 Dialog", + 0,// was visible + 0, + 0, + dlg_rect.right - dlg_rect.left, + dlg_rect.bottom - dlg_rect.top, + NULL, + NULL, + store_hInstance, + NULL); + + + // Now, give the window its items + for (i = 0; i < 200; i++) + if (GetDlgItem(hDlg,i) != NULL) + { + GetDlgItemText(hDlg,i,item_str,256); + str_offset = 1; + dlg_highest_item[free_slot] = i; + str_stored = FALSE; + + if (strlen((char *)item_str) == 0) + { + sprintf((char *) item_str, "+"); + type = 3; + flag = 0; + str_stored = TRUE; + } + else if (item_str[0] == '+') { // default is framed text + type = 3; + flag = 1; + str_stored = TRUE; + } + else if (item_str[0] == '*') { + type = 3; + flag = 0; + str_stored = TRUE; + } + else if (item_str[0] == '~') { + type = 7; + flag = 0; + str_stored = TRUE; + } + else if (item_str[0] == '!') { + type = 4; + flag = 0; + str_stored = TRUE; + } + else if (item_str[0] == '=') { + type = 9; + flag = 1; + str_stored = TRUE; + } + else if (((item_str[0] >= 65) && (item_str[0] <= 122)) || (item_str[0] == '"')) { + type = 9; + flag = 0; + str_offset = 0; + str_stored = TRUE; + } + else if ((item_str[0] == '^') || (item_str[0] == '&')) { + type = (item_str[0] == '^') ? 10 : 11; + flag = 1; + str_stored = TRUE; + } + else + { + //sscanf(item_str,"%d_%d",&type,&flag); + type = atoi(item_str); + flag = atoi(item_str+2); + } + + + free_item = -1; + // find free item + switch (type) + { + case 0: case 1: case 2: case 5: case 6: + for (j = 150; j < NI; j++) + if (item_dlg[j] < 0) { + free_item = j; + j = NI + 1; + } + break; + default: + if ((type == 9) || + ((str_stored == TRUE) && (strlen((char *) item_str) > 35))) { + for (j = 0; j < 10; j++) + if (item_dlg[j] < 0) { + free_item = j; + j = NI + 1; + } + } + else { + for (j = 10; j < 140; j++) + if (item_dlg[j] < 0) { + free_item = j; + j = NI + 1; + } + } + break; + } + + if (free_item >= 0) + { + item_dlg[free_item] = store_dlog_num; + item_type[free_item] = type; + item_number[free_item] = i; + + item_rect[free_item] = get_item_rect(hDlg,i); + item_rect[free_item].top = item_rect[free_item].top / 2; + item_rect[free_item].left = item_rect[free_item].left / 2; + item_rect[free_item].bottom = item_rect[free_item].bottom / 2; + item_rect[free_item].right = item_rect[free_item].right / 2; + + item_flag[free_item] = flag; + item_active[free_item] = 1; + item_label[free_item] = 0; + item_label_loc[free_item] = -1; + item_key[free_item] = 0; + + switch (type) { + case 0: case 1: + item_rect[free_item].right = item_rect[free_item].left + button_width[button_type[flag]]; + item_rect[free_item].bottom = item_rect[free_item].top + button_height[button_type[flag]]; + + if ((store_dlog_num >= 2000) || (store_dlog_num == 986)) + OffsetRect(&item_rect[free_item],20,0); + + item_key[free_item] = button_def_key[flag]; + if (type == 1) + item_key[free_item] = 31; + break; + case 2: + item_rect[free_item].right = item_rect[free_item].left + 14; + item_rect[free_item].bottom = item_rect[free_item].top + 10; + item_key[free_item] = 255; + break; + case 3: case 4: case 7: case 8: case 9: case 10: case 11: + sprintf(((free_item < 10) ? text_long_str[free_item] : text_short_str[free_item - 10]),""); + if (str_stored == TRUE) { + if (free_item < 10) { + sprintf(text_long_str[free_item],"%s", + (char *) (item_str + str_offset)); + for (k = 0; k < 256; k++) { + if (text_long_str[free_item][k] == '|') + text_long_str[free_item][k] = 13; + if (text_long_str[free_item][k] == '_') + text_long_str[free_item][k] = '"'; + } + // give text a little extra room + if ((store_dlog_num >= 2000) || (store_dlog_num == 986)) + item_rect[free_item].right += 20; + } + else { + sprintf(text_short_str[free_item - 10],"%-34s", + (char *) (item_str + str_offset)); + for (k = 0; k < 35; k++) { + if (text_short_str[free_item][k] == '|') + text_short_str[free_item][k] = 13; + if (text_short_str[free_item][k] == '_') + text_short_str[free_item][k] = '"'; + } + } + } + item_key[free_item] = 255; + break; + case 6: + for (l = 0; l < 80; l++) + if (store_edit_parent[l] == NULL) + { + if (item_rect[free_item].bottom - item_rect[free_item].top < 24) + item_rect[free_item].top -= 2; + if (item_rect[free_item].bottom - item_rect[free_item].top <= 22) + edit_box[l] = CreateWindow("edit",NULL,WS_CHILD | WS_BORDER | WS_VISIBLE | ES_AUTOVSCROLL, + item_rect[free_item].left,item_rect[free_item].top, + item_rect[free_item].right - item_rect[free_item].left, + max(22,item_rect[free_item].bottom - item_rect[free_item].top), + dlgs[free_slot],(HMENU)150,store_hInstance,NULL); + else edit_box[l] = CreateWindow("edit",NULL,WS_CHILD | WS_BORDER | WS_VISIBLE | ES_MULTILINE | ES_AUTOVSCROLL, + item_rect[free_item].left,item_rect[free_item].top, + item_rect[free_item].right - item_rect[free_item].left, + max(22,item_rect[free_item].bottom - item_rect[free_item].top), + dlgs[free_slot],(HMENU)150,store_hInstance,NULL); + num_text_boxes++; + store_edit_parent[l] = dlgs[free_slot]; + store_edit_parent_num[l] = store_dlog_num; + store_edit_item[l] = i; + old_edit_proc[l] = (FARPROC) GetWindowLong(edit_box[l],GWL_WNDPROC); + SetWindowLong(edit_box[l],GWL_WNDPROC,(LONG) edit_proc); + if (focus_set == FALSE) + { + SetFocus(edit_box[l]); + focus_set = TRUE; + } + l = 80; + } + break; + } + win_height = max(win_height, item_rect[free_item].bottom + 28); + win_width = max(win_width, item_rect[free_item].right + 11); + + } + + } /* end of for-if */ + MoveWindow(dlgs[free_slot],0,0,win_width,win_height,FALSE); + EndDialog(hDlg, 0); + return TRUE; + + } /* end of switch(message) */ + return TRUE; + } + +void cd_set_edit_focus(short which_win) +{ + short i; + + for (i = 0; i < 80; i++) + if (store_edit_parent_num[i] == which_win) { + if (edit_box[i] != NULL) + SetFocus(edit_box[i]); + return; + } +} + +short cd_kill_dialog(short dlog_num,short parent_message) +{ + short i,j,which_dlg = -1; + + for (i = 0; i < ND; i++) + if ((dlg_keys[i] >= 0) && (dlg_types[i] == dlog_num)) + which_dlg = i; + if (which_dlg < 0) + return -1; + + for (i = 0; i < NI; i++) + if (item_dlg[i] == dlog_num) { + if (item_type[i] == 6) { + for (j = 0; j < 80; j++) + if ((store_edit_parent_num[j] == dlog_num) && (store_edit_item[j] == item_number[i])) { + DestroyWindow(edit_box[j]); + store_edit_parent[j] = NULL; + edit_box[j] = NULL; + } + } + if (item_label[i] > 0) + label_taken[item_label_loc[i]] = FALSE; + item_dlg[i] = -1; + } + + if (dlg_parent[which_dlg] != NULL) { + EnableWindow(dlg_parent[which_dlg],TRUE); + + SetFocus(dlg_parent[which_dlg]); + SetWindowPos(dlg_parent[which_dlg],HWND_TOP,0,0,100,100, + SWP_NOMOVE | SWP_NOSIZE | SWP_NOREDRAW); + cd_set_edit_focus((short)dlg_parent[which_dlg]); + } + + if (parent_message > 0) + SendMessage(dlg_parent[which_dlg],WM_COMMAND,parent_message,0); + +DestroyWindow(dlgs[which_dlg]); + dlg_keys[which_dlg] = -1; + dialog_not_toast = TRUE; + block_erase = TRUE; + return 0; +} + +short cd_process_click(HWND window,POINT the_point, WPARAM wparam, LPARAM lparam,short *item) +{ + short i,which_dlg,dlg_num,item_id; + short dlog_key; + + if ((which_dlg = cd_find_dlog(window,&dlg_num,&dlog_key)) < 0) + return -1; + + for (i = 0; i < dlg_highest_item[which_dlg] + 1; i++) + if ((item_id = cd_get_item_id(dlg_num,i)) >= 0) { + if ((PtInRect(&item_rect[item_id],the_point)) && (item_active[item_id] > 0) + && ((item_type[item_id] < 3) || (item_type[item_id] == 8) + || (item_type[item_id] == 10)|| (item_type[item_id] == 11))) { + *item = i; + if (MK_CONTROL & wparam) + *item += 100; + if (item_type[item_id] != 8) + cd_press_button(dlg_num,i); + return dlg_num; + } + } + return -1; +} + +short cd_process_syskeystroke(HWND window,WPARAM wparam, LPARAM lparam,short *item) +{ + short i,which_dlg,dlg_num,dlg_key,item_id; + char char_hit; + + + if ((which_dlg = cd_find_dlog(window,&dlg_num,&dlg_key)) < 0) + return -1; + // specials ... 20 - <- 21 - -> 22 up 23 down 24 esc + // 25-30 ctrl 1-6 + + switch (wparam) { + case VK_ESCAPE: + char_hit = 24; + break; + //case VK_SPACE: + // char_hit = ' '; + // break; + case VK_LEFT: + char_hit = 20; + break; + case VK_UP: + char_hit = 22; + break; + case VK_RIGHT: + char_hit = 21; + break; + case VK_DOWN: + char_hit = 23; + break; + case VK_RETURN: + char_hit = 31; + break; + default: + return -1; + } + + for (i = 0; i < dlg_highest_item[which_dlg] + 1; i++) + if ((item_id = cd_get_item_id(dlg_num,i)) >= 0) { + if ((item_key[item_id] == char_hit) && (item_active[item_id] > 0) + && ((item_type[item_id] < 3) || (item_type[item_id] == 8))) { + *item = i; + if (item_type[item_id] != 8) + cd_press_button(dlg_num,i); + return dlg_num; + } + } + // kludgy. If you get an escape and is isn't processed, make it an enter + if (wparam == VK_ESCAPE) { + char_hit = 31; + for (i = 0; i < dlg_highest_item[which_dlg] + 1; i++) + if ((item_id = cd_get_item_id(dlg_num,i)) >= 0) { + if ((item_key[item_id] == char_hit) && (item_active[item_id] > 0) + && ((item_type[item_id] < 3) || (item_type[item_id] == 8))) { + *item = i; + if (item_type[item_id] != 8) + cd_press_button(dlg_num,i); + return dlg_num; + } + } + } + + return -1; +} + +short cd_process_keystroke(HWND window,WPARAM wparam, LPARAM lparam,short *item) +{ + short i,which_dlg,dlg_num,dlg_key,item_id; + char char_hit; + + if ((which_dlg = cd_find_dlog(window,&dlg_num,&dlg_key)) < 0) + return -1; + // specials ... 20 - <- 21 - -> 22 up 23 down 24 esc + // 25-30 ctrl 1-6 + + char_hit = (char) wparam; + + for (i = 0; i < dlg_highest_item[which_dlg] + 1; i++) + if ((item_id = cd_get_item_id(dlg_num,i)) >= 0) { + if ((item_key[item_id] == char_hit) && (item_active[item_id] > 0) + && ((item_type[item_id] < 3) || (item_type[item_id] == 8))) { + *item = i; + if (item_type[item_id] != 8) + cd_press_button(dlg_num,i); + return dlg_num; + } + } + return -1; +} + + +void cd_attach_key(short dlog_num,short item_num,char key) +{ + short dlg_index,item_index; + + if (cd_get_indices(dlog_num,item_num,&dlg_index,&item_index) < 0) + return; + + if ((item_type[item_index] > 2) && (item_type[item_index] != 8)) { + beep(); + return; + } + item_key[item_index] = key; +} + +void cd_set_pict(short dlog_num, short item_num, short pict_num) +{ + short dlg_index,item_index; + if (cd_get_indices(dlog_num,item_num,&dlg_index,&item_index) < 0) + return; + if (item_type[item_index] != 5) { + beep(); + return; + } + item_flag[item_index] = pict_num; + if (pict_num == -1) + cd_erase_item(dlog_num,item_num); + else cd_draw_item(dlog_num,item_num); +} + +void cd_activate_item(short dlog_num, short item_num, short status) +{ + short dlg_index,item_index; + if (cd_get_indices(dlog_num,item_num,&dlg_index,&item_index) < 0) + return; + + item_active[item_index] = status; + cd_draw_item(dlog_num,item_num); +} + +short cd_get_active(short dlog_num, short item_num) +{ + short dlg_index,item_index; + if (cd_get_indices(dlog_num,item_num,&dlg_index,&item_index) < 0) + return -1; + + return item_active[item_index]; +} + + +void cd_get_item_text(short dlog_num, short item_num, char *str) +{ + short dlg_index,item_index,i; + if (cd_get_indices(dlog_num,item_num,&dlg_index,&item_index) < 0) + return ; + if (item_type[item_index] == 6) { + sprintf(str,""); + for (i = 0; i < 80; i++) + if ((store_edit_parent_num[i] == dlog_num) && (store_edit_item[i] = item_num) + && (edit_box[i] != NULL)) + GetWindowText(edit_box[i],str,255); + return; + } + if (item_index >= 150) { + beep(); + return; + } + if (item_index < 10) + sprintf(str,"%s",text_long_str[item_index]); + else sprintf(str,"%s",text_short_str[item_index - 10]); +} + + +void cd_retrieve_text_edit_str(short dlog_num, short item_num, char *str) +{ + short dlg_index,item_index,i; + short the_type; + RECT the_rect; + + for (i = 0; i < 80; i++) + if ((store_edit_parent_num[i] == dlog_num) && (store_edit_item[i] == item_num) + && (edit_box[i] != NULL)) { + GetWindowText(edit_box[i],str,255); + return; + } +} + +short cd_retrieve_text_edit_num(short dlog_num, short item_num) +{ + short dlg_index,item_index,i; + short the_type,num_given; + RECT the_rect; + char str[256]; + + for (i = 0; i < 80; i++) + if ((store_edit_parent_num[i] == dlog_num) && (store_edit_item[i] == item_num) + && (edit_box[i] != NULL)) { + GetWindowText(edit_box[i],str,255); + sscanf(str,"%d",&num_given); + return (short) num_given; + } + return -1; + + +} + + +// NOTE!!! Expects a c string +void cd_set_text_edit_str(short dlog_num, short item_num, char *str) +{ + short dlg_index,item_index,i; + short the_type; + RECT the_rect; + for (i = 0; i < 80; i++) + if ((store_edit_parent_num[i] == dlog_num) && (store_edit_item[i] == item_num) + && (edit_box[i] != NULL)) + SetWindowText(edit_box[i],str); + +} +// NOTE!!! Expects a c string +void cd_set_text_edit_num(short dlog_num, short item_num, short num) +{ + short dlg_index,item_index,i; + short the_type; + RECT the_rect; + char store_ptr[256]; + + sprintf(store_ptr,"%d",num); + for (i = 0; i < 80; i++) + if ((store_edit_parent_num[i] == dlog_num) && (store_edit_item[i] == item_num) + && (edit_box[i] != NULL)) + SetWindowText(edit_box[i],store_ptr); +} + +void cdsin(short dlog_num, short item_num, short num) +{ + cd_set_item_num( dlog_num, item_num, num); +} +void csit(short dlog_num, short item_num, char *str) +{ +cd_set_item_text( dlog_num, item_num, str); +} +void csp(short dlog_num, short item_num, short pict_num) +{ + cd_set_pict( dlog_num, item_num, pict_num); +} + + +void cd_set_item_text(short dlog_num, short item_num, char *str) +{ + short dlg_index,item_index,i; + if (cd_get_indices(dlog_num,item_num,&dlg_index,&item_index) < 0) + return ; + if (item_type[item_index] == 6) { + for (i = 0; i < 80; i++) + if ((store_edit_parent_num[i] == dlog_num) && (store_edit_item[i] = item_num) + && (edit_box[i] != NULL)) + SetWindowText(edit_box[i],str); + return; + } + if (item_index >= 150) { + beep(); + return; + } + if (item_index < 10) + sprintf(text_long_str[item_index],"%s",str); + else sprintf(text_short_str[item_index - 10],"%-34s",str); + cd_draw_item( dlog_num,item_num); +} + +void cd_set_item_num(short dlog_num, short item_num, short num) +{ + short dlg_index,item_index; + if (cd_get_indices(dlog_num,item_num,&dlg_index,&item_index) < 0) + return ; + if (item_index >= 150) { + beep(); + return; + } + if (item_index < 10) + sprintf(text_long_str[item_index],"%d",num); + else sprintf(text_short_str[item_index - 10],"%d",num); + cd_draw_item( dlog_num,item_num); +} + + +void cd_set_led(short dlog_num,short item_num,short state) +{ + short dlg_index,item_index; + + if (cd_get_indices(dlog_num,item_num,&dlg_index,&item_index) < 0) + return; + + if (item_type[item_index] != 2) { + beep(); + return; + } + item_flag[item_index] = state; + cd_draw_item(dlog_num,item_num); +} + +short cd_get_led(short dlog_num,short item_num) +{ + short dlg_index,item_index; + + if (cd_get_indices(dlog_num,item_num,&dlg_index,&item_index) < 0) + return 0; + + if (item_type[item_index] != 2) { + beep(); + return 0; + } + return item_flag[item_index]; +} + +// Use when checking for events ... if item hit matches item num, this led was +// hit, and flip it to other thing. +void cd_flip_led(short dlog_num,short item_num,short item_hit) +{ + if (item_hit != item_num) + return; + if (cd_get_led(dlog_num,item_num) > 0) + cd_set_led(dlog_num,item_num,0); + else cd_set_led(dlog_num,item_num,1); +} + +void cd_set_led_range(short dlog_num,short first_led,short last_led,short which_to_set) +{ + short i; + + for (i = first_led; i <= last_led; i++) { + if (i - first_led == which_to_set) + cd_set_led(dlog_num,i,1); + else cd_set_led(dlog_num,i,0); + } +} + +// Use when someone presses something in the range, to light up the right button +// Also has an error check ... if which_to_set is outside range, do nothing +void cd_hit_led_range(short dlog_num,short first_led,short last_led,short which_to_set) +{ + short i; + + if ((which_to_set < first_led) || (which_to_set > last_led)) + return; + for (i = first_led; i <= last_led; i++) { + if (i == which_to_set) + cd_set_led(dlog_num,i,1); + else cd_set_led(dlog_num,i,0); + } +} +short cd_get_led_range(short dlog_num,short first_led,short last_led) +{ + short i; + + for (i = first_led; i <= last_led; i++) { + if (cd_get_led(dlog_num,i) == 1) + return i - first_led; + } + return 0; +} + + +void cd_add_label(short dlog_num, short item_num, char *label, short label_flag) +{ + short dlg_index,item_index,label_loc = -1; + short i; + + if (cd_get_indices(dlog_num,item_num,&dlg_index,&item_index) < 0) + return; + + if (item_label_loc[item_index] < 0) { + item_label[item_index] = label_flag; + for (i = 0; i < 100; i++) + if (label_taken[i] == FALSE) { + label_loc = i; + label_taken[i] = TRUE; + i = 100; + } + if (label_loc < 0) { + beep(); + return; + } + item_label_loc[item_index] = label_loc; + } + else cd_erase_item(dlog_num,item_num + 100); + label_loc = item_label_loc[item_index]; + sprintf((char *) labels[label_loc],"%-24s",label); + if (item_active[item_index] > 0) + cd_draw_item(dlog_num,item_num); +} + + +void cd_draw_item(short dlog_num,short item_num) +{ + short dlg_index,item_index,store_label; + HDC win_dc; + COLORREF colors[4] = {RGB(0,0,0),RGB(255,0,0),RGB(0,0,112),RGB(255,255,255)}; + RECT from_rect,to_rect; + HFONT old_font; + + if (cd_get_indices(dlog_num,item_num,&dlg_index,&item_index) < 0) + return; + if (dlg_draw_ready[dlg_index] == FALSE) + return; + + win_dc = cd_get_dlog_dc(dlg_index); + old_font = (HFONT) SelectObject(win_dc,small_bold_font); + dlg_force_dc = win_dc; + + if (item_active[item_index] == 0) { + cd_erase_item(dlog_num,item_num); + cd_erase_item(dlog_num,item_num + 100); + } + else { + switch (item_type[item_index]) { + case 0: case 1: case 10: case 11: + from_rect.top = button_ul_y[button_type[item_flag[item_index]]]; + from_rect.left = button_ul_x[button_type[item_flag[item_index]]]; + from_rect.bottom = from_rect.top + button_height[button_type[item_flag[item_index]]]; + from_rect.right = from_rect.left + button_width[button_type[item_flag[item_index]]]; + rect_draw_some_item(dlg_buttons_gworld,from_rect,(HBITMAP)win_dc,item_rect[item_index],0,2); + + SelectObject(win_dc,bold_font); + SetTextColor(win_dc,colors[2]); + if (item_type[item_index] < 2) + OffsetRect(&item_rect[item_index],-1 * button_left_adj[item_flag[item_index]],0); + if (item_type[item_index] < 2) { + char_win_draw_string(win_dc,item_rect[item_index], + (char *) (button_strs[item_flag[item_index]]),1,8); + } + else { + char_win_draw_string(win_dc,item_rect[item_index], + (char *) ((item_index < 10) ? text_long_str[item_index] : + text_short_str[item_index - 10]),1,8); + } + if (item_type[item_index] < 2) + OffsetRect(&item_rect[item_index],button_left_adj[item_flag[item_index]],0); + SetTextColor(win_dc,colors[0]); + + break; + + case 2: + switch (item_flag[item_index]) { + case 0: from_rect.left = 166; from_rect.top = 36; break; + case 1: from_rect.left = 152; from_rect.top = 36; break; + case 2: from_rect.left = 138; from_rect.top = 36; break; + } + from_rect.right = from_rect.left + 14; + from_rect.bottom = from_rect.top + 10; + rect_draw_some_item( dlg_buttons_gworld,from_rect,(HBITMAP) win_dc,item_rect[item_index],0,2); break; + break; + + case 3: case 4: case 7: case 8: case 9: + cd_erase_item(dlog_num,item_num); + SetTextColor(win_dc,colors[3]); + if ((item_type[item_index] == 3) || (item_type[item_index] == 9)) + SelectObject(win_dc,small_bold_font); + if (item_type[item_index] == 4) + SelectObject(win_dc,tiny_font); + if (item_type[item_index] == 7) + SelectObject(win_dc,bold_font); + if (item_flag[item_index] % 10 == 1) + cd_frame_item(dlog_num,item_num,2); + if (item_flag[item_index] >= 10) { + SetTextColor(win_dc,colors[1]); + } + + if (item_rect[item_index].bottom - item_rect[item_index].top < 20) { + item_rect[item_index].left += 3; + DrawText(win_dc,(char *) ((item_index < 10) ? text_long_str[item_index] : + text_short_str[item_index - 10]), -1, &item_rect[item_index], + DT_LEFT | DT_SINGLELINE | DT_VCENTER | DT_NOCLIP); + item_rect[item_index].left -= 3; + } + else { + InflateRect(&item_rect[item_index],-4,-4); + DrawText(win_dc,(char *) ((item_index < 10) ? text_long_str[item_index] : + text_short_str[item_index - 10]), -1, &item_rect[item_index], + DT_LEFT | DT_WORDBREAK | DT_NOCLIP); + InflateRect(&item_rect[item_index],4,4); + } + SetTextColor(win_dc,colors[0]); + break; + + case 5: + if (item_flag[item_index] == -1) + cd_erase_item(dlog_num,item_num); + else if(custom_pic > 0){ + draw_custom_dialog_graphic(dlgs[dlg_index], item_rect[item_index], + item_flag[item_index], TRUE,0); + } + else draw_dialog_graphic(dlgs[dlg_index], item_rect[item_index], + item_flag[item_index],(item_flag[item_index] >= 2000) ? FALSE : TRUE,0); + break; + + } + } + + if ( item_label[item_index] != 0) { + store_label = item_label[item_index]; + if (store_label >= 1000) { + store_label -= 1000; + SelectObject(win_dc,bold_font); + } + else SelectObject(win_dc,tiny_font); + to_rect = item_rect[item_index]; + switch (store_label / 100) { + case 0: + to_rect.right = to_rect.left; + to_rect.left -= 2 * (store_label % 100); + break; + case 1: + to_rect.bottom = to_rect.top; + to_rect.top -= 2 * (store_label % 100); + break; + case 2: + to_rect.left = to_rect.right; + to_rect.right += 2 * (store_label % 100); + break; + case 3: + to_rect.top = to_rect.bottom; + to_rect.bottom += 2 * (store_label % 100); + break; + } + + if (to_rect.bottom - to_rect.top < 14) { + to_rect.bottom += (14 - (to_rect.bottom - to_rect.top)) / 2 + 1; + to_rect.top -= (14 - (to_rect.bottom - to_rect.top)) / 2 + 1; + } + if (item_active[item_index] != 0) { + + SetTextColor(win_dc,colors[3]); + DrawText(win_dc, (char *) labels[item_label_loc[item_index]], + -1, &to_rect, DT_LEFT | DT_SINGLELINE | DT_VCENTER); + SetTextColor(win_dc,colors[0]); + } + } + + SelectObject(win_dc,old_font); + cd_kill_dc(dlg_index,win_dc); + dlg_force_dc = NULL; + } + +void cd_initial_draw(short dlog_num) +{ + short i,which_dlg = -1; + + for (i = 0; i < ND; i++) + if ((dlg_keys[i] >= 0) && (dlg_types[i] == dlog_num)) + which_dlg = i; + if (which_dlg < 0) + return; + dlg_draw_ready[which_dlg] = TRUE; + + cd_erase_item(dlog_num, 0); + cd_draw(dlog_num); +} + +void cd_draw(short dlog_num) +{ + short i,which_dlg = -1; + + for (i = 0; i < ND; i++) + if ((dlg_keys[i] >= 0) && (dlg_types[i] == dlog_num)) + which_dlg = i; + if (which_dlg < 0) + return; + + for (i = 0; i < dlg_highest_item[which_dlg] + 1; i++) { + cd_draw_item(dlog_num,i); + } +} + +void cd_redraw(HWND window) +{ + short which_dlg,dlg_num,dlg_key; + short i; + + if ((which_dlg = cd_find_dlog(window,&dlg_num,&dlg_key)) < 0) + return; + dlg_draw_ready[which_dlg] = TRUE; + cd_initial_draw(dlg_num); + + for (i = 0; i < 80; i++) + if ((store_edit_parent[i] != NULL) && + (store_edit_parent_num[i] == dlg_num)) { + + RedrawWindow(edit_box[i],NULL,NULL,RDW_INVALIDATE | RDW_UPDATENOW); + } +} + +void cd_frame_item(short dlog_num, short item_num, short width) +{ + short dlg_index,item_index; + + if (cd_get_indices(dlog_num,item_num,&dlg_index,&item_index) < 0) + return; + frame_dlog_rect(dlgs[dlg_index], item_rect[item_index], width); +} + +void cd_erase_item(short dlog_num, short item_num) +// if item_num is 0, nail whole window +// item_num + 100 just erase label +{ + short i,dlg_index,item_index,store_label; + RECT to_fry; + HDC win_dc; + HBRUSH old_brush; + HPEN old_pen; + Boolean just_label = FALSE; + + if (item_num >= 100) { + item_num -= 100; + just_label = TRUE; + } + + if (item_num == 0) { + for (i = 0; i < ND; i++) + if ((dlg_keys[i] >= 0) && (dlg_types[i] == dlog_num)) + dlg_index = i; + GetWindowRect(dlgs[dlg_index],&to_fry); + OffsetRect(&to_fry,-1 * to_fry.left,-1 * to_fry.top); + } + else { + if (cd_get_indices(dlog_num,item_num,&dlg_index,&item_index) < 0) + return; + to_fry = item_rect[item_index]; + if (just_label == TRUE) { + if (item_label[item_index] != 0) { + store_label = item_label[item_index]; + if (store_label >= 1000) + store_label -= 1000; + + switch (store_label / 100) { + case 0: + to_fry.right = to_fry.left; + to_fry.left -= 2 * (store_label % 100); + break; + case 1: + to_fry.bottom = to_fry.top; + to_fry.top -= 2 * (store_label % 100); + break; + case 2: + to_fry.left = to_fry.right; + to_fry.right += 2 * (store_label % 100); + break; + case 3: + to_fry.top = to_fry.bottom; + to_fry.bottom += 2 * (store_label % 100); + break; + } + if ((i = 12 - (to_fry.bottom - to_fry.top)) > 0) { + // adjust rect ... but doesn't work for bold letters + to_fry.bottom += i / 2; + to_fry.bottom++; // extra pixel to get dangly letters + to_fry.top -= i / 2; + } + } + } + InflateRect(&to_fry,1,1); + + } + if (dlg_draw_ready[dlg_index] == FALSE) + return; + win_dc = cd_get_dlog_dc(dlg_index); + + paint_pattern((HBITMAP)win_dc,2,to_fry,0); + cd_kill_dc(dlg_index,win_dc); + + + +} + + + +void cd_press_button(short dlog_num, short item_num) +{ + short dlg_index,item_index; + long dummy; + HDC win_dc; + RECT from_rect,to_rect; + COLORREF colors[3] = {RGB(0,0,0),RGB(0,0,112),RGB(0,255,255)}; + + if (cd_get_indices(dlog_num,item_num,&dlg_index,&item_index) < 0) + return; + // no press action for redio buttons + if (item_type[item_index] == 2) { + play_sound(34); + return; + } + + win_dc = cd_get_dlog_dc(dlg_index); + + + from_rect.top = button_ul_y[button_type[item_flag[item_index]]]; + from_rect.left = button_ul_x[button_type[item_flag[item_index]]]; + from_rect.bottom = from_rect.top + button_height[button_type[item_flag[item_index]]]; + from_rect.right = from_rect.left + button_width[button_type[item_flag[item_index]]]; + OffsetRect(&from_rect,button_width[button_type[item_flag[item_index]]],0); + + rect_draw_some_item(dlg_buttons_gworld,from_rect,(HBITMAP)win_dc,item_rect[item_index],0,2); + + SelectObject(win_dc,bold_font); + SetTextColor(win_dc,colors[2]); + if (item_type[item_index] < 2) + OffsetRect(&item_rect[item_index],-1 * button_left_adj[item_flag[item_index]],0); + if (item_type[item_index] < 2) { + char_win_draw_string(win_dc,item_rect[item_index], + (char *) (button_strs[item_flag[item_index]]),1,8); + } + else { + char_win_draw_string(win_dc,item_rect[item_index], + (char *) ((item_index < 10) ? text_long_str[item_index] : + text_short_str[item_index - 10]),1,8); + } + if (item_type[item_index] < 2) + OffsetRect(&item_rect[item_index],button_left_adj[item_flag[item_index]],0); + + if (play_sounds == TRUE) { + play_sound(37); + Delay(6,&dummy); + } + + OffsetRect(&from_rect,-1 * button_width[button_type[item_flag[item_index]]],0); + rect_draw_some_item(dlg_buttons_gworld,from_rect,(HBITMAP)win_dc,item_rect[item_index],0,2); + + SelectObject(win_dc,bold_font); + SetTextColor(win_dc,colors[1]); + if (item_type[item_index] < 2) + OffsetRect(&item_rect[item_index],-1 * button_left_adj[item_flag[item_index]],0); + if (item_type[item_index] < 2) { + char_win_draw_string(win_dc,item_rect[item_index], + (char *) (button_strs[item_flag[item_index]]),1,8); + } + else { + char_win_draw_string(win_dc,item_rect[item_index], + (char *) ((item_index < 10) ? text_long_str[item_index] : + text_short_str[item_index - 10]),1,8); + } + if (item_type[item_index] < 2) + OffsetRect(&item_rect[item_index],button_left_adj[item_flag[item_index]],0); + + SelectObject(win_dc,font); + SetTextColor(win_dc,colors[0]); + + cd_kill_dc(dlg_index,win_dc); + } + +// LOW LEVEL + +short cd_get_indices(short dlg_num, short item_num, short *dlg_index, short *item_index) +{ + if ((*dlg_index = cd_get_dlg_index(dlg_num)) < 0) { + return -1; + } + if ((*item_index = cd_get_item_id(dlg_num,item_num)) < 0) { + return -1; + } + return 0; + } + +short cd_get_dlg_index(short dlog_num) +{ + short i; + + for (i = 0; i < ND; i++) + if ((dlg_keys[i] >= 0) && (dlg_types[i] == dlog_num)) + return i; + return -1; +} + +short cd_find_dlog(HWND window, short *dlg_num, short *dlg_key) +{ + short i; + for (i = 0; i < ND; i++) + if ((dlg_keys[i] >= 0) && (dlgs[i] == window)) { + *dlg_num = dlg_types[i]; + *dlg_key = dlg_keys[i]; + return i; + } + return -1; +} + +short cd_get_item_id(short dlg_num, short item_num) +{ + short i; + + for (i = 0; i < NI; i++) + if ((item_dlg[i] == dlg_num) && (item_number[i] == item_num)) + return i; + return -1; +} + +HDC cd_get_dlog_dc(short which_slot) +{ + HDC win_dc; + + win_dc = GetDC(dlgs[which_slot]); + SetBkMode(win_dc,TRANSPARENT); + return win_dc; + } + +void cd_kill_dc(short which_slot,HDC hdc) +{ + fry_dc(dlgs[which_slot],hdc); +} + +// External graphics tools (huh huh huh ... tool ... huh huh huh) + +void center_window(HWND window) +{ + RECT main_rect,wind_rect; + short width,height; + + cursor_shown = TRUE; + showcursor(TRUE); + + GetWindowRect(GetDesktopWindow(),&main_rect); + GetWindowRect(window,&wind_rect); + width = wind_rect.right - wind_rect.left; + height = wind_rect.bottom - wind_rect.top; + MoveWindow(window,((main_rect.right - main_rect.left) - width) / 2, + ((main_rect.bottom - main_rect.top) - height) / 2,width,height,TRUE); + +} + +RECT get_item_rect(HWND hDlg, short item_num) +{ + HWND item; + RECT big_rect,small_rect; + + item = GetDlgItem(hDlg, item_num); + GetWindowRect(hDlg,&big_rect); + GetWindowRect(item,&small_rect); + OffsetRect(&small_rect, -1 * big_rect.left - 7, -1 * big_rect.top - 7); + small_rect.right += 2; + small_rect.bottom += 2; + return small_rect; +} + + +void frame_dlog_rect(HWND hDlg, RECT rect, short val) +{ + HDC hdc; + HPEN dpen,lpen,old_pen; + COLORREF x = RGB(0,204,255),y = RGB(0,204,255);//y = RGB(119,119,119); + UINT c; + Boolean keep_dc = FALSE; + + InflateRect(&rect,val,val); + + if (hDlg == mainPtr) { + keep_dc = TRUE; + hdc = main_dc; + } + else if (dlg_force_dc != NULL) { + hdc = dlg_force_dc; + keep_dc = TRUE; + } + else hdc = GetDC(hDlg); + if (hdc == NULL) { + beep(); + return; + } + dpen = CreatePen(PS_SOLID,1,y); + if (hDlg != mainPtr) + lpen = CreatePen(PS_SOLID,1,x); + else lpen = CreatePen(PS_SOLID,1,y); + old_pen = (HPEN) SelectObject(hdc,dpen); + MoveToEx(hdc,rect.left,rect.top,NULL); + LineTo(hdc,rect.right,rect.top); + SelectObject(hdc,lpen); + LineTo(hdc,rect.right,rect.bottom); + LineTo(hdc,rect.left,rect.bottom); + SelectObject(hdc,dpen); + LineTo(hdc,rect.left,rect.top); + SelectObject(hdc,old_pen); + if (keep_dc == FALSE) + fry_dc(hDlg,hdc); + DeleteObject(dpen); + DeleteObject(lpen); +} + +void draw_custom_dialog_graphic(HWND hDlg, RECT rect, short which_g, Boolean do_frame,short win_or_gworld){ +short picnum; + RECT from1 = {0,0,36,28},from2 = {0,0,36,36},from3 = {0,0,72,72},tiny_obj_rect = {0,0,18,18}; + RECT from_rect = {0,0,28, 36}; + RECT face_from = {0,0,32,32}; + RECT death_to = {6,6,78,78}; + RECT to_rect = {6,6,42,42}; + RECT m_to_rect = {10,6,38,42}; + RECT pc_info_from = {0,127,106,157}; + RECT item_info_from = {174,0,312,112}; + RECT stat_symbols_from = {0,0,386,94}; /**/ + + HBITMAP from_gworld; + short draw_dest = 2,m_start_pic; + HDC hdc; + HBRUSH old_brush; + RECT small_monst_rect = {0,0,14,18}; + + if (win_or_gworld == 1) + draw_dest = 0; + + if (which_g < 0) + return; + + if (win_or_gworld == 0) { + if (dlg_force_dc != NULL) + hdc = dlg_force_dc; + else hdc = GetDC(hDlg); + } + + + switch(custom_pic){ + case 1: // custom terrain, item or 1x1 monster + from_gworld = spec_scen_g; + from_rect = calc_rect(which_g % 10, which_g / 10); + if (rect.right - rect.left != 28) { + rect.left += 1; + rect.right = rect.left + 28; + } + rect_draw_some_item(from_gworld,from_rect,(HBITMAP) ((win_or_gworld == 1) ? (HBITMAP) (hDlg): (HBITMAP)hdc) + ,rect,0,draw_dest); + break; + + case 2: //custom 2x1 monster + + rect.right = rect.left + 28; rect.bottom = rect.top + 36; + if (win_or_gworld == 0) { + old_brush = (HBRUSH)SelectObject(hdc,GetStockObject(BLACK_BRUSH)); + Rectangle(hdc,rect.left,rect.top,rect.right,rect.bottom); + SelectObject(hdc,old_brush); + } + from_gworld = spec_scen_g; + m_start_pic = which_g; + from_rect = calc_rect(m_start_pic % 10, m_start_pic / 10); + OffsetRect(&small_monst_rect,rect.left,rect.top + 7); + + if (win_or_gworld == 1) + rect_draw_some_item(from_gworld,from_rect,(HBITMAP) hDlg,small_monst_rect,0,0); + else rect_draw_some_item(from_gworld,from_rect,(HBITMAP)hdc,small_monst_rect,0,draw_dest); + + m_start_pic = which_g + 1; + from_gworld = spec_scen_g; +// m_start_pic = m_start_pic % 20; + from_rect = calc_rect(m_start_pic % 10, m_start_pic / 10); + OffsetRect(&small_monst_rect,14,0); + if (win_or_gworld == 1) + rect_draw_some_item(from_gworld,from_rect,(HBITMAP) hDlg,small_monst_rect,0,0); + else rect_draw_some_item(from_gworld,from_rect,(HBITMAP)hdc,small_monst_rect,0,draw_dest); + + break; + case 3: //custom 1x2 monster + + rect.right = rect.left + 28; rect.bottom = rect.top + 36; + if (win_or_gworld == 0) { + old_brush = (HBRUSH) SelectObject(hdc,GetStockObject(BLACK_BRUSH)); + Rectangle(hdc,rect.left,rect.top,rect.right,rect.bottom); + SelectObject(hdc,old_brush); + } + from_gworld = spec_scen_g; + m_start_pic = which_g; + from_rect = calc_rect(m_start_pic % 10, m_start_pic / 10); + OffsetRect(&small_monst_rect,rect.left + 7,rect.top); + + if (win_or_gworld == 1) + rect_draw_some_item(from_gworld,from_rect,(HBITMAP) hDlg,small_monst_rect,0,0); + else rect_draw_some_item(from_gworld,from_rect,(HBITMAP)hdc,small_monst_rect,0,draw_dest); + m_start_pic = which_g + 1; + from_gworld = spec_scen_g; + from_rect = calc_rect(m_start_pic % 10, m_start_pic / 10); + OffsetRect(&small_monst_rect,0,18); + + if (win_or_gworld == 1) + rect_draw_some_item(from_gworld,from_rect,(HBITMAP) hDlg,small_monst_rect,0,0); + else rect_draw_some_item(from_gworld,from_rect,(HBITMAP)hdc,small_monst_rect,0,draw_dest); + + break; + + case 4: //custom 2x2 monster + rect.right = rect.left + 28; rect.bottom = rect.top + 36; + if (win_or_gworld == 0) { + old_brush = (HBRUSH)SelectObject(hdc,GetStockObject(BLACK_BRUSH)); + Rectangle(hdc,rect.left,rect.top,rect.right,rect.bottom); + SelectObject(hdc,old_brush); + } + from_gworld = spec_scen_g; + m_start_pic = which_g; + from_rect = calc_rect(m_start_pic % 10, m_start_pic / 10); + OffsetRect(&small_monst_rect,rect.left,rect.top); + + if (win_or_gworld == 1) + rect_draw_some_item(from_gworld,from_rect,(HBITMAP) hDlg,small_monst_rect,0,0); + else rect_draw_some_item(from_gworld,from_rect,(HBITMAP)hdc,small_monst_rect,0,draw_dest); + + m_start_pic = which_g + 1; + from_gworld = spec_scen_g; + from_rect = calc_rect(m_start_pic % 10, m_start_pic / 10); + OffsetRect(&small_monst_rect,14,0); + + if (win_or_gworld == 1) + rect_draw_some_item(from_gworld,from_rect,(HBITMAP) hDlg,small_monst_rect,0,0); + else rect_draw_some_item(from_gworld,from_rect,(HBITMAP)hdc,small_monst_rect,0,draw_dest); + + m_start_pic = which_g + 2; + from_gworld = spec_scen_g; + from_rect = calc_rect(m_start_pic % 10, m_start_pic / 10); + OffsetRect(&small_monst_rect,-14,18); + + if (win_or_gworld == 1) + rect_draw_some_item(from_gworld,from_rect,(HBITMAP) hDlg,small_monst_rect,0,0); + else rect_draw_some_item(from_gworld,from_rect,(HBITMAP)hdc,small_monst_rect,0,draw_dest); + + m_start_pic = which_g + 3; + from_gworld = spec_scen_g; + from_rect = calc_rect(m_start_pic % 10, m_start_pic / 10); + OffsetRect(&small_monst_rect,14,0); + + if (win_or_gworld == 1) + rect_draw_some_item(from_gworld,from_rect,(HBITMAP) hDlg,small_monst_rect,0,0); + else rect_draw_some_item(from_gworld,from_rect,(HBITMAP)hdc,small_monst_rect,0,draw_dest); + break; + + case 5: // animated custom terrain + + from_gworld = spec_scen_g; + from_rect = calc_rect(which_g % 10, which_g /10); + if (rect.right - rect.left != 28) { + rect.left += 1; + rect.right = rect.left + 28; + } + from_rect.left += 28 * ((anim_ticks / 20) % 4); + from_rect.right = from_rect.left + 28; + rect_draw_some_item(from_gworld,from_rect,(HBITMAP) ((win_or_gworld == 1) ? (HBITMAP)hDlg: (HBITMAP)hdc) + ,rect,0,draw_dest); + break; +} +if ((win_or_gworld == 0) && (dlg_force_dc == NULL)) + fry_dc(hDlg, hdc); + if ((win_or_gworld == 0) && (do_frame == TRUE)) { + rect.right--; rect.bottom--; + frame_dlog_rect(hDlg,rect,3); + } +custom_pic = 0; +} + +void draw_dialog_graphic(HWND hDlg, RECT rect, short which_g, Boolean do_frame,short win_or_gworld) +// win_or_gworld: 0 - window 1 - an HBITMAP +// 1 means hDlg is actually an HBITMAP variable! +// 0 - 300 number of terrain graphic +// 400 + x - monster graphic num +// 600 + x item graphic +// 700 + x dlog graphic +// 800 + x pc graphic +// 900 + x B&W graphic +// 950 null item +// 1000 + x Talking face +// 1100 - item info help +// 1200 - pc screen help +// 1300 - combat ap +// 1400-1402 - button help +// 1500 - stat symbols help +// 1600 + x - B&W maps +// 1700 + x - anim graphic +{ + short picnum; + RECT from1 = {0,0,36,28},from2 = {0,0,36,36},from3 = {0,0,72,72},tiny_obj_rect = {0,0,18,18}; + RECT from_rect = {0,0,28, 36}; + RECT face_from = {0,0,32,32}; + RECT death_to = {6,6,78,78}; + RECT to_rect = {6,6,42,42}; + RECT m_to_rect = {10,6,38,42}; + RECT pc_info_from = {0,127,106,157}; + RECT item_info_from = {174,0,312,112}; + RECT stat_symbols_from = {0,0,386,94}; /**/ + + HBITMAP from_gworld; + short draw_dest = 2,m_start_pic; + HDC hdc; + HBRUSH old_brush; + RECT small_monst_rect = {0,0,14,18}; + + if (win_or_gworld == 1) + draw_dest = 0; + + if (which_g < 0) + return; + + if (which_g >= 2000) + do_frame = FALSE; + which_g = which_g % 2000; + + if (win_or_gworld == 0) { + if (dlg_force_dc != NULL) + hdc = dlg_force_dc; + else hdc = GetDC(hDlg); + } + if (which_g == 950) { // Empty. Maybe clear space. + if (win_or_gworld == 0) { + rect.left -= 3; + rect.top -= 3; + rect.right += 3; + rect.bottom += 4; + paint_pattern((HBITMAP)hdc,2,rect,0); + + + } + //FillCRect(&rect,bg[5]); // don't forget to nail dc!!! + if (dlg_force_dc == NULL) + fry_dc(hDlg, hdc); + return; + } + + switch (which_g / 100) { + case 0: case 1: case 2: // terrain + from_gworld = load_pict(800 + which_g / 50); + which_g = which_g % 50; + from_rect = calc_rect(which_g % 10, which_g / 10); + if (rect.right - rect.left != 28) { + rect.left += 1; + rect.right = rect.left + 28; + } + rect_draw_some_item(from_gworld,from_rect,(HBITMAP) ((win_or_gworld == 1) ? (HBITMAP) (hDlg): (HBITMAP)hdc) + ,rect,0,draw_dest); + DeleteObject(from_gworld); + break; + case 3: // animated terrain + which_g -= 300; + if (rect.right - rect.left != 28) { + rect.left += 1; + rect.right = rect.left + 28; + } + from_gworld = load_pict(820); +// from_rect = calc_rect(4 * (which_g / 5), which_g % 5); + from_rect.left = 112 * (which_g / 5)+ 28 * ((anim_ticks / 20) % 4); + from_rect.right = from_rect.left + 28; + from_rect.top = 36 * (which_g % 5); + from_rect.bottom = from_rect.top + 36; + rect_draw_some_item(from_gworld,from_rect,(HBITMAP) ((win_or_gworld == 1) ? (HBITMAP)hDlg: (HBITMAP)hdc) + ,rect,0,draw_dest); + DeleteObject(from_gworld); + break; + case 4: case 5: // monster + // There are 4 different ways to draw, depending on size of monster + which_g -= 400; + m_start_pic = m_pic_index[which_g]; + + if ((m_pic_index_x[which_g] == 1) && (m_pic_index_y[which_g] == 1)) { + from_gworld = monst_gworld[m_start_pic / 20]; + m_start_pic = m_start_pic % 20; + from_rect = calc_rect(2 * (m_start_pic / 10), m_start_pic % 10); + rect.right = rect.left + 28; rect.bottom = rect.top + 36; + if (win_or_gworld == 0) { + old_brush = (HBRUSH)SelectObject(hdc,GetStockObject(BLACK_BRUSH)); + Rectangle(hdc,rect.left,rect.top,rect.right,rect.bottom); + SelectObject(hdc,old_brush); + } + if (win_or_gworld == 1) + rect_draw_some_item(from_gworld,from_rect,(HBITMAP) hDlg,rect,0,0); + else rect_draw_some_item(from_gworld,from_rect,(HBITMAP)hdc,rect,0,draw_dest); + } + if ((m_pic_index_x[which_g] == 2) && (m_pic_index_y[which_g] == 1)) { + rect.right = rect.left + 28; rect.bottom = rect.top + 36; + if (win_or_gworld == 0) { + old_brush = (HBRUSH)SelectObject(hdc,GetStockObject(BLACK_BRUSH)); + Rectangle(hdc,rect.left,rect.top,rect.right,rect.bottom); + SelectObject(hdc,old_brush); + } + from_gworld = monst_gworld[m_start_pic / 20]; + m_start_pic = m_start_pic % 20; + from_rect = calc_rect(2 * (m_start_pic / 10), m_start_pic % 10); + OffsetRect(&small_monst_rect,rect.left,rect.top + 7); + + if (win_or_gworld == 1) + rect_draw_some_item(from_gworld,from_rect,(HBITMAP) hDlg,small_monst_rect,0,0); + else rect_draw_some_item(from_gworld,from_rect,(HBITMAP)hdc,small_monst_rect,0,draw_dest); + + m_start_pic = m_pic_index[which_g] + 1; + from_gworld = monst_gworld[m_start_pic / 20]; + m_start_pic = m_start_pic % 20; + from_rect = calc_rect(2 * (m_start_pic / 10), m_start_pic % 10); + OffsetRect(&small_monst_rect,14,0); + if (win_or_gworld == 1) + rect_draw_some_item(from_gworld,from_rect,(HBITMAP) hDlg,small_monst_rect,0,0); + else rect_draw_some_item(from_gworld,from_rect,(HBITMAP)hdc,small_monst_rect,0,draw_dest); + } + if ((m_pic_index_x[which_g] == 1) && (m_pic_index_y[which_g] == 2)) { + rect.right = rect.left + 28; rect.bottom = rect.top + 36; + if (win_or_gworld == 0) { + old_brush = (HBRUSH) SelectObject(hdc,GetStockObject(BLACK_BRUSH)); + Rectangle(hdc,rect.left,rect.top,rect.right,rect.bottom); + SelectObject(hdc,old_brush); + } + from_gworld = monst_gworld[m_start_pic / 20]; + m_start_pic = m_start_pic % 20; + from_rect = calc_rect(2 * (m_start_pic / 10), m_start_pic % 10); + OffsetRect(&small_monst_rect,rect.left + 7,rect.top); + + if (win_or_gworld == 1) + rect_draw_some_item(from_gworld,from_rect,(HBITMAP) hDlg,small_monst_rect,0,0); + else rect_draw_some_item(from_gworld,from_rect,(HBITMAP)hdc,small_monst_rect,0,draw_dest); + m_start_pic = m_pic_index[which_g] + 1; + from_gworld = monst_gworld[m_start_pic / 20]; + m_start_pic = m_start_pic % 20; + from_rect = calc_rect(2 * (m_start_pic / 10), m_start_pic % 10); + OffsetRect(&small_monst_rect,0,18); + + if (win_or_gworld == 1) + rect_draw_some_item(from_gworld,from_rect,(HBITMAP) hDlg,small_monst_rect,0,0); + else rect_draw_some_item(from_gworld,from_rect,(HBITMAP)hdc,small_monst_rect,0,draw_dest); + } + + if ((m_pic_index_x[which_g] == 2) && (m_pic_index_y[which_g] == 2)) { + rect.right = rect.left + 28; rect.bottom = rect.top + 36; + if (win_or_gworld == 0) { + old_brush = (HBRUSH)SelectObject(hdc,GetStockObject(BLACK_BRUSH)); + Rectangle(hdc,rect.left,rect.top,rect.right,rect.bottom); + SelectObject(hdc,old_brush); + } + from_gworld = monst_gworld[m_start_pic / 20]; + m_start_pic = m_start_pic % 20; + from_rect = calc_rect(2 * (m_start_pic / 10), m_start_pic % 10); + OffsetRect(&small_monst_rect,rect.left,rect.top); + + if (win_or_gworld == 1) + rect_draw_some_item(from_gworld,from_rect,(HBITMAP) hDlg,small_monst_rect,0,0); + else rect_draw_some_item(from_gworld,from_rect,(HBITMAP)hdc,small_monst_rect,0,draw_dest); + + m_start_pic = m_pic_index[which_g] + 1; + from_gworld = monst_gworld[m_start_pic / 20]; + m_start_pic = m_start_pic % 20; + from_rect = calc_rect(2 * (m_start_pic / 10), m_start_pic % 10); + OffsetRect(&small_monst_rect,14,0); + + if (win_or_gworld == 1) + rect_draw_some_item(from_gworld,from_rect,(HBITMAP) hDlg,small_monst_rect,0,0); + else rect_draw_some_item(from_gworld,from_rect,(HBITMAP)hdc,small_monst_rect,0,draw_dest); + + m_start_pic = m_pic_index[which_g] + 2; + from_gworld = monst_gworld[m_start_pic / 20]; + m_start_pic = m_start_pic % 20; + from_rect = calc_rect(2 * (m_start_pic / 10), m_start_pic % 10); + OffsetRect(&small_monst_rect,-14,18); + + if (win_or_gworld == 1) + rect_draw_some_item(from_gworld,from_rect,(HBITMAP) hDlg,small_monst_rect,0,0); + else rect_draw_some_item(from_gworld,from_rect,(HBITMAP)hdc,small_monst_rect,0,draw_dest); + m_start_pic = m_pic_index[which_g] + 3; + from_gworld = monst_gworld[m_start_pic / 20]; + m_start_pic = m_start_pic % 20; + from_rect = calc_rect(2 * (m_start_pic / 10), m_start_pic % 10); + OffsetRect(&small_monst_rect,14,0); + + if (win_or_gworld == 1) + rect_draw_some_item(from_gworld,from_rect,(HBITMAP) hDlg,small_monst_rect,0,0); + else rect_draw_some_item(from_gworld,from_rect,(HBITMAP)hdc,small_monst_rect,0,draw_dest); + } + + break; + case 18: case 19: // item + which_g -= 1800; + if (rect.right - rect.left != 28) { + rect.left += 1; + rect.right = rect.left + 28; + } + if (win_or_gworld == 0) { + old_brush = (HBRUSH) SelectObject(hdc,GetStockObject(WHITE_BRUSH)); + Rectangle(hdc,rect.left,rect.top,rect.right,rect.bottom); + SelectObject(hdc,old_brush); + } + to_rect = rect; + if (which_g < 45) { + from_gworld = items_gworld; + from_rect = calc_rect(which_g % 5, which_g / 5); + } + else { + from_gworld = tiny_obj_gworld; + to_rect.top += 9; + to_rect.left += 5; + to_rect.right = to_rect.left + 18; + to_rect.bottom = to_rect.top + 18; + from_rect = tiny_obj_rect; + OffsetRect(&from_rect,18 * (which_g % 10), 18 * (which_g / 10)); + } + rect_draw_some_item(from_gworld,from_rect,(HBITMAP) ((win_or_gworld == 1) ? (HBITMAP)hDlg: (HBITMAP)hdc) + ,to_rect,1,draw_dest); + break; + + case 7: // dialog + which_g -= 700; + from_gworld = dlogpics_gworld; + OffsetRect(&from2,36 * (which_g % 4),36 * (which_g / 4)); + rect_draw_some_item(from_gworld,from2,(HBITMAP) ((win_or_gworld == 1) ? (HBITMAP)hDlg: (HBITMAP)hdc) + ,rect,0,draw_dest); + break; + + case 10: // talk face + which_g -= 1000; + from_gworld = talkfaces_gworld; + from_rect = face_from; + OffsetRect(&from_rect,32 * ((which_g - 1) % 10),32 * ((which_g - 1) / 10)); + if (win_or_gworld == 1) + rect_draw_some_item(from_gworld,from_rect,(HBITMAP) hDlg,rect,0,0); + else rect_draw_some_item(from_gworld,from_rect,(HBITMAP)hdc,rect,0,draw_dest); + break; + case 11: // item info help + from_rect = item_info_from; + rect.right = rect.left + from_rect.right - from_rect.left; + rect.bottom = rect.top + from_rect.bottom - from_rect.top; + rect_draw_some_item(mixed_gworld,from_rect,(HBITMAP) ((win_or_gworld == 1) ? (HBITMAP)hDlg: (HBITMAP)hdc) + ,rect,0,draw_dest); + break; + case 12: // item info help + from_rect = pc_info_from; + rect.right = rect.left + pc_info_from.right - pc_info_from.left; + rect.bottom = rect.top + pc_info_from.bottom - pc_info_from.top; + rect_draw_some_item(mixed_gworld,from_rect,(HBITMAP) ((win_or_gworld == 1) ? (HBITMAP)hDlg: (HBITMAP)hdc) + ,rect,0,draw_dest); + break; + case 16: + which_g -= 1600; + from_gworld = load_pict(851); + from_rect.right = 32; + from_rect.bottom = 32; + OffsetRect(&from_rect,32 * (which_g % 5),32 * (which_g / 5)); + rect.right = rect.left + 32; + rect.bottom = rect.top + 32; + rect_draw_some_item(from_gworld,from_rect,(HBITMAP) ((win_or_gworld == 1) ? (HBITMAP)hDlg: (HBITMAP)hdc) + ,rect,0,draw_dest); + DisposeGWorld(from_gworld); + break; + } + + if ((win_or_gworld == 0) && (dlg_force_dc == NULL)) + fry_dc(hDlg, hdc); + if ((win_or_gworld == 0) && (do_frame == TRUE)) { + rect.right--; rect.bottom--; + frame_dlog_rect(hDlg,rect,3); + } +} + +void showcursor(Boolean a) +{ + short i; + i = ShowCursor(a); + if (a == FALSE) + while (i >= 0) + i = ShowCursor(FALSE); + if (a == TRUE) + while (i < 0) + i = ShowCursor(TRUE); + } + +void ModalDialog() +{ + MSG msg; + + while ((dialog_not_toast == TRUE) && (GetMessage(&msg,NULL,0,0))) { + if (!TranslateAccelerator(mainPtr, accel, &msg)) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } +} + +RECT calc_rect(short i, short j) +{ + RECT base_rect = {0,0,28,36}; + + OffsetRect(&base_rect,i * 28, j * 36); + return base_rect; +} + +void InsetRect(RECT *rect,short x, short y) +{ + InflateRect(rect,-1 * x, -1 * y); +} diff --git a/Win32/Scenarios Editor/DLOGTOOL.H b/Win32/Scenarios Editor/DLOGTOOL.H new file mode 100644 index 00000000..390ebd0e --- /dev/null +++ b/Win32/Scenarios Editor/DLOGTOOL.H @@ -0,0 +1,63 @@ + + +short cd_get_led_range(short dlog_num,short first_led,short last_led) ; +void cd_hit_led_range(short dlog_num,short first_led,short last_led,short which_to_set); +void cd_set_led_range(short dlog_num,short first_led,short last_led,short which_to_set); +void cd_flip_led(short dlog_num,short item_num,short item_hit); +short cd_get_led(short dlog_num,short item_num); +void frame_di(HWND hDlg, short item_num, short val); +void cd_kill_dc(short which_slot,HDC hdc); +HDC cd_get_dlog_dc(short which_slot); +short cd_get_active(short dlog_num, short item_num); +short cd_create_dialog_parent_num(short dlog_num,short parent); +void cd_set_edit_focus(); +void cd_init_dialogs(); +short cd_create_dialog(short dlog_num,HWND parent) ; +short cd_kill_dialog(short dlog_num,short parent_message); +short cd_process_click(HWND window,POINT the_point, WPARAM wparam, LPARAM lparam,short *item); +short cd_process_syskeystroke(HWND window,WPARAM wparam, LPARAM lparam,short *item); +short cd_process_keystroke(HWND window,WPARAM wparam, LPARAM lparam,short *item); + +void cd_attach_key(short dlog_num,short item_num,char key); +void cd_set_pict(short dlog_num, short item_num, short pict_num); +void cd_activate_item(short dlog_num, short item_num, short status); +void cd_get_item_text(short dlog_num, short item_num, char *str); +void cd_set_item_text(short dlog_num, short item_num, char *str); +void cd_set_item_num(short dlog_num, short item_num, short num); +void cd_set_led(short dlog_num,short item_num,short state); + +void cd_add_label(short dlog_num, short item_num, char *label, short label_flag); + + +void cd_draw_item(short dlog_num,short item_num); +void cd_initial_draw(short dlog_num); +void cd_draw(short dlog_num); +void cd_redraw(HWND window); +void cd_frame_item(short dlog_num, short item_num, short width); +void cd_erase_item(short dlog_num, short item_num); +void cd_press_button(short dlog_num, short item_num); +short cd_get_indices(short dlg_num, short item_num, short *dlg_index, short *item_index); +short cd_get_dlg_index(short dlog_num); +short cd_find_dlog(HWND window, short *dlg_num, short *dlg_key); +short cd_get_item_id(short dlg_num, short item_num); +void center_window(HWND window); +RECT get_item_rect(HWND hDlg, short item_num); +void frame_dlog_rect(HWND hDlg, RECT rect, short val); +void draw_dialog_graphic(HWND hDlg, RECT rect, short which_g, Boolean do_frame,short win_or_gworld) ; +void showcursor(Boolean a); + +void cd_get_text_edit_str(short dlog_num, char *str); +void cd_set_text_edit_str(short dlog_num, char *str); +void cdsin(short dlog_num, short item_num, short num); +void csit(short dlog_num, short item_num, char *str); +void csp(short dlog_num, short item_num, short pict_num); +void ModalDialog(); + +RECT calc_rect(short i, short j); + +void cd_retrieve_text_edit_str(short dlog_num, short item_num, char *str); +short cd_retrieve_text_edit_num(short dlog_num, short item_num) ; +void cd_set_text_edit_str(short dlog_num, short item_num, char *str) ; +void cd_set_text_edit_num(short dlog_num, short item_num, short num); +void InsetRect(RECT *rect,short x, short y); +void draw_custom_dialog_graphic(HWND hDlg, RECT rect, short which_g, Boolean do_frame,short win_or_gworld); diff --git a/Win32/Scenarios Editor/EDSOUND.CPP b/Win32/Scenarios Editor/EDSOUND.CPP new file mode 100644 index 00000000..8337518e --- /dev/null +++ b/Win32/Scenarios Editor/EDSOUND.CPP @@ -0,0 +1,273 @@ +#include "math.h" +#include +#include + +#include "stdio.h" + +#include "global.h" +#include "edsound.h" + +#define NUM_SOUNDS 100 + +HGLOBAL sound_handles[NUM_SOUNDS]; +char *snds[NUM_SOUNDS]; + +extern HINSTANCE store_hInstance; + +extern Boolean play_sounds,in_startup_mode; +extern HWND mainPtr; +extern Boolean gInBackground; + +extern short num_chirps_played,overall_mode; + +short last_played = 10000; +short error_beeps = 0; +short store_last_sound_played = 0; + +Boolean always_asynch[100] = {FALSE,FALSE,FALSE,FALSE,FALSE, + TRUE,TRUE,FALSE,FALSE,FALSE, + TRUE,FALSE,FALSE,FALSE,FALSE, // 10 + FALSE,FALSE,FALSE,FALSE,FALSE, + FALSE,FALSE,TRUE,FALSE,TRUE, // 20 + TRUE,FALSE,FALSE,FALSE,FALSE, + FALSE,FALSE,FALSE,FALSE,TRUE, // 30 + FALSE,FALSE,TRUE,FALSE,TRUE, + FALSE,TRUE,TRUE,TRUE,TRUE, // 40 + TRUE,TRUE,TRUE,TRUE,TRUE, + TRUE,FALSE,FALSE,TRUE,FALSE, // 50 + TRUE,FALSE,FALSE,FALSE,FALSE, + FALSE,TRUE,FALSE,FALSE,FALSE, // 60 + FALSE,FALSE,FALSE,FALSE,FALSE, + FALSE,FALSE,FALSE,FALSE,FALSE, // 70 + FALSE,TRUE,TRUE,TRUE,TRUE, + TRUE,TRUE,TRUE,TRUE,FALSE, // 80 + TRUE,FALSE,FALSE,FALSE,FALSE, + FALSE,TRUE,FALSE,FALSE,FALSE, // 90 + FALSE,FALSE,FALSE,FALSE,FALSE}; +Boolean load_when_play[100] = { +0,0,1,1,1,0,0,1,1,1, +0,0,0,1,0,1,1,1,1,1, +1,1,0,1,1,1,1,0,1,1, +1,1,1,1,0,1,1,0,1,1, +1,1,1,1,1,1,1,0,0,0, +0,1,1,0,1,0,1,1,1,1, // 50 +1,0,1,1,1,1,1,1,1,0, +0,0,0,0,0,0,0,0,0,0, // 70 +1,1,1,1,1,0,0,0,0,0, +1,0,1,1,1,1,1,1,1,0 +}; + +short can_ignore[100] = { +0,0,0,0,0,5,3,0,0,0, +5,5,5,0,5,0,0,0,0,0, +0,0,5,0,0,0,0,0,0,2, +2,2,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,1,1,1, +1,0,0,5,0,1,0,0,0,0, // 50 +0,0,0,0,5,0,0,0,0,0, +0,0,0,0,0, 0,5,5,5,5, // 70 +4,4,4,4,0,0,0,0,0,0, +0,5,5,0,0,0,0,0,0,0}; +// 1 - polite asych, 1 or 2 or 3- lose easily when pref is set for fewer snds +// 3 can be async +// 4 - nostop asynch ... when 4, this sound is NOSTOP, i.e. when played, is played +// asynch, and refuses all other sounds. Sounds that come in are ignored, and +// disappear into the ether +// 5 - finally, bold asynch ... when 5, this sound is NOSTOP, i.e. when played, is played +// asynch, and refuses all other sounds. When a sound is played on top of this, game +// hangs on until sound is done, and then and only then plays later sound. + + +short num_devs; +Boolean sounds_fucked = FALSE; +long intro_music_start_time = -1; + +void load_sounds () +{ + short i,t,err; + HRSRC h; + char snd_name[20],str[60]; + WAVEOUTCAPS wavecaps; + + t = waveOutGetNumDevs(); + if (t == 0) { + sounds_fucked = TRUE; + return; + } + err = waveOutGetDevCaps(0,&wavecaps,sizeof(WAVEOUTCAPS)); +if (err != 0) { + sounds_fucked = TRUE; + switch (err) { + case MMSYSERR_BADDEVICEID: + MessageBox(mainPtr,"Cannot initialize sounds - No sound device detected. Game can still be played, but quietly.", + "Sound Error",MB_OK | MB_ICONEXCLAMATION); + return; + case MMSYSERR_NODRIVER: + MessageBox(mainPtr,"Cannot initialize sounds - No driver installed. Game can still be played, but quietly.", + "Sound Error",MB_OK | MB_ICONEXCLAMATION); + return; + case MMSYSERR_NOMEM : + MessageBox(mainPtr,"Cannot initialize sounds - can't find enough memory. Game can still be played, but quietly.", + "Sound Error",MB_OK | MB_ICONEXCLAMATION); + return; + case MMSYSERR_ALLOCATED: + MessageBox(mainPtr,"Cannot initialize sounds - sound card already allocated. Game can still be played, but quietly.", + "Sound Error",MB_OK | MB_ICONEXCLAMATION); + return; + case MMSYSERR_ERROR: + MessageBox(mainPtr,"Cannot initialize sounds - internal error. Game can still be played, but quietly.", + "Sound Error",MB_OK | MB_ICONEXCLAMATION); + return; + default: + MessageBox(mainPtr,"Cannot initialize sounds - unidentified error. Game can still be played, but quietly.", + "Sound Error",MB_OK | MB_ICONEXCLAMATION); + return; + + } + + } + + for (i = 0; i < NUM_SOUNDS; i++) { + sound_handles[i] = NULL; + load_when_play[i] = TRUE; + if (load_when_play[i] == FALSE) { + sprintf((char *)snd_name,"#%d",i + 1); + h = FindResource(store_hInstance,snd_name,"#100"); + + sound_handles[i] = LoadResource(store_hInstance,h); + snds[i] = (char*) LockResource(sound_handles[i]); + } + } + +} + +void play_sound(short which) // if < 0, play asynch +{ + if (play_sounds == TRUE) + force_play_sound(which); +} + + +void force_play_sound(short which) +{ + short i,err,num_fails = 0; + char snd_name[30],str[60]; + Boolean asyn = FALSE,a_sound_did_get_played = FALSE,sound_played_nostop = FALSE; + Boolean check_sound; + long dummy; + HRSRC h; + char *snd; + DWORD size; + + if ((sounds_fucked == TRUE) || (play_sounds == FALSE)) + return; + if (which < 0) { + asyn = TRUE; + which = which * -1; + } + + if (which >= 100) + return; + + if ((always_asynch[which] == TRUE) && + ((can_ignore[which] == 1) || (can_ignore[which] >= 3))) + asyn = TRUE; + if ((can_ignore[which] != 1) && (can_ignore[which] < 3)) + asyn = FALSE; + + if ((load_when_play[which] == TRUE) && (sound_handles[which] == NULL)) { + // if (can_ignore[which] != 4) + asyn = FALSE; + sprintf((char *) snd_name,"#%d",which + 1); + h = FindResource(store_hInstance,snd_name,"#100"); + + sound_handles[which] = LoadResource(store_hInstance,h); + snds[which] = (char*) LockResource(sound_handles[which]); + } + + if (store_last_sound_played == 6) { + //ASB("Interrupted snd."); + sndPlaySound(NULL,0); + } + + if (asyn == TRUE) { + if (can_ignore[which] >= 4) + check_sound = sndPlaySound(snds[which],SND_ASYNC | SND_MEMORY | SND_NOSTOP); + else check_sound = sndPlaySound(snds[which],SND_ASYNC | SND_MEMORY); + + while (check_sound == FALSE) { + + if (can_ignore[store_last_sound_played] == 4) {// then sound goes away + //ASB("Sound overruled by asynch sound."); + return; + } + + + num_fails++; + if (num_fails < 40) + sound_pause(25); + else { + MessageBox(mainPtr,"Cannot play sounds - Sounds stuck error a. Game can still be played, but quietly.", + "Sound Error",MB_OK | MB_ICONEXCLAMATION); + return; + } + sndPlaySound(NULL,0); + + if (can_ignore[which] >= 4) + check_sound = sndPlaySound(snds[which],SND_ASYNC | SND_MEMORY | SND_NOSTOP); + else check_sound = sndPlaySound(snds[which],SND_ASYNC | SND_MEMORY); + } + a_sound_did_get_played = TRUE; + } + else { + if (can_ignore[which] >= 4) + check_sound = sndPlaySound(snds[which],SND_SYNC | SND_MEMORY | SND_NOSTOP); + else check_sound = sndPlaySound(snds[which],SND_SYNC | SND_MEMORY); + while (check_sound == FALSE) { + if (can_ignore[store_last_sound_played] == 4) {// then sound goes away + return; + } + + + num_fails++; + if (num_fails < 40) + sound_pause(25); + else { + MessageBox(mainPtr,"Cannot play sounds - Sounds stuck error b. Game can still be played, but quietly.", + "Sound Error",MB_OK | MB_ICONEXCLAMATION); + return; + } + sndPlaySound(NULL,0); + + if (can_ignore[which] >= 4) + check_sound = sndPlaySound(snds[which],SND_SYNC | SND_MEMORY | SND_NOSTOP); + else check_sound = sndPlaySound(snds[which],SND_SYNC | SND_MEMORY); + } + a_sound_did_get_played = TRUE; + } + + store_last_sound_played = which; + + if ((load_when_play[which] == TRUE) && (asyn == FALSE)) { + // deleted a seemingly extraneous LoadResource here + //ASB("Dumped a sound."); + sound_handles[which] = NULL; + } + for (i = 0; i < NUM_SOUNDS; i++) + if ((load_when_play[which] == TRUE) && (sound_handles[which] != NULL) + && (a_sound_did_get_played == TRUE) && (i != which)){ + // deleted a seemingly extraneous LoadResource here + sound_handles[i] = NULL; + } + +} + +void sound_pause(long len) { + long t1,t2; + + t1 = (long) GetCurrentTime(); + t2 = t1; + while (t2 - t1 < len) { + t2 = (long)GetCurrentTime(); + } +} diff --git a/Win32/Scenarios Editor/EDSOUND.H b/Win32/Scenarios Editor/EDSOUND.H new file mode 100644 index 00000000..d2df1b86 --- /dev/null +++ b/Win32/Scenarios Editor/EDSOUND.H @@ -0,0 +1,5 @@ +void load_sounds (); +void play_sound(short which) ; // if < 0, play asynch +void force_play_sound(short which); +void sound_pause(long len); + diff --git a/Win32/Scenarios Editor/GAMEDLOG.RC b/Win32/Scenarios Editor/GAMEDLOG.RC new file mode 100644 index 00000000..5efc26a8 --- /dev/null +++ b/Win32/Scenarios Editor/GAMEDLOG.RC @@ -0,0 +1,1987 @@ +800 DIALOG 10, 10, 517, 233 + STYLE WS_POPUP | WS_DLGFRAME + { + // DEFPUSHBUTTON "" 1, 182, 127, 31, 10//, WS_GROUP | WS_TABSTOP + LTEXT "6_0" 2, 351, 34, 125, 32 + LTEXT "6_0" 3, 351, 96, 125, 16 + LTEXT "1_63" 4, 424, 205, 62, 16 + LTEXT "~Create a new scenario:" 5, 50, 6, 194, 14 + LTEXT "What is the file name for your new scenario? (max. length 28 characters, no spaces) | Example: Thor'sHammer2" 6, 52, 76, 292, 56 + LTEXT "What is the name of your new scenario? (max. length 30 characters) | Examples: 'Hammer of Thor', 'Dragon's Quest'" 7, 52, 32, 292, 40 + LTEXT "5_716" 8, 8, 8, 36, 36 + LTEXT "0_5" 9, 358, 205, 63, 16 + LTEXT "Is your outdoors going to be above ground? If so, the default outdoors will have grass instead of cave floor. (Click on the button to the left to have the outdoors be grass.)" 10, 70, 134, 291, 55 + LTEXT "2_0" 11, 51, 139, 18, 15 + } + +801 DIALOG 10, 10, 493, 457 + STYLE WS_POPUP | WS_DLGFRAME + { + // DEFPUSHBUTTON "" 1, 281, 268, 31, 10//, WS_GROUP | WS_TABSTOP + LTEXT "6_0" 2, 309, 99, 75, 16 + LTEXT "6_0" 3, 309, 125, 75, 16 + LTEXT "6_0" 4, 312, 242, 75, 16 + LTEXT "6_0" 5, 312, 269, 75, 16 + LTEXT "6_0" 6, 312, 295, 75, 16 + LTEXT "+" 7, 55, 28, 405, 124 + LTEXT "+" 8, 55, 159, 405, 157 + LTEXT "+" 9, 55, 323, 405, 107 + LTEXT "0_5" 10, 334, 436, 63, 16 + LTEXT "1_63" 11, 400, 436, 60, 15 + LTEXT "5_716" 12, 8, 8, 36, 36 + LTEXT "~How big is your scenario?" 13, 52, 6, 278, 17 + LTEXT "~Size of Outdoors:" 14, 59, 32, 158, 18 + LTEXT "~Number of towns/dungeons:" 15, 59, 166, 235, 18 + LTEXT "The outdoors for your scenario can have up to 100 48x48 sections. Note, however, that more than 50 sections may be a bit too large." 16, 70, 52, 377, 39 + LTEXT "You can have large (64 x 64), medium (48 x 48) and small (32 x 32) towns. Your scenario can have up to 200 towns and dungeon levels. However, more than 100 is an awful lot, and may take too long to design. More towns can be added later." 17, 70, 186, 383, 52 + LTEXT "*Width of outdoors (0...50)" 18, 117, 100, 181, 15 + LTEXT "*Height of outdoors (0...50)" 19, 117, 125, 181, 15 + LTEXT "*Number of large towns:" 20, 117, 243, 181, 15 + LTEXT "*Number of medium towns:" 21, 117, 269, 181, 15 + LTEXT "*Number of small towns:" 22, 117, 295, 181, 15 + LTEXT "~Place a starter town?" 23, 59, 331, 235, 16 + LTEXT "If this option is selected, Town number 0 in your scenario is 'Warrior's Grove,' a predesigned town with shops, inns, etc. This is a GREAT place to start for beginner scenario designers, and lets you put off designing characters." 24, 70, 348, 383, 53 + LTEXT "*Include starter town" 25, 119, 406, 134, 15 + LTEXT "2_0" 26, 257, 409, 38, 15 + } + +803 DIALOG 10, 10, 485, 383 + STYLE WS_POPUP | WS_DLGFRAME + { + // DEFPUSHBUTTON "" 1, 279, 223, 31, 10//, WS_GROUP | WS_TABSTOP + LTEXT "6_0" 2, 181, 80, 43, 16 + LTEXT "6_0" 3, 234, 80, 43, 16 + LTEXT "6_0" 4, 287, 80, 43, 16 + LTEXT "6_0" 5, 181, 104, 243, 47 + LTEXT "6_0" 6, 181, 159, 243, 47 + LTEXT "6_0" 7, 181, 214, 243, 65 + LTEXT "1_63" 8, 395, 357, 54, 16 + LTEXT "5_716" 9, 8, 8, 36, 36 + LTEXT "This is where you can define the various pieces of information the user will see when deciding whether or not to play your scenario. The meanings of all these fields are given in the documentation." 10, 50, 23, 372, 53 + LTEXT "~Scenario Details" 11, 50, 6, 256, 17 + LTEXT "*Version number:" 12, 50, 81, 120, 14 + LTEXT "*Credits, Part 1:" 13, 50, 102, 120, 14 + LTEXT "*Credits, Part 2:" 14, 50, 158, 120, 14 + LTEXT "*Contact Information:" 15, 50, 213, 120, 14 + LTEXT "*Rating:" 16, 50, 284, 54, 14 + LTEXT "*G" 17, 107, 284, 23, 14 + LTEXT "*PG" 18, 107, 301, 23, 14 + LTEXT "*R" 19, 107, 318, 23, 14 + LTEXT "*NC-17" 20, 107, 335, 32, 15 + LTEXT "2_0" 21, 164, 288, 23, 14 + LTEXT "2_0" 22, 164, 305, 23, 14 + LTEXT "2_0" 23, 164, 322, 23, 14 + LTEXT "2_0" 24, 164, 339, 32, 15 + LTEXT "*Difficulty:" 25, 199, 284, 71, 14 + LTEXT "*Low Level (1-8)" 26, 280, 284, 76, 15 + LTEXT "*Medium Level (9-18)" 27, 281, 301, 103, 15 + LTEXT "*High Level (19-30)" 28, 281, 318, 76, 15 + LTEXT "*Very High Level (30+)" 29, 281, 335, 76, 15 + LTEXT "2_0" 30, 423, 288, 23, 14 + LTEXT "2_0" 31, 423, 305, 23, 14 + LTEXT "2_0" 32, 423, 322, 23, 14 + LTEXT "2_0" 33, 423, 339, 26, 15 + } + +804 DIALOG 10, 10, 639, 391 +STYLE WS_POPUP | WS_DLGFRAME +{ + LTEXT "6_0", 2, 57, 83, 541, 39 + LTEXT "6_0", 3, 57, 129, 541, 39 + LTEXT "6_0", 4, 57, 175, 541, 39 + LTEXT "6_0", 5, 57, 221, 541, 39 + LTEXT "6_0", 6, 57, 267, 541, 39 + LTEXT "6_0", 7, 57, 313, 541, 39 + LTEXT "6_0", 8, 523, 19, 70, 16 + LTEXT "1_63", 9, 541, 358, 61, 16 + LTEXT "0_5", 10, 475, 358, 63, 16 + LTEXT "5_2000", 11, 8, 8, 32, 32 + LTEXT "~Scenario Details", 12, 50, 6, 256, 17 + LTEXT "This is where you can write the text that is displayed to the player upon starting the scenario. You can also pick your scenario's icon.", 13, 50, 20, 308, 40 + LTEXT "~Introductory text:", 14, 50, 63, 120, 14 + LTEXT "*Scenario icon number:", 15, 364, 22, 149, 14 + LTEXT "0_105", 16, 406, 45, 149, 14 +} + +805 DIALOG 10, 10, 462, 222 + STYLE WS_POPUP | WS_DLGFRAME + { + // DEFPUSHBUTTON "" 1, 279, 223, 31, 10//, WS_GROUP | WS_TABSTOP + LTEXT "6_0" 2, 181, 77, 43, 16 + LTEXT "6_0" 3, 181, 104, 43, 16 + LTEXT "6_0" 4, 280, 104, 43, 16 + LTEXT "1_63" 5, 359, 185, 64, 16 + LTEXT "5_716" 6, 8, 8, 36, 36 + LTEXT "Enter the town the party will start the scenario in. Also enter the x-y location in the town to place the party at. Don't forget to place that town somewhere in your scenario." 7, 50, 25, 371, 41 + LTEXT "~Starting Location" 8, 50, 6, 256, 17 + LTEXT "*Town to start in:" 9, 50, 78, 120, 14 + LTEXT "*Start location: X =" 10, 50, 105, 120, 14 + LTEXT "*Y = " 11, 232, 105, 39, 14 + LTEXT "0_5" 12, 293, 185, 63, 16 + LTEXT "NOTE: You also need to set the starting location outdoors. This is where the party ends up when they leave town for the first time. To set this, use the Set Starting Location: Outdoors option in the Scenario menu." 13, 51, 129, 372, 55 + } + +806 DIALOG 10, 10, 516, 325 + STYLE WS_POPUP | WS_DLGFRAME + { + // DEFPUSHBUTTON "" 1, 279, 223, 31, 10//, WS_GROUP | WS_TABSTOP + LTEXT "6_0" 2, 195, 57, 252, 16 + LTEXT "6_0" 3, 195, 84, 252, 104 + LTEXT "6_0" 4, 268, 249, 87, 16 + LTEXT "1_63" 5, 397, 288, 75, 16 + LTEXT "5_716" 6, 8, 8, 36, 36 + LTEXT "~Edit Special Items" 7, 50, 6, 256, 17 + LTEXT "*Name of Special Item:" 8, 50, 58, 132, 14 + LTEXT "*Special Item Description:" 9, 50, 85, 118, 27 + LTEXT "Scenario special node to be called when item is used:" 10, 51, 243, 208, 28 + LTEXT "0_5" 11, 332, 288, 63, 16 + LTEXT "0_107" 12, 329, 15, 75, 16 + LTEXT "0_106" 13, 363, 246, 75, 16 + LTEXT "*Party starts scen. with item" 14, 50, 199, 179, 14 + LTEXT "2_0" 15, 233, 198, 22, 16 + LTEXT "*Special item can be used" 16, 50, 219, 179, 14 + LTEXT "2_0" 17, 233, 218, 22, 16 + LTEXT "*Editing special item:" 18, 50, 29, 136, 14 + LTEXT "*" 19, 190, 29, 39, 14 + LTEXT "0_2" 20, 9, 288, 63, 16 + LTEXT "0_3" 21, 72, 288, 75, 16 + } + +807 DIALOG 10, 10, 523, 265 + STYLE WS_POPUP | WS_DLGFRAME + { + // DEFPUSHBUTTON "" 1, 292, 238, 31, 10//, WS_GROUP | WS_TABSTOP + LTEXT "6_0" 2, 214, 161, 67, 16 + LTEXT "6_0" 3, 293, 161, 39, 16 + LTEXT "6_0" 4, 343, 161, 39, 16 + LTEXT "6_0" 5, 393, 161, 39, 16 + LTEXT "6_0" 6, 443, 161, 39, 16 + LTEXT "6_0" 7, 214, 189, 67, 16 + LTEXT "6_0" 8, 293, 189, 39, 16 + LTEXT "6_0" 9, 343, 189, 39, 16 + LTEXT "6_0" 10, 393, 189, 39, 16 + LTEXT "6_0" 11, 443, 189, 39, 16 + LTEXT "6_0" 12, 214, 217, 67, 16 + LTEXT "6_0" 13, 293, 217, 39, 16 + LTEXT "6_0" 14, 343, 217, 39, 16 + LTEXT "6_0" 15, 393, 217, 39, 16 + LTEXT "6_0" 16, 443, 217, 39, 16 + LTEXT "1_63" 17, 413, 248, 75, 16 + LTEXT "5_716" 18, 8, 8, 36, 36 + LTEXT "~Save Items Rectangles" 19, 50, 6, 256, 17 + LTEXT "There can be areas in towns where items left there are remembered, even after the party leaves town. Enter the numbers of the towns where items are saved (-1 means no area), and the rectangles where the items are left." 20, 50, 25, 438, 53 + LTEXT "If the party leaves the given town with an item on the ground inside the given rectangle, the item will still be there when they get back. If the item is not inside the rectangle, it is lost. Note that the three towns must be different." 21, 50, 79, 438, 54 + LTEXT "*Items saved rectangle 1" 22, 50, 164, 153, 14 + LTEXT "*Items saved rectangle 2" 23, 50, 192, 153, 14 + LTEXT "*Items saved rectangle 3" 24, 50, 220, 153, 14 + LTEXT "*Town num." 25, 211, 139, 70, 14 + LTEXT "*Top" 26, 290, 139, 38, 14 + LTEXT "*Left" 27, 344, 139, 38, 14 + LTEXT "*Bottom" 28, 389, 139, 47, 14 + LTEXT "*Right" 29, 441, 139, 40, 14 + } + +808 DIALOG 10, 10, 576, 349 + STYLE WS_POPUP | WS_DLGFRAME + { + // DEFPUSHBUTTON "" 1, 292, 238, 31, 10//, WS_GROUP | WS_TABSTOP + LTEXT "6_0" 2, 214, 143, 67, 16 + LTEXT "6_0" 3, 214, 171, 67, 16 + LTEXT "6_0" 4, 214, 199, 67, 16 + LTEXT "6_0" 5, 214, 227, 67, 16 + LTEXT "6_0" 6, 214, 255, 67, 16 + LTEXT "6_0" 7, 214, 283, 67, 16 + LTEXT "6_0" 8, 329, 143, 39, 16 + LTEXT "6_0" 9, 329, 171, 39, 16 + LTEXT "6_0" 10, 329, 199, 39, 16 + LTEXT "6_0" 11, 329, 227, 39, 16 + LTEXT "6_0" 12, 329, 255, 39, 16 + LTEXT "6_0" 13, 329, 283, 39, 16 + LTEXT "6_0" 14, 410, 143, 39, 16 + LTEXT "6_0" 15, 410, 171, 39, 16 + LTEXT "6_0" 16, 410, 199, 39, 16 + LTEXT "6_0" 17, 410, 227, 39, 16 + LTEXT "6_0" 18, 410, 255, 39, 16 + LTEXT "6_0" 19, 410, 283, 39, 16 + LTEXT "1_63" 20, 463, 309, 75, 16 + LTEXT "0_2" 21, 52, 309, 63, 16 + LTEXT "0_3" 22, 115, 309, 75, 16 + LTEXT "*" 23, 152, 143, 46, 14 + LTEXT "*" 24, 152, 171, 46, 14 + LTEXT "*" 25, 153, 199, 46, 14 + LTEXT "*" 26, 153, 227, 46, 14 + LTEXT "*" 27, 153, 254, 46, 14 + LTEXT "*" 28, 153, 282, 46, 14 + LTEXT "5_716" 29, 8, 8, 36, 36 + LTEXT "~Edit Horses" 30, 50, 6, 256, 17 + LTEXT "There can be up to 30 horses in your scenario, each of which must start in some town. The horses can start as the parties property, if you want." 31, 50, 25, 439, 39 + LTEXT "Leave the town at -1 to make the horse not exist. Note that horses can't walk over certain terrain types (like floors). Be careful not to place horses where they're stuck and can't get out. This makes them sad." 32, 50, 65, 439, 41 + LTEXT "*Town to start in" 33, 199, 113, 106, 14 + LTEXT "*X Location in town" 34, 310, 107, 76, 25 + LTEXT "*Y Location in town" 35, 392, 107, 81, 26 + LTEXT "*Horse number" 36, 50, 143, 97, 14 + LTEXT "*Horse number" 37, 50, 171, 97, 14 + LTEXT "*Horse number" 38, 51, 199, 97, 14 + LTEXT "*Horse number" 39, 51, 227, 97, 14 + LTEXT "*Horse number" 40, 51, 254, 97, 14 + LTEXT "*Horse number" 41, 51, 282, 97, 14 + LTEXT "*Not Party Property" 42, 477, 107, 70, 26 + LTEXT "2_0" 43, 487, 143, 46, 14 + LTEXT "2_0" 44, 487, 171, 46, 14 + LTEXT "2_0" 45, 488, 199, 46, 14 + LTEXT "2_0" 46, 488, 227, 46, 14 + LTEXT "2_0" 47, 488, 254, 46, 14 + LTEXT "2_0" 48, 488, 282, 46, 14 + } + +809 DIALOG 10, 10, 572, 297 + STYLE WS_POPUP | WS_DLGFRAME + { + // DEFPUSHBUTTON "" 1, 292, 238, 31, 10//, WS_GROUP | WS_TABSTOP + LTEXT "6_0" 2, 214, 100, 67, 16 + LTEXT "6_0" 3, 214, 128, 67, 16 + LTEXT "6_0" 4, 214, 156, 67, 16 + LTEXT "6_0" 5, 214, 184, 67, 16 + LTEXT "6_0" 6, 214, 212, 67, 16 + LTEXT "6_0" 7, 214, 240, 67, 16 + LTEXT "6_0" 8, 329, 100, 39, 16 + LTEXT "6_0" 9, 329, 128, 39, 16 + LTEXT "6_0" 10, 329, 156, 39, 16 + LTEXT "6_0" 11, 329, 184, 39, 16 + LTEXT "6_0" 12, 329, 212, 39, 16 + LTEXT "6_0" 13, 329, 240, 39, 16 + LTEXT "6_0" 14, 410, 100, 39, 16 + LTEXT "6_0" 15, 410, 128, 39, 16 + LTEXT "6_0" 16, 410, 156, 39, 16 + LTEXT "6_0" 17, 410, 184, 39, 16 + LTEXT "6_0" 18, 410, 212, 39, 16 + LTEXT "6_0" 19, 410, 240, 39, 16 + LTEXT "1_63" 20, 468, 268, 68, 16 + LTEXT "*" 21, 381, 268, 75, 16 + LTEXT "0_2" 22, 51, 268, 63, 16 + LTEXT "0_3" 23, 114, 268, 75, 16 + LTEXT "*" 24, 152, 100, 46, 14 + LTEXT "*" 25, 152, 128, 46, 14 + LTEXT "*" 26, 153, 156, 46, 14 + LTEXT "*" 27, 153, 184, 46, 14 + LTEXT "*" 28, 153, 211, 46, 14 + LTEXT "*" 29, 153, 239, 46, 14 + LTEXT "5_716" 30, 8, 8, 36, 36 + LTEXT "~Edit Boats" 31, 50, 6, 256, 17 + LTEXT "There can be up to 30 boats in your scenario, each of which must start in some town. The boats can start as the parties property, if you want. If the town is left at -1, the boat won't exist." 32, 50, 25, 443, 38 + LTEXT "*Town to start in" 33, 199, 70, 106, 14 + LTEXT "*X Location in town" 34, 310, 64, 76, 25 + LTEXT "*Y Location in town" 35, 392, 64, 81, 26 + LTEXT "*Boat number" 36, 50, 100, 97, 14 + LTEXT "*Boat number" 37, 50, 128, 97, 14 + LTEXT "*Boat number" 38, 51, 156, 97, 14 + LTEXT "*Boat number" 39, 51, 184, 97, 14 + LTEXT "*Boat number" 40, 51, 211, 97, 14 + LTEXT "*Boat number" 41, 51, 239, 97, 14 + LTEXT "*Not Party Property" 42, 477, 64, 69, 26 + LTEXT "2_0" 43, 487, 100, 46, 14 + LTEXT "2_0" 44, 487, 128, 46, 14 + LTEXT "2_0" 45, 488, 156, 46, 14 + LTEXT "2_0" 46, 488, 184, 46, 14 + LTEXT "2_0" 47, 488, 211, 46, 14 + LTEXT "2_0" 48, 488, 239, 46, 14 + } + +810 DIALOG 10, 10, 521, 407 + STYLE WS_POPUP | WS_DLGFRAME + { + // DEFPUSHBUTTON "" 1, 292, 238, 31, 10//, WS_GROUP | WS_TABSTOP + LTEXT "6_0" 2, 146, 130, 67, 16 + LTEXT "6_0" 3, 146, 158, 67, 16 + LTEXT "6_0" 4, 146, 186, 67, 16 + LTEXT "6_0" 5, 146, 214, 67, 16 + LTEXT "6_0" 6, 146, 242, 67, 16 + LTEXT "6_0" 7, 146, 270, 67, 16 + LTEXT "6_0" 8, 146, 298, 67, 16 + LTEXT "6_0" 9, 146, 326, 67, 16 + LTEXT "6_0" 10, 146, 354, 67, 16 + LTEXT "6_0" 11, 146, 382, 67, 16 + LTEXT "6_0" 12, 258, 130, 40, 16 + LTEXT "6_0" 13, 258, 158, 40, 16 + LTEXT "6_0" 14, 258, 186, 40, 16 + LTEXT "6_0" 15, 258, 214, 40, 16 + LTEXT "6_0" 16, 258, 242, 40, 16 + LTEXT "6_0" 17, 258, 270, 40, 16 + LTEXT "6_0" 18, 258, 298, 40, 16 + LTEXT "6_0" 19, 258, 326, 40, 16 + LTEXT "6_0" 20, 258, 354, 40, 16 + LTEXT "6_0" 21, 258, 382, 40, 16 + LTEXT "6_0" 22, 344, 130, 40, 16 + LTEXT "6_0" 23, 344, 158, 40, 16 + LTEXT "6_0" 24, 344, 186, 40, 16 + LTEXT "6_0" 25, 344, 214, 40, 16 + LTEXT "6_0" 26, 344, 242, 40, 16 + LTEXT "6_0" 27, 344, 270, 40, 16 + LTEXT "6_0" 28, 344, 298, 40, 16 + LTEXT "6_0" 29, 344, 326, 40, 16 + LTEXT "6_0" 30, 344, 354, 40, 16 + LTEXT "6_0" 31, 344, 382, 40, 16 + LTEXT "1_63" 32, 419, 379, 67, 16 + LTEXT "5_716" 33, 8, 8, 36, 36 + LTEXT "~Variable Town Entry" 34, 50, 6, 256, 17 + LTEXT "When the party enters a town, you can have the exact town entered vary, depending on circumstances. To do this, specify a town number below, and the Stuff Done flag to add to the town number when that town is entered." 35, 50, 25, 439, 40 + LTEXT "Leave the town at -1 for this to have no effect. For more information on this, see the Editor help file." 36, 50, 68, 439, 27 + LTEXT "*Town entered" 37, 131, 102, 100, 14 + LTEXT "*Stuff Done Flag to add X" 38, 235, 96, 96, 25 + LTEXT "*Stuff Done Flag to add Y" 39, 329, 96, 96, 25 + } + +811 DIALOG 10, 10, 539, 500 + STYLE WS_POPUP | WS_DLGFRAME + { + // DEFPUSHBUTTON "" 1, 292, 238, 31, 10//, WS_GROUP | WS_TABSTOP + LTEXT "6_0" 2, 130, 133, 67, 16 + LTEXT "6_0" 3, 130, 161, 67, 16 + LTEXT "6_0" 4, 130, 189, 67, 16 + LTEXT "6_0" 5, 130, 217, 67, 16 + LTEXT "6_0" 6, 130, 245, 67, 16 + LTEXT "6_0" 7, 130, 273, 67, 16 + LTEXT "6_0" 8, 130, 301, 67, 16 + LTEXT "6_0" 9, 130, 329, 67, 16 + LTEXT "6_0" 10, 130, 357, 67, 16 + LTEXT "6_0" 11, 130, 385, 67, 16 + LTEXT "6_0" 12, 270, 133, 39, 16 + LTEXT "6_0" 13, 270, 161, 39, 16 + LTEXT "6_0" 14, 270, 189, 39, 16 + LTEXT "6_0" 15, 270, 217, 39, 16 + LTEXT "6_0" 16, 270, 245, 39, 16 + LTEXT "6_0" 17, 270, 273, 39, 16 + LTEXT "6_0" 18, 270, 301, 39, 16 + LTEXT "6_0" 19, 270, 329, 39, 16 + LTEXT "6_0" 20, 270, 357, 39, 16 + LTEXT "6_0" 21, 270, 385, 39, 16 + LTEXT "1_63" 22, 431, 383, 75, 16 + LTEXT "5_716" 23, 8, 8, 36, 36 + LTEXT "~Scenario event timers" 24, 50, 6, 256, 17 + LTEXT "At certain time intervals, you can have a scenario special node be called. Enter below the number of moves between each calling of the special node, and the number of the node to call. Press the Create/Edit button to make a new special." 25, 50, 25, 438, 55 + LTEXT "For more information on how this works, see the documentation." 26, 50, 81, 439, 14 + LTEXT "Number of moves between each call." 27, 102, 97, 135, 28 + LTEXT "Scenario special node to call." 28, 239, 97, 131, 28 + LTEXT "Note: If you leave the time between calls at 0, no special node is called. Don't have special nodes called too often ... it slows the game down." 29, 2, 246, 119, 106 + LTEXT "0_106" 30, 324, 131, 75, 16 + LTEXT "0_106" 31, 324, 159, 75, 16 + LTEXT "0_106" 32, 324, 187, 75, 16 + LTEXT "0_106" 33, 324, 215, 75, 16 + LTEXT "0_106" 34, 324, 243, 75, 16 + LTEXT "0_106" 35, 324, 271, 75, 16 + LTEXT "0_106" 36, 324, 299, 75, 16 + LTEXT "0_106" 37, 324, 327, 75, 16 + LTEXT "0_106" 38, 324, 355, 75, 16 + LTEXT "0_106" 39, 324, 383, 75, 16 + LTEXT "Also, the time between events must be a multiple of 10." 40, 2, 353, 119, 52 + } + +812 DIALOG 10, 10, 577, 352 + STYLE WS_POPUP | WS_DLGFRAME + { + // DEFPUSHBUTTON "" 1, 292, 238, 31, 10//, WS_GROUP | WS_TABSTOP + LTEXT "6_0" 2, 73, 188, 39, 16 + LTEXT "6_0" 3, 73, 216, 39, 16 + LTEXT "6_0" 4, 73, 244, 39, 16 + LTEXT "6_0" 5, 73, 272, 39, 16 + LTEXT "6_0" 6, 73, 300, 39, 16 + LTEXT "6_0" 7, 309, 188, 39, 16 + LTEXT "6_0" 8, 309, 216, 39, 16 + LTEXT "6_0" 9, 309, 244, 39, 16 + LTEXT "6_0" 10, 309, 272, 39, 16 + LTEXT "6_0" 11, 309, 300, 39, 16 + LTEXT "6_0" 12, 192, 188, 39, 16 + LTEXT "6_0" 13, 192, 216, 39, 16 + LTEXT "6_0" 14, 192, 244, 39, 16 + LTEXT "6_0" 15, 192, 272, 39, 16 + LTEXT "6_0" 16, 192, 300, 39, 16 + LTEXT "6_0" 17, 428, 188, 39, 16 + LTEXT "6_0" 18, 428, 216, 39, 16 + LTEXT "6_0" 19, 428, 244, 39, 16 + LTEXT "6_0" 20, 428, 272, 39, 16 + LTEXT "6_0" 21, 428, 300, 39, 16 + LTEXT "6_0" 22, 410, 113, 42, 17 + LTEXT "1_63" 23, 462, 334, 63, 16 + LTEXT "0_5" 24, 396, 334, 63, 16 + LTEXT "0_3" 25, 73, 334, 75, 16 + LTEXT "0_2" 26, 10, 334, 63, 16 + LTEXT "*" 27, 211, 115, 46, 14 + LTEXT "5_716" 28, 8, 8, 36, 36 + LTEXT "~Item Placement Shortcuts" 29, 50, 6, 256, 17 + LTEXT "You can design shortcuts for automatic placement of items in towns. When editing towns, if you select the Place Automatic Items menu item, the edit will randomly place items you specify in terrain types you specify." 30, 50, 25, 439, 40 + LTEXT "Enter the terrain type to get the items, the numbers of the items to place, and the percentage chance (0-100) that the item is places there. For more details, see the documentation." 31, 50, 66, 439, 41 + LTEXT "*Item shortcut number:" 32, 50, 115, 155, 14 + LTEXT "*Terrain type number:" 33, 269, 115, 136, 14 + LTEXT "*Number of item to place:" 34, 50, 154, 98, 26 + LTEXT "*Chance of placing: (0-100)" 35, 159, 154, 119, 26 + LTEXT "*Number of item to place:" 36, 286, 154, 99, 26 + LTEXT "*Chance of placing: (0-100)" 37, 395, 154, 119, 26 + LTEXT "2_0" 38, 215, 138, 26, 13 + LTEXT "*Items are always property:" 39, 50, 134, 155, 14 + LTEXT "*(Leave this at -1 for no shortcut.)" 40, 277, 134, 227, 14 + LTEXT "0_109" 41, 458, 110, 63, 16 + LTEXT "0_109" 42, 118, 185, 63, 13 + LTEXT "0_109" 43, 118, 213, 63, 13 + LTEXT "0_109" 44, 118, 241, 63, 13 + LTEXT "0_109" 45, 118, 270, 63, 13 + LTEXT "0_109" 46, 118, 298, 63, 13 + LTEXT "0_109" 47, 354, 185, 63, 13 + LTEXT "0_109" 48, 354, 213, 63, 13 + LTEXT "0_109" 49, 354, 241, 63, 13 + LTEXT "0_109" 50, 354, 270, 63, 13 + LTEXT "0_109" 51, 354, 298, 63, 13 + } + +813 DIALOG 10, 10, 621, 460 + STYLE WS_POPUP | WS_DLGFRAME + { + // DEFPUSHBUTTON "" 1, 283, 273, 31, 10//, WS_GROUP | WS_TABSTOP + LTEXT "6_0" 2, 186, 30, 186, 16 + LTEXT "6_0" 3, 109, 193, 52, 16 + LTEXT "6_0" 4, 467, 193, 52, 16 + LTEXT "6_0" 5, 141, 62, 52, 16 + LTEXT "6_0" 6, 329, 361, 64, 16 + LTEXT "6_0" 7, 329, 386, 64, 16 + LTEXT "6_0" 8, 271, 193, 52, 16 + LTEXT "0_5" 9, 451, 409, 63, 16 + LTEXT "0_2" 10, 11, 409, 63, 16 + LTEXT "0_3" 11, 74, 409, 75, 16 + LTEXT "*" 12, 340, 8, 37, 14 + LTEXT "0_126" 13, 205, 59, 110, 16 + LTEXT "5_0" 14, 8, 8, 36, 36 + LTEXT "~Edit Terrain Type" 15, 50, 6, 138, 17 + LTEXT "*Terrain number:" 16, 222, 8, 111, 14 + LTEXT "*Terrain type name:" 17, 50, 31, 120, 14 + LTEXT "*Terrain picture:" 18, 9, 63, 120, 14 + LTEXT "2_0" 19, 244, 90, 23, 14 + LTEXT "2_0" 20, 244, 107, 23, 14 + LTEXT "2_0" 21, 244, 124, 23, 14 + LTEXT "2_0" 22, 405, 90, 23, 14 + LTEXT "2_0" 23, 405, 107, 23, 14 + LTEXT "2_0" 24, 405, 124, 23, 14 + LTEXT "2_0" 25, 102, 150, 23, 14 + LTEXT "2_0" 26, 230, 150, 23, 14 + LTEXT "2_0" 27, 383, 150, 23, 14 + LTEXT "2_0" 28, 182, 167, 23, 14 + LTEXT "2_0" 29, 282, 167, 23, 14 + LTEXT "2_0" 30, 386, 167, 23, 14 + LTEXT "2_0" 31, 497, 167, 19, 14 + LTEXT "2_0" 32, 124, 231, 23, 14 + LTEXT "2_0" 33, 124, 246, 23, 14 + LTEXT "2_0" 34, 124, 261, 23, 14 + LTEXT "2_0" 35, 124, 276, 23, 14 + LTEXT "2_0" 36, 124, 291, 23, 14 + LTEXT "2_0" 37, 124, 306, 23, 14 + LTEXT "2_0" 38, 124, 321, 23, 14 + LTEXT "2_0" 39, 124, 336, 23, 14 + LTEXT "2_0" 40, 262, 233, 23, 14 + LTEXT "2_0" 41, 262, 248, 23, 14 + LTEXT "2_0" 42, 262, 263, 23, 14 + LTEXT "2_0" 43, 262, 278, 23, 14 + LTEXT "2_0" 44, 262, 293, 23, 14 + LTEXT "2_0" 45, 262, 308, 23, 14 + LTEXT "2_0" 46, 262, 323, 23, 14 + LTEXT "2_0" 47, 262, 338, 23, 14 + LTEXT "2_0" 48, 401, 234, 23, 14 + LTEXT "2_0" 49, 401, 249, 23, 14 + LTEXT "2_0" 50, 401, 264, 23, 14 + LTEXT "2_0" 51, 401, 279, 23, 14 + LTEXT "2_0" 52, 401, 294, 23, 14 + LTEXT "2_0" 53, 401, 309, 23, 14 + LTEXT "2_0" 54, 401, 324, 23, 14 + LTEXT "2_0" 55, 401, 339, 23, 14 + LTEXT "*Terrain blockage:" 56, 8, 90, 120, 14 + LTEXT "*Can fly over?" 57, 8, 147, 91, 14 + LTEXT "*Can boat over?" 58, 131, 147, 96, 14 + LTEXT "*Blocked to horses?" 59, 259, 147, 123, 14 + LTEXT "*Step on sound:" 60, 8, 165, 91, 14 + LTEXT "*Shortcut Key:" 61, 8, 194, 91, 14 + LTEXT "1_63" 62, 517, 409, 69, 16 + LTEXT "Light radius:" 63, 171, 194, 91, 14 + LTEXT "*Transform to what?" 64, 333, 193, 128, 14 + LTEXT "~Special properties:" 65, 8, 215, 175, 14 + LTEXT "*Extra values:" 66, 9, 362, 91, 14 + LTEXT "*" 67, 109, 362, 209, 14 + LTEXT "*" 68, 109, 387, 209, 14 + LTEXT "Enter properties for this terrain type. For a detailed description of the fields, see the documentation. Note that, for terrain types 90 and below, only changes to the picture and shortcut key will be recorded." 69, 451, 7, 137, 131 + LTEXT "0_127" 70, 319, 59, 121, 16 + } + +814 DIALOG 10, 10, 613, 470 + STYLE WS_POPUP | WS_DLGFRAME + { + // DEFPUSHBUTTON "" 1, 283, 273, 31, 10//, WS_GROUP | WS_TABSTOP + LTEXT "6_0" 2, 180, 30, 186, 16 + LTEXT "6_0" 3, 140, 57, 52, 16 + LTEXT "6_0" 4, 206, 82, 52, 16 + LTEXT "6_0" 5, 206, 106, 52, 16 + LTEXT "6_0" 6, 206, 130, 52, 16 + LTEXT "6_0" 7, 206, 154, 52, 16 + LTEXT "6_0" 8, 206, 178, 52, 16 + LTEXT "6_0" 9, 206, 202, 52, 16 + LTEXT "6_0" 10, 206, 226, 52, 16 + LTEXT "6_0" 11, 501, 101, 52, 16 + LTEXT "6_0" 12, 501, 125, 52, 16 + LTEXT "6_0" 13, 501, 149, 52, 16 + LTEXT "6_0" 14, 501, 173, 52, 16 + LTEXT "6_0" 15, 501, 197, 52, 16 + LTEXT "6_0" 16, 501, 221, 52, 16 + LTEXT "6_0" 17, 168, 327, 77, 16 + LTEXT "6_0" 18, 513, 273, 55, 16 + LTEXT "1_63" 19, 512, 418, 75, 16 + LTEXT "0_5" 20, 439, 418, 73, 16 + LTEXT "0_2" 21, 335, 388, 63, 16 + LTEXT "0_3" 22, 398, 388, 75, 16 + LTEXT "0_125" 23, 473, 388, 112, 16 + LTEXT "0_105" 24, 201, 53, 121, 16 + LTEXT "0_109" 25, 264, 250, 75, 16 + LTEXT "0_109" 26, 264, 275, 75, 16 + LTEXT "0_109" 27, 264, 300, 75, 16 + LTEXT "0_109" 28, 264, 326, 75, 16 + LTEXT "2_0" 29, 358, 355, 23, 14 + LTEXT "2_0" 30, 358, 370, 23, 14 + LTEXT "2_0" 31, 490, 355, 23, 14 + LTEXT "2_0" 32, 490, 370, 23, 14 + LTEXT "*" 33, 334, 8, 37, 14 + LTEXT "5_716" 34, 8, 8, 28, 36 + LTEXT "~Edit Monster Statistics" 35, 44, 6, 158, 16 + LTEXT "*Monster number:" 36, 216, 8, 111, 14 + LTEXT "Enter properties for this monster type. For a detailed description of the fields, see the documentation. To edit monster's special abilities, press the Edit Abilities button." 37, 4, 390, 294, 54 + LTEXT "*Monster type name:" 38, 44, 31, 120, 14 + LTEXT "*Monster picture:" 39, 8, 58, 120, 14 + LTEXT "*Width = " 40, 334, 59, 86, 14 + LTEXT "*Height = " 41, 426, 59, 86, 14 + LTEXT "*" 42, 134, 253, 120, 14 + LTEXT "*" 43, 134, 278, 120, 14 + LTEXT "*" 44, 134, 303, 120, 14 + LTEXT "*Monster type:" 45, 8, 253, 120, 14 + LTEXT "*Attack 1 type:" 46, 8, 278, 120, 14 + LTEXT "*Attack #2,3 type:" 47, 8, 303, 120, 14 + LTEXT "*Default talking picture:" 48, 8, 329, 152, 14 + LTEXT "Default attitude: (attitude creature has when you place it)" 49, 8, 352, 202, 28 + LTEXT "~Treasure:" 50, 343, 250, 158, 16 + LTEXT "*Monster treasure: (0-4)" 51, 343, 275, 162, 14 + LTEXT "*Monster level: (0 - 40)" 52, 8, 83, 179, 14 + LTEXT "*Monster health: (0 - 2500)" 53, 8, 107, 179, 14 + LTEXT "*Monster armor: (0 - 50)" 54, 8, 131, 179, 14 + LTEXT "*Monster skill: (0 - 40)" 55, 8, 155, 179, 14 + LTEXT "*Monster speed: (1-12)" 56, 8, 179, 179, 14 + LTEXT "*Monster magic spells: (0 - 7)" 57, 8, 203, 186, 14 + LTEXT "*Monster priest spells: (0 - 7)" 58, 8, 227, 191, 14 + LTEXT "~Hand to hand combat:" 59, 273, 82, 158, 16 + LTEXT "*Attack 1 number of dice: (0 - 20)" 60, 283, 102, 214, 14 + LTEXT "*Attack 1 number of sides: (1-50)" 61, 283, 126, 214, 14 + LTEXT "*Attack 2 number of dice: (0 - 20)" 62, 283, 150, 214, 14 + LTEXT "*Attack 2 number of sides: (1-50)" 63, 283, 174, 214, 14 + LTEXT "*Attack 3 number of dice: (0 - 20)" 64, 283, 198, 214, 14 + LTEXT "*Attack 3 number of sides: (1-50)" 65, 283, 222, 214, 14 + } + +815 DIALOG 10, 10, 672, 355 + STYLE WS_POPUP | WS_DLGFRAME + { + // DEFPUSHBUTTON "" 1, 283, 273, 31, 10//, WS_GROUP | WS_TABSTOP + LTEXT "6_0" 2, 206, 53, 52, 16 + LTEXT "6_0" 3, 206, 77, 52, 16 + LTEXT "6_0" 4, 382, 204, 53, 17 + LTEXT "6_0" 5, 194, 246, 64, 16 + LTEXT "6_0" 6, 464, 247, 64, 16 + LTEXT "1_63" 7, 572, 325, 63, 16 + LTEXT "0_5" 8, 506, 325, 63, 16 + LTEXT "2_0" 9, 494, 82, 23, 14 + LTEXT "2_0" 10, 494, 97, 23, 14 + LTEXT "2_0" 11, 494, 112, 23, 14 + LTEXT "2_0" 12, 494, 127, 23, 14 + LTEXT "2_0" 13, 267, 283, 23, 14 + LTEXT "2_0" 14, 267, 298, 23, 14 + LTEXT "2_0" 15, 267, 313, 23, 14 + LTEXT "2_0" 16, 267, 328, 23, 14 + LTEXT "2_0" 17, 420, 283, 23, 14 + LTEXT "2_0" 18, 420, 298, 23, 14 + LTEXT "2_0" 19, 420, 313, 23, 14 + LTEXT "2_0" 20, 420, 328, 23, 14 + LTEXT "5_716" 21, 8, 8, 36, 36 + LTEXT "~Edit Monster Abilities" 22, 50, 6, 158, 16 + LTEXT "*Monster number:" 23, 222, 8, 111, 14 + LTEXT "*" 24, 340, 8, 37, 14 + LTEXT "Enter properties for this monster type. For a detailed description of the fields, see the documentation." 25, 408, 2, 184, 54 + LTEXT "*Monster Poison: (0 - 8)" 26, 7, 54, 179, 14 + LTEXT "*Monster Breath Weapon strength (0 - 40): | Note: 0 - no breath weapon, damage is 1-8 times strength" 27, 7, 77, 190, 68 + LTEXT "*Breath weapon type:" 28, 268, 78, 131, 14 + LTEXT "~Special ability:" 29, 7, 152, 120, 14 + LTEXT "+" 30, 183, 152, 182, 14 + LTEXT "0_109" 31, 374, 149, 63, 16 + LTEXT "~Create monsters/fields:" 32, 7, 178, 166, 15 + LTEXT "+" 33, 183, 178, 183, 14 + LTEXT "0_109" 34, 374, 175, 75, 16 + LTEXT "*" 35, 54, 205, 118, 16 + LTEXT "+" 36, 180, 205, 195, 14 + LTEXT "~Special treasure:" 37, 7, 228, 158, 16 + LTEXT "*Item to drop when killed:" 38, 23, 247, 162, 14 + LTEXT "*Chance of dropping: (0-100)" 39, 270, 247, 186, 14 + LTEXT "*Monster resistances:" 40, 9, 279, 141, 14 + LTEXT "2_0" 41, 605, 153, 23, 14 + LTEXT "2_0" 42, 605, 168, 23, 14 + LTEXT "2_0" 43, 605, 183, 23, 14 + LTEXT "2_0" 44, 605, 198, 23, 14 + LTEXT "*Summon type:" 45, 440, 149, 94, 14 + } + +816 DIALOG 10, 10, 394, 173 + STYLE WS_POPUP | WS_DLGFRAME + { + // DEFPUSHBUTTON "" 1, 283, 273, 31, 10//, WS_GROUP | WS_TABSTOP + LTEXT "6_0" 2, 55, 34, 293, 98 + LTEXT "0_2" 3, 6, 141, 63, 16 + LTEXT "0_3" 4, 69, 141, 75, 16 + LTEXT "*" 5, 315, 8, 37, 14 + LTEXT "5_716" 6, 8, 8, 36, 36 + LTEXT "~Editing text:" 7, 50, 6, 138, 17 + LTEXT "*Text number:" 8, 197, 8, 111, 14 + LTEXT "1_63" 9, 279, 141, 75, 16 + } + +817 DIALOG 10, 10, 539, 437 + STYLE WS_POPUP | WS_DLGFRAME + { + // DEFPUSHBUTTON "" 1, 283, 273, 31, 10//, WS_GROUP | WS_TABSTOP + LTEXT "6_0" 2, 186, 26, 64, 16 + LTEXT "6_0" 3, 165, 54, 52, 16 + LTEXT "6_0" 4, 285, 54, 52, 16 + LTEXT "6_0" 5, 344, 114, 64, 16 + LTEXT "6_0" 6, 344, 137, 64, 16 + LTEXT "6_0" 7, 344, 160, 64, 16 + LTEXT "6_0" 8, 344, 183, 64, 16 + LTEXT "6_0" 9, 72, 223, 434, 80 + LTEXT "6_0" 10, 72, 328, 434, 80 + LTEXT "1_63" 11, 445, 415, 65, 16 + LTEXT "0_5" 12, 380, 415, 63, 16 + LTEXT "0_110" 13, 49, 415, 63, 16 + LTEXT "0_111" 14, 155, 415, 131, 16 + LTEXT "+" 15, 135, 79, 160, 14 + LTEXT "*A" 16, 104, 115, 233, 14 + LTEXT "*B" 17, 104, 138, 233, 14 + LTEXT "*C" 18, 104, 161, 233, 14 + LTEXT "*D" 19, 104, 184, 233, 14 + LTEXT "a" 20, 141, 204, 371, 14 + LTEXT "a" 21, 141, 309, 370, 14 + LTEXT "5_716" 22, 8, 8, 36, 36 + LTEXT "~Edit Character Dialogue" 23, 50, 6, 167, 14 + LTEXT "~For personality:" 24, 50, 27, 120, 14 + LTEXT "~Response to:" 25, 50, 55, 87, 14 + LTEXT "*and to:" 26, 224, 55, 52, 14 + LTEXT "~Node type:" 27, 49, 79, 77, 15 + LTEXT "0_109" 28, 306, 76, 75, 16 + LTEXT "~Extra values:" 29, 49, 100, 91, 14 + LTEXT "*A" 30, 77, 115, 24, 14 + LTEXT "*B" 31, 77, 138, 24, 14 + LTEXT "*C" 32, 77, 161, 23, 14 + LTEXT "*D" 33, 77, 184, 24, 14 + LTEXT "~Message 1:" 34, 49, 203, 83, 15 + LTEXT "~Message 2:" 35, 49, 309, 80, 14 + LTEXT "If -1: Node is unused, -2: All personalities use this response." 36, 256, 21, 207, 29 + LTEXT "0_109" 37, 414, 135, 75, 16 + LTEXT "0_106" 38, 414, 112, 75, 16 + } + +818 DIALOG 10, 10, 640, 365 + STYLE WS_POPUP | WS_DLGFRAME + { + // DEFPUSHBUTTON "" 1, 283, 273, 31, 10//, WS_GROUP | WS_TABSTOP + LTEXT "6_0" 2, 163, 30, 126, 16 + LTEXT "6_0" 3, 458, 30, 125, 16 + LTEXT "6_0" 4, 140, 62, 52, 16 + LTEXT "6_0" 5, 161, 199, 52, 16 + LTEXT "6_0" 6, 161, 223, 52, 16 + LTEXT "6_0" 7, 161, 247, 52, 16 + LTEXT "6_0" 8, 161, 271, 52, 16 + LTEXT "6_0" 9, 161, 295, 52, 16 + LTEXT "6_0" 10, 366, 199, 52, 16 + LTEXT "6_0" 11, 366, 223, 52, 16 + LTEXT "6_0" 12, 366, 247, 52, 16 + LTEXT "6_0" 13, 366, 271, 52, 16 + LTEXT "1_63" 14, 509, 337, 75, 16 + LTEXT "0_5" 15, 434, 337, 75, 16 + LTEXT "0_2" 16, 13, 337, 63, 16 + LTEXT "0_3" 17, 76, 337, 75, 16 + LTEXT "2_0" 18, 206, 89, 23, 14 + LTEXT "2_0" 19, 206, 104, 23, 14 + LTEXT "2_0" 20, 206, 119, 23, 14 + LTEXT "2_0" 21, 206, 134, 23, 14 + LTEXT "2_0" 22, 206, 149, 23, 14 + LTEXT "2_0" 23, 206, 164, 23, 14 + LTEXT "2_0" 24, 206, 179, 23, 14 + LTEXT "2_0" 25, 318, 89, 23, 14 + LTEXT "2_0" 26, 318, 104, 23, 14 + LTEXT "2_0" 27, 318, 119, 23, 14 + LTEXT "2_0" 28, 318, 134, 23, 14 + LTEXT "2_0" 29, 318, 149, 23, 14 + LTEXT "2_0" 30, 318, 164, 23, 14 + LTEXT "2_0" 31, 318, 179, 23, 14 + LTEXT "2_0" 32, 436, 89, 23, 14 + LTEXT "2_0" 33, 436, 104, 23, 14 + LTEXT "2_0" 34, 436, 119, 23, 14 + LTEXT "2_0" 35, 436, 134, 23, 14 + LTEXT "2_0" 36, 436, 149, 23, 14 + LTEXT "2_0" 37, 436, 164, 23, 14 + LTEXT "2_0" 38, 436, 179, 23, 14 + LTEXT "2_0" 39, 548, 89, 23, 14 + LTEXT "2_0" 40, 548, 104, 23, 14 + LTEXT "2_0" 41, 548, 119, 23, 14 + LTEXT "2_0" 42, 548, 134, 23, 14 + LTEXT "2_0" 43, 548, 149, 23, 14 + LTEXT "2_0" 44, 548, 164, 23, 14 + LTEXT "2_0" 45, 548, 179, 23, 14 + LTEXT "2_0" 46, 522, 233, 23, 14 + LTEXT "2_0" 47, 522, 248, 23, 14 + LTEXT "2_0" 48, 522, 263, 23, 14 + LTEXT "5_716" 49, 11, 8, 28, 36 + LTEXT "~Edit an Item Type" 50, 50, 6, 158, 16 + LTEXT "*Item number:" 51, 222, 8, 111, 14 + LTEXT "*" 52, 340, 8, 37, 14 + LTEXT "*Item Full Name:" 53, 50, 31, 107, 14 + LTEXT "*Item Unidentified Name:" 54, 298, 31, 155, 14 + LTEXT "*Item picture:" 55, 8, 63, 120, 14 + LTEXT "0_105" 56, 201, 58, 121, 16 + LTEXT "~Item type:" 57, 8, 87, 86, 16 + LTEXT "*Item level: (0 - 50)" 58, 8, 200, 148, 14 + LTEXT "*Awkwardness: (0-20)" 59, 8, 224, 148, 14 + LTEXT "*Bonus: (0-10)" 60, 8, 248, 148, 14 + LTEXT "*Protection: (-10 - 20)" 61, 8, 272, 148, 14 + LTEXT "*Charges: (0-100)" 62, 8, 296, 148, 14 + LTEXT "*Type flag: (0-1000)" 63, 220, 200, 137, 13 + LTEXT "*Value: (0-10000)" 64, 220, 224, 141, 13 + LTEXT "*Weight: (0-250)" 65, 220, 248, 141, 13 + LTEXT "*Special class: (0-100)" 66, 220, 272, 141, 13 + LTEXT "Weapon type: (ignored if not a weapon)" 67, 425, 200, 161, 28 + LTEXT "Enter properties for this item type. For a detailed description of the fields, see the documentation. Click Edit Abilities to edit item abilities." 68, 221, 293, 363, 40 + LTEXT "0_125" 69, 155, 337, 75, 16 + } + +819 DIALOG 10, 10, 482, 348 +STYLE WS_POPUP | WS_DLGFRAME +{ + LTEXT "1_0", 1, 393, 316, 56, 20 + LTEXT "5_716", 2, 6, 6, 36, 36 + LTEXT "~Select a graphic:", 3, 50, 6, 248, 16 + LTEXT "0_5", 4, 322, 316, 60, 20 + LTEXT "2_1", 5, 55, 29, 16, 17 + LTEXT "2_0", 6, 55, 74, 16, 18 + LTEXT "2_0", 7, 55, 119, 16, 18 + LTEXT "2_0", 8, 54, 164, 17, 18 + LTEXT "2_0", 9, 54, 209, 17, 18 + LTEXT "2_0", 10, 54, 254, 17, 18 + LTEXT "2_0", 11, 119, 29, 16, 17 + LTEXT "2_0", 12, 119, 74, 16, 18 + LTEXT "2_0", 13, 119, 119, 16, 18 + LTEXT "2_0", 14, 118, 164, 17, 18 + LTEXT "2_0", 15, 118, 209, 17, 18 + LTEXT "2_0", 16, 118, 254, 17, 18 + LTEXT "2_0", 17, 183, 30, 16, 17 + LTEXT "2_0", 18, 183, 75, 16, 18 + LTEXT "2_0", 19, 183, 120, 16, 18 + LTEXT "2_0", 20, 182, 165, 17, 18 + LTEXT "2_0", 21, 182, 210, 17, 18 + LTEXT "2_0", 22, 182, 255, 17, 18 + LTEXT "2_0", 23, 251, 30, 16, 17 + LTEXT "2_0", 24, 251, 75, 16, 18 + LTEXT "2_0", 25, 251, 120, 16, 18 + LTEXT "2_0", 26, 250, 165, 17, 18 + LTEXT "2_0", 27, 250, 210, 17, 18 + LTEXT "2_0", 28, 250, 255, 17, 18 + LTEXT "2_0", 29, 320, 30, 16, 17 + LTEXT "2_0", 30, 320, 75, 16, 18 + LTEXT "2_0", 31, 320, 120, 16, 18 + LTEXT "2_0", 32, 319, 165, 17, 18 + LTEXT "2_0", 33, 319, 210, 17, 18 + LTEXT "2_0", 34, 319, 255, 17, 18 + LTEXT "2_0", 35, 388, 30, 16, 17 + LTEXT "2_0", 36, 388, 75, 16, 18 + LTEXT "2_0", 37, 388, 120, 16, 18 + LTEXT "2_0", 38, 387, 165, 17, 18 + LTEXT "2_0", 39, 387, 210, 17, 18 + LTEXT "2_0", 40, 387, 255, 17, 18 + LTEXT "5_400", 41, 76, 29, 36, 36 + LTEXT "5_401", 42, 76, 74, 36, 36 + LTEXT "5_402", 43, 76, 119, 36, 36 + LTEXT "5_403", 44, 76, 164, 36, 36 + LTEXT "5_404", 45, 76, 209, 36, 36 + LTEXT "5_405", 46, 76, 254, 36, 36 + LTEXT "5_406", 47, 140, 29, 36, 36 + LTEXT "5_407", 48, 140, 74, 36, 36 + LTEXT "5_408", 49, 140, 119, 36, 36 + LTEXT "5_409", 50, 140, 164, 36, 36 + LTEXT "5_410", 51, 140, 209, 36, 36 + LTEXT "5_411", 52, 140, 254, 36, 36 + LTEXT "5_412", 53, 204, 30, 36, 36 + LTEXT "5_413", 54, 204, 75, 36, 36 + LTEXT "5_414", 55, 204, 120, 36, 36 + LTEXT "5_415", 56, 204, 165, 36, 36 + LTEXT "5_416", 57, 204, 210, 36, 36 + LTEXT "5_417", 58, 204, 255, 36, 36 + LTEXT "5_418", 59, 272, 30, 36, 36 + LTEXT "5_419", 60, 272, 75, 36, 36 + LTEXT "5_420", 61, 272, 120, 36, 36 + LTEXT "5_421", 62, 272, 165, 36, 36 + LTEXT "5_422", 63, 272, 210, 36, 36 + LTEXT "5_423", 64, 272, 255, 36, 36 + LTEXT "5_424", 65, 341, 30, 36, 36 + LTEXT "5_425", 66, 341, 75, 36, 36 + LTEXT "5_426", 67, 341, 120, 36, 36 + LTEXT "5_427", 68, 341, 165, 36, 36 + LTEXT "5_428", 69, 341, 210, 36, 36 + LTEXT "5_429", 70, 341, 255, 36, 36 + LTEXT "5_430", 71, 409, 30, 36, 36 + LTEXT "5_431", 72, 409, 75, 36, 36 + LTEXT "5_432", 73, 409, 120, 36, 36 + LTEXT "5_433", 74, 409, 165, 36, 36 + LTEXT "5_434", 75, 409, 210, 36, 36 + LTEXT "5_435", 76, 409, 255, 36, 36 + LTEXT "Click button to left of graphic to select. Use arrows to change pages.", 77, 6, 297, 422, 16 + LTEXT "0_2", 78, 6, 317, 63, 20 + LTEXT "0_3", 79, 69, 317, 60, 20 +} + +820 DIALOG 10, 10, 452, 389 + STYLE WS_POPUP | WS_DLGFRAME + { + // DEFPUSHBUTTON "" 1, 279, 223, 31, 10//, WS_GROUP | WS_TABSTOP + LTEXT "1_63" 2, 338, 358, 75, 16 + LTEXT "5_716" 3, 8, 8, 36, 36 + LTEXT "~Select:" 4, 50, 6, 256, 17 + LTEXT "0_2" 5, 8, 358, 63, 16 + LTEXT "0_3" 6, 71, 358, 75, 16 + LTEXT "0_5" 7, 272, 358, 63, 16 + LTEXT "*" 8, 8, 52, 182, 13 + LTEXT "2_0" 9, 191, 54, 23, 14 + LTEXT "*" 10, 8, 67, 182, 13 + LTEXT "2_0" 11, 191, 69, 23, 14 + LTEXT "*" 12, 8, 82, 182, 13 + LTEXT "2_0" 13, 191, 84, 23, 14 + LTEXT "*" 14, 8, 97, 182, 13 + LTEXT "2_0" 15, 191, 99, 23, 14 + LTEXT "*" 16, 8, 112, 182, 13 + LTEXT "2_0" 17, 191, 114, 23, 14 + LTEXT "*" 18, 8, 127, 182, 13 + LTEXT "2_0" 19, 191, 129, 23, 14 + LTEXT "*" 20, 8, 142, 182, 13 + LTEXT "2_0" 21, 191, 144, 23, 14 + LTEXT "*" 22, 8, 157, 182, 13 + LTEXT "2_0" 23, 191, 159, 23, 14 + LTEXT "*" 24, 8, 172, 182, 13 + LTEXT "2_0" 25, 191, 174, 23, 14 + LTEXT "*" 26, 8, 187, 182, 13 + LTEXT "2_0" 27, 191, 189, 23, 14 + LTEXT "*" 28, 8, 202, 182, 13 + LTEXT "2_0" 29, 191, 204, 23, 14 + LTEXT "*" 30, 8, 217, 182, 13 + LTEXT "2_0" 31, 191, 219, 23, 14 + LTEXT "*" 32, 8, 232, 182, 13 + LTEXT "2_0" 33, 191, 234, 23, 14 + LTEXT "*" 34, 8, 247, 182, 13 + LTEXT "2_0" 35, 191, 249, 23, 14 + LTEXT "*" 36, 8, 262, 182, 13 + LTEXT "2_0" 37, 191, 264, 23, 14 + LTEXT "*" 38, 8, 277, 182, 13 + LTEXT "2_0" 39, 191, 279, 23, 14 + LTEXT "*" 40, 8, 292, 182, 13 + LTEXT "2_0" 41, 191, 294, 23, 14 + LTEXT "*" 42, 8, 307, 182, 13 + LTEXT "2_0" 43, 191, 309, 23, 14 + LTEXT "*" 44, 8, 322, 182, 13 + LTEXT "2_0" 45, 191, 324, 23, 14 + LTEXT "*" 46, 8, 337, 182, 13 + LTEXT "2_0" 47, 191, 339, 23, 14 + LTEXT "*" 48, 216, 52, 183, 14 + LTEXT "2_0" 49, 400, 54, 23, 14 + LTEXT "*" 50, 216, 67, 183, 14 + LTEXT "2_0" 51, 400, 69, 23, 14 + LTEXT "*" 52, 216, 82, 183, 14 + LTEXT "2_0" 53, 400, 84, 23, 14 + LTEXT "*" 54, 216, 97, 183, 14 + LTEXT "2_0" 55, 400, 99, 23, 14 + LTEXT "*" 56, 216, 112, 183, 14 + LTEXT "2_0" 57, 400, 114, 23, 14 + LTEXT "*" 58, 216, 127, 183, 14 + LTEXT "2_0" 59, 400, 129, 23, 14 + LTEXT "*" 60, 216, 142, 183, 14 + LTEXT "2_0" 61, 400, 144, 23, 14 + LTEXT "*" 62, 216, 157, 183, 14 + LTEXT "2_0" 63, 400, 159, 23, 14 + LTEXT "*" 64, 216, 172, 183, 14 + LTEXT "2_0" 65, 400, 174, 23, 14 + LTEXT "*" 66, 216, 187, 183, 14 + LTEXT "2_0" 67, 400, 189, 23, 14 + LTEXT "*" 68, 216, 202, 183, 14 + LTEXT "2_0" 69, 400, 204, 23, 14 + LTEXT "*" 70, 216, 217, 183, 14 + LTEXT "2_0" 71, 400, 219, 23, 14 + LTEXT "*" 72, 216, 232, 183, 14 + LTEXT "2_0" 73, 400, 234, 23, 14 + LTEXT "*" 74, 216, 247, 183, 14 + LTEXT "2_0" 75, 400, 249, 23, 14 + LTEXT "*" 76, 216, 262, 183, 14 + LTEXT "2_0" 77, 400, 264, 23, 14 + LTEXT "*" 78, 216, 277, 183, 14 + LTEXT "2_0" 79, 400, 279, 23, 14 + LTEXT "*" 80, 216, 292, 183, 14 + LTEXT "2_0" 81, 400, 294, 23, 14 + LTEXT "*" 82, 216, 307, 183, 14 + LTEXT "2_0" 83, 400, 309, 23, 14 + LTEXT "*" 84, 216, 322, 183, 14 + LTEXT "2_0" 85, 400, 324, 23, 14 + LTEXT "*" 86, 216, 337, 183, 14 + LTEXT "2_0" 87, 400, 339, 23, 14 + } + +821 DIALOG 10, 10, 539, 403 + STYLE WS_POPUP | WS_DLGFRAME + { + // DEFPUSHBUTTON "" 1, 283, 273, 31, 10//, WS_GROUP | WS_TABSTOP + LTEXT "6_0" 2, 174, 42, 189, 16 + LTEXT "6_0" 3, 254, 66, 246, 43 + LTEXT "6_0" 4, 73, 123, 427, 68 + LTEXT "6_0" 5, 73, 215, 427, 67 + LTEXT "6_0" 6, 73, 308, 427, 67 + LTEXT "1_63" 7, 441, 381, 62, 15 + LTEXT "0_5" 8, 375, 381, 63, 15 + LTEXT "0_2" 9, 47, 381, 63, 15 + LTEXT "0_3" 10, 110, 381, 67, 15 + LTEXT "5_716" 11, 8, 8, 36, 36 + LTEXT "~Edit Character Basic Dialogue" 12, 50, 6, 249, 15 + LTEXT "*For personality number:" 13, 50, 22, 157, 14 + LTEXT "*" 14, 210, 22, 52, 14 + LTEXT "~Character name:" 15, 50, 43, 114, 14 + LTEXT "~Don't Understand response:" 16, 50, 67, 173, 15 + LTEXT "~Response to 'look'" 17, 50, 103, 160, 15 + LTEXT "~Response to 'name'" 18, 50, 196, 165, 14 + LTEXT "~Response to 'job'" 19, 52, 288, 170, 13 + } + +822 DIALOG 10, 10, 625, 424 +STYLE WS_POPUP | WS_DLGFRAME +{ + LTEXT "6_0", 2, 254, 120, 51, 16 + LTEXT "6_0", 3, 510, 120, 51, 16 + LTEXT "6_0", 4, 270, 163, 51, 16 + LTEXT "6_0", 5, 270, 187, 51, 16 + LTEXT "6_0", 6, 270, 211, 51, 16 + LTEXT "6_0", 7, 270, 253, 51, 16 + LTEXT "6_0", 8, 270, 277, 51, 16 + LTEXT "6_0", 9, 270, 322, 51, 16 + LTEXT "6_0", 10, 270, 346, 51, 16 + LTEXT "6_0", 11, 291, 375, 52, 15 + LTEXT "1_63", 12, 522, 398, 67, 16 + LTEXT "0_5", 13, 456, 398, 63, 16 + LTEXT "0_110", 14, 10, 401, 75, 16 + LTEXT "*", 15, 314, 8, 38, 14 + LTEXT "5_716", 16, 8, 8, 36, 36 + LTEXT "~Edit Special Node", 17, 50, 6, 158, 16 + LTEXT "*Node number:", 18, 222, 8, 90, 14 + LTEXT "Enter properties for this special encounter node. For a detailed description of how this window works, see the documentation.", 19, 469, 147, 125, 124 + LTEXT "+", 20, 22, 121, 220, 15 + LTEXT "+", 21, 317, 121, 176, 16 + LTEXT "+", 22, 22, 164, 238, 15 + LTEXT "+", 23, 22, 188, 238, 15 + LTEXT "+", 24, 22, 212, 238, 15 + LTEXT "+", 25, 22, 254, 238, 15 + LTEXT "+", 26, 22, 278, 238, 15 + LTEXT "+", 27, 213, 28, 187, 16 + LTEXT "+", 28, 22, 322, 238, 15 + LTEXT "+", 29, 22, 347, 238, 15 + LTEXT "+", 30, 99, 376, 182, 14 + LTEXT "~Special Type:", 31, 50, 28, 158, 16 + LTEXT "~Stuff Done Flags:", 32, 8, 98, 158, 16 + LTEXT "~Message1, Message2, Pict:", 33, 8, 141, 176, 16 + LTEXT "~Extra 1a and 1b:", 34, 8, 233, 158, 16 + LTEXT "~Extra 2a and 2b:", 35, 8, 300, 158, 16 + LTEXT "~Jump To:", 36, 8, 375, 87, 16 + LTEXT "0_112", 37, 102, 49, 120, 21 + LTEXT "0_113", 38, 102, 73, 120, 21 + LTEXT "0_114", 39, 229, 49, 120, 21 + LTEXT "0_115", 40, 229, 73, 120, 21 + LTEXT "0_116", 41, 356, 49, 120, 21 + LTEXT "0_117", 42, 356, 73, 120, 21 + LTEXT "0_106", 43, 330, 274, 129, 24 + LTEXT "0_106", 44, 330, 344, 129, 24 + LTEXT "0_106", 45, 349, 372, 131, 21 + LTEXT "0_109", 46, 329, 209, 74, 21 + LTEXT "0_109", 47, 330, 250, 74, 21 + LTEXT "0_109", 48, 330, 319, 74, 21 + LTEXT "0_106", 49, 329, 185, 129, 24 +} + +824 DIALOG 10, 10, 572, 290 + STYLE WS_POPUP | WS_DLGFRAME + { + // DEFPUSHBUTTON "" 1, 283, 273, 31, 10//, WS_GROUP | WS_TABSTOP + LTEXT "6_0" 2, 183, 88, 77, 16 + LTEXT "1_63" 3, 471, 266, 63, 15 + LTEXT "0_5" 4, 405, 266, 63, 15 + LTEXT "2_0" 5, 264, 143, 23, 13 + LTEXT "2_0" 6, 264, 158, 23, 13 + LTEXT "2_0" 7, 264, 173, 23, 13 + LTEXT "2_0" 8, 264, 188, 23, 13 + LTEXT "2_0" 9, 515, 144, 23, 13 + LTEXT "2_0" 10, 515, 159, 23, 13 + LTEXT "2_0" 11, 515, 174, 23, 13 + LTEXT "2_0" 12, 515, 189, 23, 13 + LTEXT "5_716" 13, 11, 8, 28, 36 + LTEXT "~Edit Item Abilities" 14, 50, 6, 158, 16 + LTEXT "*Item number:" 15, 222, 8, 111, 14 + LTEXT "*" 16, 340, 8, 37, 14 + LTEXT "0_119" 17, 333, 62, 98, 15 + LTEXT "~Item special ability:" 18, 8, 63, 142, 13 + LTEXT "+" 19, 159, 63, 163, 13 + LTEXT "*" 20, 486, 17, 45, 14 + LTEXT "Ability strength: (Usually 0-10, see instructions)" 21, 8, 84, 168, 27 + LTEXT "*Item use properties:" 22, 8, 140, 135, 13 + LTEXT "Only used for item abilities which are used (like healing)." 23, 21, 156, 123, 39 + LTEXT "*Other properties:" 24, 292, 140, 121, 13 + LTEXT "Item treasure class: (0 is lowest level of treasure, 4 is highest)" 25, 10, 209, 155, 42 + LTEXT "2_0" 26, 308, 213, 23, 13 + LTEXT "2_0" 27, 308, 228, 23, 13 + LTEXT "2_0" 28, 308, 243, 23, 13 + LTEXT "2_0" 29, 308, 258, 23, 13 + LTEXT "2_0" 30, 308, 273, 23, 13 + LTEXT "*Current item name:" 31, 50, 25, 145, 14 + LTEXT "*" 32, 198, 25, 196, 14 + LTEXT "*Current item variety:" 33, 50, 41, 145, 14 + LTEXT "*" 34, 198, 41, 196, 14 + LTEXT "0_120" 35, 441, 61, 98, 15 + LTEXT "0_121" 36, 333, 87, 98, 15 + LTEXT "0_124" 37, 441, 111, 98, 15 + LTEXT "0_123" 38, 333, 112, 98, 15 + LTEXT "0_122" 39, 441, 86, 98, 15 + } + +825 DIALOG 10, 10, 411, 117 + STYLE WS_POPUP | WS_DLGFRAME + { + // DEFPUSHBUTTON "" 1, 171, 138, 31, 10//, WS_GROUP | WS_TABSTOP + LTEXT "6_0" 2, 209, 64, 75, 16 + LTEXT "5_716" 3, 8, 8, 36, 36 + LTEXT "1_63" 4, 311, 87, 62, 16 + LTEXT "~Set Special Number:" 5, 50, 6, 256, 17 + LTEXT "Which special node should be called when this space is entered/examined?" 6, 50, 25, 323, 27 + LTEXT "Special node:" 7, 120, 64, 84, 16 + LTEXT "0_5" 8, 246, 87, 63, 16 + } + +826 DIALOG 10, 10, 382, 290 + STYLE WS_POPUP | WS_DLGFRAME + { + // DEFPUSHBUTTON "" 1, 283, 273, 31, 10//, WS_GROUP | WS_TABSTOP + LTEXT "6_0" 2, 53, 60, 293, 96 + LTEXT "6_0" 3, 53, 164, 293, 96 + LTEXT "5_716" 4, 8, 8, 36, 36 + LTEXT "~Editing Special Message:" 5, 50, 6, 169, 16 + LTEXT "1_63" 6, 285, 266, 67, 16 + LTEXT "0_5" 7, 219, 266, 63, 16 + LTEXT "This encounter can have one or two pieces of text appear. You can leave one or both blank." 8, 50, 24, 299, 28 + } + +830 DIALOG 10, 10, 367, 252 + STYLE WS_POPUP | WS_DLGFRAME + { + // DEFPUSHBUTTON "" 1, 279, 223, 31, 10//, WS_GROUP | WS_TABSTOP + LTEXT "6_0" 2, 140, 85, 152, 16 + LTEXT "1_63" 3, 264, 221, 62, 16 + LTEXT "5_716" 4, 8, 8, 36, 36 + LTEXT "~Create New Town" 5, 50, 6, 256, 17 + LTEXT "*Town name:" 6, 50, 86, 84, 14 + LTEXT "*Town size:" 7, 50, 111, 77, 14 + LTEXT "*Large (64x64)" 8, 145, 111, 139, 14 + LTEXT "*Medium (48x48)" 9, 145, 128, 139, 14 + LTEXT "*Small (32x32)" 10, 145, 145, 139, 14 + LTEXT "2_0" 11, 301, 114, 23, 14 + LTEXT "2_0" 12, 301, 131, 23, 14 + LTEXT "2_0" 13, 301, 148, 23, 14 + LTEXT "*Preset terrain:" 14, 51, 164, 105, 14 + LTEXT "*Just cave floor" 15, 168, 164, 100, 15 + LTEXT "*Plain Grass" 16, 168, 181, 102, 15 + LTEXT "*Grass with flowers" 17, 168, 198, 127, 15 + LTEXT "2_0" 18, 301, 167, 23, 14 + LTEXT "2_0" 19, 301, 184, 23, 14 + LTEXT "2_0" 20, 301, 201, 23, 14 + LTEXT "*Creating town number:" 21, 50, 28, 147, 14 + LTEXT "*" 22, 201, 28, 33, 14 + LTEXT "0_5" 23, 199, 221, 63, 16 + LTEXT "Note: Your new town will be tacked onto the end of your current town list." 24, 66, 49, 260, 28 + } + +831 DIALOG 10, 10, 394, 173 + STYLE WS_POPUP | WS_DLGFRAME + { + // DEFPUSHBUTTON "" 1, 283, 273, 31, 10//, WS_GROUP | WS_TABSTOP + LTEXT "6_0" 2, 55, 34, 293, 98 + LTEXT "0_5" 3, 222, 141, 63, 16 + LTEXT "Use a '|' to indicate a line break." 4, 7, 142, 198, 15 + LTEXT "*" 5, 287, 8, 37, 14 + LTEXT "5_716" 6, 12, 8, 28, 36 + LTEXT "~Editing Sign" 7, 50, 6, 138, 17 + LTEXT "*Sign number:" 8, 197, 8, 89, 14 + LTEXT "1_63" 9, 288, 141, 63, 16 + } + +832 DIALOG 10, 10, 407, 346 + STYLE WS_POPUP | WS_DLGFRAME + { + // DEFPUSHBUTTON "" 1, 279, 223, 31, 10//, WS_GROUP | WS_TABSTOP + LTEXT "6_0" 2, 186, 29, 151, 16 + LTEXT "6_0" 3, 327, 77, 43, 16 + LTEXT "6_0" 4, 327, 101, 43, 16 + LTEXT "6_0" 5, 294, 219, 54, 16 + LTEXT "6_0" 6, 294, 265, 54, 16 + LTEXT "1_63" 7, 309, 317, 63, 16 + LTEXT "5_716" 8, 8, 8, 36, 36 + LTEXT "~Town Details" 9, 50, 6, 256, 17 + LTEXT "*Town name:" 10, 50, 30, 120, 14 + LTEXT "*Town timing:" 11, 50, 58, 120, 14 + LTEXT "Day when town dies: (if -1, it doesn't)" 12, 59, 78, 242, 14 + LTEXT "Number of event which prevents town death (if -1 or 0, none) - see chapter in documentation on time for more details." 13, 59, 98, 261, 41 + LTEXT "*Lighting:" 14, 50, 143, 63, 14 + LTEXT "*Fully Lit" 15, 122, 143, 164, 14 + LTEXT "*Dark" 16, 122, 160, 164, 14 + LTEXT "Very dark (light used 10x as fast)" 17, 122, 177, 204, 14 + LTEXT "*Totally dark (no light)" 18, 122, 194, 164, 15 + LTEXT "2_0" 19, 329, 143, 23, 14 + LTEXT "2_0" 20, 329, 160, 23, 14 + LTEXT "2_0" 21, 329, 177, 23, 14 + LTEXT "2_0" 22, 329, 194, 32, 15 + LTEXT "Maximum number of monsters: (When this many monsters are killed, the dungeon will be abandoned)" 23, 50, 216, 234, 42 + LTEXT "Town difficulty (0-10): (Determines how fast wandering monsters appear, how nasty traps are, and how hard it is to unlock doors.)" 24, 50, 262, 235, 53 + } + +833 DIALOG 10, 10, 535, 450 + STYLE WS_POPUP | WS_DLGFRAME + { + // DEFPUSHBUTTON "" 1, 292, 238, 31, 10//, WS_GROUP | WS_TABSTOP + LTEXT "6_0" 2, 146, 122, 67, 16 + LTEXT "6_0" 3, 146, 150, 67, 16 + LTEXT "6_0" 4, 146, 178, 67, 16 + LTEXT "6_0" 5, 146, 206, 67, 16 + LTEXT "6_0" 6, 146, 234, 67, 16 + LTEXT "6_0" 7, 146, 262, 67, 16 + LTEXT "6_0" 8, 146, 290, 67, 16 + LTEXT "6_0" 9, 146, 318, 67, 16 + LTEXT "6_0" 10, 270, 122, 39, 16 + LTEXT "6_0" 11, 270, 150, 39, 16 + LTEXT "6_0" 12, 270, 178, 39, 16 + LTEXT "6_0" 13, 270, 206, 39, 16 + LTEXT "6_0" 14, 270, 234, 39, 16 + LTEXT "6_0" 15, 270, 262, 39, 16 + LTEXT "6_0" 16, 270, 290, 39, 16 + LTEXT "6_0" 17, 270, 318, 39, 16 + LTEXT "1_63" 18, 431, 317, 75, 16 + LTEXT "5_716" 19, 8, 8, 36, 36 + LTEXT "~Town event timers" 20, 50, 6, 256, 17 + LTEXT "At certain time intervals, you can have a town special node be called. Enter below the number of moves between each calling of the special node, and the number of the node to call." 21, 50, 25, 439, 40 + LTEXT "For more information on how this works, see the documentation." 22, 50, 68, 439, 14 + LTEXT "Number of moves between each call." 23, 123, 88, 120, 28 + LTEXT "Town special node to call." 24, 244, 88, 118, 25 + LTEXT "Note: If you leave the time between calls at 0, no special node is called. Don't have special nodes called too often ... it slows the game down." 25, 4, 216, 106, 120 + LTEXT "0_106" 26, 325, 119, 75, 16 + LTEXT "0_106" 27, 325, 147, 75, 16 + LTEXT "0_106" 28, 325, 174, 75, 16 + LTEXT "0_106" 29, 325, 203, 75, 16 + LTEXT "0_106" 30, 325, 231, 75, 16 + LTEXT "0_106" 31, 325, 258, 75, 16 + LTEXT "0_106" 32, 325, 287, 75, 16 + LTEXT "0_106" 33, 325, 315, 75, 16 + } + +834 DIALOG 10, 10, 548, 389 + STYLE WS_POPUP | WS_DLGFRAME + { + // DEFPUSHBUTTON "" 1, 292, 238, 31, 10//, WS_GROUP | WS_TABSTOP + LTEXT "6_0" 2, 308, 77, 67, 16 + LTEXT "6_0" 3, 308, 105, 67, 16 + LTEXT "6_0" 4, 440, 77, 67, 16 + LTEXT "6_0" 5, 440, 105, 67, 16 + LTEXT "6_0" 6, 405, 142, 67, 16 + LTEXT "6_0" 7, 405, 170, 67, 16 + LTEXT "6_0" 8, 323, 231, 39, 16 + LTEXT "6_0" 9, 371, 231, 39, 16 + LTEXT "6_0" 10, 323, 258, 39, 16 + LTEXT "6_0" 11, 371, 258, 39, 16 + LTEXT "6_0" 12, 323, 285, 39, 16 + LTEXT "6_0" 13, 371, 285, 39, 16 + LTEXT "6_0" 14, 323, 312, 39, 16 + LTEXT "6_0" 15, 371, 312, 39, 16 + LTEXT "1_63" 16, 452, 367, 61, 15 + LTEXT "0_5" 17, 386, 367, 63, 16 + LTEXT "5_716" 18, 8, 8, 36, 36 + LTEXT "~Advanced town details" 19, 50, 6, 256, 17 + LTEXT "You can use this window to edit some of the more esoteric details for each town, such as specials called when entering or leaving town. All of these options are decribed in the documentation chapter on town editing." 20, 50, 25, 439, 40 + LTEXT "Exit town location: (these are the locations the party ends up at outdoors if they leave in the given direction. Leave at -1 for the regular location to be used.)" 21, 50, 207, 197, 64 + LTEXT "Town entry special node: (Enter the number of the town special node to call if the party enters the town when it's still alive, and/or when it's been abandoned.)" 22, 50, 134, 202, 66 + LTEXT "Exit town specials: (These are the numbers of the town special nodes to call when the party tries to leave town in the given direction.)" 23, 50, 68, 197, 64 + LTEXT "*Still alive" 24, 259, 143, 137, 15 + LTEXT "*Been abandoned" 25, 259, 170, 137, 15 + LTEXT "*Top" 26, 250, 77, 49, 15 + LTEXT "*Left" 27, 251, 105, 49, 15 + LTEXT "*Bottom" 28, 381, 77, 53, 15 + LTEXT "*Right" 29, 382, 105, 49, 15 + LTEXT "*Top" 30, 257, 232, 49, 15 + LTEXT "*Left" 31, 258, 259, 49, 15 + LTEXT "*Bottom" 32, 258, 285, 53, 15 + LTEXT "*Right" 33, 259, 313, 49, 15 + LTEXT "*X" 34, 331, 207, 35, 15 + LTEXT "*Y" 35, 379, 207, 40, 15 + LTEXT "Town hidden? (This town cannot be seen until it's made visible with a special encounter.)" 36, 50, 336, 320, 27 + LTEXT "2_0" 37, 373, 342, 23, 14 + } + +835 DIALOG 10, 10, 531, 280 + STYLE WS_POPUP | WS_DLGFRAME + { + // DEFPUSHBUTTON "" 1, 292, 238, 31, 10//, WS_GROUP | WS_TABSTOP + LTEXT "6_0" 2, 174, 137, 39, 16 + LTEXT "6_0" 3, 174, 165, 39, 16 + LTEXT "6_0" 4, 174, 193, 39, 16 + LTEXT "6_0" 5, 174, 221, 39, 16 + LTEXT "6_0" 6, 239, 137, 39, 16 + LTEXT "6_0" 7, 239, 165, 39, 16 + LTEXT "6_0" 8, 239, 193, 39, 16 + LTEXT "6_0" 9, 239, 221, 39, 16 + LTEXT "6_0" 10, 304, 137, 39, 16 + LTEXT "6_0" 11, 304, 165, 39, 16 + LTEXT "6_0" 12, 304, 193, 39, 16 + LTEXT "6_0" 13, 304, 221, 39, 16 + LTEXT "6_0" 14, 369, 137, 39, 16 + LTEXT "6_0" 15, 369, 165, 39, 16 + LTEXT "6_0" 16, 369, 193, 39, 16 + LTEXT "6_0" 17, 369, 221, 39, 16 + LTEXT "1_63" 18, 436, 243, 63, 17 + LTEXT "~Town wandering monsters" 19, 50, 6, 256, 17 + LTEXT "Wandering monsters in towns appear in groups of up to 5. Enter the numbers of the wandering monsters in each group type, or press the Choose button to select the appearing monsters from a list." 20, 50, 25, 439, 40 + LTEXT "A group of wandering monsters contains one each of the first three monsters, and 1 or 2 of the fourth. Leave a field at 0 for no monster to appear." 21, 50, 68, 437, 40 + LTEXT "*Group 1" 22, 166, 115, 58, 14 + LTEXT "5_716" 23, 8, 8, 36, 36 + LTEXT "*Group 2" 24, 231, 115, 58, 14 + LTEXT "*Group 3" 25, 294, 115, 58, 14 + LTEXT "*Group 4" 26, 357, 115, 58, 14 + LTEXT "0_109" 27, 162, 243, 63, 17 + LTEXT "0_109" 28, 227, 243, 63, 17 + LTEXT "0_109" 29, 292, 243, 63, 17 + LTEXT "0_109" 30, 357, 243, 63, 17 + LTEXT "*Monster 1 (1 appears)" 31, 8, 138, 145, 14 + LTEXT "*Monster 2 (1 appears)" 32, 8, 166, 145, 14 + LTEXT "*Monster 3 (1 appears)" 33, 8, 194, 145, 14 + LTEXT "*Monster 4 (1-2 appears)" 34, 8, 222, 159, 14 + } + +836 DIALOG 10, 10, 427, 224 + STYLE WS_POPUP | WS_DLGFRAME + { + // DEFPUSHBUTTON "" 1, 279, 223, 31, 10//, WS_GROUP | WS_TABSTOP + LTEXT "6_0" 2, 335, 84, 52, 16 + LTEXT "1_63" 3, 316, 195, 75, 16 + LTEXT "5_716" 4, 12, 8, 28, 36 + LTEXT "~Editing Preset Item" 5, 50, 6, 175, 17 + LTEXT "*Item name:" 6, 50, 50, 77, 14 + LTEXT "Amount (if gold or food), or Charges (if item that can have charges, leave at -1 if you want the item to have its default number of charges)" 7, 50, 73, 280, 41 + LTEXT "*Special Flags:" 8, 50, 120, 116, 14 + LTEXT "*Always here" 9, 84, 138, 164, 14 + LTEXT "*Someone's property" 10, 84, 155, 164, 14 + LTEXT "*Contained in something" 11, 84, 172, 204, 14 + LTEXT "2_0" 12, 291, 138, 23, 14 + LTEXT "2_0" 13, 291, 155, 23, 14 + LTEXT "2_0" 14, 291, 172, 23, 14 + LTEXT "+" 15, 136, 50, 143, 14 + LTEXT "*Item number:" 16, 50, 28, 97, 14 + LTEXT "*" 17, 151, 28, 37, 14 + LTEXT "0_109" 18, 290, 46, 75, 16 + LTEXT "0_2" 19, 13, 195, 63, 16 + LTEXT "0_5" 20, 248, 195, 63, 16 + LTEXT "*Location:" 21, 196, 28, 70, 14 + LTEXT "*" 22, 272, 28, 116, 14 + } + +837 DIALOG 10, 10, 570, 256 + STYLE WS_POPUP | WS_DLGFRAME + { + // DEFPUSHBUTTON "" 1, 292, 238, 31, 10//, WS_GROUP | WS_TABSTOP + LTEXT "6_0" 2, 149, 189, 67, 16 + LTEXT "6_0" 3, 341, 189, 71, 16 + LTEXT "~Creature type:" 4, 51, 71, 115, 15 + LTEXT "*Personality:" 5, 51, 189, 84, 15 + LTEXT "0_109" 6, 333, 69, 75, 16 + LTEXT "+" 7, 171, 71, 155, 15 + LTEXT "*Creature starting attitude:" 8, 51, 92, 169, 15 + LTEXT "*Creature can move?" 9, 51, 128, 130, 15 + LTEXT "*Facial graphic:" 10, 230, 189, 100, 15 + LTEXT "5_0" 11, 426, 180, 36, 36 + LTEXT "0_109" 12, 471, 186, 63, 16 + LTEXT "~Editing a townsperson/monster" 13, 50, 6, 256, 17 + LTEXT "2_0" 14, 342, 97, 23, 14 + LTEXT "2_0" 15, 342, 113, 23, 14 + LTEXT "2_0" 16, 477, 97, 23, 14 + LTEXT "2_0" 17, 477, 113, 23, 14 + LTEXT "2_0" 18, 224, 133, 23, 14 + LTEXT "2_0" 19, 282, 133, 23, 14 + LTEXT "1_63" 20, 471, 224, 63, 16 + LTEXT "0_5" 21, 405, 224, 63, 16 + LTEXT "5_716" 22, 8, 8, 36, 36 + LTEXT "*Creature number:" 23, 313, 7, 126, 15 + LTEXT "*" 24, 450, 7, 50, 15 + LTEXT "0_118" 25, 51, 224, 75, 16 + LTEXT "Enter the information for this monster/townsperson. You only need to worry about the talking section if this is not a hostile monster. To edit the more advanced traits for this monster, press the Advanced button." 26, 50, 24, 476, 40 + LTEXT "~Talking to this creature:" 27, 51, 160, 256, 17 + LTEXT "Leave at 0 for no pic." 28, 230, 205, 101, 26 + } + +838 DIALOG 10, 10, 604, 400 + STYLE WS_POPUP | WS_DLGFRAME + { + // DEFPUSHBUTTON "" 1, 292, 238, 31, 10//, WS_GROUP | WS_TABSTOP + LTEXT "6_0" 2, 221, 126, 67, 16 + LTEXT "6_0" 3, 221, 153, 67, 16 + LTEXT "6_0" 4, 285, 298, 67, 16 + LTEXT "6_0" 5, 262, 334, 39, 16 + LTEXT "6_0" 6, 310, 334, 39, 16 + LTEXT "~Townsperson/monster advanced" 7, 50, 6, 256, 17 + LTEXT "*Creature type:" 8, 62, 28, 97, 15 + LTEXT "*" 9, 162, 28, 195, 15 + LTEXT "*When is creature here?" 10, 20, 72, 150, 14 + LTEXT "+" 11, 57, 127, 154, 15 + LTEXT "+" 12, 57, 153, 154, 15 + LTEXT "Number of town special node to call when creature is killed: (-1 for none)" 13, 25, 293, 247, 27 + LTEXT "Stuff done flag creature's life is linked to: (0 - alive, 1 - dead), if either is -1, this is ignored." 14, 25, 322, 230, 40 + LTEXT "~Creature and special encs." 15, 9, 182, 205, 17 + LTEXT "1_63" 16, 492, 336, 75, 16 + LTEXT "0_5" 17, 411, 336, 75, 16 + LTEXT "5_716" 18, 8, 8, 36, 36 + LTEXT "*Creature number:" 19, 317, 7, 126, 15 + LTEXT "*" 20, 454, 7, 50, 15 + LTEXT "~Creature timing:" 21, 9, 49, 130, 17 + LTEXT "2_0" 22, 290, 74, 23, 14 + LTEXT "2_0" 23, 290, 90, 23, 14 + LTEXT "2_0" 24, 290, 106, 23, 14 + LTEXT "2_0" 25, 420, 74, 23, 14 + LTEXT "2_0" 26, 420, 90, 23, 14 + LTEXT "2_0" 27, 420, 106, 23, 14 + LTEXT "2_0" 28, 549, 74, 23, 14 + LTEXT "2_0" 29, 549, 90, 23, 14 + LTEXT "2_0" 30, 77, 220, 23, 14 + LTEXT "2_0" 31, 77, 236, 23, 14 + LTEXT "2_0" 32, 77, 252, 23, 14 + LTEXT "2_0" 33, 165, 220, 23, 14 + LTEXT "2_0" 34, 165, 236, 23, 14 + LTEXT "2_0" 35, 165, 252, 23, 14 + LTEXT "2_0" 36, 254, 220, 23, 14 + LTEXT "2_0" 37, 254, 236, 23, 14 + LTEXT "2_0" 38, 254, 252, 23, 14 + LTEXT "2_0" 39, 346, 220, 23, 14 + LTEXT "2_0" 40, 346, 236, 23, 14 + LTEXT "A creature which is part of a special group does not exist until it's created by a special encounter (like special node type One-Time Place Town Encounter)." 41, 372, 203, 195, 78 + LTEXT "What special encounter group is this creature a part of?" 42, 25, 203, 343, 15 + LTEXT "For an explanation on how event codes work, see the chapter in the instructions on the passing of time." 43, 301, 133, 222, 44 + } + +839 DIALOG 10, 10, 585, 432 + STYLE WS_POPUP | WS_DLGFRAME + { + // DEFPUSHBUTTON "" 1, 292, 238, 31, 10//, WS_GROUP | WS_TABSTOP + LTEXT "6_0" 2, 167, 46, 145, 16 + LTEXT "6_0" 3, 167, 70, 145, 16 + LTEXT "6_0" 4, 167, 94, 145, 16 + LTEXT "6_0" 5, 167, 118, 145, 16 + LTEXT "6_0" 6, 167, 142, 145, 16 + LTEXT "6_0" 7, 167, 166, 145, 16 + LTEXT "6_0" 8, 167, 190, 145, 16 + LTEXT "6_0" 9, 167, 214, 145, 16 + LTEXT "6_0" 10, 168, 238, 145, 16 + LTEXT "6_0" 11, 168, 262, 145, 16 + LTEXT "6_0" 12, 168, 286, 145, 16 + LTEXT "6_0" 13, 168, 310, 145, 16 + LTEXT "6_0" 14, 168, 334, 145, 16 + LTEXT "6_0" 15, 168, 358, 145, 16 + LTEXT "6_0" 16, 168, 382, 145, 16 + LTEXT "6_0" 17, 168, 406, 145, 16 + LTEXT "1_63" 18, 472, 405, 75, 16 + LTEXT "0_5" 19, 406, 405, 59, 16 + LTEXT "Descriptive message" 20, 172, 26, 133, 14 + LTEXT "*" 21, 55, 46, 105, 15 + LTEXT "*" 22, 55, 70, 105, 15 + LTEXT "*" 23, 55, 94, 105, 15 + LTEXT "*" 24, 55, 118, 105, 15 + LTEXT "*" 25, 55, 142, 105, 15 + LTEXT "*" 26, 55, 166, 105, 15 + LTEXT "*" 27, 55, 190, 105, 15 + LTEXT "*" 28, 55, 214, 105, 15 + LTEXT "*" 29, 55, 238, 105, 15 + LTEXT "*" 30, 55, 262, 105, 15 + LTEXT "*" 31, 55, 286, 105, 15 + LTEXT "*" 32, 55, 310, 105, 15 + LTEXT "*" 33, 55, 335, 105, 15 + LTEXT "*" 34, 55, 359, 105, 15 + LTEXT "*" 35, 55, 383, 105, 15 + LTEXT "*" 36, 55, 407, 105, 15 + LTEXT "Enter the descriptions for each of the special town rectangles you may have made, or press the delete button to remove them." 37, 389, 9, 158, 69 + LTEXT "5_716" 38, 8, 8, 36, 36 + LTEXT "~Town area descriptions" 39, 50, 6, 256, 17 + LTEXT "Upper left corner" 40, 51, 26, 111, 14 + LTEXT "0_53" 41, 321, 42, 63, 23 + LTEXT "0_53" 42, 321, 66, 63, 23 + LTEXT "0_53" 43, 321, 90, 63, 23 + LTEXT "0_53" 44, 321, 114, 63, 23 + LTEXT "0_53" 45, 321, 138, 63, 23 + LTEXT "0_53" 46, 321, 162, 63, 23 + LTEXT "0_53" 47, 321, 186, 63, 23 + LTEXT "0_53" 48, 321, 210, 63, 23 + LTEXT "0_53" 49, 321, 234, 63, 23 + LTEXT "0_53" 50, 321, 258, 63, 23 + LTEXT "0_53" 51, 321, 282, 63, 23 + LTEXT "0_53" 52, 321, 306, 63, 23 + LTEXT "0_53" 53, 321, 330, 63, 23 + LTEXT "0_53" 54, 321, 354, 63, 23 + LTEXT "0_53" 55, 321, 378, 63, 23 + LTEXT "0_53" 56, 321, 402, 63, 23 + } + +840 DIALOG 10, 10, 431, 119 + STYLE WS_POPUP | WS_DLGFRAME + { + // DEFPUSHBUTTON "" 1, 283, 273, 31, 10//, WS_GROUP | WS_TABSTOP + LTEXT "6_0" 2, 55, 34, 332, 16 + LTEXT "0_5" 3, 263, 86, 63, 16 + LTEXT "5_716" 4, 8, 8, 36, 36 + LTEXT "~Enter this area's description:" 5, 50, 6, 184, 17 + LTEXT "1_63" 6, 328, 86, 62, 16 + LTEXT "Max. length: 30 characters. To edit this later, select Edit Area Descriptions from the Town or Outdoors menu." 7, 3, 60, 242, 42 + } + +841 DIALOG 10, 10, 392, 209 + STYLE WS_POPUP | WS_DLGFRAME + { + // DEFPUSHBUTTON "" 1, 279, 223, 31, 10//, WS_GROUP | WS_TABSTOP + LTEXT "6_0" 2, 224, 148, 52, 16 + LTEXT "1_63" 3, 278, 181, 75, 16 + LTEXT "5_716" 4, 8, 8, 36, 36 + LTEXT "~Importing a town" 5, 50, 6, 175, 17 + LTEXT "What town do you wish to import?" 6, 50, 143, 162, 27 + LTEXT "Enter a town number and hit OK, and you will be asked to select a scenario file. The town with that number in the selected scenario will then be loaded in over the current town." 7, 50, 27, 301, 54 + LTEXT "0_5" 8, 212, 181, 63, 16 + LTEXT "Warning: This will write over the town currently in memory. Also, the town you select must be the same size (large/medium/small) as the town currently in memory." 9, 50, 83, 301, 54 + } + +842 DIALOG 10, 10, 642, 412 +STYLE WS_POPUP | WS_DLGFRAME +{ + LTEXT "6_0", 2, 57, 55, 545, 54 + LTEXT "6_0", 3, 57, 111, 545, 54 + LTEXT "6_0", 4, 57, 167, 545, 54 + LTEXT "6_0", 5, 57, 223, 545, 54 + LTEXT "6_0", 6, 57, 279, 545, 54 + LTEXT "6_0", 7, 57, 335, 545, 54 + LTEXT "1_63", 8, 539, 395, 62, 16 + LTEXT "0_5", 9, 474, 395, 63, 16 + LTEXT "5_716", 10, 8, 8, 36, 36 + LTEXT "~Edit dialog box text:", 11, 50, 6, 256, 17 + LTEXT "Write or edit the text that will appear in this dialog box. You can put one paragraph in each box below. Leave unused boxes blank.", 12, 50, 23, 550, 28 +} + +850 DIALOG 10, 10, 593, 246 + STYLE WS_POPUP | WS_DLGFRAME + { + // DEFPUSHBUTTON "" 1, 292, 238, 31, 10//, WS_GROUP | WS_TABSTOP + LTEXT "6_0" 2, 167, 49, 145, 16 + LTEXT "6_0" 3, 167, 73, 145, 16 + LTEXT "6_0" 4, 167, 97, 145, 16 + LTEXT "6_0" 5, 167, 121, 145, 16 + LTEXT "6_0" 6, 167, 145, 145, 16 + LTEXT "6_0" 7, 167, 169, 145, 16 + LTEXT "6_0" 8, 167, 193, 145, 16 + LTEXT "6_0" 9, 167, 217, 145, 16 + LTEXT "1_63" 10, 491, 220, 65, 16 + LTEXT "0_5" 11, 424, 220, 63, 16 + LTEXT "Descriptive message" 12, 172, 27, 133, 14 + LTEXT "*" 13, 55, 49, 105, 15 + LTEXT "*" 14, 55, 73, 105, 15 + LTEXT "*" 15, 55, 97, 105, 15 + LTEXT "*" 16, 55, 121, 105, 15 + LTEXT "*" 17, 55, 145, 105, 15 + LTEXT "*" 18, 55, 169, 105, 15 + LTEXT "*" 19, 55, 193, 105, 15 + LTEXT "*" 20, 55, 217, 105, 15 + LTEXT "Enter the descriptions for each of the special outdoor rectangles you may have made, or press the delete button to remove them. Maximum length: 30 characters." 21, 396, 9, 159, 93 + LTEXT "5_716" 22, 8, 8, 36, 36 + LTEXT "~Outdoor area descriptions" 23, 50, 6, 256, 17 + LTEXT "Upper left corner" 24, 51, 27, 111, 14 + LTEXT "0_53" 25, 321, 45, 71, 23 + LTEXT "0_53" 26, 321, 69, 71, 23 + LTEXT "0_53" 27, 321, 93, 71, 23 + LTEXT "0_53" 28, 321, 117, 71, 23 + LTEXT "0_53" 29, 321, 141, 71, 23 + LTEXT "0_53" 30, 321, 165, 71, 23 + LTEXT "0_53" 31, 321, 189, 71, 23 + LTEXT "0_53" 32, 321, 213, 71, 23 + } + +851 DIALOG 10, 10, 353, 104 + STYLE WS_POPUP | WS_DLGFRAME + { + // DEFPUSHBUTTON "" 1, 279, 223, 31, 10//, WS_GROUP | WS_TABSTOP + LTEXT "6_0" 2, 162, 51, 151, 16 + LTEXT "1_63" 3, 254, 74, 63, 16 + LTEXT "5_716" 4, 8, 8, 36, 36 + LTEXT "~Outdoors Details" 5, 50, 6, 256, 17 + LTEXT "*Section name:" 6, 50, 53, 101, 14 + LTEXT "*Coordinates:" 7, 50, 29, 87, 14 + LTEXT "*" 8, 142, 29, 127, 14 + } + +852 DIALOG 10, 10, 592, 391 + STYLE WS_POPUP | WS_DLGFRAME + { + // DEFPUSHBUTTON "" 1, 292, 238, 31, 10//, WS_GROUP | WS_TABSTOP + LTEXT "6_0" 2, 361, 216, 46, 16 + LTEXT "6_0" 3, 361, 259, 46, 16 + LTEXT "6_0" 4, 361, 302, 46, 16 + LTEXT "6_0" 5, 460, 336, 39, 16 + LTEXT "6_0" 6, 508, 336, 39, 16 + LTEXT "+" 7, 129, 135, 145, 14 + LTEXT "+" 8, 129, 159, 145, 14 + LTEXT "+" 9, 129, 183, 145, 14 + LTEXT "+" 10, 129, 207, 145, 14 + LTEXT "+" 11, 129, 231, 145, 14 + LTEXT "+" 12, 129, 255, 145, 14 + LTEXT "+" 13, 129, 279, 145, 14 + LTEXT "+" 14, 129, 303, 145, 14 + LTEXT "+" 15, 129, 327, 145, 14 + LTEXT "+" 16, 129, 351, 145, 14 + LTEXT "1_63" 17, 489, 370, 65, 16 + LTEXT "0_5" 18, 423, 370, 63, 16 + LTEXT "0_2" 19, 11, 370, 63, 16 + LTEXT "0_3" 20, 74, 370, 75, 16 + LTEXT "0_109" 21, 280, 130, 63, 23 + LTEXT "0_109" 22, 280, 154, 63, 23 + LTEXT "0_109" 23, 280, 178, 63, 23 + LTEXT "0_109" 24, 280, 202, 63, 23 + LTEXT "0_109" 25, 280, 226, 63, 23 + LTEXT "0_109" 26, 280, 250, 63, 23 + LTEXT "0_109" 27, 280, 274, 63, 23 + LTEXT "0_109" 28, 280, 298, 63, 23 + LTEXT "0_109" 29, 280, 322, 63, 23 + LTEXT "0_109" 30, 280, 346, 63, 23 + LTEXT "0_106" 31, 412, 213, 75, 16 + LTEXT "0_106" 32, 412, 256, 75, 16 + LTEXT "0_106" 33, 412, 298, 75, 16 + LTEXT "*Hostile (15-30)" 34, 11, 135, 113, 14 + LTEXT "*Hostile (7-10)" 35, 11, 159, 113, 14 + LTEXT "*Hostile (4-6)" 36, 11, 183, 113, 14 + LTEXT "*Hostile (3-5)" 37, 11, 207, 113, 14 + LTEXT "*Hostile (2-3)" 38, 11, 231, 113, 14 + LTEXT "*Hostile (1-2)" 39, 11, 255, 113, 14 + LTEXT "*Hostile (1)" 40, 11, 279, 113, 14 + LTEXT "*Friendly (7-10)" 41, 11, 303, 113, 14 + LTEXT "*Friendly (2-4)" 42, 11, 327, 113, 14 + LTEXT "*Friendly (1)" 43, 11, 351, 113, 14 + LTEXT "*Encounter number:" 44, 50, 97, 127, 14 + LTEXT "*" 45, 180, 97, 35, 14 + LTEXT "5_716" 46, 8, 8, 36, 36 + LTEXT "~Outdoor Wandering Encounter:" 47, 50, 6, 191, 15 + LTEXT "Enter the characteristics for this outdoor encounter. There are four different wandering and special encounter slots. To edit the others, use the arrow buttons. " 48, 50, 22, 502, 27 + LTEXT "Each encounter contains 10 monster slots, 7 hostile to the party and 3 friendly. To place monsters in an encounter, press the Choose button by one of the slots. For more information on how this works, see the documentation." 49, 50, 53, 502, 39 + LTEXT "*Monsters can't flee party" 50, 349, 102, 154, 14 + LTEXT "2_0" 51, 522, 102, 29, 14 + LTEXT "Encounter is forced |(Party fights it right away)" 52, 350, 117, 170, 27 + LTEXT "2_0" 53, 522, 117, 29, 14 + LTEXT "~Monsters in encounter:" 54, 11, 114, 191, 17 + LTEXT "~Advanced encounter traits:" 55, 350, 152, 191, 15 + LTEXT "*Special called when enc. starts" 56, 352, 197, 194, 14 + LTEXT "*Special called when party wins" 57, 352, 240, 194, 14 + LTEXT "*Special called if party flees" 58, 352, 283, 194, 14 + LTEXT "Stuff done flag to eliminate encounter" 59, 352, 326, 103, 33 + LTEXT "Note: Ignore these if you aren't sure what they do." 60, 364, 168, 170, 27 + } + +853 DIALOG 10, 10, 477, 252 + STYLE WS_POPUP | WS_DLGFRAME + { + // DEFPUSHBUTTON "" 1, 279, 223, 31, 10//, WS_GROUP | WS_TABSTOP + LTEXT "6_0" 2, 140, 82, 152, 16 + LTEXT "1_63" 3, 364, 222, 75, 16 + LTEXT "5_716" 4, 8, 8, 36, 36 + LTEXT "~Create New Town" 5, 50, 6, 256, 17 + LTEXT "*Town name:" 6, 50, 83, 84, 14 + LTEXT "*Town size:" 7, 50, 108, 77, 14 + LTEXT "*Small (32x32)" 8, 145, 108, 139, 14 + LTEXT "*Medium (48x48)" 9, 145, 125, 139, 14 + LTEXT "*Large (64x64)" 10, 145, 142, 139, 14 + LTEXT "2_0" 11, 301, 108, 23, 14 + LTEXT "2_0" 12, 301, 125, 23, 14 + LTEXT "2_0" 13, 301, 142, 23, 14 + LTEXT "*Preset terrain:" 14, 51, 161, 105, 14 + LTEXT "*Just cave floor" 15, 168, 161, 100, 15 + LTEXT "*Plain Grass" 16, 168, 178, 102, 15 + LTEXT "*Grass with flowers" 17, 168, 195, 127, 15 + LTEXT "2_0" 18, 301, 161, 23, 14 + LTEXT "2_0" 19, 301, 178, 23, 14 + LTEXT "2_0" 20, 301, 195, 23, 14 + LTEXT "*Creating town number:" 21, 50, 28, 147, 14 + LTEXT "*" 22, 201, 28, 33, 14 + LTEXT "0_5" 23, 282, 222, 75, 16 + LTEXT "Note: Your new town will be tacked onto the end of your current town list." 24, 239, 28, 201, 41 + } + +854 DIALOG 10, 10, 297, 137 + STYLE WS_POPUP | WS_DLGFRAME + { + // DEFPUSHBUTTON "" 1, 283, 273, 31, 10//, WS_GROUP | WS_TABSTOP + LTEXT "1_63" 2, 189, 111, 61, 16 + LTEXT "0_5" 3, 124, 111, 63, 16 + LTEXT "5_716" 4, 8, 8, 36, 36 + LTEXT "~Edit Which Outdoor Section?" 5, 50, 6, 158, 16 + LTEXT "*World width:" 6, 68, 25, 111, 14 + LTEXT "*" 7, 186, 25, 37, 14 + LTEXT "+" 8, 142, 63, 75, 16 + LTEXT "*World height:" 9, 68, 41, 111, 14 + LTEXT "*" 10, 186, 41, 37, 14 + LTEXT "+" 11, 142, 88, 75, 16 + LTEXT "0_7" 12, 77, 59, 27, 23 + LTEXT "0_6" 13, 106, 59, 27, 23 + LTEXT "0_7" 14, 77, 84, 27, 23 + LTEXT "0_6" 15, 106, 84, 27, 23 + } + +855 DIALOG 10, 10, 259, 119 + STYLE WS_POPUP | WS_DLGFRAME + { + // DEFPUSHBUTTON "" 1, 292, 238, 31, 10//, WS_GROUP | WS_TABSTOP + LTEXT "6_0" 2, 102, 58, 62, 16 + LTEXT "1_63" 3, 177, 82, 58, 16 + LTEXT "0_5" 4, 111, 82, 63, 16 + LTEXT "5_716" 5, 8, 8, 36, 36 + LTEXT "~Pick Town to Edit:" 6, 50, 6, 167, 17 + LTEXT "Enter the number of the town you want to edit next:" 7, 50, 23, 185, 28 + } + +856 DIALOG 10, 10, 302, 133 + STYLE WS_POPUP | WS_DLGFRAME + { + // DEFPUSHBUTTON "" 1, 292, 238, 31, 10//, WS_GROUP | WS_TABSTOP + LTEXT "6_0" 2, 119, 71, 62, 16 + LTEXT "1_63" 3, 206, 95, 58, 16 + LTEXT "0_5" 4, 140, 95, 63, 16 + LTEXT "5_716" 5, 8, 8, 36, 36 + LTEXT "~Entrance to what town?" 6, 50, 6, 167, 17 + LTEXT "What town do you want the party to end up in when they walk into this space?" 7, 50, 23, 213, 42 + } + +857 DIALOG 10, 10, 373, 205 + STYLE WS_POPUP | WS_DLGFRAME + { + // DEFPUSHBUTTON "" 1, 292, 238, 31, 10//, WS_GROUP | WS_TABSTOP + LTEXT "6_0" 2, 205, 99, 64, 17 + LTEXT "6_0" 3, 205, 125, 64, 17 + LTEXT "6_0" 4, 205, 151, 64, 17 + LTEXT "1_63" 5, 280, 177, 58, 16 + LTEXT "0_5" 6, 214, 177, 63, 16 + LTEXT "5_716" 7, 8, 8, 36, 36 + LTEXT "~Change Terrain Randomly" 8, 50, 6, 167, 17 + LTEXT "Select a terrain type and another terrain type to turn it into. Also give a percentage chance of changing it (0 - 100). Automatic corrections (like adjusting cave walls) will not be made to these changes." 9, 50, 25, 286, 67 + LTEXT "0_109" 10, 275, 97, 63, 16 + LTEXT "0_109" 11, 275, 123, 63, 16 + LTEXT "*Change this terrain type:" 12, 7, 101, 164, 13 + LTEXT "*To this terrain type:" 13, 7, 127, 164, 13 + LTEXT "*Chance of changing: (0 - 100)" 14, 7, 153, 193, 13 + } + +858 DIALOG 10, 10, 340, 80 + STYLE WS_POPUP | WS_DLGFRAME + { + LTEXT "1_29" 1, 240, 43, 66, 20 + LTEXT "0_5" 2, 175, 43, 65, 20 + LTEXT "0_134" 3, 109, 43, 66, 20 + LTEXT "5_716" 4, 6, 6, 36, 36 + LTEXT "Save changes to your scenario before loading a new one?" 5, 49, 6, 256, 32 + } + +859 DIALOG 10, 10, 340, 92 + STYLE WS_POPUP | WS_DLGFRAME + { + LTEXT "1_29" 1, 240, 54, 66, 20 + LTEXT "0_5" 2, 175, 54, 65, 20 + LTEXT "0_134" 3, 109, 54, 66, 20 + LTEXT "5_716" 4, 6, 6, 36, 36 + LTEXT "Do you save the changes to this town/outdoor section before loading a new one?" 5, 49, 6, 257, 47 + } + +860 DIALOG 10, 10, 341, 91 +STYLE WS_POPUP | WS_DLGFRAME +{ + LTEXT "1_63", 1, 240, 58, 66, 20 + LTEXT "0_5", 2, 175, 58, 65, 20 + LTEXT "5_716", 3, 6, 6, 36, 36 + LTEXT "The Scenario Editor is about to create your new scenario, which will be ready for editing. This will take a little while ... be patient.", 4, 49, 6, 257, 47 +} + +861 DIALOG 10, 10, 341, 91 + STYLE WS_POPUP | WS_DLGFRAME + { + LTEXT "1_63" 1, 240, 54, 66, 20 + LTEXT "5_716" 2, 6, 6, 36, 36 + LTEXT "All of the items in this town are now not considered property, and can be taken by the party with no difficulty." 3, 49, 6, 257, 47 + } + +862 DIALOG 10, 10, 341, 91 + STYLE WS_POPUP | WS_DLGFRAME + { + LTEXT "1_63" 1, 239, 39, 66, 20 + LTEXT "0_5" 2, 174, 39, 65, 20 + LTEXT "5_716" 3, 6, 6, 36, 36 + LTEXT "This option erases all items in the town. Go ahead?" 4, 49, 6, 258, 32 + } + +863 DIALOG 10, 10, 350, 123 + STYLE WS_POPUP | WS_DLGFRAME + { + LTEXT "1_63" 1, 252, 89, 66, 20 + LTEXT "0_5" 2, 187, 89, 65, 20 + LTEXT "5_716" 3, 6, 6, 36, 36 + LTEXT "This option places random items in this town. Certain terrain types will randomly get relevant items. To set which items are placed on what terrain types, select Edit Item Placement Shortcuts from the Scenario menu." 4, 49, 6, 270, 81 + } + +864 DIALOG 10, 10, 354, 135 + STYLE WS_POPUP | WS_DLGFRAME + { + LTEXT "1_63" 1, 251, 103, 66, 20 + LTEXT "0_5" 2, 186, 103, 65, 20 + LTEXT "5_716" 3, 6, 6, 36, 36 + LTEXT "You are about to set this location at the parties outdoor starting location. When the party starts the scenario and leaves the town they start in, this is where they will be." 4, 49, 6, 270, 54 + LTEXT "To set the town the party starts in, use the Set Starting Location: Town option in the Scenario menu." 5, 49, 61, 268, 39 + } + +865 DIALOG 10, 10, 359, 176 + STYLE WS_POPUP | WS_DLGFRAME + { + LTEXT "1_63" 1, 252, 143, 66, 20 + LTEXT "0_5" 2, 187, 143, 65, 20 + LTEXT "5_716" 3, 6, 6, 36, 36 + LTEXT "You are about to delete the last town in your scenario's town list (so if you have 10 towns in your scenario, the tenth will disappear). This change can't be undone!" 4, 49, 6, 271, 66 + LTEXT "Are you sure you want to do this?" 5, 49, 127, 268, 14 + LTEXT "Make sure to remove all outdoor entrances to the deleted town, as well as all references to it in special encounters. Failure to do so will result in scenario run-time errors." 6, 49, 73, 276, 53 + } + +866 DIALOG 10, 10, 357, 114 +STYLE WS_POPUP | WS_DLGFRAME +{ + LTEXT "1_63", 1, 255, 89, 66, 20 + LTEXT "0_5", 2, 190, 89, 65, 20 + LTEXT "5_716", 3, 6, 6, 36, 36 + LTEXT "Lists of all the terrain types, monster types, and item types in your scenario are about to be put into a file called 'Scendata.txt' in the editor folder. You can then print out this file to act as a handy reference while designing your scenario.", 4, 49, 6, 271, 66 +} + +868 DIALOG 10, 10, 357, 114 +STYLE WS_POPUP | WS_DLGFRAME +{ + LTEXT "1_63", 1, 255, 89, 66, 20 + LTEXT "0_5", 2, 190, 89, 65, 20 + LTEXT "5_716", 3, 6, 6, 36, 36 + LTEXT "This produces a list of all the outdoor and town shops in your scenario and writes them into a file called 'Scenario Shopping.txt' in the editor folder. You can then print out this file to act as a handy reference while designing your scenario.", 4, 49, 6, 271, 66 + +} + +869 DIALOG 10, 10, 340, 80 + STYLE WS_POPUP | WS_DLGFRAME + { + LTEXT "1_29" 1, 240, 43, 66, 20 + LTEXT "0_5" 2, 175, 43, 65, 20 + LTEXT "0_83" 3, 109, 43, 66, 20 + LTEXT "5_716" 4, 6, 6, 36, 36 + LTEXT "Do you want to save changes to your scenario before quitting?" 5, 49, 6, 256, 32 + } + +870 DIALOG 10, 10, 356, 71 + STYLE WS_POPUP | WS_DLGFRAME + { + LTEXT "1_63" 1, 256, 37, 66, 20 + LTEXT "5_716" 2, 6, 6, 36, 36 + LTEXT "You can't place a sign or special encounter at the edge of an outdoor section." 3, 49, 6, 272, 28 + } + +871 DIALOG 10, 10, 356, 154 +STYLE WS_POPUP | WS_DLGFRAME +{ + LTEXT "1_63", 1, 254, 129, 66, 20 + LTEXT "0_5", 2, 189, 129, 65, 20 + LTEXT "5_716", 3, 6, 6, 36, 36 + LTEXT "This features takes all of the text in your scenario (all dialogue, all special messages, all signs, etc.) and puts them into a file called 'Scentext.txt' in the editor folder. All this text can then be easily spell-checked and proofread.", 4, 49, 6, 271, 66 + LTEXT "Pulling out all of the text in your scenario takes a little while, so be patient.", 5, 49, 95, 271, 29 +} + + +872 DIALOG 10, 10, 341, 91 + STYLE WS_POPUP | WS_DLGFRAME + { + LTEXT "1_63" 1, 239, 39, 66, 20 + LTEXT "0_5" 2, 174, 39, 65, 20 + LTEXT "5_716" 3, 6, 6, 36, 36 + LTEXT "This option erases all monsters in the town. Go ahead?" 4, 49, 6, 258, 32 + } +873 DIALOG 10, 10, 341, 91 + STYLE WS_POPUP | WS_DLGFRAME + { + LTEXT "1_63" 1, 239, 39, 66, 20 + LTEXT "0_5" 2, 174, 39, 65, 20 + LTEXT "5_716" 3, 6, 6, 36, 36 + LTEXT "This option erases all placed specials in the town. Go ahead?" 4, 49, 6, 258, 32 + } +874 DIALOG 10, 10, 341, 91 + STYLE WS_POPUP | WS_DLGFRAME + { + LTEXT "1_63" 1, 239, 39, 66, 20 + LTEXT "0_5" 2, 174, 39, 65, 20 + LTEXT "5_716" 3, 6, 6, 36, 36 + LTEXT "This option erases all preset fields in the town. Go ahead?" 4, 49, 6, 258, 32 + } +875 DIALOG 10, 10, 341, 91 + STYLE WS_POPUP | WS_DLGFRAME + { + LTEXT "1_63" 1, 239, 39, 66, 20 + LTEXT "0_5" 2, 174, 39, 65, 20 + LTEXT "5_716" 3, 6, 6, 36, 36 + LTEXT "This option erases all placed specials in the zone. Go ahead?" 4, 49, 6, 258, 32 + } +876 DIALOG 10, 10, 341, 91 + STYLE WS_POPUP | WS_DLGFRAME + { + LTEXT "1_63" 1, 239, 39, 66, 20 + LTEXT "0_5" 2, 174, 39, 65, 20 + LTEXT "5_716" 3, 6, 6, 36, 36 + LTEXT "This option erases all preset stains in the town. Go ahead?" 4, 49, 6, 258, 32 + } + +970 DIALOG 10, 10, 346, 167 + STYLE WS_POPUP | WS_DLGFRAME + { + LTEXT "1_0" 1, 251, 107, 70, 20 + LTEXT "*" 2, 8, 107, 70, 20 + LTEXT "5_708" 3, 9, 9, 36, 36 + LTEXT "= " 4, 55, 8, 257, 90 + } + +971 DIALOG 10, 10, 347, 240 + STYLE WS_POPUP | WS_DLGFRAME + { + LTEXT "1_0" 1, 248, 212, 70, 20 + LTEXT "*" 2, 6, 212, 70, 20 + LTEXT "5_708" 3, 9, 9, 36, 36 + LTEXT "= " 4, 55, 8, 257, 91 + LTEXT "= " 5, 55, 107, 257, 98 + } + +972 DIALOG 10, 10, 350, 164 + STYLE WS_POPUP | WS_DLGFRAME + { + LTEXT "1_0" 1, 247, 140, 70, 20 + LTEXT "*" 2, 8, 140, 70, 20 + LTEXT "5_708" 3, 9, 9, 36, 36 + LTEXT "= " 4, 53, 38, 257, 92 + LTEXT "*" 5, 26, 74, 14, 19 + LTEXT "+" 6, 53, 9, 257, 19 + } + +973 DIALOG 10, 10, 347, 264 + STYLE WS_POPUP | WS_DLGFRAME + { + LTEXT "1_0" 1, 253, 238, 70, 20 + LTEXT "*" 2, 9, 238, 70, 20 + LTEXT "5_708" 3, 9, 9, 36, 36 + LTEXT "= " 4, 55, 39, 257, 87 + LTEXT "= " 5, 55, 136, 257, 93 + LTEXT "+" 6, 55, 9, 257, 19 + } + +986 DIALOG 10, 10, 503, 299 +STYLE WS_POPUP | WS_DLGFRAME +{ + LTEXT "0_63", 1, 403, 285, 65, 20 + LTEXT "5_716", 2, 6, 6, 36, 36 + LTEXT "The Blades of Exile Scenario Editor can be a tricky program to use. It has lots of options and a lot of features. Fortunately, it also comes with very comprehensive online documentation.", 3, 50, 22, 413, 49 + LTEXT "To get to this documentation, run the program Blades Editor Documentation. This file contains the full instructions for the editor, ready to be printed out.", 4, 50, 75, 412, 48 + LTEXT "Of special importance is the section 'How to Make a Simple Scenario.' It describes, in exact, step-by-step detail, how to make a simple scenario with dungeons, monsters, and treasure. This section will give you a quick, easy start.", 5, 50, 126, 412, 62 + LTEXT "Once you've mastered the basics, using this section, skim through the documentation. Unfortunately, this is not a program you will be able to get the best use out of without using the instructions.", 6, 50, 190, 418, 51 + LTEXT "Finally, if you're stuck and need ideas, go to http://www.spidweb.com. There is a Scenario Editor forum there, which has all kinds of hints, tips, and answers for better scenario design.", 7, 50, 241, 418, 41 + LTEXT "BLADES OF EXILE - GETTING STARTED", 8, 50, 4, 265, 16 +} + +1000 DIALOG 10, 10, 502, 349 +STYLE WS_POPUP | WS_DLGFRAME +{ + LTEXT "0_63", 1, 399, 329, 65, 20 + LTEXT "5_716", 2, 6, 6, 36, 36 + LTEXT "If you want other people to play your scenario, it is vitally important that you test it. Otherwise, lots of people might waste lots of hours playing a scenairo that is unwinnable or otherwise doesn't work.", 3, 50, 22, 413, 54 + LTEXT "To run your scenario, copy it into the Blades of Exile Scenarios folder and start it using the Custom Scenario button on the game title screen. Play from your scenario from start to finish, and, if possible, have friends play it too.", 4, 50, 77, 414, 64 + LTEXT "When testing your scenario, one useful feature is debug mode. While playing the game, type 'D'. This will put you in Debug Mode. Monsters will no longer move or attack you, and you will be able to play much faster.", 5, 50, 142, 412, 63 + LTEXT "When you make a change in a town, before testing it, be sure to leave the town and type '>'. This causes the game to forget everything you've done in that town. If you don't do this, your corrections may not be remembered properly.", 6, 50, 206, 417, 64 + LTEXT "Finally, if you edit your scenario while playing in it, whenever you save a change go back to the game and reload your save file. Otherwise, the game may not read the scenario data properly and crash.", 7, 50, 271, 418, 51 + LTEXT "BLADES OF EXILE - TESTING YOUR SCENARIO", 8, 50, 4, 312, 16 +} + +1001 DIALOG 10, 10, 502, 306 +STYLE WS_POPUP | WS_DLGFRAME +{ + LTEXT "0_63", 1, 403, 330, 65, 20 + LTEXT "5_716", 2, 6, 6, 36, 36 + LTEXT "When you've completed your scenario, you probably want to give other people the chance to play through it. It's a big kick letting other people run around in your own fantasy world, get stuck at your puzzles, and kill your creations.", 3, 50, 22, 413, 66 + LTEXT "The easiest way to release a scenario is to send it over to Spiderweb Software. Go to www.spidweb.com. There's a scenario upload area there. Alternately, mail it to us on disk (PO Box 85659, Seattle, WA 98145).", 4, 50, 89, 414, 64 + LTEXT "Before you send a scenario, however, be sure to read the License Agreement (in the file Blades of Exile License). It says a lot of big no-no's and describes your (and our) rights for your scenario.", 5, 50, 154, 412, 50 + LTEXT "If you need help, be sure to check the Blades of Exile forum in the Spiderweb Software community boards.", 6, 50, 205, 417, 50 + LTEXT "There are quite a few databases to upload your scenario to, see the list in the Blades of Exile forum.", 7, 50, 266, 418, 62 + LTEXT "BLADES OF EXILE - DISTRIBUTING YOUR SCENARIO", 8, 50, 4, 312, 16 +} + +1062 DIALOG 10, 10, 531, 387 +STYLE WS_POPUP | WS_DLGFRAME +{ + LTEXT "1_63", 1, 435, 295, 61, 20 + LTEXT "5_716", 2, 6, 6, 36, 36 + LTEXT "Classic Blades of Exile Scenario Editor Beta 1 | Copyright 1997, Spiderweb Software, Inc., All rights reserved.||Blades of Exile is distributed for free under GNU General Public License version 2.", 3, 50, 6, 420, 33 + LTEXT "CREDITS : Initial coding/32-bit porting by Ormus . Aesthetic touches by Ishad Nha.", 4, 50, 227, 424, 33 + LTEXT "Comments? Questions? Bugs? Post them at the Blades section of the Irony Central Board: www.ironycentral.com/forum/", 5, 50, 271, 354, 32 + LTEXT "Blades of Exile was brought to you by Spiderweb Software - | _Where our aberrations become your reality._ |_Blades of Exile_ and Spiderweb Software are trademarks of Spiderweb Software.", 7, 50, 154, 410, 51 + LTEXT "ORIGINAL CREDITS: | Concept, Design, Programming: Jeff Vogel | Graphics: Andrew Hunter (Wormius@aol.com) | Title Screen: James Ernest (ernest@speakeasy.org)", 8, 50, 82, 415, 51 +} + +1066 DIALOG 10, 10, 336, 64 + STYLE WS_POPUP | WS_DLGFRAME + { + LTEXT "1_84" 1, 230, 31, 80, 20 + LTEXT "0_85" 2, 122, 31, 77, 20 + LTEXT "0_5" 3, 54, 31, 58, 20 + LTEXT "5_723" 4, 9, 9, 36, 36 + LTEXT "~Do you want to save before quitting?" 5, 52, 5, 254, 18 + } + +1067 DIALOG 10, 10, 336, 78 + STYLE WS_POPUP | WS_DLGFRAME + { + LTEXT "1_5" 1, 248, 46, 58, 20 + LTEXT "0_83" 2, 178, 46, 63, 20 + LTEXT "5_723" 3, 9, 9, 36, 36 + LTEXT "Warning: If you quit now, your game will be lost." 4, 51, 5, 255, 32 + } + +1070 DIALOG 10, 10, 320, 112 + STYLE WS_POPUP | WS_DLGFRAME + { + // DEFPUSHBUTTON "Go for it!" 1, 103, 41, 41, 10//, WS_GROUP | WS_TABSTOP + PUSHBUTTON "Exit Editor" 100, 59, 41, 42, 10//, WS_GROUP | WS_TABSTOP + LTEXT "Unfortunately, this program requires 8-bit Color Quickdraw to run optimally. It might work with less, or it might not work at all. Do you wish to try?" 3, 10, 7, 276, 66 + } + +1071 DIALOG 10, 10, 306, 208 + STYLE WS_POPUP | WS_DLGFRAME + { + // DEFPUSHBUTTON "Yes" 1, 105, 90, 31, 10//, WS_GROUP | WS_TABSTOP + PUSHBUTTON "Exit Editor" 100, 61, 90, 42, 10//, WS_GROUP | WS_TABSTOP + PUSHBUTTON "Play as is" 3, 10, 90, 50, 10//, WS_GROUP | WS_TABSTOP + LTEXT "This program is best with 256 Color Quickdraw, which you have on your system. It works acceptably well with 16 colors." 4, 8, 6, 260, 64 + LTEXT "Would you like your monitor set to 256 colors?" 5, 8, 139, 263, 31 + LTEXT "With thousands or millions of colors, the game will only work well if you increase the memory (to do this, click on the game in the finder and hit -I)." 6, 8, 71, 259, 67 + } + diff --git a/Win32/Scenarios Editor/GLOBAL.CPP b/Win32/Scenarios Editor/GLOBAL.CPP new file mode 100644 index 00000000..8d0436d5 --- /dev/null +++ b/Win32/Scenarios Editor/GLOBAL.CPP @@ -0,0 +1,119 @@ + +#include +#include "global.h" +#include "math.h" +#include + +extern char scen_strs[160][256]; +extern char scen_strs2[110][256]; +extern char talk_strs[170][256]; +extern char town_strs[180][256]; +extern Boolean give_delays; +unsigned long anim_ticks = 0; +BOOL do_choose_anim = FALSE; +short custom_pic = 0; +BOOL play_anim=FALSE; + +RECT RECT16::rect32() +{ + RECT tmp; + tmp.left = left; + tmp.top = top; + tmp.right = right; + tmp.bottom = bottom; + return tmp; +} + +RECT16::RECT16 (const RECT & tmp) +{ + left = tmp.left; + top = tmp.top; + right = tmp.right; + bottom = tmp.bottom; +} + +RECT16 & RECT16::operator=(const RECT & tmp) +{ + left = tmp.left; + top = tmp.top; + right = tmp.right; + bottom = tmp.bottom; + return (*this); +} + +POINT MAKEPOINT(LONG lParam) +{ + POINT point; + + point.x = LOWORD(lParam); + point.y = HIWORD(lParam); + + return point; +} + +short get_ran (short times,short min,short max) +{ + short store; + short i, to_ret = 0; + + if ((max - min + 1) == 0) + return 0; + for (i = 1; i < times + 1; i++) { + store = rand() % (max - min + 1); + to_ret = to_ret + min + store; + } + return to_ret; +} + +short s_pow(short x,short y) +{ + return (short) pow((double) x, (double) y); +} + +short dist(location p1,location p2) +{ + return (short) sqrt((double)((p1.x - p2.x) * (p1.x - p2.x) + + (p1.y - p2.y) * (p1.y - p2.y))); +} + +short minmax(short min,short max,short k) +{ + if (k < min) + return min; + if (k > max) + return max; + return k; +} + +short abs(short x) +{ + if (x < 0) + return x * -1; + return x; +} +void Delay(short val,long *dummy) +{ + long then,now,wait_val; + + wait_val = (long) val; + wait_val = wait_val * 16; + then = (long)GetCurrentTime(); + now = then; + while (now - then < wait_val) { + now = (long) GetCurrentTime(); + } +} + +void beep() +{ + long dummy; + + MessageBeep(MB_OK); + Delay(200,&dummy); + + } + +void SysBeep(short) +{ + MessageBeep(MB_ICONQUESTION); +} diff --git a/Win32/Scenarios Editor/GLOBAL.H b/Win32/Scenarios Editor/GLOBAL.H new file mode 100644 index 00000000..65614742 --- /dev/null +++ b/Win32/Scenarios Editor/GLOBAL.H @@ -0,0 +1,340 @@ + +#define DRAG_EDGE 15 +#define NIL 0L + +#define DISPLAY_LEFT 23 +#define DISPLAY_TOP 23 +#define BITMAP_WIDTH 28 +#define BITMAP_HEIGHT 36 +#define NUM_BUTTONS 15 + +#define NUM_DLOG_B 53 + +#define NLS 25 +// number of left slots for buttons +#define NRS 400 +// number of right slots for scrolling list +#define NRSONPAGE 33 +// number of right slots for scrolling list on page at 1 time + +#define RIGHT_AREA_UL_X 287 +#define RIGHT_AREA_UL_Y 5 +#define RIGHT_AREA_WIDTH 290 +#define RIGHT_AREA_HEIGHT 400 + +#define TER_RECT_UL_X 6 +#define TER_RECT_UL_Y 25 +#define GWorldPtr HBITMAP + +#define CDGT cd_retrieve_text_edit_str +#define CDGN cd_retrieve_text_edit_num +#define CDST cd_set_text_edit_str +#define CDSN cd_set_text_edit_num + +#define huge + +struct RECT16 +{ + short left; + short top; + short right; + short bottom; + + RECT rect32(); + RECT16 () {} + RECT16 (const RECT & ); + RECT16 & operator=(const RECT &); +}; + +extern POINT MAKEPOINT(LONG lparam); + +typedef unsigned char BYTE; + +typedef char Boolean; + +typedef struct { + char x,y; + } location; + +typedef struct { + short type,sd1,sd2,pic,m1,m2,ex1a,ex1b,ex2a,ex2b,jumpto; + } special_node_type; + +typedef struct { + short personality,type; + char link1[4],link2[4]; + short extras[4]; + } talking_node_type; + +typedef struct { + unsigned char strlens[200]; + talking_node_type talk_nodes[60]; + } talking_record_type; + +typedef struct { + short picture; + unsigned char blockage,flag1,flag2,special,trans_to_what,fly_over,boat_over; + unsigned char block_horse,light_radius,step_sound,shortcut_key,res1,res2,res3; + } terrain_type_type; + +typedef struct { + unsigned char monst[4]; + } wandering_type; + +typedef struct { + unsigned char monst[7]; + unsigned char friendly[3]; + short spec_on_meet,spec_on_win,spec_on_flee,cant_flee; + short end_spec1,end_spec2; +} out_wandering_type; + +typedef struct { + unsigned char terrain[48][48]; + location special_locs[18]; + unsigned char special_id[18]; + location exit_locs[8]; + char exit_dests[8]; + location sign_locs[8]; + out_wandering_type wandering[4],special_enc[4]; + location wandering_locs[4]; + RECT16 info_rect[8]; + unsigned char strlens[180]; + special_node_type specials[60]; + } outdoor_record_type; + +typedef struct { + unsigned char number; + unsigned char start_attitude; + location start_loc; + unsigned char mobile; + unsigned char time_flag; + unsigned char extra1,extra2; + short spec1, spec2; + char spec_enc_code,time_code; + short monster_time,personality; + short special_on_kill,facial_pic; + + } creature_start_type; + + +typedef struct { + short variety, item_level; + char awkward, bonus, protection, charges, type; + unsigned char graphic_num,ability, type_flag, is_special; + short value; + Boolean identified, magic; + unsigned char weight, description_flag; + char full_name[25], name[15]; + unsigned char reserved1,reserved2; + unsigned char magic_use_type, ability_strength, treas_class, real_abil; +} short_item_record_type; + + +typedef struct { + short variety, item_level; + char awkward, bonus, protection, charges, type, magic_use_type; + unsigned char graphic_num,ability, ability_strength,type_flag, is_special,a; + short value; + unsigned char weight, special_class; + location item_loc; + char full_name[25], name[15]; + unsigned char treas_class,item_properties,reserved1,reserved2; +} item_record_type; + +typedef struct { + location item_loc; + short item_code,ability; + unsigned char charges,always_there,property,contained; + } preset_item_type; + +typedef struct { + location field_loc; + short field_type; + } preset_field_type; + +typedef struct { + short town_chop_time,town_chop_key; + wandering_type wandering[4]; + location wandering_locs[4]; + location special_locs[50]; + unsigned char spec_id[50]; + location sign_locs[15]; + short lighting; + location start_locs[4]; + location exit_locs[4]; + short exit_specs[4]; + RECT16 in_town_rect; + preset_item_type preset_items[64]; + short max_num_monst; + preset_field_type preset_fields[50]; + short spec_on_entry,spec_on_entry_if_dead; + short timer_spec_times[8]; + short timer_specs[8]; + unsigned char strlens[180]; + special_node_type specials[100]; + unsigned char specials1,specials2,res1,res2; + short difficulty; + } town_record_type; + +typedef struct { + unsigned char terrain[64][64]; + RECT16 room_rect[16]; + creature_start_type creatures[60]; + unsigned char lighting[8][64]; + } big_tr_type; + +typedef struct { + unsigned char terrain[48][48]; + RECT16 room_rect[16]; + creature_start_type creatures[40]; + unsigned char lighting[6][48]; + } ave_tr_type; + +typedef struct { + unsigned char terrain[32][32]; + RECT16 room_rect[16]; + creature_start_type creatures[30]; + unsigned char lighting[4][32]; + } tiny_tr_type; + +typedef struct { + short block_type; + short block_destroy_time; + char block_alignment; + char block_key_time; + location block_loc; + } city_block_type; + +typedef struct { + RECT16 what_rect; + unsigned char ter_type; + unsigned char hollow; + } city_ter_rect_type; + +typedef struct { + creature_start_type creatures[30]; + city_block_type city_block[15]; + city_ter_rect_type city_ter_rect[10]; + } template_town_type; + +typedef struct { + item_record_type scen_items[400]; + char monst_names[256][20]; + char ter_names[256][30]; + } scen_item_data_type; + +typedef struct { + short ter_type,item_num[10],item_odds[10],property; + } item_storage_shortcut_type; + +typedef struct { + unsigned char m_num,level,m_name[26]; + short health,m_health,mp,max_mp; + unsigned char armor,skill; + short a[3]; + unsigned char a1_type,a23_type,m_type,speed,ap,mu,cl,breath,breath_type,treasure,spec_skill,poison; + short morale,m_morale; + short corpse_item,corpse_item_chance; + short status[15]; + unsigned char direction,immunities,x_width,y_width,radiate_1,radiate_2; + unsigned char default_attitude,summon_type,default_facial_pic,res1,res2,res3; + short picture_num; + + } monster_record_type; + +typedef struct { + location horse_loc,horse_loc_in_sec,horse_sector; + short which_town; + Boolean exists,property; + } horse_record_type; +typedef struct { + location boat_loc,boat_loc_in_sec,boat_sector; + short which_town; + Boolean exists,property; +} boat_record_type; + + typedef struct { + unsigned char flag1, flag2, flag3, flag4; + unsigned char ver[3],min_run_ver,prog_make_ver[3],num_towns; + unsigned char out_width,out_height,difficulty,intro_pic,default_ground; + unsigned char town_size[200]; + unsigned char town_hidden[200],a; + short flag_a; + short intro_mess_pic,intro_mess_len; + location where_start,out_sec_start,out_start; + short which_town_start; + short flag_b; + short town_data_size[200][5]; + short town_to_add_to[10]; + short flag_to_add_to_town[10][2]; + short flag_c; + short out_data_size[100][2]; + RECT16 store_item_rects[3]; + short store_item_towns[3]; + short flag_e; + short special_items[50]; + short special_item_special[50]; + short rating,uses_custom_graphics; + short flag_f; + monster_record_type scen_monsters[256]; + boat_record_type scen_boats[30]; + horse_record_type scen_horses[30]; + short flag_g; + terrain_type_type ter_types[256]; + short scenario_timer_times[20]; + short scenario_timer_specs[20]; + short flag_h; + special_node_type scen_specials[256]; + item_storage_shortcut_type storage_shortcuts[10]; + short flag_d; + unsigned char scen_str_len[300]; + short flag_i; + location last_out_edited; + short last_town_edited; + + } scenario_data_type; + +// for game +typedef struct { + short personality; + short str1,str2; + } talk_save_type; + +typedef struct { + short active,attitude; + unsigned char number; + location m_loc; + monster_record_type m_d; + short mobile; + short summoned; + creature_start_type monst_start; + } creature_data_type; + +typedef struct { + creature_data_type dudes[60]; + short which_town; + short friendly; + } creature_list_type; + +typedef struct { + Boolean exists; + short direction; + out_wandering_type what_monst; + location which_sector,m_loc; + } outdoor_creature_type; + +typedef struct { + char strings_ls[NLS][40]; + char strings_rs[NRS][40]; + char out_strs[120][256]; + + } piles_of_stuff_dumping_type; + +short get_ran (short times,short min,short max); +short s_pow(short x,short y); +short dist(location p1,location p2); +void beep(); +void SysBeep(short a); +void Delay(short val,long *dummy); +short minmax(short min,short max,short k); +short abs(short x); diff --git a/Win32/Scenarios Editor/GRAPHICS.CPP b/Win32/Scenarios Editor/GRAPHICS.CPP new file mode 100644 index 00000000..986422e4 --- /dev/null +++ b/Win32/Scenarios Editor/GRAPHICS.CPP @@ -0,0 +1,1570 @@ +#include + +#include "stdio.h" +#include "string.h" +#include "global.h" +#include "graphics.h" +#include "math.h" +#include "dlogtool.h" +#include "edsound.h" +#include "graphutl.h" +#include "keydlgs.h" + +extern char scen_strs[160][256]; +extern char scen_strs2[110][256]; +extern char talk_strs[170][256]; +extern char town_strs[180][256]; +extern HFONT font,italic_font,underline_font,bold_font,tiny_font,small_bold_font; +extern HDC main_dc,main_dc2,main_dc3; + +extern HCURSOR cursors[8]; +extern outdoor_record_type current_terrain; +extern HWND mainPtr; +extern town_record_type current_town; +extern short cen_x, cen_y,current_terrain_type,cur_town; +extern town_record_type town; +extern big_tr_type t_d; +extern template_town_type town_template; +extern short town_type; // 0 - big 1 - ave 2 - small +extern short cur_viewing_mode,overall_mode; +extern short available_dlog_buttons[NUM_DLOG_B]; +extern Boolean editing_town; +extern short max_dim[3]; +extern short dungeon_font_num,geneva_font_num; +extern RECT windRect; +extern piles_of_stuff_dumping_type *data_store; +extern scenario_data_type scenario; +extern RECT world_screen; +extern scen_item_data_type scen_item_list; + +extern RECT left_button[NLS]; +extern RECT right_buttons[NRSONPAGE]; +extern RECT right_scrollbar_rect; +extern RECT right_area_rect; +extern unsigned char borders[4][50]; +extern HWND right_sbar; + +extern Boolean left_buttons_active,right_buttons_active; +extern short left_button_status[NLS]; // 0 - clear, 1 - text, 2 - title text, +10 - button +extern short right_button_status[NRS]; +extern unsigned char m_pic_index[200]; +extern char *button_strs[140]; +extern location cur_out; +extern short ulx,uly; +extern HINSTANCE store_hInstance; +extern HACCEL accel; +extern unsigned long anim_ticks; + +short num_ir[3] = {12,10,4}; + +GWorldPtr monst_gworld[10],terrain_gworld[6],small_terrain_gworld,editor_mixed,terrain_buttons_gworld; +GWorldPtr anim_gworld,field_gworld,dialog_gworld,items_gworld,tiny_obj_gworld; +GWorldPtr dlg_buttons_gworld,ter_draw_gworld,dlogpics_gworld,talkfaces_gworld,mixed_gworld; +GWorldPtr dialog_pattern_gworld,pattern_gworld; +HBITMAP spec_scen_g = NULL; + + short small_icons[24] = {0,23,37,38,39,35,33,34,30,0, + 30,26,0,0,36,0,27,28,29,20, + 21,22,0,0}; + +HBRUSH map_brush[25]; +HBITMAP map_bitmap[25]; + +// begin new stuff +RECT blue_button_from = {91,112,107,126};// +RECT start_button_from = {70,112,91,119}; +RECT boat_button_from = {61,1,88,35}; +RECT horse_button_from = {117,110,144,145}; +RECT base_small_button_from = {0,112,7,119}; +extern RECT palette_buttons[8][6]; +RECT palette_button_base = {0,0,25,18}; +RECT terrain_buttons_rect = {0,0,294,410}; +extern RECT left_buttons[NLS][2]; // 0 - whole, 1 - blue button +RECT left_button_base = {5,5,200,21}; +RECT right_button_base = {RIGHT_AREA_UL_Y,RIGHT_AREA_UL_X,17,RIGHT_AREA_UL_Y}; +RECT terrain_rect = {0,0,272,340}; +char current_string[256] = ""; +char current_string2[256] = ""; +extern RECT terrain_rects[256]; + +short map_pats[220] = {50,50,1,1,1,6,6,6,6,6, + 6,6,6,6,6,6,6,6,2,2, + 2,2,2,2,2,2,2,2,2,2, + 2,2,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,3,3,3,3, + 3,3,3,3,3,3,3,3,3,0, // 50 + 0,0,0,0,0,0,0,23,23,23, + 15,15,50,50,0,0,0,0,0,7, + 7,8,8,14,14,9,9,9,5,5, + 0,0,0,0,0,0,0,0,0,0, + 18,18,0,0,0,0,0,0,0,0, // 100 + 22,22,0,0,0,0,0,0,0,0, + 0,0,0,10,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,11,0,0, // 150 + 0,0,0,12,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0, // 200 + 0,0,0,0,0,0,0,0,0,0 + }; + + +unsigned char small_what_drawn[64][64]; +extern Boolean small_any_drawn; + +void Set_up_win () +{ + short i,j; + RECT whole_win_rect; + + GetClientRect(mainPtr,&whole_win_rect); + ulx = (whole_win_rect.right - 600) / 2 ; + uly = (whole_win_rect.bottom - 440) / 2 + 8; + + + for (i = 0; i < 8; i++) + for (j = 0; j < 6; j++) { + palette_buttons[i][j] = palette_button_base; + OffsetRect(&palette_buttons[i][j],i * 25, j * 17); + if (i == 7) + palette_buttons[i][j].right++; + } + for (i = 0; i < 8; i++) + for (j = 2; j < 6; j++) + OffsetRect(&palette_buttons[i][j],0,3); + for (i = 0; i < 8; i++) + for (j = 3; j < 6; j++) + OffsetRect(&palette_buttons[i][j],0,3); + for (i = 0; i < 8; i++) + for (j = 4; j < 6; j++) + OffsetRect(&palette_buttons[i][j],0,3); + + for (i = 0; i < NLS; i++) { + left_buttons[i][0] = left_button_base; + OffsetRect(&left_buttons[i][0],0,i * 16); + left_buttons[i][1] = left_buttons[i][0]; + left_buttons[i][1].top += 1; + left_buttons[i][1].bottom -= 1; + left_buttons[i][1].left += 0; + left_buttons[i][1].right = left_buttons[i][1].left + 16; + } + right_button_base.left = RIGHT_AREA_UL_X + 1; + right_button_base.top = RIGHT_AREA_UL_Y + 1; + right_button_base.bottom = right_button_base.top + 12; + right_button_base.right = right_button_base.left + RIGHT_AREA_WIDTH - 20; + for (i = 0; i < NRSONPAGE; i++) { + right_buttons[i] = right_button_base; + OffsetRect(&right_buttons[i],0,i * 12); + } + load_main_screen(); +} + +void run_startup_g() +{ + RECT pict_rect = {0,0,640,480},to_rect; + //PicHandle pict_to_draw; + HBITMAP start_g; + RECT pat_rect; + HBRUSH old_brush; + + pat_rect = windRect; + InflateRect(&pat_rect,500,500); +// paint_pattern(NULL,1,pat_rect,3); + old_brush = (HBRUSH) SelectObject(main_dc,GetStockObject(BLACK_BRUSH)); + Rectangle(main_dc, pat_rect.left,pat_rect.top, + pat_rect.right,pat_rect.bottom); + SelectObject(main_dc,old_brush); + + start_g = load_pict(3002); + to_rect = pict_rect; + OffsetRect(&to_rect,-18,-30); + rect_draw_some_item(start_g,pict_rect,start_g,to_rect,0,1); + DeleteObject(start_g); + play_sound(95); + +} + +void load_main_screen() +{ + + short i,j; + RECT map_from_orig = {372,0,380,8},map_from,brush_to = {0,0,8,8}; + + main_dc = GetDC(mainPtr); + + SelectObject(main_dc,font); + SetBkMode(main_dc,TRANSPARENT); + + + SetStretchBltMode(main_dc,STRETCH_DELETESCANS); + + terrain_buttons_gworld = CreateCompatibleBitmap(main_dc,terrain_buttons_rect.right,terrain_buttons_rect.bottom); + + ter_draw_gworld = CreateCompatibleBitmap(main_dc,terrain_rect.right,terrain_rect.bottom); + + dlg_buttons_gworld = load_pict(2000); + mixed_gworld = load_pict(903); + + run_startup_g(); + + + world_screen = terrain_rect; + OffsetRect(&world_screen,TER_RECT_UL_X,TER_RECT_UL_Y); + + for (i = 0; i < 10; i++) + monst_gworld[i] = load_pict(1100 + i); + for (i = 0; i < 6; i++) + terrain_gworld[i] = load_pict(800 + i); + small_terrain_gworld = load_pict(904); + editor_mixed = load_pict(906); + anim_gworld = load_pict(820); + field_gworld = load_pict(821); + talkfaces_gworld = load_pict(860); + items_gworld = load_pict(901); + tiny_obj_gworld = load_pict(900); + dlogpics_gworld = load_pict(850); + dialog_pattern_gworld = CreateCompatibleBitmap(main_dc,192,256); + pattern_gworld = CreateCompatibleBitmap(main_dc,192,256); + //draw_main_screen(); + + for (i = 0; i < 25; i++) { + map_from = map_from_orig; + OffsetRect(&map_from,8 * (i / 10),8 * (i % 10)); + map_bitmap[i] = CreateCompatibleBitmap(main_dc,8,8); + rect_draw_some_item(mixed_gworld,map_from,map_bitmap[i],brush_to,0,0); + map_brush[i] = CreatePatternBrush(map_bitmap[i]); + } +} + +void redraw_screen() +{ + RECT pat_rect; + + pat_rect = windRect; + InflateRect(&pat_rect,500,500); + paint_pattern(NULL,1,pat_rect,3); + draw_main_screen(); + if (overall_mode < 60); + draw_terrain(); +} + +void draw_main_screen() +{ + short i; + RECT draw_rect,big_rect = {-1,-1,582,414}; + HBRUSH old_brush,new_brush; + COLORREF y = RGB(128,128,128);//y = RGB(119,119,119); + UINT c; + + // draw left buttons (always active) + draw_lb(); + + // draw right buttons (only when not editing terrain) + if (overall_mode >= 60) { + draw_rect.left = RIGHT_AREA_UL_X; + draw_rect.top = RIGHT_AREA_UL_Y; + draw_rect.right = RIGHT_AREA_UL_X + RIGHT_AREA_WIDTH - 16; + draw_rect.bottom = RIGHT_AREA_UL_Y + RIGHT_AREA_HEIGHT; + + //c = GetNearestPaletteIndex(hpal,y); + new_brush = CreateSolidBrush(y); + OffsetRect(&draw_rect,ulx,uly); + FrameRect(main_dc,&draw_rect,new_brush); + OffsetRect(&big_rect,ulx,uly); + if (ulx > 40) + FrameRect(main_dc,&big_rect,new_brush); + DeleteObject(new_brush); + + InsetRect(&draw_rect,1,1); + OffsetRect(&draw_rect,-1 * ulx,-1 * uly); + paint_pattern(NULL,1,draw_rect,3); + + draw_rb(); + + // redraw scroll bar here + } + + // draw terrain palette + if ((overall_mode < 60) || (overall_mode == 62)) { + place_location(); + } + + +} + +void draw_lb() +{ + RECT temp_rect; + short i; + + temp_rect = windRect; + temp_rect.right = RIGHT_AREA_UL_X - 2; + paint_pattern(NULL,1,temp_rect,3); + for (i = 0; i < NLS; i++) + draw_lb_slot(i,0); +} + +// mode 0 normal 1 click +void draw_lb_slot (short which,short mode) +{ + RECT text_rect,from_rect; + COLORREF colors = RGB(0,0,102),colors2 = RGB(0,0,0); + + paint_pattern(NULL,1,left_buttons[which][0],3); + if (left_button_status[which] == 0) + return; + text_rect = left_buttons[which][0]; + if (left_button_status[which] >= 10) { + text_rect.left += 18; + from_rect = blue_button_from; + if (mode > 0) + OffsetRect(&from_rect,from_rect.right - from_rect.left,0); + rect_draw_some_item(editor_mixed,from_rect,editor_mixed,left_buttons[which][1],0,1); + } + if (left_button_status[which] % 10 == 3) + text_rect.left += 16; + if (left_button_status[which] % 10 == 2) { + SelectObject(main_dc,bold_font); + } + else OffsetRect(&text_rect,0,2); + if (mode > 0) + SetTextColor(main_dc,colors); + + char_win_draw_string(main_dc,text_rect,(char *)data_store->strings_ls[which],0,12); + SetTextColor(main_dc,colors2); + + SelectObject(main_dc,font); + +} + +void draw_rb() +{ + short i,pos; + + pos = GetScrollPos(right_sbar,SB_CTL); + for (i = pos; i < pos + NRSONPAGE; i++) + draw_rb_slot(i,0); +} + +// mode 0 normal 1 pressed +void draw_rb_slot (short which,short mode) +{ + RECT text_rect; + short pos; + COLORREF colors = RGB(255,0,0),colors2 = RGB(0,0,0); + + pos = GetScrollPos(right_sbar,SB_CTL); + if ((which < pos) || (which >= pos + NRSONPAGE)) + return; + + text_rect = right_buttons[which - pos]; + text_rect.right += 2; + text_rect.bottom += 2; + paint_pattern(NULL,1,text_rect,1); + text_rect.bottom -= 2; + if (right_button_status[which] == 0) + return; + + if (mode > 0) + SetTextColor(main_dc,colors); + OffsetRect(&text_rect,0,-1); + char_win_draw_string(main_dc,text_rect,(char *)data_store->strings_rs[which],0,12); + SetTextColor(main_dc,colors2); +} + +void set_up_terrain_buttons() +{ + short i,pic,small_i; + RECT ter_from,ter_to,ter_from_base = {0,0,28,36}; + RECT tiny_from,tiny_to; + HDC hdc; + RECT palette_from = {0,0,0,0},palette_to; + HBITMAP store_bmp; + COLORREF y = RGB(128,128,128);//y = RGB(119,119,119); + HBRUSH new_brush; + + paint_pattern(terrain_buttons_gworld,0,terrain_buttons_rect,1); + + hdc = CreateCompatibleDC(main_dc); + + SetBkMode(hdc,TRANSPARENT); + SelectObject(hdc,small_bold_font); + SetStretchBltMode(hdc,STRETCH_DELETESCANS); + store_bmp = (HBITMAP)SelectObject(hdc,terrain_buttons_gworld); + + new_brush = CreateSolidBrush(y); + + store_bmp = (HBITMAP)SelectObject(hdc,terrain_buttons_gworld); + FrameRect(hdc,&terrain_buttons_rect,new_brush); + + // first make terrain buttons + for (i = 0; i < 256; i++) { + ter_from = ter_from_base; + pic = scenario.ter_types[i].picture; + } + SelectObject(hdc,store_bmp); + DeleteObject(hdc); + DeleteObject(new_brush); + SetStretchBltMode(main_dc,STRETCH_DELETESCANS); + + // first make terrain buttons + for (i = 0; i < 256; i++) { + ter_from = ter_from_base; + pic = scenario.ter_types[i].picture; + if (pic >= 1000) { + ter_from = get_custom_rect(pic % 1000); + rect_draw_some_item(spec_scen_g,ter_from,terrain_buttons_gworld,terrain_rects[i],0,0); + } + else if (pic < 400) { + pic = pic % 50; + OffsetRect(&ter_from,28 * (pic % 10), 36 * (pic / 10)); + rect_draw_some_item(terrain_gworld[scenario.ter_types[i].picture/50],ter_from,terrain_buttons_gworld,terrain_rects[i],0,0); + } + else if (pic < 1000) { + pic = pic % 50; + ter_from.left = 112 * (pic / 5); + ter_from.right = ter_from.left + 28; + ter_from.top = 36 * (pic % 5); + ter_from.bottom = ter_from.top + 36; + + rect_draw_some_item(anim_gworld,ter_from,terrain_buttons_gworld,terrain_rects[i],0,0); + } + small_i = small_icons[scenario.ter_types[i].special]; + if ((small_i == 30) && (scenario.ter_types[i].flag2 >= 5)) + small_i = 31; + if ((small_i == 31) && (scenario.ter_types[i].flag2 == 10)) + small_i = 32; + if (i == 82) + small_i = 3; + if (i == 83) + small_i = 2; + if ((i == 7) || (i == 10) || (i == 13) || (i == 16)) + small_i = 23; + tiny_from = base_small_button_from; + OffsetRect(&tiny_from,7 * (small_i % 10),7 * (small_i / 10)); + tiny_to = terrain_rects[i]; + tiny_to.top = tiny_to.bottom - 7; + tiny_to.left = tiny_to.right - 7; + if (small_i > 0) { + rect_draw_some_item(editor_mixed, + tiny_from,terrain_buttons_gworld,tiny_to,0,0); + } + } + + if (overall_mode < 60) { + palette_to.left = 5; + palette_to.top = terrain_rects[255].bottom + 5; + if (editing_town == TRUE) { + palette_from.bottom = palette_buttons[0][5].bottom; + palette_from.right = palette_buttons[7][5].right; + } + else { + palette_from.bottom = palette_buttons[0][2].bottom; + palette_from.right = palette_buttons[7][2].right; + } + palette_to.right = palette_to.left + palette_from.right; + palette_to.bottom = palette_to.top + palette_from.bottom; + rect_draw_some_item(editor_mixed, + palette_from,terrain_buttons_gworld,palette_to,1,0); + } + + +} + +void draw_terrain() +{ + short q,r,x,y,i,small_i; + location which_pt,where_draw; + RECT draw_rect,clipping_rect = {8,8,260,332}; + unsigned char t_to_draw; + RECT tiny_to,tiny_to_base = {29,37,36,44},tiny_from,from_rect,to_rect; + HBITMAP store_bmp; + COLORREF gray = RGB(128,128,128); + COLORREF red = RGB(255,0,0); + COLORREF white = RGB(255,255,255); + + HBRUSH new_brush; + HDC hdc; + HPEN old_pen; + + if (overall_mode >= 60) + return; + + if (cur_viewing_mode == 0) { + paint_pattern(ter_draw_gworld,0,terrain_rect,1); + } + hdc = CreateCompatibleDC(main_dc); + + SetBkMode(hdc,TRANSPARENT); + SelectObject(hdc,small_bold_font); + store_bmp = (HBITMAP)SelectObject(hdc,ter_draw_gworld); + + + new_brush = CreateSolidBrush(gray); + FrameRect(hdc,&terrain_rect,new_brush); + DeleteObject(new_brush); + old_pen = (HPEN)SelectObject(hdc,GetStockObject(NULL_PEN)); + SelectObject(hdc,store_bmp); + + if (cur_viewing_mode == 0) { + for (q = 0; q < 9; q++) + for (r = 0; r < 9; r++) + { + where_draw.x = q; where_draw.y = r; + if (editing_town == TRUE) { + t_to_draw = t_d.terrain[cen_x + q - 4][cen_y + r - 4]; + } + else { + if (cen_x + q - 4 == -1) + t_to_draw = borders[3][cen_y + r - 4]; + else if (cen_x + q - 4 == 48) + t_to_draw = borders[1][cen_y + r - 4]; + else if (cen_y + r - 4 == -1) + t_to_draw = borders[0][cen_x + q - 4]; + else if (cen_y + r - 4 == 48) + t_to_draw = borders[2][cen_x + q - 4]; + else t_to_draw = current_terrain.terrain[cen_x + q - 4][cen_y + r - 4]; + } + draw_one_terrain_spot(q,r,t_to_draw); + which_pt.x = cen_x + q - 4; + which_pt.y =cen_y + r - 4; + + tiny_to = tiny_to_base; + OffsetRect(&tiny_to,28 * q, 36 * r); + + // draw start icon, if starting point + if ((editing_town == TRUE) && + (cur_town == scenario.which_town_start) && (scenario.where_start.x == cen_x + q - 4) + && (scenario.where_start.y == cen_y + r - 4)) { + from_rect = start_button_from; + to_rect = tiny_to; + to_rect.left -= 14; + rect_draw_some_item(editor_mixed,from_rect,ter_draw_gworld,to_rect,0,0); + OffsetRect(&tiny_to,0,-7); + } + if ((editing_town == FALSE) + && (scenario.out_sec_start.x == cur_out.x) + && (scenario.out_sec_start.y == cur_out.y) + && (scenario.out_start.x == cen_x + q - 4) + && (scenario.out_start.y == cen_y + r - 4)) { + from_rect = start_button_from; + to_rect = tiny_to; + to_rect.left -= 14; + rect_draw_some_item(editor_mixed,from_rect,ter_draw_gworld,to_rect,0,0); + OffsetRect(&tiny_to,0,-7); + } + small_i = small_icons[scenario.ter_types[t_to_draw].special]; + if ((small_i == 30) && (scenario.ter_types[t_to_draw].flag2 >= 5)) + small_i = 31; + if ((small_i == 31) && (scenario.ter_types[t_to_draw].flag2 == 10)) + small_i = 32; + tiny_from = base_small_button_from; + OffsetRect(&tiny_from,7 * (small_i % 10),7 * (small_i / 10)); + if (small_i > 0) { + rect_draw_some_item(editor_mixed,tiny_from,ter_draw_gworld,tiny_to,0,0); + OffsetRect(&tiny_to,0,-7); + } + + if (is_special(cen_x + q - 4,cen_y + r - 4) == TRUE) { + tiny_from = base_small_button_from; + OffsetRect(&tiny_from,7 * (7),7 * (0)); + rect_draw_some_item(editor_mixed,tiny_from,ter_draw_gworld,tiny_to,0,0); + OffsetRect(&tiny_to,0,-7); + } + if ((t_to_draw == 7) || (t_to_draw == 10) || (t_to_draw == 13) || (t_to_draw == 16)) { + tiny_from = base_small_button_from; + OffsetRect(&tiny_from,7 * (3),7 * (2)); + rect_draw_some_item(editor_mixed,tiny_from,ter_draw_gworld,tiny_to,0,0); + OffsetRect(&tiny_to,0,-7); + } + if (editing_town == FALSE) { + for (i = 0; i < 4; i++) + if ((cen_x + q - 4 == current_terrain.wandering_locs[i].x) && + (cen_y + r - 4 == current_terrain.wandering_locs[i].y)) { + tiny_from = base_small_button_from; + OffsetRect(&tiny_from,7 * (2),7 * (1)); + rect_draw_some_item(editor_mixed,tiny_from,ter_draw_gworld,tiny_to,0,0); + OffsetRect(&tiny_to,0,-7); + i = 4; + } + + } + + if (editing_town == TRUE) { + for (i = 0; i < 4; i++) + if ((cen_x + q - 4 == town.start_locs[i].x) && + (cen_y + r - 4 == town.start_locs[i].y)) { + tiny_from = base_small_button_from; + OffsetRect(&tiny_from,7 * (6 + i),7 * (1)); + rect_draw_some_item(editor_mixed,tiny_from,ter_draw_gworld,tiny_to,0,0); + OffsetRect(&tiny_to,0,-7); + } + for (i = 0; i < 4; i++) + if ((cen_x + q - 4 == town.wandering_locs[i].x) && + (cen_y + r - 4 == town.wandering_locs[i].y)) { + tiny_from = base_small_button_from; + OffsetRect(&tiny_from,7 * (2),7 * (1)); + rect_draw_some_item(editor_mixed,tiny_from,ter_draw_gworld,tiny_to,0,0); + OffsetRect(&tiny_to,0,-7); + i = 4; + } + if (is_web(cen_x + q - 4,cen_y + r - 4) == TRUE) { + from_rect = calc_rect(5,0); + Draw_Some_Item(field_gworld,from_rect,ter_draw_gworld,where_draw,1,0); + } + if (is_crate(cen_x + q - 4,cen_y + r - 4) == TRUE) { + from_rect = calc_rect(6,0); + Draw_Some_Item(field_gworld,from_rect,ter_draw_gworld,where_draw,1,0); + } + if (is_barrel(cen_x + q - 4,cen_y + r - 4) == TRUE) { + from_rect = calc_rect(7,0); + Draw_Some_Item(field_gworld,from_rect,ter_draw_gworld,where_draw,1,0); + } + if (is_fire_barrier(cen_x + q - 4,cen_y + r - 4) == TRUE) { + from_rect = calc_rect(0,2); + Draw_Some_Item(field_gworld,from_rect,ter_draw_gworld,where_draw,1,0); + } + if (is_quickfire(cen_x + q - 4,cen_y + r - 4) == TRUE) { + from_rect = calc_rect(7,1); + Draw_Some_Item(field_gworld,from_rect,ter_draw_gworld,where_draw,1,0); + } + if (is_force_barrier(cen_x + q - 4,cen_y + r - 4) == TRUE) { + from_rect = calc_rect(2,2); + Draw_Some_Item(field_gworld,from_rect,ter_draw_gworld,where_draw,1,0); + } + for (i = 0; i < 8; i++) + if (is_sfx(cen_x + q - 4,cen_y + r - 4,i)) { + from_rect = calc_rect(i,3); + Draw_Some_Item(field_gworld,from_rect,ter_draw_gworld,where_draw,1,0); + } + for (x = 0; x < 64; x++) + if ((cen_x + q - 4 == town.preset_items[x].item_loc.x) && + (cen_y + r - 4 == town.preset_items[x].item_loc.y) && (town.preset_items[x].item_code >= 0)) { + } + for (x = 0; x < 60; x++) + if ((cen_x + q - 4 == t_d.creatures[x].start_loc.x) && + (cen_y + r - 4 == t_d.creatures[x].start_loc.y) && (t_d.creatures[x].number != 0)) { + } + + } + } + if (editing_town == TRUE) { + draw_monsts(hdc); + draw_items(hdc); + } + + store_bmp = (HBITMAP)SelectObject(hdc,ter_draw_gworld); + ClipRect(hdc,&clipping_rect); + + if (editing_town == TRUE) { + // draw info rects + for (i = 0; i < 16; i++) + if (t_d.room_rect[i].left > 0) { + draw_rect.left = 22 + 28 * (t_d.room_rect[i].left - cen_x + 4); + draw_rect.right = 22 + 28 * (t_d.room_rect[i].right - cen_x + 4); + draw_rect.top = 24 + 36 * (t_d.room_rect[i].top - cen_y + 4); + draw_rect.bottom = 24 + 36 * (t_d.room_rect[i].bottom - cen_y + 4); + + //c = GetNearestPaletteIndex(hpal,red); + new_brush = CreateSolidBrush(red); + FrameRect(hdc,&draw_rect,new_brush); + DeleteObject(new_brush); + } + // draw border rect + draw_rect.left = 21 + 28 * (town.in_town_rect.left - cen_x + 4); + draw_rect.right = 21 + 28 * (town.in_town_rect.right - cen_x + 4); + draw_rect.top = 25 + 36 * (town.in_town_rect.top - cen_y + 4); + draw_rect.bottom = 25 + 36 * (town.in_town_rect.bottom - cen_y + 4); + +// c = GetNearestPaletteIndex(hpal,white); + new_brush = CreateSolidBrush(white); + FrameRect(hdc,&draw_rect,new_brush); + DeleteObject(new_brush); + } + if (editing_town == FALSE) { + // draw info rects + for (i = 0; i < 8; i++) + if (current_terrain.info_rect[i].left > 0) { + draw_rect.left = 22 + 28 * (current_terrain.info_rect[i].left - cen_x + 4); + draw_rect.right = 22 + 28 * (current_terrain.info_rect[i].right - cen_x + 4); + draw_rect.top = 24 + 36 * (current_terrain.info_rect[i].top - cen_y + 4); + draw_rect.bottom = 24 + 36 * (current_terrain.info_rect[i].bottom - cen_y + 4); + //c = GetNearestPaletteIndex(hpal,red); + new_brush = CreateSolidBrush(red); + + FrameRect(hdc,&draw_rect,new_brush); + DeleteObject(new_brush); + } + } + undo_clip(hdc); + SelectObject(hdc,store_bmp); + + small_any_drawn = FALSE; + } + + if (cur_viewing_mode == 1) { + if (small_any_drawn == FALSE) { + InsetRect(&terrain_rect,1,1); + paint_pattern(ter_draw_gworld,0,terrain_rect,1); + InsetRect(&terrain_rect,-1,-1); + //FrameRect(&terrain_rect); + } + for (q = 0; q < ((editing_town == TRUE) ? max_dim[town_type] : 48); q++) + for (r = 0; r < ((editing_town == TRUE) ? max_dim[town_type] : 48); r++) { + t_to_draw = (editing_town == TRUE) ? t_d.terrain[q][r] : + current_terrain.terrain[q][r]; + if ((small_what_drawn[q][r] != t_to_draw) || (small_any_drawn == FALSE)) { + draw_one_tiny_terrain_spot(q,r,t_to_draw,hdc); + small_what_drawn[q][r] = t_to_draw; + } + } + small_any_drawn = TRUE; + } + + SelectObject(hdc,old_pen); + DeleteObject(hdc); + //draw_cur_string(); + place_location(); + + rect_draw_some_item(ter_draw_gworld,terrain_rect,ter_draw_gworld,world_screen,0,1); +} + +void draw_monsts(HDC hdc) +{ + short i,k,width,height,m_start_pic; + GWorldPtr from_gworld; + RECT source_rect,draw_rect; + location where_draw,store_loc; + COLORREF y = RGB(128,128,128),red = RGB(255,0,0),white = RGB(255,255,255);//y = RGB(119,119,119); + HBITMAP store_bmp; + UINT c; + HBRUSH new_brush; + + for (i = 0; i < 60; i++) + if (t_d.creatures[i].number != 0) { + where_draw.x = t_d.creatures[i].start_loc.x - cen_x + 4; + where_draw.y = t_d.creatures[i].start_loc.y - cen_y + 4; + width = scenario.scen_monsters[t_d.creatures[i].number].x_width; + height = scenario.scen_monsters[t_d.creatures[i].number].y_width; + + for (k = 0; k < width * height; k++) { + store_loc = where_draw; + if ((where_draw.x == minmax(0,8,where_draw.x)) && + (where_draw.y == minmax(0,8,where_draw.y)) && + (scenario.scen_monsters[t_d.creatures[i].number].picture_num >= 1000)) { + source_rect = get_custom_rect((scenario.scen_monsters[t_d.creatures[i].number].picture_num + k) % 1000); + store_loc.x += k % width; + store_loc.y += k / width; + Draw_Some_Item(spec_scen_g, source_rect, ter_draw_gworld, store_loc, 1, 0); + } + else if (scenario.scen_monsters[t_d.creatures[i].number].picture_num < 1000) { + m_start_pic = m_pic_index[scenario.scen_monsters[t_d.creatures[i].number].picture_num] + k; + from_gworld = monst_gworld[m_start_pic / 20]; + m_start_pic = m_start_pic % 20; + source_rect = calc_rect(2 * (m_start_pic / 10), m_start_pic % 10); + store_loc.x += k % width; + store_loc.y += k / width; + Draw_Some_Item(from_gworld, source_rect, ter_draw_gworld, store_loc, 1, 0); + } + } + } +} + +// Returns rect for drawing an item, if num < 25, rect is in big item template, +// otherwise in small item template +RECT get_item_template_rect (short type_wanted) +{ + RECT store_rect; + + if (type_wanted < 45) { + store_rect.top = (type_wanted / 5) * BITMAP_HEIGHT; + store_rect.bottom = store_rect.top + BITMAP_HEIGHT; + store_rect.left = (type_wanted % 5) * BITMAP_WIDTH; + store_rect.right = store_rect.left + BITMAP_WIDTH; + } + else { + store_rect.top = (type_wanted / 10) * 18; + store_rect.bottom = store_rect.top + 18; + store_rect.left = (type_wanted % 10) * 18; + store_rect.right = store_rect.left + 18; + } + + return store_rect; +} + +void draw_items(HDC hdc) +{ + short i; + RECT source_rect,draw_rect; + location where_draw; + short pic_num; + COLORREF y = RGB(128,128,128),red = RGB(255,0,0),blue = RGB(0,0,255);//y = RGB(119,119,119); + HBITMAP store_bmp; + UINT c; + HBRUSH new_brush; + + for (i = 0; i < 64; i++) { + if (town.preset_items[i].item_code >= 0) { + where_draw.x = town.preset_items[i].item_loc.x - cen_x + 4; + where_draw.y = town.preset_items[i].item_loc.y - cen_y + 4; + pic_num = scen_item_list.scen_items[town.preset_items[i].item_code].graphic_num; + if ((where_draw.x >= 0) && (where_draw.x <= 8) && + (where_draw.y >= 0) && (where_draw.y <= 8)) { + + if (pic_num >= 150) { + source_rect = get_custom_rect(pic_num - 150); + draw_rect = calc_rect(where_draw.x,where_draw.y); + rect_draw_some_item(spec_scen_g,source_rect, ter_draw_gworld, draw_rect, 1, 0); + } + else { + source_rect = get_item_template_rect(pic_num); + draw_rect = calc_rect(where_draw.x,where_draw.y); + OffsetRect(&draw_rect,8,8); + if (pic_num >= 45) { + draw_rect.top += 9; + draw_rect.bottom -= 9; + draw_rect.left += 5; + draw_rect.right -= 5; + } + rect_draw_some_item((pic_num < 45) ? items_gworld : tiny_obj_gworld,source_rect, ter_draw_gworld, draw_rect, 1, 0); + } + } + } + } +} + + +void redraw_selected_ter() +{ + +} + +void draw_one_terrain_spot (short i,short j,unsigned char terrain_to_draw) +{ + location where_draw; + RECT source_rect; + short picture_wanted; + GWorldPtr source_gworld; + short k; + + picture_wanted = scenario.ter_types[terrain_to_draw].picture; + + where_draw.x = (char) i; + where_draw.y = (char) j; + + if ((picture_wanted >= 2000) && (spec_scen_g != NULL)) { + source_gworld = spec_scen_g; + source_rect = get_custom_rect(picture_wanted % 2000); + source_rect.left += 28 * ((anim_ticks / 20) % 4); + source_rect.right = source_rect.left + 28; + } + else if ((picture_wanted >= 1000) && (spec_scen_g != NULL)) { + source_gworld = spec_scen_g; + source_rect = get_custom_rect(picture_wanted % 1000); + } + else if (picture_wanted >= 400) { + source_gworld = anim_gworld; + picture_wanted -= 400; + source_rect.left = 112 * (picture_wanted / 5)+ 28 * ((anim_ticks / 20) % 4); + source_rect.right = source_rect.left + 28; + source_rect.top = 36 * (picture_wanted % 5); + source_rect.bottom = source_rect.top + 36; + } + else { + source_rect = get_template_rect(terrain_to_draw); + source_gworld = terrain_gworld[picture_wanted / 50]; + } + + Draw_Some_Item(source_gworld, source_rect, ter_draw_gworld, where_draw, 0, 0); + + if(editing_town) + for(k=0;k<30;k++){ + if ((cur_town == scenario.scen_horses[k].which_town) && + (scenario.scen_horses[k].horse_loc.x == cen_x + i - 4) && + (scenario.scen_horses[k].horse_loc.y == cen_y + j - 4)) { + source_rect = horse_button_from; + Draw_Some_Item(mixed_gworld,source_rect,ter_draw_gworld,where_draw,1,0); + } + if ((scenario.scen_boats[k].which_town == cur_town) && + (scenario.scen_boats[k].boat_loc.x == cen_x + i - 4) && + (scenario.scen_boats[k].boat_loc.y == cen_y + j - 4)) { + source_rect = boat_button_from; + Draw_Some_Item(mixed_gworld,source_rect,ter_draw_gworld,where_draw,1,0); + } + } + +} + +void draw_one_tiny_terrain_spot (short i,short j,unsigned char terrain_to_draw,HDC hdc) +{ + + location where_draw; + RECT source_rect,dest_rect = {0,0,5,5},from_rect = {0,0,4,4},orig_draw_rect = {0,0,4,4}; + short picture_wanted,k; + GWorldPtr source_gworld; + HBITMAP store_bmp; + HBRUSH old_brush; + + picture_wanted = scenario.ter_types[terrain_to_draw].picture; + + where_draw.x = (char) i; + where_draw.y = (char) j; + OffsetRect(&dest_rect,8 + 4 * i,8 + 4 * j); + + store_bmp = (HBITMAP)SelectObject(hdc,ter_draw_gworld); + old_brush = (HBRUSH) SelectObject(hdc,map_brush[0]); + + switch (picture_wanted) { + + case 0: case 1: case 73: case 72: + SelectObject(hdc,map_brush[0]); + Rectangle(hdc,dest_rect.left, dest_rect.top,dest_rect.right,dest_rect.bottom); + break; + case 2: case 3: case 4: + SelectObject(hdc,map_brush[1]); + Rectangle(hdc,dest_rect.left, dest_rect.top,dest_rect.right,dest_rect.bottom); + break; + + default: + if ((picture_wanted < 170) && (map_pats[picture_wanted] > 0)) { + SelectObject(hdc,map_brush[map_pats[picture_wanted]]); + Rectangle(hdc,dest_rect.left, dest_rect.top,dest_rect.right,dest_rect.bottom); + } + else if (picture_wanted >= 1000) { + SelectObject(hdc,store_bmp); + from_rect = get_custom_rect(picture_wanted % 1000); + rect_draw_some_item(spec_scen_g, from_rect, ter_draw_gworld, dest_rect, 0, 0); + store_bmp = (HBITMAP)SelectObject(hdc,ter_draw_gworld); + } + + else if (picture_wanted >= 400) { + source_gworld = anim_gworld; + picture_wanted -= 400; + if (picture_wanted == 0) { + SelectObject(hdc,map_brush[13]); + Rectangle(hdc,dest_rect.left, dest_rect.top,dest_rect.right,dest_rect.bottom); + } + else if (picture_wanted == 4) { + SelectObject(hdc,map_brush[21]); + Rectangle(hdc,dest_rect.left, dest_rect.top,dest_rect.right,dest_rect.bottom); + } + else if (picture_wanted == 7) { + SelectObject(hdc,map_brush[20]); + Rectangle(hdc,dest_rect.left, dest_rect.top,dest_rect.right,dest_rect.bottom); + } + else if (picture_wanted == 8) { + SelectObject(hdc,map_brush[19]); + Rectangle(hdc,dest_rect.left, dest_rect.top,dest_rect.right,dest_rect.bottom); + } + else if (picture_wanted == 9) { + SelectObject(hdc,map_brush[20]); + Rectangle(hdc,dest_rect.left, dest_rect.top,dest_rect.right,dest_rect.bottom); + } + else if (picture_wanted == 10) { + SelectObject(hdc,map_brush[19]); + Rectangle(hdc,dest_rect.left, dest_rect.top,dest_rect.right,dest_rect.bottom); + } + else { + from_rect = orig_draw_rect; + OffsetRect(&from_rect, + 312 + 24 * (picture_wanted / 5) + 1, + 163 + 6 * (picture_wanted % 5) + 1); + SelectObject(hdc,store_bmp); + dest_rect.right--; dest_rect.bottom--; + rect_draw_some_item(mixed_gworld, from_rect, ter_draw_gworld, dest_rect, 0, 0); + store_bmp = (HBITMAP)SelectObject(hdc,ter_draw_gworld); + } + } + else { + + from_rect = orig_draw_rect; + OffsetRect(&from_rect, + 6 * (picture_wanted % 10) + 312 + 1,1 + 6 * (picture_wanted / 10)); + + SelectObject(hdc,store_bmp); + dest_rect.right--; dest_rect.bottom--; + rect_draw_some_item(mixed_gworld, from_rect, ter_draw_gworld, dest_rect, 0, 0); + store_bmp = (HBITMAP)SelectObject(hdc,ter_draw_gworld); + } + break; + } + SelectObject(hdc,store_bmp); + SelectObject(hdc,old_brush); +} + +/* Draw a bitmap in the world window. hor in 0 .. 8, vert in 0 .. 8, + object is ptr. to bitmap to be drawn, and masking is for Copybits. */ +void Draw_Some_Item ( GWorldPtr src_gworld,RECT src_rect,GWorldPtr targ_gworld,location target, +char masked,short main_win) +{ +RECT destrec; + + if ((target.x < 0) || (target.x > 8) || (target.y < 0) || (target.y > 8)) + return; + destrec.left = 8 + BITMAP_WIDTH * target.x; + destrec.right = destrec.left + BITMAP_WIDTH; + destrec.top = 8 + BITMAP_HEIGHT * target.y; + destrec.bottom = destrec.top + BITMAP_HEIGHT; + + destrec.left = destrec.right - (src_rect.right - src_rect.left); + destrec.top = destrec.bottom - (src_rect.bottom - src_rect.top); + + rect_draw_some_item(src_gworld,src_rect,ter_draw_gworld,destrec,masked,0); + +} + + +void discard_graphics() +{ + short i; + + DeleteObject(terrain_buttons_gworld); + DeleteObject(ter_draw_gworld); + DeleteObject(dlg_buttons_gworld); + for (i = 0; i < 10; i++) + DeleteObject(monst_gworld[i]); + for (i = 0; i < 6; i++) + DeleteObject(terrain_gworld[i]); + DeleteObject(small_terrain_gworld); + DeleteObject(editor_mixed); + DeleteObject(anim_gworld); + DeleteObject(talkfaces_gworld); + DeleteObject(field_gworld); + DeleteObject(tiny_obj_gworld); + DeleteObject(items_gworld); + DeleteObject(dlogpics_gworld); + DeleteObject(mixed_gworld); + DeleteObject(pattern_gworld); + DeleteObject(dialog_pattern_gworld); + if (spec_scen_g != NULL) + DeleteObject(spec_scen_g); + + DeleteDC(main_dc); + + DeleteObject(font); +// DeleteObject(small_bold_font); + DeleteObject(underline_font); + DeleteObject(italic_font); + DeleteObject(bold_font); + + for (i = 0; i < 8; i++) + if (cursors[i] != NULL) + DeleteObject(cursors[i]); + for (i = 0; i < 25; i++) { + DeleteObject(map_bitmap[i]); + DeleteObject(map_brush[i]); + } +} + +/* Input terrain currently trying to draw. Get back RECT in terrain template containing +desired pixmap, or RECT to darkness if desired map not present */ +RECT get_template_rect (unsigned char type_wanted) +{ + RECT store_rect; + short i,j; + short picture_wanted; + + picture_wanted = scenario.ter_types[type_wanted].picture; + if (picture_wanted >= 1000) + picture_wanted = 0; + picture_wanted = picture_wanted % 50; + store_rect.top = 0 + (picture_wanted / 10) * BITMAP_HEIGHT; + store_rect.bottom = store_rect.top + BITMAP_HEIGHT; + store_rect.left = 0 + (picture_wanted % 10) * BITMAP_WIDTH; + store_rect.right = store_rect.left + BITMAP_WIDTH; + + return store_rect; +} + + +void place_location() +{ + RECT text_rect = {367,290,384,510}; + char draw_str[256]; + RECT from_rect,draw_rect,source_rect,erase_rect; + short picture_wanted; + HBITMAP store_bmp; + COLORREF y = RGB(128,128,128),red = RGB(255,0,0),white = RGB(255,255,255);//y = RGB(119,119,119); + UINT c; + HBRUSH new_brush; + HDC hdc; + + erase_rect.left = terrain_rects[255].left + 17; + erase_rect.right = RIGHT_AREA_WIDTH - 1; + erase_rect.top = terrain_rects[255].top + 12 - 10; + erase_rect.bottom = erase_rect.top + 12; + paint_pattern(terrain_buttons_gworld,0,erase_rect,1); + erase_rect.left = 2; + erase_rect.right = RIGHT_AREA_WIDTH - 1; + erase_rect.top = terrain_rects[255].bottom + 117; + erase_rect.bottom = RIGHT_AREA_HEIGHT + 6; + paint_pattern(terrain_buttons_gworld,0,erase_rect,1); + + hdc = CreateCompatibleDC(main_dc); + + SetBkMode(hdc,TRANSPARENT); + SelectObject(hdc,small_bold_font); + store_bmp = (HBITMAP)SelectObject(hdc,terrain_buttons_gworld); + + draw_rect.left = terrain_rects[255].left + 20; + draw_rect.top = terrain_rects[255].top; + if (overall_mode < 60) + sprintf((char *) draw_str,"Center: x = %d, y = %d ",(short) cen_x, (short) cen_y); + else { + draw_rect.left = 5; + draw_rect.top = terrain_rects[255].top + 28; + sprintf((char *) draw_str,"Click terrain to edit. ",cen_x,cen_y); + } + + draw_rect.bottom = draw_rect.top + 14; + draw_rect.right = draw_rect.left + 200; + win_draw_string(hdc,draw_rect,draw_str,0,12); + SelectObject(hdc,store_bmp); + + + store_bmp = (HBITMAP)SelectObject(hdc,terrain_buttons_gworld); + if (overall_mode < 60) { + draw_rect.left = 5; + draw_rect.top = terrain_rects[255].bottom + 119; + draw_rect.bottom = draw_rect.top + 14; + draw_rect.right = draw_rect.left + 400; + win_draw_string(hdc,draw_rect,current_string,0,12) ; + + draw_rect.left = RIGHT_AREA_WIDTH / 2; + draw_rect.top = terrain_rects[255].bottom + 119; + draw_rect.bottom = draw_rect.top + 14; + draw_rect.right = draw_rect.left + 200; + win_draw_string(hdc,draw_rect,current_string2,0,12) ; + } + + SelectObject(hdc,store_bmp); + DeleteObject(hdc); + + draw_rect.top = palette_buttons[0][0].top + terrain_rects[255].bottom + 5; + draw_rect.left = palette_buttons[7][0].right + 17; + draw_rect.bottom = draw_rect.top + 36; + draw_rect.right = draw_rect.left + 28; + picture_wanted = scenario.ter_types[current_terrain_type].picture; + + if (overall_mode < 60) { + if (picture_wanted >= 1000) { + source_rect = get_custom_rect(picture_wanted % 1000); + rect_draw_some_item(spec_scen_g,source_rect,terrain_buttons_gworld,draw_rect,0,0); + } + else if (picture_wanted >= 400) { + picture_wanted -= 400; + source_rect.left = 112 * (picture_wanted / 5); + source_rect.right = source_rect.left + 28; + source_rect.top = 36 * (picture_wanted % 5); + source_rect.bottom = source_rect.top + 36; + rect_draw_some_item(anim_gworld,source_rect,terrain_buttons_gworld,draw_rect,0,0); + } + else { + source_rect = get_template_rect(current_terrain_type); + rect_draw_some_item(terrain_gworld[picture_wanted / 50],source_rect, + terrain_buttons_gworld,draw_rect,0,0); + } + } + + draw_rect = terrain_buttons_rect; + OffsetRect(&draw_rect,RIGHT_AREA_UL_X,RIGHT_AREA_UL_Y); + rect_draw_some_item(terrain_buttons_gworld,terrain_buttons_rect, + terrain_buttons_gworld,draw_rect,0,1); +} + +// klugde for speed ...exactly like place location above, but just writes location +void place_just_location() +{ + RECT text_rect = {367,290,384,510}; + char draw_str[256]; + RECT from_rect,draw_rect,source_rect,erase_rect; + short picture_wanted; + HBITMAP store_bmp; + COLORREF y = RGB(128,128,128),red = RGB(255,0,0),white = RGB(255,255,255);//y = RGB(119,119,119); + UINT c; + HBRUSH new_brush; + HDC hdc; + + erase_rect.left = terrain_rects[255].left + 17; + erase_rect.right = RIGHT_AREA_WIDTH - 1; + erase_rect.top = terrain_rects[255].top + 12 - 9; + erase_rect.bottom = erase_rect.top + 12; + paint_pattern(terrain_buttons_gworld,0,erase_rect,1); + + hdc = CreateCompatibleDC(main_dc); + + SetBkMode(hdc,TRANSPARENT); + SelectObject(hdc,small_bold_font); + store_bmp = (HBITMAP)SelectObject(hdc,terrain_buttons_gworld); + + draw_rect.left = terrain_rects[255].left + 20; + draw_rect.top = terrain_rects[255].top; + if (overall_mode < 60) + sprintf((char *) draw_str,"Center: x = %d, y = %d ",cen_x,cen_y); + else { + draw_rect.left = 5; + draw_rect.top = terrain_rects[255].top + 28; + sprintf((char *) draw_str,"Click terrain to edit. ",cen_x,cen_y); + } + + draw_rect.bottom = draw_rect.top + 14; + draw_rect.right = draw_rect.left + 200; + win_draw_string(hdc,draw_rect,draw_str,0,12); + SelectObject(hdc,store_bmp); + + + from_rect = terrain_buttons_rect; + from_rect.top = erase_rect.top; + from_rect.bottom = erase_rect.bottom; + draw_rect = from_rect; + OffsetRect(&draw_rect,RIGHT_AREA_UL_X,RIGHT_AREA_UL_Y); + rect_draw_some_item(terrain_buttons_gworld,from_rect, + terrain_buttons_gworld,draw_rect,0,1); + DeleteObject(hdc); +} + +void set_string(char *string,char *string2) +{ + strcpy((char *)current_string,string); + strcpy((char *)current_string2,string2); + place_location(); +} + +Boolean is_special(short i,short j) +{ + short k; + + if (editing_town == TRUE) + for (k = 0; k < 50; k++) + if ((town.special_locs[k].x == i) && (town.special_locs[k].y == j)) + return TRUE; + if (editing_town == FALSE) + for (k = 0; k < 18; k++) + if ((current_terrain.special_locs[k].x == i) && (current_terrain.special_locs[k].y == j)) + return TRUE; + + return FALSE; +} + +Boolean is_field_type(short i,short j,short field_type) +{ + short k; + + for (k = 0; k < 50; k++) + if ((town.preset_fields[k].field_type == field_type) && + (town.preset_fields[k].field_loc.x == i) && + (town.preset_fields[k].field_loc.y == j)) + return TRUE; + return FALSE; +} + +void make_field_type(short i,short j,short field_type) +{ + short k; + + if (is_field_type(i,j,field_type) == TRUE) + return; + for (k = 0; k < 50; k++) + if (town.preset_fields[k].field_type == 0) { + town.preset_fields[k].field_loc.x = i; + town.preset_fields[k].field_loc.y = j; + town.preset_fields[k].field_type = field_type; + return; + } + give_error("Each town can have at most 50 fields and special effects (webs, barrels, blood stains, etc.). To place more, use the eraser first.","",0); +} + + +void take_field_type(short i,short j,short field_type) +{ + short k; + + for (k = 0; k < 50; k++) + if ((town.preset_fields[k].field_type == field_type) && + (town.preset_fields[k].field_loc.x == i) && + (town.preset_fields[k].field_loc.y == j)) { + town.preset_fields[k].field_type = 0; + return; + } +} + +Boolean is_web(short i,short j) +{ + return is_field_type(i,j,3); + +} +void make_web(short i,short j) +{ + make_field_type(i,j,3); +} +void take_web(short i,short j) +{ + take_field_type(i,j,3); +} + +Boolean is_crate(short i,short j) +{ + return is_field_type(i,j,4); +} +void make_crate(short i,short j) +{ + make_field_type(i,j,4); + +} +void take_crate(short i,short j) +{ + take_field_type(i,j,4); +} + +Boolean is_barrel(short i,short j) +{ + return is_field_type(i,j,5); +} +void make_barrel(short i,short j) +{ + make_field_type(i,j,5); +} +void take_barrel(short i,short j) +{ + take_field_type(i,j,5); +} + +Boolean is_fire_barrier(short i,short j) +{ + return is_field_type(i,j,6); +} +void make_fire_barrier(short i,short j) +{ + make_field_type(i,j,6); +} +void take_fire_barrier(short i,short j) +{ + take_field_type(i,j,6); +} + +Boolean is_force_barrier(short i,short j) +{ + return is_field_type(i,j,7); +} +void make_force_barrier(short i,short j) +{ + make_field_type(i,j,7); +} +void take_force_barrier(short i,short j) +{ + take_field_type(i,j,7); + +} + +Boolean is_sfx(short i,short j,short type) +{ + return is_field_type(i,j,type + 14); +} +void make_sfx(short i,short j,short type) +{ + make_field_type(i,j,type + 14); +} +void take_sfx(short i,short j,short type) +{ + take_field_type(i,j,type + 14); +} + + +Boolean is_quickfire(short i,short j) +{ + return is_field_type(i,j,8); +} +void make_quickfire(short i,short j) +{ + make_field_type(i,j,8); +} +void take_quickfire(short i,short j) +{ + take_field_type(i,j,8); +} + +Boolean container_there(location l) +{ + + unsigned char ter; + + if (editing_town == FALSE) + return FALSE; + if (scenario.ter_types[t_d.terrain[l.x][l.y]].special == 14) + return TRUE; + if (is_barrel(l.x,l.y) == TRUE) + return TRUE; + if (is_crate(l.x,l.y) == TRUE) + return TRUE; + return 0; +} + + +void char_win_draw_string(HDC dest_window,RECT dest_rect,char *str,short mode,short line_height) +{ + char store_s[256]; + + strcpy((char *) store_s,str); + win_draw_string( dest_window, dest_rect,store_s, mode, line_height); + +} + +// mode: 0 - align up and left, 1 - center on one line +// str is a c string, 256 characters +// uses current font +void win_draw_string(HDC dest_hdc,RECT dest_rect,char *str,short mode,short line_height) +{ + short i; + +// this will need formatting for '|' line breaks + + for (i = 0; i < 256; i++) { + if (str[i] == '|') + str[i] = 13; + if (str[i] == '_') + str[i] = 34; + } + // if dest is main window, add ulx, uly + if (dest_hdc == main_dc) + OffsetRect(&dest_rect,ulx,uly); + + switch (mode) { + case 0: + dest_rect.bottom += 6; + DrawText(dest_hdc,str,strlen((char *)str),&dest_rect,DT_LEFT | DT_WORDBREAK); break; + case 1: + dest_rect.bottom += 6; dest_rect.top -= 6; + DrawText(dest_hdc,str,strlen((char *)str),&dest_rect, + DT_CENTER | DT_VCENTER | DT_NOCLIP | DT_SINGLELINE); break; + case 2: case 3: + dest_rect.bottom += 6; dest_rect.top -= 6; + DrawText(dest_hdc,str,strlen((char *)str),&dest_rect, + DT_LEFT | DT_VCENTER | DT_NOCLIP | DT_SINGLELINE); break; + } + // not yet done adjusts for 1, 2, 3 + +} + +// Note ... this expects a str len of at most 256 and +// len_array pointing to a 256 long array of shorts +void MeasureText(short str_len,char *str, short *len_array,HDC hdc) +{ + short text_len[257]; + short total_width = 0,i,len; + char p_str[257]; + SIZE val_returned; + char *store_array; + short *store2; + + store_array = (char *) len_array; + //text_len = len_array; + for (i = 0; i < 256; i++) + text_len[i] = 0; + for (i = 1; i < str_len; i++) { + strncpy(p_str,str,i); + p_str[i] = 0; + GetTextExtentPoint32(hdc,p_str,i,&val_returned); + text_len[i] = val_returned.cx; + } + for (i = 0; i < 256; i++) { + store2 = (short *) store_array; + *store2 = text_len[i]; + store_array += 2; + } + } + + +void GetIndString(char *str,short i, short j) { + UINT resnum = 0,len; + short k; + + resnum = i * 300 + j; + + len = LoadString(store_hInstance,resnum,str,256); + if (len == 0) { + sprintf(str,""); + return; + } + for (k = 0; k < 256; k++) { + if (str[k] == '|') + str[k] = 13; + if (str[k] == '_') + str[k] = 34; + } +} + +void get_str(char *str,short i, short j) +{ + if (i == -1) { + strcpy((char *) str,scen_item_list.monst_names[j]); + return; + } + if (i == -2) { + strcpy((char *) str,scen_item_list.scen_items[j].full_name); + return; + } + if (i == -3) { + strcpy((char *) str,button_strs[available_dlog_buttons[j]]); + return; + } + if (i == -4) { + strcpy((char *) str,scen_item_list.ter_names[j]); + return; + } + if (i == -5) { + get_str(str,40,j * 7 + 1); + return; + } + GetIndString(str, i, j); +} + + +void undo_clip(HDC hdc) +{ + // RECT overall_rect = {0,0,530,435}; + HRGN rgn; + + rgn = CreateRectRgn(0,0,5000,5000); + SelectClipRgn(hdc,rgn); + DeleteObject(rgn); +} + +void ClipRect(HDC hdc,RECT *rect) +{ + HRGN rgn; + RECT rect2; + + rect2 = *rect; +// OffsetRect(&rect2,ulx,uly); + + rgn = CreateRectRgn(rect2.left,rect2.top,rect2.right,rect2.bottom); + SelectClipRgn(hdc,rgn); + DeleteObject(rgn); +} + +void FlushEvents(short mode) +// mode... 0 - keystrokes 1 - mouse presses 2 - both +{ + MSG msg; + + if ((mode == 0) || (mode == 2)) { + while ((PeekMessage(&msg, mainPtr, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE)) != 0) + ; + } + if ((mode == 1) || (mode == 2)) { + while ((PeekMessage(&msg, mainPtr, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE)) != 0) + ; + } + +} + +RECT get_custom_rect (short which_rect) //// +{ + RECT store_rect = {0,0,28,36}; + + OffsetRect(&store_rect,28 * (which_rect % 10),36 * (which_rect / 10)); + return store_rect; +} diff --git a/Win32/Scenarios Editor/GRAPHICS.H b/Win32/Scenarios Editor/GRAPHICS.H new file mode 100644 index 00000000..160c819e --- /dev/null +++ b/Win32/Scenarios Editor/GRAPHICS.H @@ -0,0 +1,63 @@ +RECT get_custom_rect (short which_rect); +void Draw_Some_Item ( GWorldPtr src_gworld,RECT src_rect,GWorldPtr targ_gworld,location target, +char masked,short main_win) ; +void Set_up_win (); +void run_startup_g(); +void load_main_screen(); +void draw_main_screen(); +void redraw_screen(); +void draw_lb(); +void draw_lb_slot (short which,short mode) ; +void draw_rb(); +void draw_rb_slot (short which,short mode) ; +void set_up_terrain_buttons(); +void draw_terrain(); +void draw_monsts(HDC hdc); +RECT get_item_template_rect (short type_wanted); +void draw_items(HDC hdc); +void redraw_selected_ter(); +void draw_one_terrain_spot (short i,short j,unsigned char terrain_to_draw); +void draw_one_tiny_terrain_spot (short i,short j,unsigned char terrain_to_draw,HDC hdc); + +RECT get_template_rect (unsigned char type_wanted); +void draw_frames(); +void place_location(); +void place_just_location(); +void set_string(char *string,char *string2); +void undo_clip(); +Boolean is_special(short i,short j); +Boolean is_field_type(short i,short j,short field_type); +void make_field_type(short i,short j,short field_type); +void take_field_type(short i,short j,short field_type); +Boolean is_web(short i,short j); +void make_web(short i,short j); +void take_web(short i,short j); +Boolean is_crate(short i,short j); +void make_crate(short i,short j); +void take_crate(short i,short j); +Boolean is_barrel(short i,short j); +void make_barrel(short i,short j); +void take_barrel(short i,short j); +Boolean is_fire_barrier(short i,short j); +void make_fire_barrier(short i,short j); +void take_fire_barrier(short i,short j); +Boolean is_force_barrier(short i,short j); +void make_force_barrier(short i,short j); +void take_force_barrier(short i,short j); +Boolean is_sfx(short i,short j,short type); +void make_sfx(short i,short j,short type); +void take_sfx(short i,short j,short type); +Boolean is_quickfire(short i,short j); +void make_quickfire(short i,short j); +void take_quickfire(short i,short j); +Boolean container_there(location l); +void char_win_draw_string(HDC dest_window,RECT dest_rect,char *str,short mode,short line_height); +void win_draw_string(HDC dest_hdc,RECT dest_rect,char *str,short mode,short line_height); +void get_str(char *str,short i, short j); +void MeasureText(short str_len,char *str, short *len_array,HDC hdc); +void GetIndString(char *str,short i, short j); +void undo_clip(HDC hdc); +void ClipRect(HDC hdc,RECT *rect); +void FlushEvents(short mode); +void discard_graphics(); + diff --git a/Win32/Scenarios Editor/GRAPHUTL.CPP b/Win32/Scenarios Editor/GRAPHUTL.CPP new file mode 100644 index 00000000..46b2963c --- /dev/null +++ b/Win32/Scenarios Editor/GRAPHUTL.CPP @@ -0,0 +1,365 @@ +#define xmin(a,b) ((a) < (b) ? (a) : (b)) + +#include +#include +#include +#include +#include +#include +#include "global.h" + +#include "KEYDLGS.h" +#include "edsound.h" + +#include "graphutl.h" + +extern HWND mainPtr; + + +extern HDC main_dc,main_dc2,main_dc3; +extern short ulx,uly; +extern HBITMAP mixed_gworld,dialog_pattern_gworld,pattern_gworld,status_pattern_gworld; +extern Boolean suppress_load_file_name; + +extern char scen_strs[160][256]; +extern char scen_strs2[110][256]; +extern char talk_strs[170][256]; +extern char town_strs[180][256]; +extern char file_path_name[256]; +extern char szFileName[128]; + + +BOOL pal_ok = FALSE; +Boolean syscolors_stored = FALSE; + int elements[5] = {COLOR_ACTIVEBORDER,COLOR_ACTIVECAPTION, + COLOR_WINDOWFRAME,COLOR_SCROLLBAR,COLOR_BTNFACE}; + COLORREF store_element_colors[5]; +short dlog_pat_placed = 0; +short current_pattern = -1; + +/*void get_filename(char * scen_name){ + + char buffer[128]; + int i=strlen(szFileName),j=0; + + while(szFileName[i] != '\\') + i--; + + while(szFileName[i+j] != '.'){ + buffer[j]=szFileName[i+j+1]; + j++; + } + buffer[j]='b'; + buffer[j+1]='m'; + buffer[j+2]='p'; + buffer[j+3]='\0'; + sprintf(scen_name,"scenarios/%s",buffer); +}*/ + +HBITMAP load_pict(short pict_num) +{ + HBITMAP got_bitmap; + HDC model_hdc; + + model_hdc = main_dc; + + switch(pict_num) { + case 700: got_bitmap = ReadBMP("Images/STATAREA.BMP"); break; + case 701: got_bitmap = ReadBMP("Images/STATAREA.BMP"); break; + case 702: got_bitmap = ReadBMP("Images/STATAREA.BMP"); break; + case 703: got_bitmap = ReadBMP("Images/TEXTBAR.BMP"); break; + case 704: got_bitmap = ReadBMP("Images/BUTTONS.BMP"); break; + case 705: got_bitmap = ReadBMP("Images/TERSCRN.BMP"); break; + case 800: got_bitmap = ReadBMP("Images/TER1.BMP"); break; + case 801: got_bitmap = ReadBMP("Images/TER2.BMP"); break; + case 802: got_bitmap = ReadBMP("Images/TER3.BMP"); break; + case 803: got_bitmap = ReadBMP("Images/TER4.BMP"); break; + case 804: got_bitmap = ReadBMP("Images/TER5.BMP"); break; + case 805: got_bitmap = ReadBMP("Images/TER6.BMP"); break; + case 820: got_bitmap = ReadBMP("Images/TERANIM.BMP"); break; + case 821: got_bitmap = ReadBMP("Images/FIELDS.BMP"); break; + case 830: got_bitmap = ReadBMP("Images/STARTUP.BMP"); break; + case 850: got_bitmap = ReadBMP("Images/DLOGPICS.BMP"); break; + case 851: got_bitmap = ReadBMP("Images/SCENPICS.BMP"); break; + case 860: got_bitmap = ReadBMP("Images/TALKPORT.BMP"); break; + case 880: got_bitmap = ReadBMP("Images/MISSILES.BMP"); break; + case 900: got_bitmap = ReadBMP("Images/TINYOBJ.BMP"); break; + case 901: got_bitmap = ReadBMP("Images/OBJECTS.BMP"); break; + case 902: got_bitmap = ReadBMP("Images/PCS.BMP"); break; + case 905: got_bitmap = ReadBMP("Images/PCS.BMP"); break; + case 903: got_bitmap = ReadBMP("Images/MIXED.BMP"); break; + case 904: got_bitmap = ReadBMP("Images/MIXED.BMP"); break; + case 906: got_bitmap = ReadBMP("Images/EDBTNS.BMP"); break; + case 910: got_bitmap = ReadBMP("Images/BIGSCEN.BMP"); break; + case 911: got_bitmap = ReadBMP("Images/BIGSCEN.BMP"); break; + case 912: got_bitmap = ReadBMP("Images/BIGSCEN.BMP"); break; + case 1100: case 1200: got_bitmap = ReadBMP("Images/MONST1.BMP"); break; + case 1101: case 1201: got_bitmap = ReadBMP("Images/MONST2.BMP"); break; + case 1102: case 1202: got_bitmap = ReadBMP("Images/MONST3.BMP"); break; + case 1103: case 1203: got_bitmap = ReadBMP("Images/MONST4.BMP"); break; + case 1104: case 1204: got_bitmap = ReadBMP("Images/MONST5.BMP"); break; + case 1105: case 1205: got_bitmap = ReadBMP("Images/MONST6.BMP"); break; + case 1106: case 1206: got_bitmap = ReadBMP("Images/MONST7.BMP"); break; + case 1107: case 1207: got_bitmap = ReadBMP("Images/MONST8.BMP"); break; + case 1108: case 1208: got_bitmap = ReadBMP("Images/MONST9.BMP"); break; + case 1109: case 1209: got_bitmap = ReadBMP("Images/MONST10.BMP"); break; + case 1400: got_bitmap = ReadBMP("Images/STSCICON.BMP"); break; + case 1401: got_bitmap = ReadBMP("Images/HELPPICS.BMP"); break; + case 1402: got_bitmap = ReadBMP("Images/APPIC.BMP"); break; + case 1500: case 1501: case 1502: case 1503: case 1504: case 1505: case 1506: case 1507: + got_bitmap = ReadBMP("Images/BIGMAPS.BMP"); break; + case 2000: got_bitmap = ReadBMP("Images/DLOGBTNS.BMP"); break; + case 3000: got_bitmap = ReadBMP("Images/START.BMP"); break; + case 3001: got_bitmap = ReadBMP("Images/SPIDLOGO.BMP"); break; + case 3002: got_bitmap = ReadBMP("Images/EDSTART.BMP"); break; + case 5000: got_bitmap = ReadBMP("Images/E3EDTITL.BMP"); break; + + default: got_bitmap = NULL; + } + return got_bitmap; +} + +void rect_draw_some_item(HBITMAP src,RECT src_rect,HBITMAP dest,RECT dest_rect, + short trans, short main_win) { + HDC hdcMem,hdcMem2,hdcMem3,destDC,storeDC; + HBITMAP transbmp; + COLORREF white = RGB(255,255,255),black = RGB(0,0,0),oldcolor; + RECT debug = {0,0,200,20}; + HBRUSH hbrush,old_brush; + COLORREF x = RGB(17,17,17); + HBITMAP store,store2; + Boolean dlog_draw = FALSE; + + main_dc2 = CreateCompatibleDC(main_dc); + SetMapMode(main_dc2,GetMapMode((HDC)mainPtr)); + main_dc3 = CreateCompatibleDC(main_dc); + SetMapMode(main_dc3,GetMapMode((HDC)mainPtr)); + SetStretchBltMode(main_dc2,STRETCH_DELETESCANS); + SetStretchBltMode(main_dc3,STRETCH_DELETESCANS); + + if (main_win == 2) { + destDC = (HDC) dest; + main_win = 1; + dlog_draw = TRUE; + hdcMem = CreateCompatibleDC(destDC); + SelectObject(hdcMem, src); + SetMapMode(hdcMem,GetMapMode((HDC)mainPtr)); + SetStretchBltMode(hdcMem,STRETCH_DELETESCANS); + } + else { + destDC = main_dc; + hdcMem = main_dc2; + store = (HBITMAP)SelectObject(hdcMem,src); + } + + + SetStretchBltMode(destDC,STRETCH_DELETESCANS); + SetStretchBltMode(hdcMem,STRETCH_DELETESCANS); + if (trans != 1) { + if (main_win == 0) { // Not transparent, into bitmap + hdcMem2 = main_dc3; + store2 = (HBITMAP)SelectObject(hdcMem2, dest); + + SetStretchBltMode(hdcMem2,STRETCH_DELETESCANS); + + StretchBlt(hdcMem2,dest_rect.left,dest_rect.top,dest_rect.right - dest_rect.left, + dest_rect.bottom - dest_rect.top, + hdcMem,src_rect.left,src_rect.top,src_rect.right - src_rect.left, + src_rect.bottom - src_rect.top,(trans >= 0) ? SRCCOPY : SRCAND); + SelectObject(hdcMem2,store2); + } + + else { // Not transparent, onto screen + if (trans == 2) { + hbrush = CreateSolidBrush(x); + old_brush = (HBRUSH)SelectObject(destDC,hbrush); + //SelectObject(hdcMem,hbrush); + } + if (dlog_draw == FALSE) + SetViewportOrgEx(destDC,ulx,uly,NULL); + + SetStretchBltMode(destDC,STRETCH_DELETESCANS); + SetStretchBltMode(hdcMem,STRETCH_DELETESCANS); + StretchBlt(destDC,dest_rect.left,dest_rect.top,dest_rect.right - dest_rect.left, + dest_rect.bottom - dest_rect.top, + hdcMem,src_rect.left,src_rect.top,src_rect.right - src_rect.left, + src_rect.bottom - src_rect.top,(trans == 0) ? SRCCOPY : MERGECOPY); + if (trans == 2) { + SelectObject(destDC,old_brush); + if (DeleteObject(hbrush) == 0) + play_sound(1); + } + if (dlog_draw == FALSE) + SetViewportOrgEx(destDC,0,0,NULL); + + + } + } // end of non-transparent draws + else { + if (main_win == 0) { + hdcMem3 = CreateCompatibleDC(hdcMem); + SelectObject(hdcMem3, dest); + SetMapMode(hdcMem3,GetMapMode((HDC)mainPtr)); + transbmp = CreateBitmap(src_rect.right - src_rect.left, + src_rect.bottom - src_rect.top,1,1,NULL); + hdcMem2 = CreateCompatibleDC(destDC); + SelectObject(hdcMem2, transbmp); + oldcolor = SetBkColor(hdcMem, white); + StretchBlt(hdcMem2,0,0,dest_rect.right - dest_rect.left, + dest_rect.bottom - dest_rect.top, + hdcMem,src_rect.left,src_rect.top,src_rect.right - src_rect.left, + src_rect.bottom - src_rect.top,SRCCOPY); + SetBkColor(hdcMem, oldcolor); + + StretchBlt(hdcMem3,dest_rect.left,dest_rect.top,dest_rect.right - dest_rect.left, + dest_rect.bottom - dest_rect.top, + hdcMem,src_rect.left,src_rect.top,src_rect.right - src_rect.left, + src_rect.bottom - src_rect.top,SRCINVERT); + StretchBlt(hdcMem3,dest_rect.left,dest_rect.top,dest_rect.right - dest_rect.left, + dest_rect.bottom - dest_rect.top, + hdcMem2,0,0,src_rect.right - src_rect.left, + src_rect.bottom - src_rect.top,SRCAND); + StretchBlt(hdcMem3,dest_rect.left,dest_rect.top,dest_rect.right - dest_rect.left, + dest_rect.bottom - dest_rect.top, + hdcMem,src_rect.left,src_rect.top,src_rect.right - src_rect.left, + src_rect.bottom - src_rect.top,SRCINVERT); + DeleteDC(hdcMem3); + DeleteDC(hdcMem2); + + DeleteObject(transbmp); + } + else { + if (dlog_draw == FALSE) + SetViewportOrgEx(destDC,ulx,uly,NULL); + transbmp = CreateBitmap(src_rect.right - src_rect.left, + src_rect.bottom - src_rect.top,1,1,NULL); + hdcMem2 = CreateCompatibleDC(destDC); + SelectObject(hdcMem2, transbmp); + oldcolor = SetBkColor(hdcMem, white); + StretchBlt(hdcMem2,0,0,dest_rect.right - dest_rect.left, + dest_rect.bottom - dest_rect.top, + hdcMem,src_rect.left,src_rect.top,src_rect.right - src_rect.left, + src_rect.bottom - src_rect.top,SRCCOPY); + + SetBkColor(hdcMem, oldcolor); + + StretchBlt(destDC,dest_rect.left,dest_rect.top,dest_rect.right - dest_rect.left, + dest_rect.bottom - dest_rect.top, + hdcMem,src_rect.left,src_rect.top,src_rect.right - src_rect.left, + src_rect.bottom - src_rect.top,SRCINVERT); + StretchBlt(destDC,dest_rect.left,dest_rect.top,dest_rect.right - dest_rect.left, + dest_rect.bottom - dest_rect.top, + hdcMem2,0,0,src_rect.right - src_rect.left, + src_rect.bottom - src_rect.top,SRCAND); + StretchBlt(destDC,dest_rect.left,dest_rect.top,dest_rect.right - dest_rect.left, + dest_rect.bottom - dest_rect.top, + hdcMem,src_rect.left,src_rect.top,src_rect.right - src_rect.left, + src_rect.bottom - src_rect.top,SRCINVERT); + if (dlog_draw == FALSE) + SetViewportOrgEx(destDC,0,0,NULL); + DeleteDC(hdcMem2); + + DeleteObject(transbmp); + + + } + } + if (dlog_draw == TRUE) + DeleteDC(hdcMem); + else SelectObject(hdcMem,store); + DeleteDC(main_dc2); + DeleteDC(main_dc3); +} + + void fry_dc(HWND hwnd,HDC dc) { + if (ReleaseDC(hwnd,dc) == 0) + // add_string_to_buf("xx"); + PostQuitMessage(0); + } + +void DisposeGWorld(HBITMAP bitmap) +{ + DeleteObject(bitmap); +} + +// which_mode is 0 ... dest is a bitmap +// is 1 ... ignore dest ... paint on mainPtr +// is 2 ... dest is a dialog, use the dialog pattern +// both pattern gworlds are 192 x 256 +void paint_pattern(HBITMAP dest,short which_mode,RECT dest_rect,short which_pattern) +{ + HBITMAP source_pat; + RECT pattern_source = {32,168,96,232}, pat_dest_orig = {0,0,64,64},pat_dest; + short i,j; + + RECT draw_from_orig = {0,0,192,256},draw_from,draw_to; + short store_ulx,store_uly; + + if (which_mode == 1) + OffsetRect(&dest_rect,ulx, uly); + else if (which_mode == 3) + which_mode = 1; + if (which_mode == 2) { + source_pat = dialog_pattern_gworld; + if (dlog_pat_placed == 0) { + dlog_pat_placed = 1; + OffsetRect(&pattern_source, 64 * 2,0); + for (i = 0; i < 3; i++) + for (j = 0; j < 4; j++) { + pat_dest = pat_dest_orig; + OffsetRect(&pat_dest,64 * i, 64 * j); + rect_draw_some_item(mixed_gworld,pattern_source, + dialog_pattern_gworld,pat_dest,0,0); + } + } + } + else { + source_pat = pattern_gworld; + if (current_pattern != which_pattern) { + current_pattern = which_pattern; + OffsetRect(&pattern_source, 64 * (which_pattern % 5), + 64 * (which_pattern / 5)); + for (i = 0; i < 3; i++) + for (j = 0; j < 4; j++) { + pat_dest = pat_dest_orig; + OffsetRect(&pat_dest,64 * i, 64 * j); + rect_draw_some_item(mixed_gworld,pattern_source, + pattern_gworld,pat_dest,0,0); + } + } + } + + // now patterns are loaded, so have fun + // first nullify ul shifting + store_ulx = ulx; + store_uly = uly; + ulx = uly = 0; + for (i = 0; i < (dest_rect.right / 192) + 1; i++) + for (j = 0; j < (dest_rect.bottom / 256) + 1; j++) { + draw_to = draw_from_orig; + OffsetRect(&draw_to,192 * i, 256 * j); + IntersectRect(&draw_to,&draw_to,&dest_rect); + if (draw_to.right != 0) { + draw_from = draw_to; + OffsetRect(&draw_from, -192 * i, -256 * j); + switch (which_mode) { + case 0: + rect_draw_some_item(source_pat,draw_from, + dest,draw_to,0,0); break; + case 1: + rect_draw_some_item(source_pat,draw_from, + source_pat,draw_to,0,1); break; + case 2: + rect_draw_some_item(source_pat,draw_from, + dest,draw_to,0,2); break; + } + } + } + ulx = store_ulx; + uly = store_uly; +} + +HBITMAP ReadBMP(char * fileName) +{ + return (HBITMAP) LoadImage(0, fileName, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE); +} diff --git a/Win32/Scenarios Editor/GRAPHUTL.H b/Win32/Scenarios Editor/GRAPHUTL.H new file mode 100644 index 00000000..a9c58562 --- /dev/null +++ b/Win32/Scenarios Editor/GRAPHUTL.H @@ -0,0 +1,8 @@ +HBITMAP load_pict(short pict_num); +void rect_draw_some_item(HBITMAP src,RECT src_rect,HBITMAP dest,RECT dest_rect, + short trans, short main_win); +void fry_dc(HWND hwnd,HDC dc); +HBITMAP load_pict(short pict_num,HDC model_hdc); +void DisposeGWorld(HBITMAP bitmap); +void paint_pattern(HBITMAP dest,short which_mode,RECT dest_rect,short which_pattern); +HBITMAP ReadBMP(char * fileName); diff --git a/Win32/Scenarios Editor/KEYDLGS.CPP b/Win32/Scenarios Editor/KEYDLGS.CPP new file mode 100644 index 00000000..4190b3e4 --- /dev/null +++ b/Win32/Scenarios Editor/KEYDLGS.CPP @@ -0,0 +1,1322 @@ +#include +#include "string.h" +#include "stdio.h" +#include "Global.h" +#include "graphics.h" +#include "dlogtool.h" +#include "keydlgs.h" +#include "scenario.h" +#include "edsound.h" + +extern short cen_x, cen_y, overall_mode; +extern Boolean mouse_button_held,dialog_not_toast; +extern short cur_viewing_mode; +extern town_record_type town; +extern big_tr_type t_d; +extern short town_type; // 0 - big 1 - ave 2 - small +extern short max_dim[3],mode_count,to_create; +extern unsigned char template_terrain[64][64]; +extern short_item_record_type item_list[400]; +extern scenario_data_type scenario; +extern special_node_type null_spec_node; +extern talking_node_type null_talk_node; +extern piles_of_stuff_dumping_type *data_store; +extern outdoor_record_type current_terrain; +extern HINSTANCE store_hInstance; +extern BOOL do_choose_anim; + +extern char scen_strs[160][256]; +extern char scen_strs2[110][256]; +extern char talk_strs[170][256]; +extern char town_strs[180][256]; + +extern short dialog_answer; +short store_which_string_dlog; +short store_first_g ; +short store_last_g ; +short store_cur_pic ; +short which_page ; +short store_res_list; +short store_first_t ; +short store_last_t ; +short store_cur_t ; +short store_which_str ; +short store_str_mode ; +short store_which_mode,*store_str1,*store_str2; +short store_which_node,store_spec_str_mode,store_spec_mode; +short last_node[256]; +special_node_type store_spec_node; +short num_specs[3] = {256,60,100}; +HCURSOR cursors[8] = {NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL}; +short current_cursor = 0; + + short ex1a_choose[12] = {19,50,55,56,57,58,59,60,182,229,-1,-1}; + short ex2a_choose[18] = {55,56,57,-1,-1, -1,135,136,171,172, 181,192,226,-1,-1, -1,-1,-1}; + short ex1b_choose[40] = {13,20,55,56,57,24,-1,-1,80,130, 131,132,133,137,138,140,141,142,143,145,146,147,148,149,150,151,152,153,154,184, 188,195,186,-1,-1,-1,-1,-1,-1,155}; +short ex2b_choose[20] = {19,50,55,56,57,58,59,60,130,134,135,136,139,144,154,-1,-1,-1,-1,-1}; + +char edit_spec_stuff_done_mess[256] = { + 0,1,1,0,0,0,1,0,0,0, + 0,0,0,0,0,0,0,0,0,0, + 0,0,3,1,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0, + 1,1,1,1,1,1,1,1,1,1, // 50 + 1,1,1,1,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0, // 100 + 0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0, + 1,0,0,0,1,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,1,0,0,0,0, // 150 + 0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0, + 2,2,2,2,2,2,2,2,2,2, // 200 + 7,8,4,0,5,6,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0}; +char edit_spec_mess_mess[256] = { + 0,1,1,1,0,1,1,0,0,0, + 0,1,1,0,0,0,0,1,1,1, + 1,0,0,0,0,1,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0, + 1,1,0,0,1,4,4,4,5,5, // 50 + 5,1,1,1,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0, + 1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,0,0,0, // 100 + 0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0, // 150 + 0,0,0,0,0,0,0,0,0,0, + 1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,0,0,0,0,2,2, + 2,1,1,1,1,1,0,0,0,0, + 1,1,1,1,1,1,1,1,1,1, // 200 + 1,1,1,1,1,1,1,1,1,0, + 0,0,0,0,0,0,1,1,1,3, + 0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0}; +char edit_pict_mess[256] = { + 0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,1,2,3,1,2, // 50 + 3,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,4,0, + 0,0,0,0,0,0,0,0,0,0, // 100 + 0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,5,0,0,0,0,0, // 150 + 0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,6,0,0,0, + 0,0,0,0,0,0,0,0,2,1, + 0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0, // 200 + 0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0}; +char edit_jumpto_mess[256] = { + 0,0,0,0,0,0,0,1,1,1, + 1,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,4,4,4,0,0, // 50 + 0,0,0,2,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0, // 100 + 0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0, + 3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,0,0,0,0,0, // 150 + 0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0, // 200 + 0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0}; + + +void fancy_choice_dialog_event_filter (short item_hit) +{ + dialog_not_toast = FALSE; + dialog_answer = item_hit; +} + +short fancy_choice_dialog(short which_dlog,short parent) +// ignore parent in Mac version +{ + short item_hit,i,store_dialog_answer; + char temp_str[256]; + + store_dialog_answer = dialog_answer; + //make_cursor_sword(); + + cd_create_dialog_parent_num(which_dlog,parent); + + + while (dialog_not_toast) + ModalDialog(); + + cd_kill_dialog(which_dlog,0); + + + i = dialog_answer; + dialog_answer = store_dialog_answer; + + return i; +} + + + +//cre = check range error +Boolean cre(short val,short min,short max,char *text1, char *text2,short parent_num) +{ + if ((val < min) || (val > max)) { + give_error(text1,text2,parent_num); + return TRUE; + } + return FALSE; +} + +void give_error(char *text1, char *text2,short parent_num) +{ + display_strings(text1,text2,"Error!",57,716,parent_num); +} + +void display_strings_event_filter (short item_hit) +{ + short i; + Boolean had1 = FALSE, had2 = FALSE; + + switch (item_hit) { + case 1: + dialog_not_toast = FALSE; + break; + + } +} + +void display_strings(char *text1, char *text2, + char *title,short sound_num,short graphic_num,short parent_num) +{ + + short item_hit; + char sign_text[256]; + location view_loc; + Boolean sound_done = FALSE; + + //make_cursor_sword(); + + if ((text1 == NULL) && (text2 == NULL)) + return; + store_which_string_dlog = 970; + if (strlen(title) > 0) + store_which_string_dlog += 2; + if ((text2 != NULL) && (text2[0] != 0)) + store_which_string_dlog++; + cd_create_dialog_parent_num(store_which_string_dlog,parent_num); + + csp(store_which_string_dlog,store_which_string_dlog,graphic_num); + + csit(store_which_string_dlog,4,(char *) text1); + if (text2 != NULL) { + csit(store_which_string_dlog,5,(char *) text2); + } + if (strlen(title) > 0) + csit(store_which_string_dlog,6,title); + csp(store_which_string_dlog,3,graphic_num); + + while (dialog_not_toast) + ModalDialog(); + + cd_kill_dialog(store_which_string_dlog,0); +} + +void choose_graphic_event_filter (short item_hit) +{ + short i; + Boolean had1 = FALSE, had2 = FALSE; + + switch (item_hit) { + case 1: + dialog_answer = store_cur_pic; + dialog_not_toast = FALSE; + break; + case 4: + dialog_answer = -1; + dialog_not_toast = FALSE; + break; + case 78: + if (which_page == 0) + which_page = (store_last_g - store_first_g) / 36; + else which_page--; + put_choice_pics(); + break; + case 79: + if (which_page == (store_last_g - store_first_g) / 36) + which_page = 0; + else which_page++; + put_choice_pics(); + break; + default: + if ((item_hit >= 5) && (item_hit <= 40)) { + store_cur_pic = 36 * which_page + item_hit - 5 + store_first_g; + for (i = 5; i <= 40; i++) + cd_set_led(819,i,(i == item_hit) ? 1 : 0); + } + break; + } +} + +void put_choice_pics() +{ + short i; + + for (i = 0; i < 36; i++) { + if (store_first_g + which_page * 36 + i > store_last_g) { + csp(819,41 + i,950); + cd_activate_item(819,5 + i,0); + } + else { + csp(819,41 + i,store_first_g + 36 * which_page + i); + cd_activate_item(819,5 + i,1); + } + if (which_page * 36 + i == store_cur_pic - store_first_g) + cd_set_led(819,5 + i,1); + else cd_set_led(819,5 + i,0); + } + +} + +short choose_graphic(short first_g,short last_g,short cur_choice,short parent_num) +{ + + short item_hit; + location view_loc; + Boolean sound_done = FALSE; + + //make_cursor_sword(); + + store_first_g = first_g; + store_last_g = last_g; + if ((cur_choice >= first_g) && (cur_choice <= last_g)) + store_cur_pic = cur_choice; + else store_cur_pic = first_g; + which_page = (store_cur_pic - store_first_g) / 36; + + cd_create_dialog_parent_num(819,parent_num); + + if (last_g - first_g < 36) { + cd_activate_item(819,79,0); + cd_activate_item(819,78,0); + } + put_choice_pics(); + + while (dialog_not_toast) + ModalDialog(); + + cd_kill_dialog(819,0); + + do_choose_anim = FALSE; + + return dialog_answer; +} + +void choose_text_res_event_filter (short item_hit) +{ + short i; + Boolean had1 = FALSE, had2 = FALSE; + + switch (item_hit) { + case 2: + dialog_answer = store_cur_t; + dialog_not_toast = FALSE; + break; + case 7: + dialog_answer = -1; + dialog_not_toast = FALSE; + break; + case 5: + if (which_page == 0) + which_page = (store_last_t - store_first_t) / 40; + else which_page--; + put_text_res(); + break; + case 6: + if (which_page == (store_last_t - store_first_t) / 40) + which_page = 0; + else which_page++; + put_text_res(); + break; + default: + if ((item_hit >= 9) && (item_hit <= 87)) { + store_cur_t = 40 * which_page + (item_hit - 9) / 2 + store_first_t; + for (i = 9; i <= 87; i += 2) + cd_set_led(820,i,(i == item_hit) ? 1 : 0); + } + break; + } +} + +void put_text_res() +{ + short item_hit,i; + char str[256]; + + for (i = 0; i < 40; i++) { + if (store_first_t + which_page * 40 + i > store_last_t) { + csit(820,8 + i * 2,""); + cd_activate_item(820,9 + i * 2,0); + } + else { + get_str(str,store_res_list,store_first_t + 40 * which_page + i); + csit(820,8 + i * 2,(char *) str); + cd_activate_item(820,9 + i * 2,1); + } + if (which_page * 40 + i == store_cur_t - store_first_t) + cd_set_led(820,9 + i * 2,1); + else cd_set_led(820,9 + i * 2,0); + } + +} + +short choose_text_res(short res_list,short first_t,short last_t,short cur_choice,short parent_num,char *title) +{ + + short item_hit; + char sign_text[256]; + location view_loc; + Boolean sound_done = FALSE; + + //make_cursor_sword(); + store_res_list = res_list; + store_first_t = first_t; + store_last_t = last_t; + if ((cur_choice >= first_t) && (cur_choice <= last_t)) + store_cur_t = cur_choice; + else store_cur_t = first_t; + which_page = (store_cur_t - store_first_t) / 40; + + cd_create_dialog_parent_num(820,parent_num); + + csit(820,4,title); + if (last_t - first_t < 40) { + cd_activate_item(820,5,0); + cd_activate_item(820,6,0); + } + put_text_res(); + + while (dialog_not_toast) + ModalDialog(); + + cd_kill_dialog(820,0); + + return dialog_answer; +} + +void edit_text_event_filter (short item_hit) +{ + char str[256]; + short i; + short num_strs[3] = {260,108,140}; + + if (store_str_mode == 0) + CDGT(816,2,(store_which_str >= 160) ? + scen_strs2[store_which_str - 160] : scen_strs[store_which_str]); + if (store_str_mode == 1) + CDGT(816,2,data_store->out_strs[store_which_str]); + if (store_str_mode == 2) + CDGT(816,2,town_strs[store_which_str]); + switch (item_hit) { + case 9: + dialog_not_toast = FALSE; + break; + + case 4: + case 3: + if (item_hit == 3) + store_which_str--; + else store_which_str++; + if (store_which_str < 0) store_which_str = num_strs[store_str_mode] - 1; + if (store_which_str >= num_strs[store_str_mode]) store_which_str = 0; + break; + } + cdsin(816,5,store_which_str); + if (store_str_mode == 0) + CDST(816,2,(store_which_str >= 160) ? + scen_strs2[store_which_str - 160] : scen_strs[store_which_str]); + if (store_str_mode) + CDST(816,2,data_store->out_strs[store_which_str]); + if (store_str_mode == 2) + CDST(816,2,town_strs[store_which_str]); +} + +// mode 0 - scen 1 - out 2 - town +void edit_text_str(short which_str,short mode) +// ignore parent in Mac version +{ + short text_hit,i,store_dialog_answer,item_hit; + char temp_str[256]; + + store_which_str = which_str; + store_str_mode = mode; + + cd_create_dialog_parent_num(816,0); + + cdsin(816,5,store_which_str); + if (mode == 0) + CDST(816,2,(which_str >= 160) ? + scen_strs2[which_str - 160] : scen_strs[which_str]); + if (mode == 1) + CDST(816,2,data_store->out_strs[which_str]); + if (mode == 2) + CDST(816,2,town_strs[which_str]); + cd_attach_key(816,3,0); + cd_attach_key(816,4,0); + while (dialog_not_toast) + ModalDialog(); + + cd_kill_dialog(816,0); +} + +void edit_area_rect_event_filter (short item_hit) +{ + char str[256]; + short i; + + switch (item_hit) { + case 6: + dialog_answer = TRUE; + dialog_not_toast = FALSE; + CDGT(840,2,(char *) str); + if (store_str_mode == 0) + sprintf(data_store->out_strs[store_which_str + 1],"%-29.29s",(char *) str); + else sprintf(town_strs[store_which_str + 1],"%-29.29s",(char *) str); + break; + + case 3: + dialog_answer = FALSE; + dialog_not_toast = FALSE; + break; + } +} + +// mode 0 - out 1 - town +Boolean edit_area_rect_str(short which_str,short mode) +// ignore parent in Mac version +{ + short area_rect_hit,i,store_dialog_answer,item_hit; + char temp_str[256]; + + store_which_str = which_str; + store_str_mode = mode; + + cd_create_dialog_parent_num(840,0); + + if (store_str_mode == 0) + CDST(840,2,data_store->out_strs[store_which_str + 1]); + else CDST(840,2,town_strs[store_which_str + 1]); + + while (dialog_not_toast) + ModalDialog(); + + cd_kill_dialog(840,0); + + return dialog_answer; +} + +Boolean save_spec_enc() +{ + char str[256]; + short i; + + store_spec_node.sd1 = CDGN(822,2); + store_spec_node.sd2 = CDGN(822,3); + store_spec_node.m1 = CDGN(822,4); + store_spec_node.m2 = CDGN(822,5); + store_spec_node.pic = CDGN(822,6); + if (store_spec_node.pic < 0) + store_spec_node.pic = 0; + store_spec_node.ex1a = CDGN(822,7); + store_spec_node.ex1b = CDGN(822,8); + store_spec_node.ex2a = CDGN(822,9); + store_spec_node.ex2b = CDGN(822,10); + store_spec_node.jumpto = CDGN(822,11); + + if (edit_spec_stuff_done_mess[store_spec_node.type] == 1) { + if (cre(store_spec_node.sd1,-1,299,"The first part of a Stuff Done flag must be from 0 to 299 (or -1 if the Stuff Done flag is ignored.", + "",822) > 0) return FALSE; + if (cre(store_spec_node.sd2,-1,9,"The second part of a Stuff Done flag must be from 0 to 9 (or -1 if the Stuff Done flag is ignored.", + "",822) > 0) return FALSE; + } + + if (store_which_mode == 0) + scenario.scen_specials[store_which_node] = store_spec_node; + if (store_which_mode == 1) + current_terrain.specials[store_which_node] = store_spec_node; + if (store_which_mode == 2) + town.specials[store_which_node] = store_spec_node; + return TRUE; +} + +void put_spec_enc_in_dlog() +{ + char str[256]; + short i; + + cdsin(822,15,store_which_node); + get_str(str,22,store_spec_node.type + 1); + csit(822,27,(char *) str); + + if (last_node[0] == -1) + cd_activate_item(822,14,0); + else cd_activate_item(822,14,1); + + CDSN(822,2,store_spec_node.sd1); + CDSN(822,3,store_spec_node.sd2); + switch (edit_spec_stuff_done_mess[store_spec_node.type]) { + case 0: csit(822,20,"Unused."); csit(822,21,"Unused."); break; + case 1: csit(822,20,"Stuff Done Flag Part A"); csit(822,21,"Stuff Done Flag Part B"); break; + case 2: csit(822,20,"Chance of placing (0 - 100)"); csit(822,21,"Unused"); break; + case 3: csit(822,20,"Stuff Done Flag Part A"); csit(822,21,"Unused"); break; + case 4: csit(822,20,"X of space to move to"); csit(822,21,"Y of space to move to"); break; + case 5: csit(822,20,"Terrain to change to"); csit(822,21,"Chance of changing (0 - 100)"); break; + case 6: csit(822,20,"Switch this ter. type"); csit(822,21,"with this ter. type"); break; + case 7: csit(822,20,"Chance of placing (0 - 100)"); csit(822,21,"What to place (see docs.)"); break; + case 8: csit(822,20,"Chance of placing (0 - 100)"); csit(822,21,"0 - web, 1 - barrel, 2 - crate"); break; + } + + CDSN(822,4,store_spec_node.m1); + CDSN(822,5,store_spec_node.m2); + switch (edit_spec_mess_mess[store_spec_node.type]) { + case 0: csit(822,22,"Unused."); csit(822,23,"Unused."); cd_activate_item(822,49,0); break; + case 1: csit(822,22,"First part of message"); csit(822,23,"Second part of message"); + cd_activate_item(822,49,1); break; + case 2: csit(822,22,"Number of first message in dialog"); csit(822,23,"Unused"); + cd_activate_item(822,49,1); break; + case 3: csit(822,22,"Name of Store"); csit(822,23,"Unused"); + cd_activate_item(822,49,1); break; + case 4: csit(822,22,"Number of first message in dialog"); + csit(822,23,"1 - add 'Leave'/'OK' button, else no"); + cd_activate_item(822,49,1); break; + case 5: csit(822,22,"Number of first message in dialog"); + csit(822,23,"Num. of spec. item to give (-1 none)"); + cd_activate_item(822,49,1); break; + } + + CDSN(822,6,store_spec_node.pic); + switch (edit_pict_mess[store_spec_node.type]) { + case 0: csit(822,24,"Unused."); cd_activate_item(822,46,0); break; + case 1: csit(822,24,"Dialog Picture number"); cd_activate_item(822,46,1); break; + case 2: csit(822,24,"Terrain Picture number"); cd_activate_item(822,46,1); break; + case 3: csit(822,24,"Monster Picture number"); cd_activate_item(822,46,1); break; + case 4: csit(822,24,"Chance of changing (0 - 100)"); cd_activate_item(822,46,0); break; + case 5: csit(822,24,"Number of letters to match"); cd_activate_item(822,46,0); break; + case 6: csit(822,24,"Radius of explosion"); cd_activate_item(822,46,0); break; + } + + CDSN(822,7,store_spec_node.ex1a); + get_str(str,30,store_spec_node.type + 1); + csit(822,25,(char *) str); + cd_activate_item(822,47,0); + for (i = 0 ; i < 12; i++) + if (store_spec_node.type == ex1a_choose[i]) + cd_activate_item(822,47,1); + + CDSN(822,8,store_spec_node.ex1b); + get_str(str,31,store_spec_node.type + 1); + csit(822,26,(char *) str); + cd_activate_item(822,43,0); + for (i = 0 ; i < 40; i++) + if (store_spec_node.type == ex1b_choose[i]) + cd_activate_item(822,43,1); + + CDSN(822,9,store_spec_node.ex2a); + get_str(str,32,store_spec_node.type + 1); + csit(822,28,(char *) str); + cd_activate_item(822,48,0); + for (i = 0 ; i < 18; i++) + if (store_spec_node.type == ex2a_choose[i]) + cd_activate_item(822,48,1); + + CDSN(822,10,store_spec_node.ex2b); + get_str(str,33,store_spec_node.type + 1); + csit(822,29,(char *) str); + cd_activate_item(822,44,0); + for (i = 0 ; i < 20; i++) + if (store_spec_node.type == ex2b_choose[i]) + cd_activate_item(822,44,1); + + CDSN(822,11,store_spec_node.jumpto); + switch (edit_jumpto_mess[store_spec_node.type]) { + case 0: csit(822,30,"Special to Jump To"); break; + case 1: csit(822,30,"Special node if not blocked"); break; + case 2: csit(822,30,"Special after trap finished"); break; + case 3: csit(822,30,"Otherwise call this special"); break; + case 4: csit(822,30,"Special if OK/Leave picked"); break; + } +} + +void edit_spec_enc_event_filter (short item_hit) +{ + char str[256]; + short i,node_to_change_to = -1,spec; + + switch (item_hit) { + case 12: + if (save_spec_enc() == TRUE) + dialog_not_toast = FALSE; + break; + case 14: //go_back + if (save_spec_enc() == FALSE) + break; + for (i = 0; i < 256; i++) + if (last_node[i] < 0) { + node_to_change_to = last_node[i - 1]; + if (i > 0) + last_node[i - 1] = -1; + i = 256; + } + break; + case 13: + if (last_node[0] != -1) { + give_error("You can't cancel out of making a special until you're back at the beginning of the special chain.", + "Press the Go Back button until it disappears.",822); + break; + } + dialog_not_toast = FALSE; break; + case 43: case 44: case 45: // 1b, 2b, jump to spec + if (save_spec_enc() == FALSE) + break; + if (item_hit == 43) + spec = CDGN(822,8); + if (item_hit == 44) + spec = CDGN(822,10); + if (item_hit == 45) + spec = CDGN(822,11); + if ((spec < 0) || (spec >= num_specs[store_which_mode])) { + spec = -1; + //CDSN(822,8,-1) + if ((item_hit == 43) && (store_spec_node.type == 13)) + spec = get_fresh_spec(0); + else if ((item_hit == 45) && (store_spec_node.type == 21)) + spec = get_fresh_spec(0); + else spec = get_fresh_spec(store_which_mode); + if (spec < 0) { + give_error("You can't create a new special encounter because there are no more free special nodes.", + "To free a special node, set its type to No Special and set its Jump To special to -1.",822); + break; + } + if (item_hit == 43) + CDSN(822,8,spec); + if (item_hit == 44) + CDSN(822,10,spec); + if (item_hit == 45) + CDSN(822,11,spec); + } + if (save_spec_enc() == FALSE) + break; + if ((item_hit == 43) && (store_spec_node.type == 13)) + node_to_change_to = spec; + else if ((item_hit == 45) && (store_spec_node.type == 21)) + node_to_change_to = spec; + else node_to_change_to = store_which_mode * 1000 + spec; + for (i = 0; i < 256; i++) + if (last_node[i] < 0) { + last_node[i] = store_which_mode * 1000 + store_which_node; + i = 256; + } + break; + case 47: // 1a choose + switch (store_spec_node.type) { + case 19: case 50: case 58: case 59: case 60: + i = choose_text_res(-2,0,399,store_spec_node.ex1a,822,"Give which item?"); break; + case 229: + i = choose_text_res(-2,0,399,store_spec_node.ex1a,822,"First item in store?"); break; + case 55: case 56: case 57: + i = choose_text_res(-3,0,NUM_DLOG_B - 1,store_spec_node.ex1a,822,"Which button label?"); break; + case 182: + i = choose_text_res(-1,1,255,store_spec_node.ex1a,822,"Choose Which Monster:"); break; + } + store_spec_node.ex1a = i; + CDSN(822,7,store_spec_node.ex1a); + break; + case 48: // 2a choose + switch (store_spec_node.type) { + case 19: case 50: case 192: case 229: + i = choose_text_res(-2,0,399,store_spec_node.ex2a,822,"Give which item?"); break; + case 55: case 56: case 57: case 58: case 59: case 60: + i = choose_text_res(-3,0,NUM_DLOG_B - 1,store_spec_node.ex2a,822,"Which button label?"); break; + case 181: + i = choose_text_res(-1,1,255,store_spec_node.ex2a,822,"Choose Which Monster:"); break; + case 135: case 136: case 171: case 172: case 226: + i = choose_text_res(-4,0,255,store_spec_node.ex2a,822,"Which Terrain?"); break; + } + store_spec_node.ex2a = i; + CDSN(822,9,store_spec_node.ex2a); + break; + case 49: // message + if (save_spec_enc() == TRUE) + dialog_not_toast = FALSE; + if ((edit_spec_mess_mess[store_spec_node.type] == 2) || + (edit_spec_mess_mess[store_spec_node.type] == 4) || + (edit_spec_mess_mess[store_spec_node.type] == 5)) { + edit_dialog_text(store_which_mode,&store_spec_node.m1,822); + put_spec_enc_in_dlog(); + } + else if ((edit_spec_mess_mess[store_spec_node.type] == 1) || + (edit_spec_mess_mess[store_spec_node.type] == 3)) { + edit_spec_text(store_which_mode,&store_spec_node.m1, + &store_spec_node.m2,822); + put_spec_enc_in_dlog(); + } + break; + case 46: // pict + if (save_spec_enc() == TRUE) + dialog_not_toast = FALSE; + i = -1; + switch (edit_pict_mess[store_spec_node.type]) { + case 1: i = choose_graphic(700,731,store_spec_node.pic,822); break; + case 2: i = choose_graphic(0,252,store_spec_node.pic,822); break; + case 3: i = choose_graphic(400,572,store_spec_node.pic,822); break; + } + if (i >= 0) { + store_spec_node.pic = i; + put_spec_enc_in_dlog(); + } + break; + + case 37: // 1st spec type + if (save_spec_enc() == TRUE) + dialog_not_toast = FALSE; + i = choose_text_res(22,1,28,store_spec_node.type + 1,822,"Choose General Use Special:"); + if (i >= 0) { + store_spec_node.type = i - 1; + } + put_spec_enc_in_dlog(); + break; + case 38: // 2 spec type + if (save_spec_enc() == TRUE) + dialog_not_toast = FALSE; + i = choose_text_res(22,51,64,store_spec_node.type + 1,822,"Choose One-Shot Special:"); + if (i >= 0) { + store_spec_node.type = i - 1; + store_spec_node.sd1 = -1; + store_spec_node.sd2 = -1; + if ((store_spec_node.type >= 55) && (store_spec_node.type <= 57)) + store_spec_node.m2 = 1; + } + put_spec_enc_in_dlog(); + break; + case 39: // 3 spec type + if (save_spec_enc() == TRUE) + dialog_not_toast = FALSE; + i = choose_text_res(22,81,107,store_spec_node.type + 1,822,"Choose Affect Party Special:"); + if (i >= 0) store_spec_node.type = i - 1; + put_spec_enc_in_dlog(); + break; + case 40: // 4 spec type + if (save_spec_enc() == TRUE) + dialog_not_toast = FALSE; + i = choose_text_res(22,131,156,store_spec_node.type + 1,822,"Choose If-Then Special:"); + if (i >= 0) { + store_spec_node.type = i - 1; + } + put_spec_enc_in_dlog(); + break; + case 41: // 5 spec type + if (save_spec_enc() == TRUE) + dialog_not_toast = FALSE; + i = choose_text_res(22,171,219,store_spec_node.type + 1,822,"Choose Town Special:"); + if (i >= 0) store_spec_node.type = i - 1; + put_spec_enc_in_dlog(); + break; + case 42: // 6 spec type + if (save_spec_enc() == TRUE) + dialog_not_toast = FALSE; + i = choose_text_res(22,226,230,store_spec_node.type + 1,822,"Choose Outdoor Special:"); + if (i >= 0) store_spec_node.type = i - 1; + put_spec_enc_in_dlog(); + break; + } + /*if ((item_hit >= 37) && (item_hit <= 42)) { + if (cd_get_active(822,43) == 0) + CDSN(822,8,0); + if (cd_get_active(822,44) == 0) + CDSN(822,10,0); + }*/ // Might be useful, but I forget what I was thinking when I added it. + if (node_to_change_to >= 0) { + store_which_mode = node_to_change_to / 1000; + store_which_node = node_to_change_to % 1000; + if (store_which_mode == 0) + store_spec_node = scenario.scen_specials[store_which_node]; + if (store_which_mode == 1) + store_spec_node = current_terrain.specials[store_which_node]; + if (store_which_mode == 2) + store_spec_node = town.specials[store_which_node]; + if (store_spec_node.pic < 0) + store_spec_node.pic = 0; + put_spec_enc_in_dlog(); + } +} + +// mode - 0 scen 1 - out 2 - town +void edit_spec_enc(short which_node,short mode,short parent_num) +// ignore parent in Mac version +{ + short spec_enc_hit,i,store_dialog_answer; + char temp_str[256]; + + store_which_mode = mode; + store_which_node = which_node; + for (i = 0; i < 256; i++) + last_node[i] = -1; + //last_node[0] = store_which_mode * 1000 + store_which_node; + if (mode == 0) + store_spec_node = scenario.scen_specials[store_which_node]; + if (mode == 1) + store_spec_node = current_terrain.specials[store_which_node]; + if (mode == 2) + store_spec_node = town.specials[store_which_node]; + if (store_spec_node.pic < 0) + store_spec_node.pic = 0; + + cd_create_dialog_parent_num(822,parent_num); + + cd_activate_item(822,14,0); + put_spec_enc_in_dlog(); + + while (dialog_not_toast) + ModalDialog(); + cd_kill_dialog(822,0); +} + +short get_fresh_spec(short which_mode) +{ + short i; + special_node_type store_node; + + for (i = 0; i < num_specs[which_mode]; i++) { + if (which_mode == 0) + store_node = scenario.scen_specials[i]; + if (which_mode == 1) + store_node = current_terrain.specials[i]; + if (which_mode == 2) + store_node = town.specials[i]; + if ((store_node.type == 0) && (store_node.jumpto == -1) && (store_node.pic == -1)) + return i; + } + + return -1; +} + +void edit_spec_text_event_filter (short item_hit) +{ + char str[256]; + short i; + + switch (item_hit) { + case 7: + dialog_not_toast = FALSE; + break; + + case 6: + CDGT(826,2,(char *) str); + if (strlen((char *) str) > 0) { + if (*store_str1 < 0) { + switch (store_spec_str_mode) { + case 0: + for (i = 0; i < 100; i++) + if (scen_strs2[i][0] == '*') { + *store_str1 = i; + i = 500; + } + break; + case 1: + for (i = 10; i < 100; i++) + if (data_store->out_strs[i][0] == '*') { + *store_str1 = i - 10; + i = 500; + } + break; + case 2: + for (i = 20; i < 120; i++) + if (town_strs[i][0] == '*') { + *store_str1 = i - 20; + i = 500; + } + break; + + } + if (i < 500) { + give_error("There are no more free message slots.", + "To free up some slots, go into Edit Town/Out/Scenario Text to clear some messages.", 826); + break; + } + } + if (*store_str1 >= 0) { + switch (store_spec_str_mode) { + case 0: + strcpy(scen_strs2[*store_str1],(char *) str); + break; + case 1: + strcpy(data_store->out_strs[*store_str1 + 10],(char *) str); + break; + case 2: + strcpy(town_strs[*store_str1 + 20],(char *) str); + break; + } + } + } + CDGT(826,3,(char *) str); + if (strlen((char *) str) > 0) { + if (*store_str2 < 0) { + switch (store_spec_str_mode) { + case 0: + for (i = 0; i < 100; i++) + if (scen_strs2[i][0] == '*') { + *store_str2 = i; + i = 500; + } + break; + case 1: + for (i = 10; i < 100; i++) + if (data_store->out_strs[i][0] == '*') { + *store_str2 = i - 10; + i = 500; + } + break; + case 2: + for (i = 20; i < 120; i++) + if (town_strs[i][0] == '*') { + *store_str2 = i - 20; + i = 500; + } + break; + + } + if (i < 500) { + give_error("There are no more free message slots.", + "To free up some slots, go into Edit Town/Out/Scenario Text to clear some messages.", 826); + break; + } + } + if (*store_str2 >= 0) { + switch (store_spec_str_mode) { + case 0: + strcpy(scen_strs2[*store_str2],(char *) str); + break; + case 1: + strcpy(data_store->out_strs[*store_str2 + 10],(char *) str); + break; + case 2: + strcpy(town_strs[*store_str2 + 20],(char *) str); + break; + } + } + } + dialog_not_toast = FALSE; + break; + } +} + +// mode 0 - scen 1 - out 2 - town +void edit_spec_text(short mode,short *str1,short *str2,short parent) +{ + short text_hit,i,store_dialog_answer,item_hit; + char temp_str[256]; + short num_s_strs[3] = {100,90,100}; + + store_str1 = str1; + store_str2 = str2; + store_spec_str_mode = mode; + + cd_create_dialog_parent_num(826,parent); + + if (*str1 >= num_s_strs[mode]) + *str1 = -1; + if (*str1 >= 0){ + if (mode == 0) + CDST(826,2,scen_strs2[*str1]); + if (mode == 1) + CDST(826,2,data_store->out_strs[*str1 + 10]); + if (mode == 2) + CDST(826,2,town_strs[*str1 + 20]); + } + if (*str2 >= num_s_strs[mode]) + *str2 = -1; + if (*str2 >= 0){ + if (mode == 0) + CDST(826,3,scen_strs2[*str2]); + if (mode == 1) + CDST(826,3,data_store->out_strs[*str2 + 10]); + if (mode == 2) + CDST(826,3,town_strs[*str2 + 20]); + } + + while (dialog_not_toast) + ModalDialog(); + + cd_kill_dialog(826,0); +} + +void edit_dialog_text_event_filter (short item_hit) +{ + char str[256]; + short i; + + switch (item_hit) { + case 9: + dialog_not_toast = FALSE; + break; + + case 8: + for (i = 0; i < 6; i++) { + CDGT(842,2 + i,(char *) str); + switch (store_spec_str_mode) { + case 0: + strcpy(scen_strs2[*store_str1 + i],(char *) str); + break; + case 1: + strcpy(data_store->out_strs[*store_str1 + 10 + i],(char *) str); + break; + case 2: + strcpy(town_strs[*store_str1 + 20 + i],(char *) str); + break; + } + } + dialog_not_toast = FALSE; + break; + } +} + +// mode 0 - scen 1 - out 2 - town +void edit_dialog_text(short mode,short *str1,short parent) +{ + short text_hit,i,j,store_dialog_answer,item_hit; + char temp_str[256]; + short num_s_strs[3] = {100,90,100}; + + store_str1 = str1; + store_spec_str_mode = mode; + + if (*str1 >= num_s_strs[mode] - 6) + *str1 = -1; + // first, assign the 6 strs for the dialog. + if (*str1 < 0) { + switch (store_spec_str_mode) { + case 0: + for (i = 0; i < 100 - 6; i++) { + for (j = i; j < i + 6; j++) + if (scen_strs2[j][0] != '*') { + j = 500; + } + if (j < 500) { + *str1 = i; + i = 500; + } + } + break; + case 1: + for (i = 10; i < 100 - 6; i++) { + for (j = i; j < i + 6; j++) + if (data_store->out_strs[j][0] != '*') { + j = 500; + } + if (j < 500) { + *str1 = i - 10; + i = 500; + } + } + break; + case 2: + for (i = 20; i < 120 - 6; i++) { + for (j = i; j < i + 6; j++) + if (town_strs[j][0] != '*') { + j = 500; + } + if (j < 500) { + *str1 = i - 20; + i = 500; + } + } + break; + + } + if (*str1 >= 0) + for (i = *str1; i < *str1 + 6; i++) { + switch (store_spec_str_mode) { + case 0: + sprintf(scen_strs2[i],""); + break; + case 1: + sprintf(data_store->out_strs[10 + i],""); + break; + case 2: + sprintf(town_strs[20 + i],""); + break; + } + } + } + if (*str1 < 0) { + give_error("To create a dialog, you need 6 consecutive unused messages. To free up 6 messages, select Edit Out/Town/Scenario Text from the menus.","",parent); + return; + } + + cd_create_dialog_parent_num(842,parent); + + if (*str1 >= 0){ + for (i = 0; i < 6; i++) { + if (mode == 0) + CDST(842,2 + i,scen_strs2[*str1 + i]); + if (mode == 1) + CDST(842,2 + i,data_store->out_strs[*str1 + 10 + i]); + if (mode == 2) + CDST(842,2 + i,town_strs[*str1 + 20 + i]); + } + } + + while (dialog_not_toast) + ModalDialog(); + + cd_kill_dialog(842,0); +} + +void edit_special_num_event_filter (short item_hit) +{ + char str[256]; + short i; + + switch (item_hit) { + case 8: + dialog_answer = -1; + dialog_not_toast = FALSE; + break; + + case 4: + i = CDGN(825,2); + if ((i < 0) || (i >= num_specs[store_spec_mode])) { + give_error("There is no special node with that number. Legal ranges are 0 to 255 for scenario specials, 0 to 59 for outdoor specials, and 0 to 99 for town specials.","",825); + break; + } + dialog_answer = i; + dialog_not_toast = FALSE; + break; + } +} + +short edit_special_num(short mode,short what_start) +{ + short text_hit,i,j,store_dialog_answer,item_hit; + char temp_str[256]; + + store_spec_mode = mode; + + cd_create_dialog_parent_num(825,0); + + CDSN(825,2,what_start); + + while (dialog_not_toast) + ModalDialog(); + + cd_kill_dialog(825,0); + + return dialog_answer; +} + +void edit_scen_intro_event_filter (short item_hit) +{ + char str[256]; + short i; + + switch (item_hit) { + case 9: + scenario.intro_pic = CDGN(804,8); + if ((scenario.intro_pic < 0) || (scenario.intro_pic > 29)) { + give_error("Intro picture number is out of range.","",804); + break; + } + for (i = 0; i < 6; i++) + CDGT(804, 2 + i,scen_strs[4 + i]); + dialog_not_toast = FALSE; + break; + case 10: + dialog_not_toast = FALSE; + break; + + case 16: + i = CDGN(804,8); + i = choose_graphic(1600,1629,1600 + i,804); + if (i >= 0) { + CDSN(804,8,i - 1600); + csp(804,11,i ); + } + break; + } +} + +void edit_scen_intro() +{ + short text_hit,i,j,store_dialog_answer,item_hit; + char temp_str[256]; + short num_s_strs[3] = {100,90,100}; + + + cd_create_dialog_parent_num(804,0); + + CDSN(804,8,scenario.intro_pic); + for (i = 0; i < 6; i++) + CDST(804, 2 + i,scen_strs[4 + i]); + csp(804,11,scenario.intro_pic + 1600); + + while (dialog_not_toast) + ModalDialog(); + + cd_kill_dialog(804,0); +} + +void set_cursor(short which_c) +{ + short i; + + if (cursors[0] == NULL) { + for (i = 0; i < 8; i++) + cursors[i] = LoadCursor(store_hInstance,MAKEINTRESOURCE(130 + i)); + } + current_cursor = which_c; + SetCursor(cursors[current_cursor]); +} +void restore_cursor() +{ + set_cursor(current_cursor); +} + diff --git a/Win32/Scenarios Editor/KEYDLGS.H b/Win32/Scenarios Editor/KEYDLGS.H new file mode 100644 index 00000000..f70e7505 --- /dev/null +++ b/Win32/Scenarios Editor/KEYDLGS.H @@ -0,0 +1,36 @@ +void fancy_choice_dialog_event_filter (short item_hit); +short fancy_choice_dialog(short which_dlog,short parent); +void display_strings_event_filter (short item_hit); +Boolean cre(short val,short min,short max,char *text1, char *text2,short parent_num) ; +void give_error(char *text1, char *text2,short parent_num); + +void display_strings(char *text1, char *text2, + char *title,short sound_num,short graphic_num,short parent_num); +void choose_graphic_event_filter (short item_hit); +void put_choice_pics(); +short choose_graphic(short first_g,short last_g,short cur_choice,short parent_num); +void put_text_res(); +short choose_text_res(short res_list,short first_t,short last_t,short cur_choice,short parent_num,char *title); +void choose_text_res_event_filter (short item_hit); +void edit_text_event_filter (short item_hit); +void edit_text_str(short which_str,short mode); +Boolean save_spec_enc(); +void put_spec_enc_in_dlog(); +void edit_spec_enc_event_filter (short item_hit); +void edit_spec_enc(short which_node,short mode,short parent_num); +short get_fresh_spec(short which_mode); +void edit_spec_text_event_filter (short item_hit); +void edit_spec_text(short mode,short *str1,short *str2,short parent); +void edit_dialog_text(short mode,short *str1,short parent); + +void edit_special_num_event_filter (short item_hit); +short edit_special_num(short mode,short what_start); +void edit_scen_intro_event_filter (short item_hit); +void edit_scen_intro(); +short choice_dialog(short pic,short num); +Boolean edit_area_rect_str(short which_str,short mode); +void edit_area_rect_event_filter (short item_hit); +void edit_dialog_text_event_filter (short item_hit); + +void set_cursor(short which_c) ; +void restore_cursor(); diff --git a/Win32/Scenarios Editor/SCENARIO.CPP b/Win32/Scenarios Editor/SCENARIO.CPP new file mode 100644 index 00000000..9841c88a --- /dev/null +++ b/Win32/Scenarios Editor/SCENARIO.CPP @@ -0,0 +1,2784 @@ +#include +#include +#include "string.h" +#include "Global.h" +#include "graphics.h" +#include "graphutl.h" +#include "scenario.h" +#include "dlogtool.h" +#include "keydlgs.h" +#include "townout.h" +#include "tfileio.h" +#include "tactions.h" +#include "edsound.h" + +extern short cen_x, cen_y, overall_mode,cur_town; +extern Boolean mouse_button_held,dialog_not_toast; +extern short cur_viewing_mode,dialog_answer; +extern town_record_type town; +extern big_tr_type t_d; +extern short town_type; // 0 - big 1 - ave 2 - small +extern short max_dim[3],mode_count,to_create; +extern unsigned char template_terrain[64][64]; +extern HBITMAP spec_scen_g; +extern scenario_data_type scenario; +extern special_node_type null_spec_node; +extern talking_node_type null_talk_node; +extern piles_of_stuff_dumping_type *data_store; +extern char scen_strs[160][256]; +extern char scen_strs2[110][256]; +extern char talk_strs[170][256]; +extern char town_strs[180][256]; +extern BOOL do_choose_anim; +extern short custom_pic; + +extern location cur_out; +extern scen_item_data_type scen_item_list; + +short store_which_ter; +terrain_type_type store_ter; +short store_which_monst; +monster_record_type store_monst,store_monst2; +short store_which_item; +item_record_type store_item,store_item2; +short store_which_spec_item ; +short spec_item_spec,store_horse_page,store_boat_page ; +item_storage_shortcut_type store_storage; +short cur_shortcut; +RECT source_rect,draw_rect; +extern GWorldPtr terrain_buttons_gworld; + + + char *item_types[] = {"No Item","1-Handed weapon","2-Handed weapon","Gold","Bow","Arrows","Thrown missile", + "Potion/Magic Item","Scroll/Magic Item","Wand","Tool","Food","Shield","Armor","Helm", + "Gloves","Shield","Boots","Ring","Necklace", + "Weapon Poison","Non-Use Object","Pants","Crossbow","Bolts","Missile (no ammo)","Unused","Unused"}; + +unsigned char m_level[200] = { +0,1,1,1,1,1,1,1,1,1, // 0 +1,1,30,4,8,12,20,25,3,5, // 10 +28,3,8,20,4,8,20,5,10,25, // 20 +35,8,6,2,2,7,6,12,2,5, // 30 +4,6,5,6,8,7,18,7,10,8, // 40 +8,12,12,15,18,22,28,26,3,10, // 50 +4,3,6,8,12,11,10,14,18,35, // 60 +14,10,4,8,8,3,7,3,2,4, // 70 +3,18,2,18,7,20,30,35,5,3, // 80 +1,9,8,7,7,18,18,25,35,3, // 90 +5,24,18,10,25,7,2,28,1,1, // 100 +1,1,1,1,1,3,7,8,4,8, // 110 +3,12,18,4,7,5,8,18,22,10, // 120 +12,6,12,16,7,25,28,25,3,3, // 130 +3,4,14,2,6,8,8,10,4,5, // 140 +8,7,10,12,14,10,12,14,24,13, // 150 +18,18,22,22,10,30,20,27,30,7, // 160 +30,15,12,18,3,5,7,39,20,24, // 170 +24,8,7,25,2,10,18,0,0,0, // 180 +0,0,0,0,0,0,0,0,0,0}; // 190 + +short m_health[200] = { +0,6,6,6,6,6,6,6,6,6, // 0 +3,3,140,20,40,75,115,140,14,16, // 10 +90,18,40,90,18,40,90,16,40,90, // 20 +160,40,35,6,6,35,30,80,10,22, // 30 +15,25,18,30,45,35,70,30,50,40, // 40 +40,70,70,100,90,110,140,130,15,50, // 50 +20,15,30,40,60,55,50,70,90,170, // 60 +70,50,20,40,40,15,35,30,10,20, // 70 +15,100,10,90,35,70,150,200,25,20, // 80 +5,90,75,70,70,120,120,190,400,15, // 90 +25,120,90,50,120,35,10,200,3,3, // 100 +3,7,7,1,5,15,35,40,14,40, // 110 +15,50,90,150,35,25,40,90,110,50, // 120 +60,25,50,80,35,125,140,150,8,8, // 130 +10,10,140,10,30,40,40,60,30,25, // 140 +40,35,50,60,70,50,60,70,200,70, // 150 +70,70,90,120,100,200,100,150,200,40, // 160 +500,100,80,110,17,30,30,2500,100,125, // 170 +140,40,10,80,6,30,50,150,0,0, // 180 +0,0,0,0,0,0,0,0,0,0}; // 190 + +unsigned char m_armor[200] = { +1,1,1,1,1,1,1,1,1,1, // 0 +1,1,30,8,12,18,22,25,6,6, // 10 +20,8,14,20,8,14,20,5,10,20, // 20 +30,4,4,2,2,9,7,15,3,5, // 30 +4,7,6,12,18,9,15,7,3,5, // 40 +10,18,18,24,10,14,24,25,2,6, // 50 +0,0,2,2,2,7,8,10,5,15, // 60 +7,10,4,7,7,0,0,0,2,2, // 70 +2,1,10,12,8,14,20,20,4,2, // 80 +2,10,10,14,14,14,14,18,25,2, // 90 +2,8,8,5,9,12,12,18,1,1, // 100 +1,1,1,1,1,1,1,3,1,1, // 110 +1,6,6,12,8,5,5,7,10,0, // 120 +7,2,5,13,6,20,18,25,0,0, // 130 +0,0,10,2,3,4,5,6,0,6, // 140 +10,10,12,20,30,8,14,8,18,20, // 150 +14,14,18,25,25,25,20,30,9,0, // 160 +15,6,10,14,3,1,10,40,14,14, // 170 +10,6,30,20,1,2,4,12,0,0, // 180 +0,0,0,0,0,0,0,0,0,0}; // 190 + +unsigned char m_skill[200] = { +2,2,2,2,2,2,2,2,2,1, // 0 +1,2,30,8,10,14,20,23,5,6, // 10 +28,2,4,8,2,4,8,2,4,5, // 20 +5,3,3,1,1,12,8,25,5,8, // 30 +3,9,8,4,18,10,10,7,14,6, // 40 +6,6,6,28,12,10,28,28,4,10, // 50 +5,3,9,13,18,7,10,17,20,30, // 60 +8,16,7,12,12,4,7,7,3,5, // 70 +5,15,4,18,12,18,24,33,5,5, // 80 +3,12,12,8,8,8,8,23,35,4, // 90 +6,7,7,5,12,0,0,0,1,1, // 100 +1,1,1,1,1,5,9,12,3,25, // 110 +5,9,20,25,10,5,12,15,24,13, // 120 +8,3,12,18,10,4,28,33,3,3, // 130 +3,3,12,4,6,7,7,13,30,5, // 140 +8,6,8,14,22,12,18,10,30,20, // 150 +15,15,13,26,0,0,30,36,30,4, // 160 +26,18,15,17,6,5,10,35,20,20, // 170 +17,7,2,16,2,8,14,18,0,0, // 180 +0,0,0,0,0,0,0,0,0,0}; // 190 + +short m_a1[200] = { +6,6,6,6,6,6,6,6,6,1, // 0 +1,2,210,107,109,110,208,212,8,6, // 10 +10,8,8,208,8,8,208,6,8,10, // 20 +12,6,6,3,3,12,106,108,7,9, // 30 +8,107,8,8,110,206,206,10,208,12, // 40 +10,10,10,310,408,408,510,410,8,108, // 50 +104,8,108,208,308,10,108,0,110,0, // 60 +210,0,106,206,206,8,110,12,6,10, // 70 +8,0,7,215,0,208,0,510,106,8, // 80 +3,212,16,18,18,112,112,410,514,8, // 90 +10,10,10,106,206,0,0,0,2,2, // 100 +2,2,2,2,2,106,206,306,8,206, // 110 +8,106,0,0,12,8,10,206,306,409, // 120 +306,106,407,410,106,12,310,0,106,8, // 130 +8,7,110,8,108,208,108,308,108,10, // 140 +112,8,10,210,310,208,308,208,410,0, // 150 +310,310,10,410,0,0,810,913,913,8, // 160 +710,512,210,212,12,0,208,840,308,308, // 170 +308,209,8,912,8,108,210,312,0,0, // 180 +0,0,0,0,0,0,0,0,0,0}; // 190 + +short m_a2[200] = { +0,0,0,0,0,0,0,0,0,0, // 0 +0,0,210,0,0,110,208,212,0,0, // 10 +0,0,0,0,0,0,0,0,0,0, // 20 +0,0,0,0,0,0,106,108,0,0, // 30 +0,0,0,0,110,0,0,0,208,0, // 40 +0,0,0,310,0,0,0,0,0,0, // 50 +0,0,10,13,405,0,0,306,0,308, // 60 +0,208,8,10,10,8,0,0,0,0, // 70 +0,310,0,110,10,15,310,310,0,0, // 80 +0,0,0,0,0,0,0,310,0,0, // 90 +0,0,0,8,10,0,0,0,0,0, // 100 +0,0,0,0,0,0,0,12,0,0, // 110 +0,0,210,409,0,0,0,8,106,0, // 120 +0,0,0,0,0,0,0,410,0,0, // 130 +0,0,110,0,0,0,0,0,0,0, // 140 +0,0,0,0,0,0,0,0,0,212, // 150 +0,0,0,0,0,0,0,0,0,0, // 160 +310,0,108,12,0,105,0,730,308,308, // 170 +308,209,0,0,0,0,0,212,0,0, // 180 +0,0,0,0,0,0,0,0,0,0}; // 190 + +short m_a3[200] = { +0,0,0,0,0,0,0,0,0,0, // 0 +0,0,0,0,0,0,0,0,0,0, // 10 +0,0,0,0,0,0,0,0,0,0, // 20 +0,0,0,0,00,0,0,108,0,0, // 30 +0,0,0,0,0,00,00,0,0,0, // 40 +0,0,0,0,0,0,0,0,0,0, // 50 +00,0,10,13,405,0,0,306,0,308, // 60 +0,208,8,10,10,8,0,0,0,0, // 70 +0,310,0,110,10,15,310,310,0,0, // 80 +0,0,0,0,0,0,0,0,0,0, // 90 +0,0,0,8,10,0,0,0,0,0, // 100 +0,0,0,0,0,0,0,12,0,0, // 110 +0,0,210,409,0,0,0,8,106,0, // 120 +0,0,0,0,0,0,0,410,0,0, // 130 +0,0,0,0,0,0,0,0,0,0, // 140 +0,0,0,0,0,0,0,0,0,212, // 150 +0,0,0,0,0,0,0,0,0,0, // 160 +310,0,108,12,0,105,0,730,308,308, // 170 +308,0,0,0,0,0,0,212,0,0, // 180 +0,0,0,0,0,0,0,0,0,0}; // 190 + +unsigned char m_a1t[200] = { +0,0,0,0,0,0,0,0,0,0, // 0 +0,0,0,0,0,0,0,0,0,0, // 10 +0,0,0,0,0,0,0,0,0,0, // 20 +0,0,0,0,0,0,4,4,0,0, // 30 +0,0,0,0,0,0,0,0,0,0, // 40 +0,0,0,0,0,0,0,0,1,1, // 50 +1,1,2,2,2,1,1,0,1,0, // 60 +1,0,2,2,2,3,3,3,2,2, // 70 +2,0,2,2,0,2,0,2,2,0, // 80 +0,0,0,0,0,0,0,0,0,2, // 90 +2,2,2,2,2,0,0,0,2,2, // 100 +2,2,2,2,2,2,2,2,2,2, // 110 +4,1,0,0,0,0,0,2,2,3, // 120 +2,2,2,2,4,4,2,0,3,3, // 130 +3,3,3,2,2,2,2,2,2,0, // 140 +0,0,0,0,0,0,0,0,0,0, // 150 +0,0,0,0,0,0,2,2,2,4, // 160 +2,2,2,2,0,0,3,2,2,2,// 170 +2,2,7,9,0,0,0,2,0,0, // 180 +0,0,0,0,0,0,0,0,0,0}; // 190 + +unsigned char m_a23t[200] = { +0,0,0,0,0,0,0,0,0,0, // 0 +0,0,0,0,0,0,0,0,0,0, // 10 +0,0,0,0,0,0,0,0,0,0, // 20 +0,0,0,0,0,0,4,4,0,0, // 30 +0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0, // 50 +0,0,1,1,1,0,0,1,0,1, +0,1,1,1,1,3,3,3,0,0, +0,1,0,1,1,1,4,1,0,0, +0,0,0,0,0,0,0,0,0,0, +0,0,0,1,1,0,0,0,0,0, //100 +0,0,0,0,0,0,0,1,0,0, +0,0,0,1,1,0,0,1,1,0, +0,0,0,0,0,0,0,1,0,0, +0,0,3,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0, // 150 +0,0,0,0,0,0,0,0,0,0, +1,1,1,1,0,1,0,1,2,2, +2,2,0,0,0,0,0,1,0,0, +0,0,0,0,0,0,0,0,0,0}; // 190 + + +unsigned char m_type[200] = { +0,0,0,0,0,0,0,0,0,0, // 0 +0,0,0,0,0,0,0,0,0,0, // 10 +0,5,5,5,5,5,5,4,4,4, // 20 +4,4,4,0,0,0,5,5,6,6, // 30 +6,6,6,6,6,6,6,6,6,6, // 40 +6,6,6,6,9,9,9,9,8,8, // 50 +8,8,8,8,8,8,8,8,8,8, // 60 +8,8,1,1,1,10,10,10,2,2, // 70 +2,2,2,1,7,7,7,7,7,6, // 80 +6,6,6,6,6,6,6,6,6,1, // 90 +1,2,2,1,1,11,11,11,2,2, // 100 +2,2,2,2,2,2,2,2,12,12, // 110 +6,2,2,3,2,8,8,1,1,10, // 120 +12,12,12,12,2,2,2,2,10,10, // 130 +10,10,10,12,12,12,12,12,12,6, // 140 +6,6,6,6,6,9,9,9,9,11, // 150 +11,11,11,11,11,11,2,2,2,6, // 160 +1,2,2,2,1,8,10,13,1,1, // 170 +1,1,14,14,6,6,6,7,0,0, // 180 +0,0,0,0,0,0,0,0,0,0}; // 190 + +unsigned char m_speed[200] = { +0,4,4,4,4,4,4,4,4,4, // 0 +4,4,6,4,4,5,8,8,4,4, // 10 +4,4,4,4,4,4,4,4,5,6, // 20 +7,4,4,4,4,4,5,8,3,3, // 30 +4,6,4,4,6,4,4,4,4,4, // 40 +4,4,4,4,3,4,4,4,4,4, // 50 +4,4,4,4,9,4,4,4,4,5, // 60 +4,4,4,4,4,3,3,3,4,4, // 70 +4,3,8,4,4,4,4,4,4,4, // 80 +4,7,6,4,4,4,4,6,8,4, // 90 +4,5,6,4,4,4,4,5,2,3, // 100 +3,3,3,2,2,4,4,4,4,4, // 110 +7,4,4,4,3,4,4,4,4,3, // 120 +4,4,4,4,4,5,5,5,3,3, // 130 +3,3,3,3,3,4,4,4,4,4, // 140 +4,4,4,4,4,4,4,4,4,4, // 150 +4,4,4,7,4,4,4,5,3,4, // 160 +4,4,3,4,4,3,4,4,4,4, // 170 +4,4,9,8,3,5,5,6,4,4, // 180 +4,4,4,4,4,4,4,4,4,4}; // 190 + +unsigned char m_mu[200] = { +0,0,0,0,0,0,0,0,0,0, // 0 +0,0,0,0,0,0,0,0,0,0, // 10 +0,0,0,0,0,0,0,2,4,7, // 20 +7,5,3,0,0,0,0,0,0,0, // 30 +0,0,0,3,0,0,6,0,0,0, +4,0,6,0,0,4,0,0,0,0, // 50 +0,0,0,0,0,3,0,0,5,7, +4,0,0,0,0,0,0,0,0,0, +0,0,0,4,2,5,0,7,1,0, +0,0,0,3,0,6,0,0,7,0, +0,6,0,0,0,1,0,7,0,0, //100 +0,0,0,0,0,0,0,0,0,0, +0,3,0,0,0,0,0,0,3,0, +0,0,0,0,0,6,5,4,0,0, +0,1,0,0,0,0,0,0,0,0, +0,4,6,0,0,0,0,3,0,0, // 150 +0,0,0,0,0,7,0,0,0,0, +5,0,0,0,0,0,0,7,0,0, +0,0,3,2,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0}; // 190 + +unsigned char m_cl[200] = { +0,0,0,0,0,0,0,0,0,0, // 0 +0,0,0,0,0,0,0,0,0,0, // 10 +0,2,4,6,2,4,6,0,0,0, // 20 +0,0,0,0,0,0,0,0,0,0, // 30 +0,0,0,3,0,0,0,0,0,4, +0,7,0,0,0,4,0,0,0,0, // 50 +0,0,0,0,0,0,0,0,0,7, +0,0,0,0,0,0,0,0,0,0, +0,0,0,0,2,3,0,7,1,0, +0,0,0,0,3,0,6,0,7,0, +0,3,0,0,0,1,0,7,0,0, //100 +0,0,0,0,0,0,0,0,0,0, +0,5,0,0,0,0,2,0,3,0, +0,0,0,0,0,0,4,0,0,0, +0,1,0,0,0,0,0,0,0,0, +0,5,6,0,0,0,0,3,0,0, // 150 +0,0,0,5,0,7,0,0,0,0, +7,0,0,0,0,0,0,7,0,0, +0,0,0,2,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0}; // 190 + +unsigned char m_breath[200] = { +0,0,0,0,0,0,0,0,0,0, // 0 +0,0,0,0,0,0,0,0,0,0, // 10 +0,0,0,0,0,0,0,0,0,0, // 20 +0,0,0,0,0,0,0,0,0,0, // 30 +0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0, // 50 +0,0,0,0,0,0,0,0,0,0, +0,0,0,4,104,0,0,0,0,0, +0,0,0,6,0,0,0,8,1,0, +0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0, //100 +0,0,0,0,0,0,0,0,0,0, +0,0,5,0,0,0,0,4,107,0, +0,0,0,0,0,0,0,7,0,0, +0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,// 150 +7,107,208,9,209,0,0,0,0,0, +9,0,0,0,0,0,0,35,0,15, +115,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0}; // 190 + +unsigned char m_poison[200] = { +0,0,0,0,0,0,0,0,0,0, // 0 +0,0,0,0,0,0,0,0,0,0, // 10 +0,0,0,0,0,0,0,0,0,0, // 20 +0,0,0,0,0,4,0,0,0,2, // 30 +0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0, // 50 +0,0,0,0,0,0,0,0,0,0, +3,0,0,0,0,0,0,2,0,0, +2,0,0,0,0,0,6,8,1,0, +0,0,0,0,0,0,0,0,0,0, +5,0,0,0,0,0,0,0,0,0, //100 +0,0,0,0,0,0,0,0,3,9, +0,0,0,0,7,0,0,0,0,0, +0,0,4,0,0,0,7,0,0,0, +0,0,0,0,0,0,4,0,0,0, +0,0,0,0,0,0,0,0,0,0, // 150 +0,0,0,0,0,0,0,6,7,0, +0,0,0,4,1,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0}; // 190 + +unsigned char m_treas[200] = { +0,0,0,0,0,0,0,0,0,0, // 0 +0,0,0,2,2,2,2,2,1,1, // 10 +2,1,2,3,1,2,3,1,2,3, // 20 +4,2,1,1,1,1,1,2,1,1, // 30 +1,2,1,2,3,1,2,1,2,2, // 40 +2,3,3,4,1,2,4,2,0,0, // 50 +0,0,0,0,0,0,1,2,3,4, // 60 +0,0,0,2,2,0,0,0,0,0, // 70 +0,0,0,2,2,2,3,4,2,1, // 80 +0,2,2,2,2,2,2,3,4,0, // 90 +0,2,2,0,0,0,0,0,0,0, // 100 +0,0,0,0,0,0,0,0,0,0, // 110 +1,0,0,0,0,0,0,2,3,0, // 120 +0,0,0,0,0,3,3,3,0,0, // 130 +0,0,0,0,0,0,0,0,0,1, // 140 +2,2,2,2,4,1,2,2,4,0, // 150 +0,0,0,0,0,0,0,0,3,2, // 160 +3,2,1,2,0,0,0,4,2,3, // 170 +3,0,0,0,1,2,3,0,0,0, // 180 +0,0,0,0,0,0,0,0,0,0}; // 190 + +unsigned char m_abil[200] = { +0,0,0,0,0,0,0,0,0,0, // 0 +0,0,3,0,0,0,0,0,0,2, // 10 +20,0,0,0,0,0,0,0,0,0, // 20 +0,0,0,0,0,0,0,0,0,0, // 30 +0,0,2,0,0,0,0,0,3,0, // 40 +0,0,0,0,4,5,6,5,0,10, // 50 +0,0,18,18,18,0,16,17,17,17, // 60 +0,0,0,0,0,0,15,12,0,14, // 70 +0,27,0,0,0,0,9,0,0,0, // 80 +0,0,7,0,0,0,0,0,0,0, // 90 +0,0,9,8,8,13,13,0,0,0, // 100 +0,0,0,0,0,0,0,0,19,19, // 110 +21,11,11,12,0,0,0,22,23,23, // 120 +27,0,24,33,25,26,29,22,27,31, // 130 +28,0,35,30,30,25,0,25,25,0, // 140 +0,0,0,0,0,4,5,5,6,0, // 150 +0,0,33,28,24,9,0,0,29,0, // 160 +0,34,0,32,0,0,31,13,0,0, // 170 +0,0,28,29,0,0,0,33,0,0, // 180 +0,0,0,0,0,0,0,0,0,0}; // 190 + +unsigned char m_pict[200] = { +149,0,1,2,3,4,5,6,7,8, // 0 +9,10,11,12,13,14,15,16,17,18, // 10 +19,20,21,21,22,23,23,24,25,26, // 20 +27,28,29,30,31,3,32,33,34,35, // 30 +36,37,38,39,40,41,43,44,45,46, // 40 +47,46,47,48,49,50,51,52,53,54, // 50 +55,42,57,58,58,56,59,60,61,62, // 60 +63,64,65,66,67,68,69,68,70,70, // 70 +70,71,72,73,74,75,76,76,77,78, // 80 +79,80,81,82,83,84,85,86,87,88, // 90 +88,89,89,90,90,91,91,92,93,94, // 100 +95,96,97,98,99,100,106,101,102,102, // 110 +103,56,149,104,71,56,60,66,105,69, // 120 +107,108,109,110,71,111,112,113,114,115, // 130 +116,117,118,119,120,121,120,121,122,123, // 140 +124,125,126,127,128,49,51,50,51,129, // 150 +130,131,132,133,134,135,136,137,138,139, // 160 +140,141,142,143,144,55,68,140,157,156, // 170 +158,159,166,165,170,155,155,171,149,149, // 180 +149,149,149,149,149,149,149,149,149,149}; // 190 + + +unsigned char m_magic_r[200] = { +0,0,0,0,0,0,0,0,0,0, // 0 +0,0,1,0,0,0,0,0,0,0, // 10 +0,1,1,1,1,1,1,1,1,2, // 20 +2,1,1,0,0,0,0,1,0,0, // 30 +0,0,0,0,0,0,1,0,0,0, +0,1,1,0,0,0,0,0,0,0, // 50 +0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0, +0,0,0,1,0,0,1,1,0,0, +0,0,0,0,0,0,0,1,1,0, +0,2,2,0,0,0,0,2,0,0, //100 +0,0,0,0,0,0,0,0,0,0, +0,0,0,2,0,0,0,0,0,0, +0,0,0,0,0,2,1,1,0,0, +0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,1, // 150 +1,1,1,1,2,2,0,0,1,2, +1,0,0,1,0,0,1,2,0,0, +0,0,2,1,0,0,0,2,0,0, +0,0,0,0,0,0,0,0,0,0}; // 190 + +unsigned char m_fire_r[200] = { +0,0,0,0,0,0,0,0,0,0, // 0 +0,0,1,0,0,0,0,0,0,0, // 10 +0,0,0,1,0,0,1,1,1,1, // 20 +2,0,0,0,0,0,0,1,0,0, // 30 +0,0,0,0,0,0,1,0,0,0, +0,1,1,0,0,0,0,0,0,2, // 50 +0,0,0,0,0,0,0,0,0,1, +0,0,0,2,0,0,0,0,0,0, +0,0,0,2,2,2,2,2,2,0, +0,0,0,0,0,1,1,1,1,0, +0,1,1,0,0,0,0,2,0,0, //100 +0,0,0,0,0,0,0,0,0,0, +0,0,0,2,0,0,0,2,0,0, +0,0,0,0,0,2,1,2,0,0, +0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0, // 150 +2,0,0,1,2,2,0,0,0,0, +2,0,0,0,0,0,1,2,0,2, +0,0,2,1,0,0,0,1,0,0, +0,0,0,0,0,0,0,0,0,0}; // 190 + +unsigned char m_cold_r[200] = { +0,0,0,0,0,0,0,0,0,0, // 0 +0,0,1,0,0,0,0,0,0,0, // 10 +0,0,0,1,0,0,1,0,1,1, // 20 +2,0,0,0,0,0,0,1,0,0, // 30 +0,0,0,0,0,0,1,0,0,0, +0,1,1,0,0,0,0,0,2,2, // 50 +2,2,2,2,2,2,2,2,2,2, +2,2,0,0,2,0,2,0,0,0, +0,1,0,0,0,0,1,1,0,0, +0,0,0,0,0,1,1,1,1,0, +0,1,1,0,0,0,0,2,0,0, //100 +0,0,0,0,0,0,0,0,0,0, +0,2,2,2,0,2,2,0,2,2, +1,1,1,0,0,2,1,0,0,0, +0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0, // 150 +0,2,0,1,2,2,0,0,0,0, +0,0,0,0,0,2,0,1,0,0, +2,0,2,1,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0}; // 190 + +unsigned char m_poison_r[200] = { +0,0,0,0,0,0,0,0,0,0, // 0 +0,0,1,0,0,0,0,0,0,0, // 10 +0,0,0,0,0,0,0,0,0,0, // 20 +1,0,0,0,0,0,1,1,0,0, // 30 +0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,2,2,2, // 50 +2,2,2,2,2,2,2,2,2,2, +2,2,0,0,0,2,2,2,0,0, +2,2,0,0,2,2,2,2,2,0, +0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,2,2,2,0,0, //100 +0,0,0,0,0,0,0,0,0,0, +0,2,2,2,2,2,2,0,0,0, +0,0,0,0,2,1,1,2,2,2, +2,2,2,1,1,1,1,0,0,0, +0,0,0,0,0,0,0,0,0,2, // 150 +2,2,2,1,2,2,0,0,0,0, +1,1,0,0,0,2,2,1,0,0, +0,0,2,2,0,0,0,2,0,0, +0,0,0,0,0,0,0,0,0,0}; // 190 + +unsigned char m_pic_index[200] = { +1,2,3,4,5,6,7,8,9,10, +11,12,13,14,15,16,17,18,19,20, //10 + +21,22,23,24,25, 26,27,28,29,30, //20 +31,32,33,34,35, 36,37,38,39,40, //30 + +41,42,43,44,46,47,48,49,50,51, //40 +53,55,57,59,60,61,62,63,64,65, //50 + +66,67,68,69,70, 71,72,73,74,75, //60 +76,77,78,79,81, 82,83,85,86,87, //70 + +88,89,90,91,92, 93,94,95,96,97, //80 +98,99,100,101,102, 103,104,105,106,107, //90 + +108,109,111,112,113, 114,116,117,118,119, //100 +120,122,123,125,127, 128,129,130,131,135, //110 + +136,137,139,140,141,142,143,144,145,146, //120 +147,148,149,150,151,152,153,154,155,159, //130 + +160,164,166,168,170,171,172,173,174,175, //140 +176,177,178,179,180,181,182,183,184,185, //150 + +186,187,188,189,190,191,192,193,194,195, //160 +196,197,198,199,0,0,0,0,0,0, //170 + +0,0,0,0,0,0,0,0,0,0, //180 +0,0,0,0,0,0,0,0,0,0}; //190 + +unsigned char m_pic_index_x[200] = { + +1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1, //10 +1,1,1,1,1,1,1,1,1,1, //20 +1,1,1,1,1,1,1,1,1,1, //30 +1,1,1,1,1,1,1,1,1,1, //40 +1,1,1,1,1,1,1,1,1,1, //50 +1,1,1,1,1,1,1,1,1,1, //60 +1,1,1,2,1,1,1,1,1,1, //70 +1,1,1,1,1,1,1,1,1,1, //80 +1,1,1,1,1,1,1,1,1,1, //90 + +1,2,1,1,1,2,1,1,1,1, // 100 +2,1,1,1,1,1,1,1,2,1, //110 +1,2,1,1,1,1,1,1,1,1, //120 +1,1,1,1,1,1,1,1,2,1, //130 + +2,2,2,1,1,1,1,1,1,1, //140 +1,1,1,1,1,1,1,1,1,1, //150 +1,1,1,1,1,1,1,1,1,1, //160 +1,1,1,1,1,1,1,1,1,1, //170 +1,1,1,1,1,1,1,1,1,1, //180 +1,1,1,1,1,1,1,1,1,1}; //190 + +unsigned char m_pic_index_y[200] = { +1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1, //10 +1,1,1,1,1,1,1,1,1,1, //20 +1,1,1,1,1,1,1,1,1,1, //30 +1,1,1,1,1,1,1,1,1,2, //40 +2,2,2,1,1,1,1,1,1,1, //50 +1,1,1,1,1,1,1,1,1,1, //60 +1,1,1,1,1,1,2,1,1,1, //70 +1,1,1,1,1,1,1,1,1,1, //80 +1,1,1,1,1,1,1,1,1,1, //90 + +1,1,1,1,1,1,1,1,1,1, //100 +1,1,2,2,1,1,1,1,2,1, //110 +1,1,1,1,1,1,1,1,1,1, //120 +1,1,1,1,1,1,1,1,2,1, //130 +2,1,1,2,1,1,1,1,1,1, //140 + +1,1,1,1,1,1,1,1,1,1, //150 +1,1,1,1,1,1,1,1,1,1, //160 +1,1,1,1,1,1,1,1,1,1, //170 +1,1,1,1,1,1,1,1,1,1, //180 +1,1,1,1,1,1,1,1,1,1}; //190 + +short ter_pics[256] = {0,1,2,3,4,5,6,6,7,8, +8,9,10,10,11,12,12,13,14,15, +16,17,18,19,20,21,22,23,24,25, +26,27,28,29,30,31,32,33,34,35, +36,37,38,39,40,41,42,43,44,45, +46,47,48,49,50,51,52,53,54,55, +56,57,58,59,60,61,62,63,64,65, +66,400,401,402,403,404,404,405,406,202, +203,204,215,216,67,68,69,85,86,87, +74,70,71,72,73,75,76,83,84,121, +122,178,179,180,411,182,183,184,185,186, +79,80,81,82,83,84,198,199,181,205, +206,227,88,88,89,90,90,90,90,91, +92,93,94,95,96,88,97,98,99,100, +100,101,102,102,102,102,103,104,105,106, +107,108,100,109,110,110,111,112,112,112, +112,113,114,115,116,117,118,110,119,120, +123,123,123,124,125,126,127,128,129,150, +151,152,146,147,148,149,130,131,132,133, +134,135,136,137,138,139,140,141,142,143, +144,145,153,154,155,156,412,413,213,214, +157,157,158,159,160,161,162,163,164,165, +166,167,168,169,170,171,172,173,174,175, +176,177,187,188,189,190,2,192,193,195, +194,196,197,191,200,201,207,208,209,210, +211,212,407,408,409,410}; + +short ter_block[256] = { +0,0,0,0,0,5,5,1,5,5, +1,5,5,1,5,5,1,5,5,5, +5,5,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,0,0,0,0, +0,0,0,0,0,0,0,0,0,0, + +3,3,3,3,3,3,3,3,3,3, +3,3,3,0,3,0,0,0,0,0, +0,3,0,0,3,2,2,4,2,0, +0,0,0,0,0,0,0,0,0,0, +3,4,0,0,0,4,0,4,0,4, + +4,4,0,0,4,0,4,4,0,4, +4,0,4,4,0,0,5,5,0,4, +4,4,5,5,1,5,5,5,5,0, +4,0,5,4,5,5,5,5,4,5, +5,1,5,5,5,5,0,4,0,5, + +5,5,5,4,5,5,1,5,5,5, +5,0,4,0,5,5,5,5,5,4, +0,2,2,0,4,4,4,4,4,4, +4,4,4,4,4,4,4,4,4,4, +4,5,4,4,4,0,0,0,0,0, + +0,4,4,4,0,4,0,0,2,2, +0,2,4,4,4,0,4,0,4,0, +0,0,4,4,0,0,4,4,4,4, +4,4,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,2,2,2,2, +2,2,0,0,0,0}; + +short ter_traits[256] = { +0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0, + +0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,2,0,15,0,0, +0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,5,0,0,0, + +0,14,14,0,0,0,11,11,0,0, +0,5,0,0,0,0,0,0,0,0, +0,11,0,1,0,1,10,10,10,22, +9,8,11,7,7,7,0,0,0,0, +1,0,1,10,10,10,22,9,8,11, + +7,7,7,0,0,1,0,1,10,10, +10,22,9,8,11,7,7,7,0,0, +0,20,4,20,0,14,0,0,0,0, +0,0,0,0,0,0,0,0,0,0, +0,14,0,0,14,0,0,0,0,0, + +0,14,0,0,0,0,0,0,0,0, +0,20,0,0,0,0,0,0,0,0, +0,14,0,14,20,0,0,0,0,0, +0,0,21,21,21,21,21,21,21,21, +21,21,21,21,21,21,0,0,0,0, +0,0,16,17,18,19}; + +monster_record_type return_monster_template(unsigned char store) +{ + monster_record_type monst; + short m_num,i; + + m_num = store; + monst.m_num = m_num; + if (m_num >= 187) + m_num = 187; + monst.level = m_level[m_num]; + monst.m_health = m_health[m_num]; + monst.health = monst.m_health; + monst.max_mp = 0; + monst.mp = monst.max_mp; + monst.armor = m_armor[m_num]; + monst.skill = m_skill[m_num]; + monst.a[0] = m_a1[m_num]; + monst.a[1] = m_a2[m_num]; + monst.a[2] = m_a3[m_num]; + if (monst.a[0] > 0) + monst.a[0] += 100; + if (monst.a[1] > 0) + monst.a[1] += 100; + if (monst.a[2] > 0) + monst.a[2] += 100; + monst.a1_type = m_a1t[m_num]; + monst.a23_type = m_a23t[m_num]; + monst.m_type = m_type[m_num]; + monst.speed = m_speed[m_num]; + monst.ap = 0; + monst.mu = m_mu[m_num]; + monst.cl = m_cl[m_num]; + if ((monst.mu > 0) || (monst.cl > 0)) + monst.max_mp = monst.mp = 14 * m_level[m_num]; + monst.breath = m_breath[m_num] % 100; + monst.breath_type = m_breath[m_num] / 100; + monst.treasure = m_treas[m_num]; + monst.spec_skill = m_abil[m_num]; + monst.m_morale = 10 * m_level[m_num]; + if (m_level[m_num] >= 20) + monst.m_morale += 10 * (m_level[m_num] - 20); + + monst.morale = monst.m_morale; + monst.poison = m_poison[m_num]; + monst.picture_num = m_pict[m_num]; + monst.direction = 0; + monst.corpse_item = -1; + monst.corpse_item_chance = -1; + for (i = 0; i < 15; i++) + monst.status[i] = 0; + monst.x_width = monst.y_width = 1; + for (i = 0; i < 200; i++) + if (m_pict[m_num] == m_pic_index[i]) { + monst.picture_num = i; + monst.x_width = m_pic_index_x[i]; + monst.y_width = m_pic_index_y[i]; + i = 200; + } +// monst.x_width = xdim[m_num]; +// monst.y_width = ydim[m_num]; + monst.radiate_1 = 0; + monst.radiate_2 = 0; + monst.default_attitude = 0; + monst.summon_type = 0; + monst.default_facial_pic = 0; + monst.res1 = 0; + monst.res2 = 0; + monst.res3 = 0; + + monst.immunities = 0; + if (m_magic_r[m_num] == 1) + monst.immunities = monst.immunities | 1; + if (m_magic_r[m_num] == 2) + monst.immunities = monst.immunities | 2; + if (m_fire_r[m_num] == 1) + monst.immunities = monst.immunities | 4; + if (m_fire_r[m_num] == 2) + monst.immunities = monst.immunities | 8; + if (m_cold_r[m_num] == 1) + monst.immunities = monst.immunities | 16; + if (m_cold_r[m_num] == 2) + monst.immunities = monst.immunities | 32; + if (m_poison_r[m_num] == 1) + monst.immunities = monst.immunities | 64; + if (m_poison_r[m_num] == 2) + monst.immunities = monst.immunities | 128; + + return monst; +} + + +void init_scenario() +{ + short i; + RECT dummy_rect = {0,0,0,0}; + char temp_str[256]; + boat_record_type null_boat = {{0,0},{0,0},{0,0},-1,FALSE,FALSE}; + horse_record_type null_horse = {{0,0},{0,0},{0,0},-1,FALSE,FALSE}; + item_storage_shortcut_type null_item_s ={-1,{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},{0,0,0,0,0,0,0,0,0,0},0}; + short j,item_to_hide[13] = {214,233,270,271,280,281,286,290,291,297,304,311,348}; + + scenario.ver[0] = 1; + scenario.ver[1] = 0; + scenario.ver[2] = 0; + scenario.min_run_ver = 1; + scenario.prog_make_ver[0] = 1; + scenario.prog_make_ver[1] = 0; + scenario.prog_make_ver[2] = 0; + scenario.num_towns = 1; + scenario.out_width = 1; + scenario.out_height = 1; + scenario.difficulty = 0; + scenario.intro_pic = 0; + scenario.default_ground = 1; + for (i = 0; i < 200; i++) { + scenario.town_size[i] = 1; + scenario.town_hidden[i] = 0; + scenario.town_data_size[i][0] = 0; + scenario.town_data_size[i][1] = 0; + scenario.town_data_size[i][2] = 0; + scenario.town_data_size[i][3] = 0; + scenario.town_data_size[i][4] = 0; + } + scenario.intro_mess_len = 0; + scenario.where_start.x = 24; + scenario.where_start.y = 24; + scenario.out_sec_start.x = 0; + scenario.out_sec_start.y = 0; + scenario.out_start = scenario.where_start; + scenario.which_town_start = 0; + for (i = 0; i < 10; i++) { + scenario.town_to_add_to[i] = -1; + scenario.flag_to_add_to_town[i][0] = 0; + scenario.flag_to_add_to_town[i][1] = 0; + } + for (i = 0; i < 100; i++) { + scenario.out_data_size[i][0] = 0; + scenario.out_data_size[i][1] = 0; + } + for (i = 0; i < 3; i++) { + scenario.store_item_rects[i] = dummy_rect; + scenario.store_item_towns[i] = -1; + } + for (i = 0; i < 50; i++) { + scenario.special_items[i] = 0; + scenario.special_item_special[i] = -1; + } + scenario.rating = 0; + scenario.uses_custom_graphics = 0; + for (i = 0; i < 256; i++) { + scenario.scen_monsters[i] = return_monster_template(i); + get_str(temp_str,2,i); + if ((i > 187) || (i == 0)) + sprintf((char *)scen_item_list.monst_names[i], "Unused"); + else sprintf((char *)scen_item_list.monst_names[i], "%s", temp_str); + if (i == 0) + sprintf((char *)scen_item_list.monst_names[i], "Empty"); + } + for (i = 0; i < 30; i++) { + scenario.scen_boats[i] = null_boat; + scenario.scen_horses[i] = null_horse; + } + for (i = 0; i < 256; i++) { + scenario.ter_types[i].picture = ter_pics[i]; + scenario.ter_types[i].blockage = ter_block[i]; + scenario.ter_types[i].special = ter_traits[i]; + get_str(temp_str,1,i + 1); + sprintf((char *)scen_item_list.ter_names[i], "%s", temp_str); + + scenario.scen_specials[i] = null_spec_node; + } + for (i = 0; i < 20; i++) { + scenario.scenario_timer_times[i] = 0; + scenario.scenario_timer_specs[i] = -1; + } + for (i = 0; i < 10; i++) { + scenario.storage_shortcuts[i] = null_item_s; + } + scenario.last_out_edited.x = 0; + scenario.last_out_edited.y = 0; + scenario.last_town_edited = 0; + for (i = 0; i < 400; i++) { + scen_item_list.scen_items[i].variety = 0; + // = + + for (j = 0; j < 13; j++) + if (i == item_to_hide[j]) + scen_item_list.scen_items[i].item_properties = + scen_item_list.scen_items[i].item_properties | 32; + } + for (i = 0; i < 270; i++) { + get_str(temp_str,35,i + 1); + if (i < 160) { + sprintf((char *)scen_strs[i], "%s", temp_str); + scenario.scen_str_len[i] = strlen((char *) scen_strs[i]); + } + else { + sprintf((char *)scen_strs2[i - 160], "%s", temp_str); + scenario.scen_str_len[i] = strlen((char *) scen_strs[i - 160]); + } + } +} +void put_ter_info_in_dlog() +{ + char str[256]; + + cdsin(813,12,store_which_ter); + CDST(813,2,scen_item_list.ter_names[store_which_ter]); + CDSN(813,5,store_ter.picture); + cd_set_led_range(813,19,24,store_ter.blockage); + cd_set_led(813,25,store_ter.fly_over); + cd_set_led(813,26,store_ter.boat_over); + cd_set_led(813,27,store_ter.block_horse); + cd_set_led_range(813,28,31,store_ter.step_sound); + str[0] = store_ter.shortcut_key; + str[1] = 0; + CDST(813,3,(char *) str); + CDSN(813,4,store_ter.trans_to_what); + CDSN(813,8,store_ter.light_radius); + cd_set_led_range(813,32,55,store_ter.special); + CDSN(813,6,store_ter.flag1); + CDSN(813,7,store_ter.flag2); + get_str(str,21,40 + store_ter.special); + csit(813,67,(char *) str); + get_str(str,21,80 + store_ter.special); + csit(813,68,(char *) str); + if (store_ter.picture >= 2000){ + custom_pic = 5; + csp(813,14,store_ter.picture-2000); + } + else if (store_ter.picture >= 1000){ + custom_pic = 1; + csp(813,14,store_ter.picture-1000); + } + else if (store_ter.picture >= 400) + csp(813,14,store_ter.picture - 100); + else csp(813,14,store_ter.picture); +} + + +Boolean save_ter_info() +{ + char str[256]; + short i; + + + store_ter.picture = CDGN(813,5); + if ((store_ter.picture < 0) || + ((store_ter.picture > 413) && (store_ter.picture < 1000))) { + give_error("Picture number isn't in the proper range.","",813); + return FALSE; + } + + if (store_which_ter >= 0) { + store_ter.blockage = cd_get_led_range(813,19,24); + store_ter.special = cd_get_led_range(813,32,55); + i = CDGN(813,6); + if ((store_ter.special < 2) || (store_ter.special > 6)) { // 0, 1, >= 7 + if (cre(i,0,256,"First special flag must be from 0 to 255.","",813) == TRUE) return FALSE; + } + else if ((store_ter.special > 1) && (store_ter.special <= 4)) { // 2, 3, 4 + if (cre(i,0,256,"First special flag must be from 0 to 100.","",813) == TRUE) return FALSE; + } + else if ((store_ter.special > 4) && (store_ter.special <= 7)) { // 5, 6, 7 + if (cre(i,0,256,"First special flag must be from 0 to 8.","",813) == TRUE) return FALSE; + } + store_ter.flag1 = CDGN(813,6); + + i = CDGN(813,7); + if ((store_ter.special == 1) || (store_ter.special == 21)) { + if (cre(i,0,256,"Second special flag must be from 0 to 200.","",813) == TRUE) return FALSE; + } + else if ((store_ter.special > 1) && (store_ter.special <= 7)) { // 2,3,4,5,6,7 + if (cre(i,0,256,"Second special flag must be from 0 to 100.","",813) == TRUE) return FALSE; + } + store_ter.flag2 = CDGN(813,7); + + i = CDGN(813,4); + if (cre(i,0,255,"Transform To What must be from 0 to 255.","",813) == TRUE) return FALSE; + store_ter.trans_to_what = CDGN(813,4); + store_ter.fly_over = cd_get_led(813,25); + store_ter.boat_over = cd_get_led(813,26); + store_ter.block_horse = cd_get_led(813,27); + store_ter.light_radius = CDGN(813,8); + if (cre(store_ter.light_radius,0,8,"Light radius must be from 0 to 8.","",813) == TRUE) return FALSE; + + store_ter.step_sound = cd_get_led_range(813,28,31); + } + CDGT(813,3,(char *) str); + store_ter.shortcut_key = str[0]; + + CDGT(813,2,(char *) str); + str[29] = 0; + sprintf(scen_item_list.ter_names[store_which_ter],"%s",str); + + scenario.ter_types[store_which_ter] = store_ter; + return TRUE; +} + +void edit_ter_type_event_filter (short item_hit) +{ + char str[256]; + short i; + switch (item_hit) { + case 9: + dialog_not_toast = FALSE; + store_ter.picture = 0; + break; + case 62: + if (save_ter_info() == TRUE) + dialog_not_toast = FALSE; + store_ter.picture = 0; + break; + case 10: + if (save_ter_info() == FALSE) break; + store_which_ter--; + if (store_which_ter < 0) store_which_ter = 255; + store_ter = scenario.ter_types[store_which_ter]; + put_ter_info_in_dlog(); + break; + case 11: + if (save_ter_info() == FALSE) break; + store_which_ter++; + if (store_which_ter > 255) store_which_ter = 0; + store_ter = scenario.ter_types[store_which_ter]; + put_ter_info_in_dlog(); + break; + + case 13: case 70: + if (item_hit == 13) // Pick Picture + i = choose_graphic(0,252,store_ter.picture,813); + else { + do_choose_anim = TRUE; + i = choose_graphic(300,313,store_ter.picture,813); // Animated + } + if (i >= 0) { + if (i >= 300) i += 100; + store_ter.picture = i; + custom_pic = store_ter.picture / 1000; + } + else { + custom_pic = store_ter.picture / 1000; + break; + } + CDSN(813,5,store_ter.picture); + + if(store_ter.picture >= 2000){ + custom_pic = 5; + csp(813,14,store_ter.picture-2000); + } + else if (store_ter.picture >= 1000) { + custom_pic = 1; + csp(813,14,store_ter.picture-1000); + } + else if (store_ter.picture >= 400) + csp(813,14,store_ter.picture - 100); + else csp(813,14,store_ter.picture); + break; + + default: + cd_hit_led_range(813,32,55,item_hit); + cd_hit_led_range(813,28,31,item_hit); + cd_hit_led_range(813,19,24,item_hit); + cd_flip_led(813,25,item_hit); + cd_flip_led(813,26,item_hit); + cd_flip_led(813,27,item_hit); + if ((item_hit >= 32) && (item_hit <= 55)) { + get_str(str,21,40 + item_hit - 32); + csit(813,67,(char *) str); + get_str(str,21,80 + item_hit - 32); + csit(813,68,(char *) str); + } + break; + + } +} + +short edit_ter_type(short which_ter) +// ignore parent in Mac version +{ + short item_hit,i,store_dialog_answer; + char temp_str[256]; + char *blocked_strs[6] = {"Clear","Walk through, Opaque","Clear, Special","Clear, Blocked","Blocked, Obstructed", + "Blocked, Opaque"}; + char *sound_strs[4] = {"Footstep","Squish","Crunch","Silence"}; + + store_which_ter = which_ter; + store_ter = scenario.ter_types[which_ter]; + //make_cursor_sword(); + + cd_create_dialog_parent_num(813,0); + put_ter_info_in_dlog(); + for (i = 0; i < 24; i++) { + get_str(temp_str,21,i + 1); + cd_add_label(813,32 + i,(char *) temp_str,57); + } + for (i = 0; i < 4; i++) + cd_add_label(813,28 + i,sound_strs[i],35); + for (i = 0; i < 6; i++) + cd_add_label(813,19 + i,blocked_strs[i],57); + cd_attach_key(813,10,0); + cd_attach_key(813,11,0); + while (dialog_not_toast) + ModalDialog(); + + cd_kill_dialog(813,0); + return 0; +} + +void put_monst_info_in_dlog() +{ + char str[256]; + + if (store_monst.picture_num < 1000) + csp(814,34,400 + store_monst.picture_num); + else{ + custom_pic = store_monst.picture_num / 1000; + csp(814,34,store_monst.picture_num - custom_pic * 1000); + } + cdsin(814,33,store_which_monst); + CDST(814,2,scen_item_list.monst_names[store_which_monst]); + CDSN(814,3,store_monst.picture_num); + sprintf((char *) str,"Width = %d",store_monst.x_width); + csit(814,40,(char *) str); + sprintf((char *) str,"Height = %d",store_monst.y_width); + csit(814,41,(char *) str); + CDSN(814,4,store_monst.level); + CDSN(814,5,store_monst.health); + CDSN(814,6,store_monst.armor); + CDSN(814,7,store_monst.skill); + CDSN(814,8,store_monst.speed); + CDSN(814,9,store_monst.mu); + CDSN(814,10,store_monst.cl); + CDSN(814,11,store_monst.a[0] / 100); + CDSN(814,12,store_monst.a[0] % 100); + CDSN(814,13,store_monst.a[1] / 100); + CDSN(814,14,store_monst.a[1] % 100); + CDSN(814,15,store_monst.a[2] / 100); + CDSN(814,16,store_monst.a[2] % 100); + CDSN(814,17,store_monst.default_facial_pic); + CDSN(814,18,store_monst.treasure); + + cd_set_led_range(814,29,32,store_monst.default_attitude); + + get_str(str,20,150 + store_monst.m_type); + csit(814,42,(char *) str); + get_str(str,20,130 + store_monst.a1_type); + csit(814,43,(char *) str); + get_str(str,20,130 + store_monst.a23_type); + csit(814,44,(char *) str); +} + +Boolean save_monst_info() +{ + char str[256]; + short i; + + CDGT(814,2,(char *) str); + str[19] = 0; + sprintf(scen_item_list.monst_names[store_which_monst],"%s",str); + //CDGT(814,2,scen_item_list.monst_names[store_which_monst]); + store_monst.picture_num = CDGN(814,3); + if (cre(store_monst.picture_num,0,5000,"Monster pic must be from 0 to 5000.","",814) > 0) return FALSE; + // later check pic num for error, and assign widths if custom + if (store_monst.picture_num >= 1000) { + if ((store_monst.picture_num >= 1000) && (store_monst.picture_num < 2000)) { + store_monst.x_width = 1; store_monst.y_width = 1; } + if ((store_monst.picture_num >= 2000) && (store_monst.picture_num < 3000)) { + store_monst.x_width = 2; store_monst.y_width = 1; } + if ((store_monst.picture_num >= 3000) && (store_monst.picture_num < 4000)) { + store_monst.x_width = 1; store_monst.y_width = 2; } + if ((store_monst.picture_num >= 4000) && (store_monst.picture_num < 5000)) { + store_monst.x_width = 2; store_monst.y_width = 2; } + } + else { + if (cre(store_monst.picture_num,0,174,"Non-customized monster pic must be from 0 to 173.","",814) > 0) return FALSE; + store_monst.x_width = m_pic_index_x[store_monst.picture_num]; + store_monst.y_width = m_pic_index_y[store_monst.picture_num]; + + } + store_monst.level = CDGN(814,4); + if (cre(store_monst.level,0,40,"Level must be from 0 to 40.","",814) > 0) return FALSE; + store_monst.m_health = store_monst.health = CDGN(814,5); + if (cre(store_monst.health,0,2500,"Health must be from 0 to 2500.","",814) > 0) return FALSE; + store_monst.armor = CDGN(814,6); + if (cre(store_monst.armor,0,50,"Armor must be from 0 to 50.","",814) > 0) return FALSE; + store_monst.skill = CDGN(814,7); + if (cre(store_monst.skill,0,40,"Skill must be from 0 to 40.","",814) > 0) return FALSE; + store_monst.speed = CDGN(814,8); + if (cre(store_monst.speed,1,12,"Speed must be from 2 to 12.","",814) > 0) return FALSE; + store_monst.mu = CDGN(814,9); + if (cre(store_monst.mu,0,7,"Magic Spells must be from 0 to 7.","",814) > 0) return FALSE; + store_monst.cl = CDGN(814,10); + if (cre(store_monst.cl,0,7,"Priest Spells must be from 0 to 7.","",814) > 0) return FALSE; + + i = CDGN(814,11); + if (cre(i,0,20,"Attack 1 number of dice must be from 0 to 20 (0 means no attack).","",814) > 0) return FALSE; + i = CDGN(814,13); + if (cre(i,0,20,"Attack 2 number of dice must be from 0 to 20 (0 means no attack).","",814) > 0) return FALSE; + i = CDGN(814,15); + if (cre(i,0,20,"Attack 3 number of dice must be from 0 to 20 (0 means no attack).","",814) > 0) return FALSE; + i = CDGN(814,12); + if (cre(i,0,50,"Attack 1 damage per die must be from 1 to 50.","",814) > 0) return FALSE; + i = CDGN(814,14); + if (cre(i,0,50,"Attack 2 damage per die must be from 1 to 50.","",814) > 0) return FALSE; + i = CDGN(814,16); + if (cre(i,0,50,"Attack 3 damage per die must be from 1 to 50.","",814) > 0) return FALSE; + + + store_monst.a[0] = CDGN(814,11) * 100 + CDGN(814,12); + store_monst.a[1] = CDGN(814,13) * 100 + CDGN(814,14); + store_monst.a[2] = CDGN(814,15) * 100 + CDGN(814,16); + + store_monst.default_facial_pic = CDGN(814,17); // later + store_monst.treasure = CDGN(814,18); + if (cre(store_monst.treasure,0,4,"Treasure must be from 0 to 4.","",814) > 0) return FALSE; + store_monst.default_attitude = cd_get_led_range(814,29,32); + + return TRUE; +} + +void edit_monst_type_event_filter (short item_hit) +{ + char str[256]; + short i; + monster_record_type temp_monst; + + switch (item_hit) { + case 20: + dialog_not_toast = FALSE; break; + case 19: + if (save_monst_info() == TRUE) { + scenario.scen_monsters[store_which_monst] = store_monst; + dialog_not_toast = FALSE; + } + break; + case 23: // abils + if (save_monst_info() == FALSE) break; + temp_monst = edit_monst_abil(store_monst,814); + if ((temp_monst.level >= 0) && (temp_monst.level < 255)) + store_monst = temp_monst; + put_monst_info_in_dlog(); + break; + case 21: + if (save_monst_info() == FALSE) break; + scenario.scen_monsters[store_which_monst] = store_monst; + store_which_monst--; + if (store_which_monst < 1) store_which_monst = 255; + store_monst = scenario.scen_monsters[store_which_monst]; + put_monst_info_in_dlog(); + break; + case 22: + if (save_monst_info() == FALSE) break; + scenario.scen_monsters[store_which_monst] = store_monst; + store_which_monst++; + if (store_which_monst > 255) store_which_monst = 1; + store_monst = scenario.scen_monsters[store_which_monst]; + put_monst_info_in_dlog(); + break; + case 24: // picture + if (save_monst_info() == FALSE) break; + i = choose_graphic(400,572,store_monst.picture_num + 400,814); + if (i >= 0) { + store_monst.picture_num = i - 400; + } + else break; + store_monst.x_width = m_pic_index_x[i-400]; + store_monst.y_width = m_pic_index_y[i-400]; + put_monst_info_in_dlog(); + break; + case 25: // m type + if (save_monst_info() == FALSE) break; + i = choose_text_res(20,150,164,store_monst.m_type + 150,814,"Choose Monster Type:"); + if (i >= 0) { + store_monst.m_type = i - 150; + put_monst_info_in_dlog(); + } + break; + case 26: // att type 1 + if (save_monst_info() == FALSE) break; + i = choose_text_res(20,130,139,store_monst.a1_type + 130,814,"Choose Attack 1 Type:"); + if (i >= 0) { + store_monst.a1_type = i - 130; + put_monst_info_in_dlog(); + } + break; + case 27: // att type 23 + if (save_monst_info() == FALSE) break; + i = choose_text_res(20,130,139,store_monst.a23_type + 130,814,"Choose Attack 2 & 3 Type:"); + if (i >= 0) { + store_monst.a23_type = i - 130; + put_monst_info_in_dlog(); + } + break; + case 28: // talk pic + if (save_monst_info() == FALSE) break; + i = choose_graphic(1001,1084,store_monst.default_facial_pic + 1000,814); + if (i >= 0) { + store_monst.default_facial_pic = i - 1000; + } + else break; + put_monst_info_in_dlog(); + break; + default: + cd_hit_led_range(814,29,32,item_hit); + break; + + } +} + +short edit_monst_type(short which_monst) +// ignore parent in Mac version +{ + short item_hit,i,store_dialog_answer; + char temp_str[256]; + char *attitude[4] = {"Friendly, Docile","Hostile, Type A","Friendly, Will Fight","Hostile, Type B"}; + + store_which_monst = which_monst; + store_monst = scenario.scen_monsters[which_monst]; + //make_cursor_sword(); + + cd_create_dialog_parent_num(814,0); + + put_monst_info_in_dlog(); + + for (i = 0; i < 4; i++) + cd_add_label(814,29 + i,attitude[i],57); + cd_attach_key(814,21,0); + cd_attach_key(814,22,0); + while (dialog_not_toast) + ModalDialog(); + + cd_kill_dialog(814,0); + + return 0; + } + +void put_monst_abils_in_dlog() +{ + char str[256]; + short i; + + cdsin(815,24,store_which_monst); + + + CDSN(815,2,store_monst2.poison); + CDSN(815,3,store_monst2.breath); + + get_str(str,20,store_monst2.spec_skill + 1); + csit(815,30,(char *) str); + get_str(str,20,store_monst2.radiate_1 + 50); + csit(815,33,(char *) str); + get_str(str,20,store_monst2.radiate_1 + 80); + csit(815,36,(char *) str); + CDSN(815,4,store_monst2.radiate_2); + CDSN(815,5,store_monst2.corpse_item); + CDSN(815,6,store_monst2.corpse_item_chance); + cd_set_led_range(815,9,12,store_monst2.breath_type); + cd_set_led_range(815,41,44,store_monst2.summon_type); + for (i = 0; i < 8; i++) + cd_set_led(815,13 + i,0); + if (store_monst2.immunities & 1 ) cd_set_led(815,13,1); + if (store_monst2.immunities & 2 ) cd_set_led(815,14,1); + if (store_monst2.immunities & 4 ) cd_set_led(815,15,1); + if (store_monst2.immunities & 8 ) cd_set_led(815,16,1); + if (store_monst2.immunities & 16 ) cd_set_led(815,17,1); + if (store_monst2.immunities & 32 ) cd_set_led(815,18,1); + if (store_monst2.immunities & 64 ) cd_set_led(815,19,1); + if (store_monst2.immunities & 128 ) cd_set_led(815,20,1); +} + +Boolean save_monst_abils() +{ + char str[256]; + short i; + + store_monst2.poison = CDGN(815,2); + if (cre(store_monst2.poison,0,8,"Poison must be from 0 to 8.","",815) > 0) return FALSE; + store_monst2.breath = CDGN(815,3); + if (cre(store_monst2.poison,0,40,"Breath Damage must be from 0 to 4.","",815) > 0) return FALSE; + store_monst2.breath_type = cd_get_led_range(815,9,12); + store_monst2.summon_type = cd_get_led_range(815,41,44); + store_monst2.radiate_2 = CDGN(815,4); + if ((store_monst2.radiate_1 >= 1) && (store_monst2.radiate_1 <= 6)) + if (cre(store_monst2.radiate_2,0,100,"Radiation Chance must be from 0 to 100.","",815) > 0) return FALSE; + if ((store_monst2.radiate_1 >= 10) && (store_monst2.radiate_1 <= 12)) + if (cre(store_monst2.radiate_2,0,255,"Summoned Monster must be from 0 to 255.","",815) > 0) return FALSE; + + store_monst2.corpse_item = CDGN(815,5); + if (cre(store_monst2.corpse_item,-1,399,"Item To Drop must be from 0 to 399 (or -1 for no item).","",815) > 0) return FALSE; + store_monst2.corpse_item_chance = CDGN(815,6); + if (cre(store_monst2.corpse_item_chance,-1,100,"Dropping Chance must be from 0 to 100 (or -1 for no item).","",815) > 0) return FALSE; + store_monst2.immunities = 0; + if (cd_get_led(815,13) == 1) store_monst2.immunities = store_monst2.immunities | 1; + if (cd_get_led(815,14) == 1) store_monst2.immunities = store_monst2.immunities | 2; + if (cd_get_led(815,15) == 1) store_monst2.immunities = store_monst2.immunities | 4; + if (cd_get_led(815,16) == 1) store_monst2.immunities = store_monst2.immunities | 8; + if (cd_get_led(815,17) == 1) store_monst2.immunities = store_monst2.immunities | 16; + if (cd_get_led(815,18) == 1) store_monst2.immunities = store_monst2.immunities | 32; + if (cd_get_led(815,19) == 1) store_monst2.immunities = store_monst2.immunities | 64; + if (cd_get_led(815,20) == 1) store_monst2.immunities = store_monst2.immunities | 128; + return TRUE; +} + +void edit_monst_abil_event_filter (short item_hit) +{ + char str[256]; + short i; + + switch (item_hit) { + case 8: store_monst2.level = -1; + dialog_not_toast = FALSE; break; + case 7: + if (save_monst_abils() == TRUE) + dialog_not_toast = FALSE; + break; + case 31: // abils + if (save_monst_abils() == FALSE) break; + i = choose_text_res(20,1,38,store_monst2.spec_skill + 1,815,"Choose Monster Ability:"); + if (i >= 0) { + store_monst2.spec_skill = i - 1; + put_monst_abils_in_dlog(); + } + break; + case 34: // radiate + if (save_monst_abils() == FALSE) break; + i = choose_text_res(20,50,65,store_monst2.radiate_1 + 50,815,"Choose Radiation Ability:"); + if (i >= 0) { + store_monst2.radiate_1 = i - 50; + put_monst_abils_in_dlog(); + } + break; + default: + cd_hit_led_range(815,9,12,item_hit); + cd_hit_led_range(815,41,44,item_hit); + for (i = 13; i < 21; i++) + cd_flip_led(815,i,item_hit); + break; + + } +} + +monster_record_type edit_monst_abil(monster_record_type starting_record,short parent_num) +// ignore parent in Mac version +{ + short item_hit,i,store_dialog_answer; + char temp_str[256]; + + //store_which_monst = which_monst; + store_monst2 = starting_record; + //make_cursor_sword(); + + cd_create_dialog_parent_num(815,parent_num); + + put_monst_abils_in_dlog(); + + cd_add_label(815,9,"Fire",35); + cd_add_label(815,10,"Cold",35); + cd_add_label(815,11,"Electricity",35); + cd_add_label(815,12,"Darkness",35); + cd_add_label(815,41,"No Summon",35); + cd_add_label(815,42,"Type 1",35); + cd_add_label(815,43,"Type 2",35); + cd_add_label(815,44,"Type 3",35); + + cd_add_label(815,13,"Resist Magic",55); + cd_add_label(815,15,"Resist Fire",55); + cd_add_label(815,17,"Resist Cold",55); + cd_add_label(815,19,"Resist Poison",55); + cd_add_label(815,14,"Immune To Magic",55); + cd_add_label(815,16,"Immune To Fire",55); + cd_add_label(815,18,"Immune To Cold",55); + cd_add_label(815,20,"Immune To Poison",55); + + while (dialog_not_toast) + ModalDialog(); + + cd_kill_dialog(815,0); + return store_monst2; +} + +void put_item_info_in_dlog() +{ + char str[256]; + + cdsin(818,52,store_which_item); + CDST(818,2,store_item.full_name); + CDST(818,3,store_item.name); + if (store_item.graphic_num >= 150){ //150 ?? should be 122 ... + custom_pic = 1; + csp(818,49,store_item.graphic_num - 150); + } + else csp(818,49,1800 + store_item.graphic_num); + CDSN(818,4,store_item.graphic_num); + cd_set_led_range(818,18,45,store_item.variety); + CDSN(818,5,store_item.item_level); + CDSN(818,6,store_item.awkward); + CDSN(818,7,store_item.bonus); + CDSN(818,8,store_item.protection); + CDSN(818,9,store_item.charges); + CDSN(818,10,store_item.type_flag); + CDSN(818,11,store_item.value); + CDSN(818,12,store_item.weight); + CDSN(818,13,store_item.special_class); + cd_set_led_range(818,46,48,store_item.type - 1); + +} + +Boolean save_item_info() +{ + char str[256]; + short i; + + CDGT(818,2,(char *) str); + str[24] = 0; + sprintf(store_item.full_name,"%s",str); + CDGT(818,3,(char *) str); + str[14] = 0; + sprintf(store_item.name,"%s",str); + store_item.graphic_num = CDGN(818,4); + + store_item.variety = cd_get_led_range(818,18,45); + store_item.type = cd_get_led_range(818,46,48) + 1; + + store_item.item_level = CDGN(818,5); + if (cre(store_item.item_level,0,50,"Item Level must be from 0 to 50.","",818) > 0) return FALSE; + if (((store_item.variety == 3) || (store_item.variety == 11)) && (store_item.item_level == 0)) + store_item.item_level = 1; + + store_item.awkward = CDGN(818,6); + if (cre(store_item.awkward,0,20,"Awkward must be from 0 to 20.","",818) > 0) return FALSE; + store_item.bonus = CDGN(818,7); + if (cre(store_item.bonus,0,60,"Bonus must be from 0 to 60.","",818) > 0) return FALSE; + store_item.protection = CDGN(818,8); + if (cre(store_item.protection,-10,20,"Protection must be from -10 to 20.","",818) > 0) return FALSE; + store_item.charges = CDGN(818,9); + if (cre(store_item.charges,0,100,"Charges must be from 0 to 100.","",818) > 0) return FALSE; + store_item.type_flag = CDGN(818,10); + if (cre(store_item.type_flag,0,1000,"Type Flag must be from 0 to 1000.","",818) > 0) return FALSE; + store_item.value = CDGN(818,11); + if (cre(store_item.value,0,10000,"Value must be from 0 to 10000.","",818) > 0) return FALSE; + store_item.weight = CDGN(818,12); + if (cre(store_item.weight,0,250,"Weight must be from 0 to 250.","",818) > 0) return FALSE; + store_item.special_class = CDGN(818,13); + if (cre(store_item.special_class,0,100,"Special Class must be from 0 to 100.","",818) > 0) return FALSE; + + if ((store_item.type_flag > 0) && (store_item.charges == 0)) { + give_error("If the Type Flag is greater than 0, the Charges must also be greater than 0.","",818); + return FALSE; + } + if (store_item.variety > 25) { + give_error("The Unused item varieties are reserved for later expansions, and can't be used now.","",818); + return FALSE; + } + if ((store_item.ability >= 70) && (store_item.ability < 170) && (store_item.charges == 0)) { + give_error("An item with the special ability selected must have at least 1 charge.","",818); + return FALSE; + } + scen_item_list.scen_items[store_which_item] = store_item ; + + return TRUE; +} + +void edit_item_type_event_filter (short item_hit) +{ + char str[256]; + short i; + item_record_type temp_item; + + switch (item_hit) { + case 15: + dialog_not_toast = FALSE; break; + case 14: + if (save_item_info() == TRUE) + dialog_not_toast = FALSE; break; + break; + + case 16: + if (save_item_info() == FALSE) break; + store_which_item--; + if (store_which_item < 0) store_which_item = 399; + store_item = scen_item_list.scen_items[store_which_item]; + put_item_info_in_dlog(); + break; + case 17: + if (save_item_info() == FALSE) break; + store_which_item++; + if (store_which_item > 399) store_which_item = 0; + store_item = scen_item_list.scen_items[store_which_item]; + put_item_info_in_dlog(); + break; + case 56: + if (save_item_info() == FALSE) break; + i = choose_graphic(1800,1922,store_item.graphic_num + 1800,818); + if (i >= 0) { + store_item.graphic_num = i - 1800; + } + else break; + put_item_info_in_dlog(); + break; + case 69: + if (store_item.variety == 0) { + give_error("You must give the item a type (weapon, armor, etc.) before you can choose its abilities.","",818); + break; + } + if ((store_item.variety == 3) || (store_item.variety == 11)) { + give_error("Gold and Food cannot be given special abilities.","",818); + break; + } + temp_item = edit_item_abil(store_item,818); + if (temp_item.variety != 0) + store_item = temp_item; + break; + default: + cd_hit_led_range(818,18,45,item_hit); + store_item.variety = cd_get_led_range(818,18,45); + if ((store_item.variety == 1) || (store_item.variety == 2)) + store_item.type = 1; + cd_hit_led_range(818,46,48,item_hit); + break; + + } +} + +short edit_item_type(short which_item) +// ignore parent in Mac version +{ + short item_hit,i,store_dialog_answer; + char temp_str[256]; + + store_which_item = which_item; + store_item = scen_item_list.scen_items[store_which_item]; + //make_cursor_sword(); + + cd_create_dialog_parent_num(818,0); + + put_item_info_in_dlog(); + + for (i = 18; i < 46; i++) + cd_add_label(818, i,item_types[i - 18],47); + cd_add_label(818,46,"Edged",23); + cd_add_label(818,47,"Bashing",23); + cd_add_label(818,48,"Pole",23); + cd_attach_key(818,16,0); + cd_attach_key(818,17,0); + while (dialog_not_toast) + ModalDialog(); + + cd_kill_dialog(818,0); + return 0; +} + +void put_item_abils_in_dlog() +{ + char str[256]; + short i; + + cdsin(824,16,store_which_item); + csit(824,32,store_item2.full_name); + csit(824,34,item_types[store_item2.variety]); + get_str(str,23,store_item2.ability + 1); + csit(824,19,(char *) str); + + cd_set_led_range(824,5,8,store_item2.magic_use_type); + cd_set_led_range(824,26,30,store_item2.treas_class); + CDSN(824,2,store_item2.ability_strength); + if (store_item2.item_properties & 1) + cd_set_led(824,9,1); + else cd_set_led(824,9,0); + if (store_item2.item_properties & 4) + cd_set_led(824,10,1); + else cd_set_led(824,10,0); + if (store_item2.item_properties & 16) + cd_set_led(824,11,1); + else cd_set_led(824,11,0); + if (store_item2.item_properties & 32) + cd_set_led(824,12,1); + else cd_set_led(824,12,0); +} + +Boolean save_item_abils() +{ + char str[256]; + short i; + + store_item2.magic_use_type = cd_get_led_range(824,5,8); + store_item2.treas_class = cd_get_led_range(824,26,30); + store_item2.ability_strength = CDGN(824,2); + if ((store_item2.ability != 119) && (store_item2.ability != 120)) { + if (cre(store_item2.ability_strength,0,10,"Ability Strength must always be a number from 0 to 10.","",824) > 0) return FALSE; + } + else if (cre(store_item2.ability_strength,0,255,"Ability Strength must be 0 to 255 - the number of the monster to summon.","",824) > 0) return FALSE; + store_item2.item_properties = 0; + store_item2.item_properties |= (cd_get_led(824,9) == 1) ? 1 : 0; + store_item2.item_properties |= (cd_get_led(824,10) == 1) ? 4 : 0; + store_item2.item_properties |= (cd_get_led(824,11) == 1) ? 16 : 0; + store_item2.item_properties |= (cd_get_led(824,12) == 1) ? 32 : 0; + return TRUE; +} + +void edit_item_abil_event_filter (short item_hit) +{ + char str[256]; + short i; + + switch (item_hit) { + case 4: store_item2.ability = 0; + dialog_not_toast = FALSE; break; + case 3: + if (save_item_abils() == TRUE) + dialog_not_toast = FALSE; + break; + case 17: + if (save_item_abils() == FALSE) break; + if (store_item.variety > 2) { + give_error("You can only give an ability of this sort to a melee weapon.","",824); + break; + } + i = choose_text_res(23,1,15,store_item2.ability + 1,824,"Choose Weapon Ability (inherent)"); + if (i >= 0) store_item2.ability = i - 1; + else store_item2.ability = 0; + put_item_abils_in_dlog(); + break; + case 35: + if (save_item_abils() == FALSE) break; + if ((store_item.variety == 5) || (store_item.variety == 6)|| (store_item.variety == 7) || (store_item.variety == 8) || + (store_item.variety == 9) || (store_item.variety == 10) || (store_item.variety == 20) || + (store_item.variety == 21) || (store_item.variety == 24)){ + give_error("You can only give an ability of this sort to an non-missile item which can be equipped (like armor, or a ring).","",824); + break; + } + i = choose_text_res(23,31,63,store_item2.ability + 1,824,"Choose General Ability (inherent)"); + if (i >= 0) store_item2.ability = i - 1; + else store_item2.ability = 0; + put_item_abils_in_dlog(); + break; + case 36: + if (save_item_abils() == FALSE) break; + if ((store_item.variety == 5) || (store_item.variety == 6) || (store_item.variety == 24)){ + give_error("You can only give an ability of this sort to an item which isn't a missile.","",824); + break; + } + i = choose_text_res(23,71,95,store_item2.ability + 1,824,"Choose Usable Ability (Not spell)"); + if (i >= 0) store_item2.ability = i - 1; + else store_item2.ability = 0; + put_item_abils_in_dlog(); + break; + case 39: + if (save_item_abils() == FALSE) break; + if ((store_item.variety == 5) || (store_item.variety == 6) || (store_item.variety == 24)){ + give_error("You can only give an ability of this sort to an item which isn't a missile.","",824); + break; + } + i = choose_text_res(23,111,136,store_item2.ability + 1,824,"Choose Usable Ability (Spell)"); + if (i >= 0) store_item2.ability = i - 1; + else store_item2.ability = 0; + put_item_abils_in_dlog(); + break; + case 38: + if (save_item_abils() == FALSE) break; + if (store_item.variety != 21){ + give_error("You can only give an ability of this sort to an item of type Non-Use Object.","",824); + break; + } + i = choose_text_res(23,151,162,store_item2.ability + 1,824,"Choose Reagent Ability"); + if (i >= 0) store_item2.ability = i - 1; + else store_item2.ability = 0; + put_item_abils_in_dlog(); + break; + case 37: + if (save_item_abils() == FALSE) break; + if ((store_item.variety != 5) && (store_item.variety != 6) && (store_item.variety != 24)){ + give_error("You can only give an ability of this sort to an item which isn't a missile.","",824); + break; + } + i = choose_text_res(23,171,177,store_item2.ability + 1,824,"Choose Missile Ability"); + if (i >= 0) store_item2.ability = i - 1; + else store_item2.ability = 0; + put_item_abils_in_dlog(); + break; + default: + cd_hit_led_range(824,26,30,item_hit); + cd_hit_led_range(824,5,8,item_hit); + for (i = 9; i < 13; i++) + cd_flip_led(824,i,item_hit); + break; + + } +} + +item_record_type edit_item_abil(item_record_type starting_record,short parent_num) +// ignore parent in Mac version +{ + short item_hit,i,store_dialog_answer; + char temp_str[256]; + + //store_which_item = which_item; + store_item2 = starting_record; + //make_cursor_sword(); + + cd_create_dialog_parent_num(824,parent_num); + + put_item_abils_in_dlog(); + + cd_add_label(824,26,"Type 0: Junk, Not left",68); + cd_add_label(824,27,"Type 1: Lousy, 1 - 20 gp",68); + cd_add_label(824,28,"Type 2: So-so, 20-200 gp",68); + cd_add_label(824,29,"Type 3: Good, 200+ gp",68); + cd_add_label(824,30,"Type 4: Great, 2500+ gp",68); + + cd_add_label(824,5,"Help using PC",50); + cd_add_label(824,6,"Harm using PC",50); + cd_add_label(824,7,"Help whole party",50); + cd_add_label(824,8,"Harm whole party",50); + + cd_add_label(824,9,"Always identified",50); + cd_add_label(824,10,"Magical",50); + cd_add_label(824,11,"Cursed",50); + cd_add_label(824,12,"Conceal ability",50); + + + while (dialog_not_toast) + ModalDialog(); + + cd_kill_dialog(824,0); + return store_item2; +} + +void put_spec_item_in_dlog() +{ + char str[256]; + short i; + + cdsin(806,19,store_which_spec_item); + CDST(806,2,scen_strs[60 + store_which_spec_item * 2]); + CDST(806,3,scen_strs[60 + store_which_spec_item * 2 + 1]); + CDSN(806,4,scenario.special_item_special[store_which_spec_item]); + if (scenario.special_items[store_which_spec_item] >= 10) + cd_set_led(806,15,1); else cd_set_led(806,15,0); + if (scenario.special_items[store_which_spec_item] % 10 > 0) + cd_set_led(806,17,1); else cd_set_led(806,17,0); +} + +Boolean save_spec_item() +{ + char str[256]; + short i; + + CDGT(806,2,(char *) str); + str[25] = 0; + sprintf(scen_strs[60 + store_which_spec_item * 2 + 0],"%s",str); + CDGT(806,3,scen_strs[60 + store_which_spec_item * 2 + 1]); + spec_item_spec = CDGN(806,4); + if (cre(scenario.special_item_special[store_which_spec_item], + -1,255,"Scenario special node called must be from 0 to 255 (or -1 for no special).","",806) > 0) return FALSE; + scenario.special_item_special[store_which_spec_item] = spec_item_spec; + scenario.special_items[store_which_spec_item] = 0; + if (cd_get_led(806,15) == 1) + scenario.special_items[store_which_spec_item] += 10; + if (cd_get_led(806,17) == 1) + scenario.special_items[store_which_spec_item] += 1; + return TRUE; +} + +void edit_spec_item_event_filter (short spec_item_hit) +{ + char str[256]; + short i,spec; + + switch (spec_item_hit) { + case 11: + dialog_not_toast = FALSE; break; + case 5: + if (save_spec_item() == TRUE) + dialog_not_toast = FALSE; + break; + + case 20: + if (save_spec_item() == FALSE) break; + store_which_spec_item--; + if (store_which_spec_item < 0) store_which_spec_item = 49; + spec_item_spec = scenario.special_item_special[store_which_spec_item]; + put_spec_item_in_dlog(); + break; + case 21: + if (save_spec_item() == FALSE) break; + store_which_spec_item++; + if (store_which_spec_item > 49) store_which_spec_item = 0; + spec_item_spec = scenario.special_item_special[store_which_spec_item]; + put_spec_item_in_dlog(); + break; + case 13: //choose edit + if (save_spec_item() == FALSE) + break; + spec = CDGN(806,4); + if ((spec < 0) || (spec >= 256)) { + spec = get_fresh_spec(0); + if (spec < 0) { + give_error("You can't create a new special encounter because there are no more free scenario special nodes.", + "To free a special node, set its type to No Special and set its Jump To special to -1.",806); + break; + } + CDSN(806,4,spec); + } + edit_spec_enc(spec,0,806); + if ((spec >= 0) && (spec < 256) && (scenario.scen_specials[spec].pic < 0)) + CDSN(806,4,-1); + if (save_spec_item() == FALSE) + break; + break; + default: + cd_flip_led(806,15,spec_item_hit); + cd_flip_led(806,17,spec_item_hit); + break; + + } +} + +void edit_spec_item(short which_item) +// ignore parent in Mac version +{ + short spec_item_hit,i,store_dialog_answer; + char temp_str[256]; + + //store_which_spec_item = which_spec_item; + store_which_spec_item = which_item; + spec_item_spec = scenario.special_item_special[store_which_spec_item]; + + cd_create_dialog_parent_num(806,0); + + put_spec_item_in_dlog(); + cd_attach_key(806,20,0); + cd_attach_key(806,21,0); + cd_activate_item(806,12,0); + + while (dialog_not_toast) + ModalDialog(); + + cd_kill_dialog(806,0); +} + +void put_save_rects_in_dlog() +{ + char str[256]; + short i; + + for (i = 0; i < 3; i++) { + CDSN(807,3 + 5 * i,scenario.store_item_rects[i].top); + CDSN(807,4 + 5 * i,scenario.store_item_rects[i].left); + CDSN(807,5 + 5 * i,scenario.store_item_rects[i].bottom); + CDSN(807,6 + 5 * i,scenario.store_item_rects[i].right); + CDSN(807,2 + 5 * i,scenario.store_item_towns[i]); + + } + +} + +Boolean save_save_rects() +{ + char str[256]; + short i; + + for (i = 0; i < 3; i++) { + scenario.store_item_rects[i].top = CDGN(807,3 + 5 * i); + scenario.store_item_rects[i].left = CDGN(807,4 + 5 * i); + scenario.store_item_rects[i].bottom = CDGN(807,5 + 5 * i); + scenario.store_item_rects[i].right = CDGN(807,6 + 5 * i); + scenario.store_item_towns[i] = CDGN(807,2 + 5 * i); + if ((scenario.store_item_towns[i] < -1) || (scenario.store_item_towns[i] >= 200)) { + give_error("Towns must be in 0 to 200 range (or -1 for no save items rectangle).","",807); + return FALSE; + } + } + if (((scenario.store_item_towns[0] == scenario.store_item_towns[1]) && + (scenario.store_item_towns[0] >= 0) && (scenario.store_item_towns[1] >= 0)) + || + ((scenario.store_item_towns[2] == scenario.store_item_towns[1]) && + (scenario.store_item_towns[2] >= 0) && (scenario.store_item_towns[1] >= 0)) + || + ((scenario.store_item_towns[2] == scenario.store_item_towns[0]) && + (scenario.store_item_towns[2] >= 0) && (scenario.store_item_towns[0] >= 0)) + ) { + give_error("The three towns towns with saved item rectangles must be different.","",807); + return FALSE; + } + return TRUE; +} + +void edit_save_rects_event_filter (short save_rects_hit) +{ + char str[256]; + short i; + + switch (save_rects_hit) { + case 18: + dialog_not_toast = FALSE; break; + case 17: + if (save_save_rects() == TRUE) + dialog_not_toast = FALSE; + break; + + } +} + +void edit_save_rects() +// ignore parent in Mac version +{ + short save_rects_hit,i,store_dialog_answer; + char temp_str[256]; + + cd_create_dialog_parent_num(807,0); + + put_save_rects_in_dlog(); + + while (dialog_not_toast) + ModalDialog(); + + cd_kill_dialog(807,0); +} + +Boolean save_horses() +{ + char str[256]; + short i; + + for (i = 0; i < 6; i++) { + scenario.scen_horses[6 * store_horse_page + i].which_town = CDGN(808,2 + i); + if (cre(scenario.scen_horses[6 * store_horse_page + i].which_town, + -1,199,"Town number must be from 0 to 199 (or -1 for horse to not exist).","",808) == TRUE) return FALSE; + scenario.scen_horses[6 * store_horse_page + i].horse_loc.x = CDGN(808,8 + i); + if (cre(scenario.scen_horses[6 * store_horse_page + i].horse_loc.x, + 0,63,"Horse location coordinates must be from 0 to 63.","",808) == TRUE) return FALSE; + scenario.scen_horses[6 * store_horse_page + i].horse_loc.y = CDGN(808,14 + i); + if (cre(scenario.scen_horses[6 * store_horse_page + i].horse_loc.y, + 0,63,"Horse location coordinates must be from 0 to 63.","",808) == TRUE) return FALSE; + scenario.scen_horses[6 * store_horse_page + i].property = cd_get_led(808,43 + i); + } + return TRUE; +} + +void put_horses_in_dlog() +{ + char str[256]; + short i; + + for (i = 0; i < 6; i++) { + cdsin(808,23 + i,6 * store_horse_page + i); + CDSN(808,2 + i,scenario.scen_horses[6 * store_horse_page + i].which_town); + CDSN(808,8 + i,scenario.scen_horses[6 * store_horse_page + i].horse_loc.x); + CDSN(808,14 + i,scenario.scen_horses[6 * store_horse_page + i].horse_loc.y); + cd_set_led(808,43 + i,scenario.scen_horses[6 * store_horse_page + i].property); + } + +} + +void edit_horses_event_filter (short item_hit) +{ + char str[256]; + short i; + + switch (item_hit) { + case 20: + if (save_horses() == TRUE) + dialog_not_toast = FALSE; + break; + case 21: + if (save_horses() == FALSE) break; + store_horse_page--; + if (store_horse_page < 0) store_horse_page = 4; + put_horses_in_dlog(); + break; + case 22: + if (save_horses() == FALSE) break; + store_horse_page++; + if (store_horse_page > 4) store_horse_page = 0; + put_horses_in_dlog(); + break; + default: + for (i = 0; i < 6; i++) + cd_flip_led(808,43 + i,item_hit); + break; + } +} + +void edit_horses() +// ignore parent in Mac version +{ + short horses_hit,i,store_dialog_answer; + char temp_str[256]; + + store_horse_page = 0; + + cd_create_dialog_parent_num(808,0); + + put_horses_in_dlog(); + + while (dialog_not_toast) + ModalDialog(); + + cd_kill_dialog(808,0); +} + +Boolean save_boats() +{ + char str[256]; + short i; + + for (i = 0; i < 6; i++) { + scenario.scen_boats[6 * store_boat_page + i].which_town = CDGN(809,2 + i); + if (cre(scenario.scen_boats[6 * store_boat_page + i].which_town, + -1,199,"Town number must be from 0 to 199 (or -1 for boat to not exist).","",809) == TRUE) return FALSE; + scenario.scen_boats[6 * store_boat_page + i].boat_loc.x = CDGN(809,8 + i); + if (cre(scenario.scen_boats[6 * store_boat_page + i].boat_loc.x, + 0,63,"boat location coordinates must be from 0 to 63.","",809) == TRUE) return FALSE; + scenario.scen_boats[6 * store_boat_page + i].boat_loc.y = CDGN(809,14 + i); + if (cre(scenario.scen_boats[6 * store_boat_page + i].boat_loc.y, + 0,63,"boat location coordinates must be from 0 to 63.","",809) == TRUE) return FALSE; + scenario.scen_boats[6 * store_boat_page + i].property = cd_get_led(809,43 + i); + } + return TRUE; +} + +void put_boats_in_dlog() +{ + char str[256]; + short i; + + for (i = 0; i < 6; i++) { + cdsin(809,24 + i,6 * store_boat_page + i); + CDSN(809,2 + i,scenario.scen_boats[6 * store_boat_page + i].which_town); + CDSN(809,8 + i,scenario.scen_boats[6 * store_boat_page + i].boat_loc.x); + CDSN(809,14 + i,scenario.scen_boats[6 * store_boat_page + i].boat_loc.y); + cd_set_led(809,43 + i,scenario.scen_boats[6 * store_boat_page + i].property); + } + +} + +void edit_boats_event_filter (short item_hit) +{ + char str[256]; + short i; + + switch (item_hit) { + case 20: + if (save_boats() == TRUE) + dialog_not_toast = FALSE; + break; + case 22: + if (save_boats() == FALSE) break; + store_boat_page--; + if (store_boat_page < 0) store_boat_page = 4; + put_boats_in_dlog(); + break; + case 23: + if (save_boats() == FALSE) break; + store_boat_page++; + if (store_boat_page > 4) store_boat_page = 0; + put_boats_in_dlog(); + break; + default: + for (i = 0; i < 6; i++) + cd_flip_led(809,43 + i,item_hit); + break; + } +} + +void edit_boats() +// ignore parent in Mac version +{ + short boats_hit,i,store_dialog_answer; + char temp_str[256]; + + store_boat_page = 0; + + cd_create_dialog_parent_num(809,0); + + put_boats_in_dlog(); + + while (dialog_not_toast) + ModalDialog(); + + cd_kill_dialog(809,0); +} + +Boolean save_add_town() +{ + char str[256]; + short i; + + for (i = 0; i < 10; i++) { + scenario.town_to_add_to[i] = CDGN(810,2 + i); + if (cre(scenario.town_to_add_to[i], + -1,199,"Town number must be from 0 to 199 (or -1 for no effect).","",810) == TRUE) return FALSE; + scenario.flag_to_add_to_town[i][0] = CDGN(810,12 + i); + if (cre(scenario.flag_to_add_to_town[i][0], + 0,299,"First part of flag must be from 0 to 299.","",810) == TRUE) return FALSE; + scenario.flag_to_add_to_town[i][1] = CDGN(810,22 + i); + if (cre(scenario.flag_to_add_to_town[i][1], + 0,9,"Second part of flag must be from 0 to 9.","",810) == TRUE) return FALSE; + } + return TRUE; +} + +void put_add_town_in_dlog() +{ + char str[256]; + short i; + + for (i = 0; i < 10; i++) { + CDSN(810,2 + i,scenario.town_to_add_to[i]); + CDSN(810,12 + i,scenario.flag_to_add_to_town[i][0]); + CDSN(810,22 + i,scenario.flag_to_add_to_town[i][1]); + } + +} + +void edit_add_town_event_filter (short item_hit) +{ + char str[256]; + short i; + + switch (item_hit) { + case 32: + if (save_add_town() == TRUE) + dialog_not_toast = FALSE; + break; + + } +} + +void edit_add_town() +// ignore parent in Mac version +{ + short add_town_hit,i,store_dialog_answer; + char temp_str[256]; + + cd_create_dialog_parent_num(810,0); + + put_add_town_in_dlog(); + + while (dialog_not_toast) + ModalDialog(); + + cd_kill_dialog(810,0); +} + +Boolean save_item_placement() +{ + char str[256]; + short i; + + store_storage.property = cd_get_led(812,38); + store_storage.ter_type = CDGN(812,22); + if (cre(store_storage.ter_type, + -1,255,"Terrain Type must be from 0 to 255 (or -1 for No Shortcut).","",812) == TRUE) return FALSE; + for (i = 0; i < 10; i++) { + store_storage.item_num[i] = CDGN(812,2 + i); + if (cre(store_storage.item_num[i], + -1,399,"All item numbers must be from 0 to 399 (or -1 for No Item).","",812) == TRUE) return FALSE; + store_storage.item_odds[i] = CDGN(812,12 + i); + if (cre(store_storage.item_odds[i], + 0,100,"All item chances must bve from 0 to 100.","",812) == TRUE) return FALSE; + } + scenario.storage_shortcuts[cur_shortcut] = store_storage; + + return TRUE; +} + +void put_item_placement_in_dlog() +{ + char str[256]; + short i; + + cdsin(812,27,cur_shortcut); + cd_set_led(812,38,store_storage.property); + CDSN(812,22,store_storage.ter_type); + for (i = 0; i < 10; i++) { + CDSN(812,2 + i,store_storage.item_num[i]); + CDSN(812,12 + i,store_storage.item_odds[i]); + } + +} + +void edit_item_placement_event_filter (short item_hit) +{ + char str[256]; + short i; + + switch (item_hit) { + case 23: + if (save_item_placement() == TRUE) + dialog_not_toast = FALSE; + break; + case 24: + dialog_not_toast = FALSE; + break; + case 26: + if (save_item_placement() == FALSE) break; + cur_shortcut--; + if (cur_shortcut < 0) cur_shortcut = 9; + store_storage = scenario.storage_shortcuts[cur_shortcut]; + put_item_placement_in_dlog(); + break; + case 25: + if (save_item_placement() == FALSE) break; + cur_shortcut++; + if (cur_shortcut > 9) cur_shortcut = 0; + store_storage = scenario.storage_shortcuts[cur_shortcut]; + put_item_placement_in_dlog(); + break; + case 41: + store_storage.ter_type = CDGN(812,22); + i = choose_text_res(-4,0,255,store_storage.ter_type,812,"Which Terrain?"); + store_storage.ter_type = i; + CDSN(812,22,i); + break; + default: + if ((item_hit >= 42) && (item_hit <= 51)) { + i = CDGN(812,2 + item_hit - 42); + i = choose_text_res(-2,0,399,i,812,"Place which item?"); + if (i >= 0) + CDSN(812,2 + item_hit - 42,i); + break; + } + cd_flip_led(812,38,item_hit); + break; + } +} + +void edit_item_placement() +// ignore parent in Mac version +{ + short item_placement_hit,i,store_dialog_answer; + char temp_str[256]; + + store_storage = scenario.storage_shortcuts[0]; + cur_shortcut = 0; + + cd_create_dialog_parent_num(812,0); + + put_item_placement_in_dlog(); + + while (dialog_not_toast) + ModalDialog(); + + cd_kill_dialog(812,0); +} + +Boolean save_scen_details() +{ + char str[256]; + short i; + + scenario.difficulty = cd_get_led_range(803,30,33); + scenario.rating = cd_get_led_range(803,21,24); + scenario.ver[0] = CDGN(803,2); + scenario.ver[1] = CDGN(803,3); + scenario.ver[2] = CDGN(803,4); + for (i = 0; i < 3; i++) + if (cre(scenario.ver[i], + 0,9,"The digits in the version number must be in the 0 to 9 range.","",803) == TRUE) return FALSE; + CDGT(803,5,(char *) str); + str[59] = 0; + strcpy(scen_strs[1],(char *) str); + CDGT(803,6,(char *) str); + str[59] = 0; + strcpy(scen_strs[2],(char *) str); + CDGT(803,7,scen_strs[3]); + + return TRUE; +} + +void put_scen_details_in_dlog() +{ + char str[256]; + short i; + + cd_set_led_range(803,30,33,scenario.difficulty); + cd_set_led_range(803,21,24,scenario.rating); + CDSN(803,2,scenario.ver[0]); + CDSN(803,3,scenario.ver[1]); + CDSN(803,4,scenario.ver[2]); + CDST(803,5,scen_strs[1]); + CDST(803,6,scen_strs[2]); + CDST(803,7,scen_strs[3]); +} + +void edit_scen_details_event_filter (short item_hit) +{ + char str[256]; + short i; + + switch (item_hit) { + case 8: + if (save_scen_details() == TRUE) + dialog_not_toast = FALSE; + break; + default: + cd_hit_led_range(803,21,24,item_hit); + cd_hit_led_range(803,30,33,item_hit); + break; + } +} + +void edit_scen_details() +// ignore parent in Mac version +{ + short scen_details_hit,i,store_dialog_answer; + char temp_str[256]; + + cd_create_dialog_parent_num(803,0); + + put_scen_details_in_dlog(); + + while (dialog_not_toast) + ModalDialog(); + + cd_kill_dialog(803,0); +} + + + +void put_make_scen_1_in_dlog() +{ + short i; + + CDST(800,2,"Scenario name"); + CDST(800,3,"filename"); +} + +void edit_make_scen_1_event_filter (short item_hit) +{ + char str[256]; + short i,j; + + switch (item_hit) { + case 4: + CDGT(800,3,(char *) str); + j = strlen((char *) str); + if (j == 0) { + give_error("You've left the file name empty.","",800); + break; + } + if (j > 28) { + give_error("The file name can be at most 28 characters long.","",800); + break; + } + for (i = 0; i < j; i++) + if ((str[i] < 33) || (str[i] == 34) || (str[i] == 42) || (str[i] == 47) || (str[i] == 58) || (str[i] == 60) || (str[i] == 62) || (str[i] == 63) || (str[i] == 92) || (str[i] == 124) || (str[i] > 126)) { + give_error("The file name must not include these symbols: \\, /, :, *, ?, \", <, >, |","",800); + return; + } + dialog_answer = 1; + dialog_not_toast = FALSE; + break; + case 9: + dialog_answer = 0; + dialog_not_toast = FALSE; + break; + default: + cd_flip_led(800,11,item_hit); + break; + } +} + +short edit_make_scen_1(char *filename,char *title,short *grass) +// ignore parent in Mac version +{ + short make_scen_1_hit,i,store_dialog_answer; + char temp_str[256]; + + cd_create_dialog_parent_num(800,0); + + put_make_scen_1_in_dlog(); + + while (dialog_not_toast) + ModalDialog(); + + CDGT(800,2,title); + title[30] = 0; + CDGT(800,3,filename); + *grass = cd_get_led(800,11); + cd_kill_dialog(800,0); + return dialog_answer; +} + +void put_make_scen_2_in_dlog() +{ + char str[256]; + short i; + + CDSN(801,2,1); + CDSN(801,3,1); + CDSN(801,4,0); + CDSN(801,5,1); + CDSN(801,6,0); +} + +void edit_make_scen_2_event_filter (short item_hit) +{ + char str[256]; + short i,j,k; + + switch (item_hit) { + case 11: + i = CDGN(801,2); + if (cre(i, + 1,50,"Outdoors width must be between 1 and 50.","",801) == TRUE) return ; + j = CDGN(801,3); + if (cre(j, + 1,50,"Outdoors height must be between 1 and 50.","",801) == TRUE) return ; + if (cre(i * j, + 1,100,"The total number of outdoor sections (width times height) must be between 1 and 100.","",801) == TRUE) return ; + i = CDGN(801,4); + j = CDGN(801,5); + k = CDGN(801,6); + if (cre(i, + 0,200,"Number of small towns must be between 0 and 200.","",801) == TRUE) return ; + if (cre(j, + 1,200,"Number of medium towns must be between 0 and 200. The first town (Town 0) must always be of medium size.","",801) == TRUE) return ; + if (cre(k, + 0,200,"Number of large towns must be between 0 and 200.","",801) == TRUE) return ; + if (cre(i + j + k, + 1,200,"The total number of towns must be from 1 to 200 (you must have at least 1 town).","",801) == TRUE) return ; + + dialog_not_toast = FALSE; + break; + case 10: + dialog_answer = 0; + dialog_not_toast = FALSE; + break; + default: + cd_flip_led(801,26,item_hit); + break; + } +} + +short edit_make_scen_2(short *val_array) +// ignore parent in Mac version +{ + short make_scen_2_hit,i,store_dialog_answer;//array[6]; + char temp_str[256]; + + //array = val_array; + cd_create_dialog_parent_num(801,0); + + put_make_scen_2_in_dlog(); + + while (dialog_not_toast) + ModalDialog(); + + for (i = 0; i < 5; i++) + val_array[i] = CDGN(801,2 + i); + val_array[5] = cd_get_led(801,26); + cd_kill_dialog(801,0); + return dialog_answer; +} + +void build_scenario() +{ + short two_flags[6]; // width, height, large, med, small, default_town + char f_name[256],f_name2[256],title[256]; + short grass,which_town; + short i,j; + long dummy; + + if (edit_make_scen_1((char *) f_name,(char *) title,&grass) == FALSE) + return; + sprintf((char *) f_name2,"%s.exs",f_name); + if (edit_make_scen_2((short *) two_flags) == FALSE) + return; + + if (fancy_choice_dialog(860,0) == 2) + return; + + init_out(); + init_scenario(); + strcpy((char *) scen_strs[0],(char *) title); + if (two_flags[5] == 0) { + init_town(1); + if (grass == 0) + for (i = 0; i < 48; i++) + for (j = 0; j < 48; j++) + t_d.terrain[i][j] = 0; + } + else { + import_town(-1); + } + if (two_flags[3] > 0) + two_flags[3]--; + + make_new_scenario(f_name2,two_flags[0],two_flags[1],two_flags[5],grass,title); + //strcpy((char *) scen_strs[0],(char *) title); + //scenario.scen_str_len[0] = strlen(scen_strs[0]); + // now make sure correct outdoors is in memory, because we're going to be saving scenarios + // for a while + if (strlen(f_name2) == 0) + return; + overall_mode = 60; + cur_out.x = 0; cur_out.y = 0; + load_outdoors(cur_out,0); + + for (i = 0; i < two_flags[2]; i++) { + which_town = scenario.num_towns; + scenario.num_towns++; + scenario.town_size[which_town] = 0; + scenario.town_hidden[which_town] = 0; + cur_town = which_town; + init_town(0); + strcpy(town_strs[0],"Large town"); + town_type = 0; + save_scenario(); + } + for (i = 0; i < two_flags[3]; i++) { + which_town = scenario.num_towns; + scenario.num_towns++; + scenario.town_size[which_town] = 1; + scenario.town_hidden[which_town] = 0; + cur_town = which_town; + init_town(1); + strcpy(town_strs[0],"Medium town"); + town_type = 1; + save_scenario(); + } + for (i = 0; i < two_flags[4]; i++) { + which_town = scenario.num_towns; + scenario.num_towns++; + scenario.town_size[which_town] = 2; + scenario.town_hidden[which_town] = 0; + cur_town = which_town; + init_town(2); + strcpy(town_strs[0],"Small town"); + town_type = 2; + save_scenario(); + } + //Delay(200,&dummy); + load_town(0); + augment_terrain(cur_out); + update_item_menu(); +} + +void set_starting_loc_filter (short item_hit) +{ + char str[256]; + short i,j,k; + + switch (item_hit) { + case 5: + i = CDGN(805,2); + j = CDGN(805,3); + k = CDGN(805,4); + if ((i < 0) || (i >= scenario.num_towns)) { + sprintf((char *) str,"The starting town must be from 0 to %d.",scenario.num_towns - 1); + give_error((char *) str,"",805); + break; + } + if ((j < 0) || (j >= max_dim[scenario.town_size[i]] - 1) || + (k < 0) || (k >= max_dim[scenario.town_size[i]] - 1)) { + give_error("This coordinate is not inside the bounds of the town.","",805); + break; + } + scenario.which_town_start = i; + scenario.where_start.x = j; + scenario.where_start.y = k; + dialog_not_toast = FALSE; + break; + case 12: + dialog_not_toast = FALSE; + break; + } +} + +void set_starting_loc() +// ignore parent in Mac version +{ + short town_strs_hit,i,store_dialog_answer; + char temp_str[256],str2[256]; + + cd_create_dialog_parent_num(805,0); + + CDSN(805,2,scenario.which_town_start); + CDSN(805,3,scenario.where_start.x); + CDSN(805,4,scenario.where_start.y); + + while (dialog_not_toast) + ModalDialog(); + + + cd_kill_dialog(805,0); + +} + +Boolean save_scenario_events() +{ + char str[256]; + short i; + + for (i = 0; i < 10; i++) { + scenario.scenario_timer_times[i] = CDGN(811,2 + i); + if ((scenario.scenario_timer_times[i] > 0) && + (scenario.scenario_timer_times[i] % 10 != 0)) { + give_error("All scenario event times must be multiples of 10 (e.g. 100, 150, 1000, etc.).","",811); + return FALSE; + } + scenario.scenario_timer_specs[i] = CDGN(811,12 + i); + if (cre(scenario.scenario_timer_specs[i],-1,255,"The scenario special nodes must be between 0 at 255 (or -1 for no special)." + ,"",811) == TRUE) return FALSE; + } + return TRUE; +} + +void put_scenario_events_in_dlog() +{ + char str[256]; + short i; + + for (i = 0; i < 10; i++) { + CDSN(811,2 + i,scenario.scenario_timer_times[i]); + CDSN(811,12 + i,scenario.scenario_timer_specs[i]); + } + +} + +void edit_scenario_events_event_filter (short item_hit) +{ + char str[256]; + short i,spec; + + switch (item_hit) { + case 22: + if (save_scenario_events() == TRUE) + dialog_not_toast = FALSE; + break; + default: + if ((item_hit >= 30) && (item_hit <= 39)) { + if (save_scenario_events() == FALSE) + break; + spec = CDGN(811,item_hit - 30 + 12); + if ((spec < 0) || (spec > 255)) { + spec = get_fresh_spec(0); + if (spec < 0) { + give_error("You can't create a new scenario special encounter because there are no more free special nodes.", + "To free a special node, set its type to No Special and set its Jump To special to -1.",811); + break; + } + CDSN(811,item_hit - 30 + 12,spec); + } + edit_spec_enc(spec,0,811); + if ((spec >= 0) && (spec < 256) && (scenario.scen_specials[spec].pic < 0)) + CDSN(811,item_hit - 30 + 12,-1); + } + break; + } +} + +void edit_scenario_events() +// ignore parent in Mac version +{ + short advanced_town_hit,i,store_dialog_answer; + char temp_str[256]; + + + cd_create_dialog_parent_num(811,0); + + put_scenario_events_in_dlog(); + + while (dialog_not_toast) + ModalDialog(); + + cd_kill_dialog(811,0); +} diff --git a/Win32/Scenarios Editor/SCENARIO.H b/Win32/Scenarios Editor/SCENARIO.H new file mode 100644 index 00000000..c4818e3b --- /dev/null +++ b/Win32/Scenarios Editor/SCENARIO.H @@ -0,0 +1,59 @@ +monster_record_type return_monster_template(unsigned char store); +void init_scenario(); +short edit_ter_type(short which_ter); +void edit_ter_type_event_filter (short item_hit); +Boolean save_ter_info(); +void put_ter_info_in_dlog(); +void put_monst_info_in_dlog(); +Boolean save_monst_info(); +void edit_monst_type_event_filter (short item_hit); +short edit_monst_type(short which_monst); +void put_monst_abils_in_dlog(); +Boolean save_monst_abils(); +void edit_monst_abil_event_filter (short item_hit); +monster_record_type edit_monst_abil(monster_record_type starting_record,short parent_num); +void put_item_info_in_dlog(); +Boolean save_item_info(); +void edit_item_type_event_filter (short item_hit); +short edit_item_type(short which_item); +void put_item_abils_in_dlog(); +Boolean save_item_abils(); +void edit_item_abil_event_filter (short item_hit); +item_record_type edit_item_abil(item_record_type starting_record,short parent_num); +void edit_spec_item(short which_item); +void edit_spec_item_event_filter (short spec_item_hit); +Boolean save_spec_item(); +void put_spec_item_in_dlog(); +void put_save_rects_in_dlog(); +Boolean save_save_rects(); +void edit_save_rects_event_filter (short save_rects_hit); +void edit_save_rects(); +void edit_horses(); +void edit_horses_event_filter (short item_hit); +void put_horses_in_dlog(); +Boolean save_horses(); +Boolean save_add_town(); +void put_add_town_in_dlog(); +void edit_add_town_event_filter (short item_hit); +void edit_add_town(); +void edit_item_placement(); +void edit_item_placement_event_filter (short item_hit); +void put_item_placement_in_dlog(); +Boolean save_item_placement(); +void edit_scen_details_event_filter (short item_hit); +void edit_scen_details(); +short edit_make_scen_2(short *val_array); +void edit_make_scen_2_event_filter (short item_hit); +void put_make_scen_2_in_dlog(); +short edit_make_scen_1(char *filename,char *title,short *grass); +void edit_make_scen_1_event_filter (short item_hit); +void put_make_scen_1_in_dlog(); +void edit_scenario_events(); +void edit_scenario_events_event_filter (short item_hit); +void put_scenario_events_in_dlog(); +Boolean save_scenario_events(); +void build_scenario(); +void set_starting_loc_filter (short item_hit); +void set_starting_loc(); +void edit_boats_event_filter (short item_hit); +void edit_boats(); diff --git a/Win32/Scenarios Editor/SND0.WAV b/Win32/Scenarios Editor/SND0.WAV new file mode 100644 index 00000000..47325995 Binary files /dev/null and b/Win32/Scenarios Editor/SND0.WAV differ diff --git a/Win32/Scenarios Editor/SND1.WAV b/Win32/Scenarios Editor/SND1.WAV new file mode 100644 index 00000000..94a98be2 Binary files /dev/null and b/Win32/Scenarios Editor/SND1.WAV differ diff --git a/Win32/Scenarios Editor/SND34.WAV b/Win32/Scenarios Editor/SND34.WAV new file mode 100644 index 00000000..a4ab3d41 Binary files /dev/null and b/Win32/Scenarios Editor/SND34.WAV differ diff --git a/Win32/Scenarios Editor/SND37.WAV b/Win32/Scenarios Editor/SND37.WAV new file mode 100644 index 00000000..68217ffa Binary files /dev/null and b/Win32/Scenarios Editor/SND37.WAV differ diff --git a/Win32/Scenarios Editor/SND95.WAV b/Win32/Scenarios Editor/SND95.WAV new file mode 100644 index 00000000..35c3bd09 Binary files /dev/null and b/Win32/Scenarios Editor/SND95.WAV differ diff --git a/Win32/Scenarios Editor/STRINGS.RC b/Win32/Scenarios Editor/STRINGS.RC new file mode 100644 index 00000000..b32c1280 --- /dev/null +++ b/Win32/Scenarios Editor/STRINGS.RC @@ -0,0 +1,2002 @@ +STRINGTABLE +{ + 1501, "This makes you more resistant to damage. Blows of all sorts have less of an effect on you." + 1502, "The possessor of this advantage will find that his or her spells will function better. This helps both Priest and Mage spells." + 1503, "An ambidextrous warrior will be able to use one weapon in each hand without any penalties. Normally, using two weapons makes both of them much less likely to hit." + 1504, "Having nimble fingers improves one's chances of picking locks and disarming traps." + 1505, "When underground, knowledge of Cave Lore helps one hunt and forage for food and deal better with special circumstances." + 1506, "When roaming the surface of the world, a Woodsman is able to hunt and bring down food, find useful herbs, and deal with circumstances involving nature's adversity." + 1507, "Someone with a Good Constitution will find that poison and disease have a reduced (although not eliminated) effect." + 1508, "Highly Alert people have the edginess that helps them resist magical sleep. In addition, having someone in your group who is Highly Alert may help keep you from being surprised." + 1509, "An Exceptionally Strong character will be able to carry much more stuff, and, in addition, will do a small amount more damage in combat." + 1510, "A very few adventurers have magical blood running in their veins, causing them to heal damage to their bodies at an amazing rate." + 1511, "Sluggish characters just can't move that quickly, even when circumstances seem to demand it. A sluggish character gets fewer action points in combat." + 1512, "Magically Inept characters, for some reason, resist the effects of magical items, and are unable to use them. Potions and scrolls won't work for them, although worn items, such as rings, will have a small effect." + 1513, "Frail characters are cursed at birth with a weak constitution. Poison and disease will have a greater effect on such characters." + 1514, "Chronic Disease is the worst disadvantage a character may possess. Such characters have a slow, lingering, incurable physical ailment, causing them to occasionally suffer the effects of a mild disease." + 1515, "A character with a Bad Back cannot bear to haul too much weight. Such a person cannot carry as much as he or she might have been able to otherwise." + 1516, "Human is the default species in Exile III. Humans have skins of a variety of hues, and are soft, generally fragile, and incredibly resourceful." + 1517, "The Nephilim are a race of feline humanoids. Once common on the surface world, they have been hunted to near extinction, although some now remain in Exile. Nephilim characters start with better dexterity, and are much better at using missile weapons." + 1518, "The Slithzerikai (sliths for short) are a race of lizard men, both strong and smart. Once unknown on the surface world, they are starting to appear there. Slith characters get bonuses to strength and intelligence, and are better at using pole weapons." + 2101, "Light|" + 2102, "Creates a weak light." + 2103, "Spark" + 2104, "Fires a weak bolt of electricity at an enemy." + 2105, "Minor Haste" + 2106, "Makes the selected PC move faster for a while. All haste spells take effect at the beginning of the next round." + 2107, "Strength" + 2108, "Makes the selected PC more skilled for a short time. Works like the priest spell ïBless.Í" + 2109, "Scare" + 2110, "Decreases the morale of the victim. Casting this on a weak foe will make the foe flee. Even if the monster doesn't flee, later castings have a higher chance of success." + 2111, "Flame Cloud" + 2112, "This spell fills the selected space with a short-lasting wall of fire." + 2113, "Identify" + 2114, "This draining spell identifies all the unidentified items being held by your characters." + 2115, "Scry Monster" + 2116, "This spell is cast during combat. When cast, you receive information about the monster you target: current health, spell points, morale, etc." + 2117, "Goo" + 2118, "This spell covers the target with sticky goo, slowing it down and interfering with its attacks." + 2119, "True Sight" + 2120, "This spell lets you see everything in a short radius around you, even spaces blocked off by walls. It's useful for finding secret passages, for example." + 2121, "Minor Poison|" + 2122, "Poisons the target creature. This does a fair amount of damage, but it takes time to happen." + 2123, "Flame" + 2124, "Fires a decent-sized bolt of flame at the target. The damage done increases with the level of the caster." + 2125, "Slow" + 2126, "Makes the victim get half its usual number of actions for a while." + 2127, "Dumbfound" + 2128, "Makes the victim incompetent: easier to hit, easier to damage, and less able to attack you." + 2129, "Envenom |" + 2130, "This spell puts poison on the weapon of the selected PC, with no chance of failure or accidental poisoning." + 2131, "Stinking Cloud" + 2132, "When cast, a 3x3 area you select becomes filled with choking gasses. Anyone entering will have far less effective attacks for a short time. The gas will slowly fade on its own." + 2133, "Summon Beast" + 2134, "This spell summons one low-level, non-magical monster to fight on your side. It disappears after a short time." + 2135, "Conflagration" + 2136, "This spell makes the air in a radius 2 circle burst into flames, charring anyone inside the cloud. After creation, the cloud will rapidly fade." + 2137, "Dispel Fields" + 2138, "This spell dispels magical fields in the selected area. It removes blade walls, ice walls, and similar fields. Note, however, that the spell doesn't work on Fire and Force Barriers." + 2139, "Sleep Cloud" + 2140, "This spell creates a small cloud of sleep gas. There is a chance that anyone passing through the cloud will fall asleep (note that some creatures, like slimes, never sleep)." + 2141, "Unlock Doors" + 2142, "Some doors are magically locked, and others are just hard to open. This spell can unlock them. However, it isnÍt guaranteed to succeed, and wonÍt work on all doors." + 2143, "Haste |" + 2144, "Makes the selected PC get twice the usual number of actions for a long time. All haste spells take effect at the beginning of the next round." + 2145, "Fireball" + 2146, "Fires a powerful ball of flame, which affects the target space and every adjacent space. The damage done increases with the level of the caster." + 2147, "Long Light" + 2148, "Like the first level light spell, but much more effective." + 2149, "Fear" + 2150, "Like scare, but much more powerful. " + 2151, "Wall of Force" + 2152, "This powerful spell creates a line of force walls, which are like fire walls but more damaging and lasting. Hitting the space bar while targeting makes the wall rotate." + 2153, "Weak Summoning" + 2154, "When cast, a group of monsters appears and attacks all enemies of the caster. The number of monsters depends on the level of the caster. After a time, they disappear." + 2155, "Flame Arrows" + 2156, "This spell is like flame, but the caster gets to select several targets. The number of missiles increases with the level of the caster. If you don't want to use all the missiles, hit the space bar to cast the spell." + 2157, "Web" + 2158, "This spell covers a large circle with icky webs, slowing down everyone inside. The webs last until torn down." + 2159, "Resist Magic" + 2160, "You can cast this spell on another PC to make him/her resistant to magical damage and effects. Note this does not help against damage from fire or cold." + 2161, "Poison" + 2162, "This makes poison run thick in the veins of the target. Repeated castings will have a devastating effect." + 2163, "Ice Bolt" + 2164, "Slams the target with a heavy, pointed bolt of ice. Effective against monsters who are resistant to fire. Damage increases as the level of the caster increases." + 2165, "Slow Group" + 2166, "Makes all monsters within a 12 space radius move at half speed for a time." + 2167, "Magic Map" + 2168, "When cast in town, this powerful spell gives you a vision - your map will show you the entire area. However, to cast this spell you need a sapphire." + 2169, "Capture Soul" + 2170, "This spell stores a target monster in a Soul Crystal, so that it may later be created with the Simulacrum spell. You need a Soul Crystal to cast this." + 2171, "Simulacrum" + 2172, "This spell summons a monster you select from your Soul Crystal. The cost depends on the level of the monster being summoned." + 2173, "Venom Arrows" + 2174, "This spell is similar to Flame Arrows, except that your targets are poisoned." + 2175, "Wall of Ice" + 2176, "This spell is similar to Wall of Force, except that it creates an ice wall. Ice walls do as much damage as force walls, but last a lot longer." + 2177, "Stealth" + 2178, "This powerful spell makes monsters less likely to see you for a time (duration depends on your level). Try casting it before walking through a room crowded with monsters." + 2179, "Major Haste" + 2180, "Gives the entire party double its actions (duration depends on the level of the caster). All haste spells take effect at the beginning of the next round." + 2181, "Fire Storm" + 2182, "This spell is like fireball, but does more damage, and affects all creatures within two spaces of the space you target. Be careful not to fry your party!" + 2183, "Dispel Barrier" + 2184, "This spell has a chance (increasing with level) of destroying magical barriers. Some barriers are harder to dispel than others; some cannot be dispelled. Some barriers can be walked through." + 2185, "Fire Barrier" + 2186, "This spell creates a single fire barrier at the target space. Fire barriers are damaging and permanent." + 2187, "Summoning" + 2188, "This spell is like Minor Summoning, but summons more powerful monsters." + 2189, "Shockstorm" + 2190, "This spell creates a large sphere of force walls." + 2191, "Spray Fields" + 2192, "This spell creates a large number of small fields of a random sort, each of which may be individually targeted. The number of fields increases with the level of the caster." + 2193, "Major Poison" + 2194, "This spell makes the targeted monster very poisoned. This spell does a huge amount of damage, but it takes time to take effect." + 2195, "Group Fear" + 2196, "When cast, the caster begins to radiate a horrible aura of fear. All monsters within 12 spaces lose a lot of morale. This spell gains effectiveness rapidly with the level of the caster." + 2197, "Kill" + 2198, "The deadly Kill spell deals a devastating blow to one target you select." + 2199, "Paralyze" + 2200, "This spell affects several monsters - the number affected increases with your level and intelligence. Whoever you cast this on will be immobilized for a very long time. Powerful monsters might resist this spell." + 2201, "Daemon" + 2202, "This dangerous spell summons a beast from the netherworld to fight at your side." + 2203, "Antimagic Cloud" + 2204, "This spell creates a spherical field, from which no spells may be cast and in which no spells may be targeted. After creation, it slowly fades." + 2205, "Mindduel" + 2206, "When cast on a magic-using enemy, the two creatures get in a mental battle, absorbing spell points from each other. The loser may end up dumbfounded or killed. Requires a Smoky Crystal to cast." + 2207, "Flight" + 2208, "When cast outdoors, the party can fly for a short time." + 2209, "Shockwave" + 2210, "This spell sends a wave of force out from the caster, damaging everyone nearby. The farther someone is from the caster, the more damage is taken, out to a radius of 10. DonÍt cast in towns." + 2211, "Major Blessing" + 2212, "When cast, the entire party is blessed and hasted, and has their weapons mildly poisoned." + 2213, "Mass Paralysis" + 2214, "When cast, every monsters within a small radius of the caster will become paralyzed for quite some time. There is a chance they might resist the spell." + 2215, "Protection" + 2216, "One of the most powerful spells in the mageÍs repertoire. It makes the whole party temporarily magic resistant, and makes one PC you select immune to ALL damage for a short time." + 2217, "Major Summoning" + 2218, "This spell works like Summoning, but brings forth much more powerful creatures." + 2219, "Force Barrier" + 2220, "This spell creates an impenetrable, permanent barrier. Be careful not to trap yourself." + 2221, "Quickfire" + 2222, "Devastating beyond words, this spell creates a space of quickfire, which will sweep over the area killing everyone and everything." + 2223, "Death Arrows" + 2224, "This spell is like the previous Arrow spells, but strikes each target with a kill spell. The number of arrows increases with the level of the caster." + 2401, "Minor Bless" + 2402, "Makes the character harder to hit and take less damage from blows. It also makes the PC hit more often, and his or her blows do more damage. Its effects decay with time." + 2403, "Minor Heal" + 2404, "Increases the health of the selected PC a small amount, up to the PC's maximum health." + 2405, "Weaken Poison" + 2406, "Reduces the amount of poison running around in the veins of the selected PC." + 2407, "Turn Undead" + 2408, "When cast on an undead creature, it usually does a reasonable amount of damage to it. It has no effect on non-undead." + 2409, "Location" + 2410, "Displays the partyÍs x-y location in the town." + 2411, "Sanctuary" + 2412, "The target of this spell becomes magically shielded. For a time, monsters probably won't be able to attack him/her. The effects disappear when the PC attacks someone." + 2413, "Symbiosis" + 2414, "This spell has the caster absorb the damage taken by another character. The higher the level, the less damage the caster takes per health point healed." + 2415, "Minor Manna" + 2416, "Casting this spell gives the party a little more food." + 2417, "Ritual - Sanctify" + 2418, "When cast on a location filled with evil magic, the location receives a blessing. This might drive out the evil magic. Then again, it might not." + 2419, "Stumble" + 2420, "The victim of this spell moves more slowly and has less effective attacks for a short time." + 2421, "Bless" + 2422, "Like Minor Bless, but better. Its effect increases with the level of the caster." + 2423, "Cure Poison" + 2424, "Like Weaken Poison, but better. Its effect increases with the level of the caster." + 2425, "Curse" + 2426, "The opposite of bless. It makes everything much worse for the victim, for a time. Hitting someone with this spell several times vastly increases the effect." + 2427, "Light" + 2428, "Creates a short duration magical light source." + 2429, "Wound" + 2430, "Deals a painful blow to the targeted victim. The damage increases with your level." + 2431, "Summon Spirit" + 2432, "This spell summons a shade from the netherworld to aid you. It will disappear after a short time." + 2433, "Move Mountains" + 2434, "When cast on a fragile wall or outcropping of rock, the wall or outcropping crumbles into rubble. It doesn't work on all walls." + 2435, "Charm Foe" + 2436, "This spell has a chance of making the target monster start to fight for the party. The chance of it working drops sharply with the level of the monster." + 2437, "Disease" + 2438, "The victim of this spell is afflicted by a disease, which slowly weakens it. The disease lasts a long time." + 2439, "Awaken" + 2440, "Casting this on a sleeping character instantly wakes that character up." + 2441, "Heal" + 2442, "A much better version of Minor Heal." + 2443, "Light Heal All" + 2444, "Casts one minor heal on each PC." + 2445, "Holy Scourge" + 2446, "This spell gives the victim a powerful curse, the effect of which increases with the level of the caster." + 2447, "Detect Life" + 2448, "This spell causes all other living things to appear on your map for a short time. Note, however, that this spell only detects creatures in areas you have explored." + 2449, "Cure Paralysis" + 2450, "This spell instantly removes the effects of paralysis." + 2451, "Manna" + 2452, "This spell magically creates a lot of food for the party." + 2453, "Forcefield" + 2454, "This spell fills an area with walls of force, which are fairly damaging and reasonably long lasting." + 2455, "Cure Disease" + 2456, "Casting this spell on a PC cures all his/her disease." + 2457, "Restore Mind" + 2458, "This spell completely unfeebleminds the recipient." + 2459, "Smite" + 2460, "This spell fires a number of bolts of divinely inspired cold, the number of which increases with the level of the caster. To cast without using all of the targets, hit the space bar." + 2461, "Cure All Poison" + 2462, "Causes everyone to become less poisoned. Useful for dealing with those nasty swamps." + 2463, "Curse All" + 2464, "Causes all monsters within ten spaces to receive a powerful curse." + 2465, "Dispel Undead" + 2466, "Deals a deadly blow to the targeted undead nasty. The chance of the spell having an effect increases with the caster's level." + 2467, "Remove Curse" + 2468, "Occasionally, you will put on an item which then refuses to be taken off. Casting this spell has a chance of removing the curse." + 2469, "Sticks to Snakes" + 2470, "This spell summons a bunch of snakes to aid the party. Skillful casters have a chance of getting asps instead of the weaker giant snakes." + 2471, "Martyr's Shield" + 2472, "When something strikes the recipient of this spell in hand-to-hand combat, it takes as much damage as the victim. The duration of this spell increases with the level of the caster." + 2473, "Cleanse" + 2474, "This spell purifies the recipient. The beneficiary is completely unwebbed, and all disease is cured." + 2475, "Firewalk" + 2476, "When cast, for a short time everyone in the party can walk across lava with no damage. The duration increases slowly with the level of the caster." + 2477, "Bless Party" + 2478, "Much like Bless, but affects everyone." + 2479, "Major Heal" + 2480, "Works like the Heal spell, but gives much more bang for the spell points." + 2481, "Raise Dead" + 2482, "This spell returns a body to life. You need Resurrection Balm to cast this. There is a small chance (decreasing with level) that it turns the body to dust. A dusted character can only be raised with a Resurrect spell. Raising a PC reduces his/her stats." + 2483, "Flamestrike" + 2484, "The first 'area of affect' offensive priest spell. It chars all beings adjacent to the space you target. The damage done increases with level." + 2485, "Mass Sanctuary" + 2486, "This spell hides all PCs (like a sanctuary spell). As before, the effect for a PC is voided when that PC attacks." + 2487, "Summon Host" + 2488, "This powerful spell summons four spirits, and a magical being to lead them. They then fight on the side of the caster for a little while. " + 2489, "Shatter" + 2490, "This spell strikes every space adjacent to the party with a Move Mountains spell." + 2491, "Dispel Fields" + 2492, "All magical walls, etc. in the large area affected by this spell will be dispelled. It has a small chance of affecting quickfire." + 2493, "Heal All" + 2494, "Like the Heal spell, but affects the whole party. Very efficient." + 2495, "Revive" + 2496, "This spell heals all damage and cures all poison for one PC." + 2497, "Hyperactivity" + 2498, "This powerful spell instantly wakes up any sleeping characters in the party. What's more, it provides total resistance to magical sleep for a short time. Finally, it speeds back up any slowed character." + 2499, "Destone" + 2500, "Certain rare monsters can turn one of your characters to stone. This valuable spell undoes the damage." + 2501, "Summon Guardian" + 2502, "This spell summons a powerful, invisible being to fight on the side of the party. Be careful not to damage it by mistake!" + 2503, "Mass Charm" + 2504, "When cast, all creatures within eight spaces of the caster have a chance of coming under his/her control." + 2505, "Protective Circle" + 2506, "A very unusual and effective spell for a party on the defensive. The caster is surrounded by several layers of magical fields, which fend off anyone attacking." + 2507, "Pestilence" + 2508, "This spell afflicts everyone within eight spaces with an effective but slow-acting disease." + 2509, "Revive All" + 2510, "When cast, the party receives a powerful healing (increasing with level of the caster) and has poison cured as well." + 2511, "Ravage Spirit" + 2512, "Demons are resistant to most magic. This spell gives them a blow which usually does a lot of damage. The chance of success increases with the level of the caster." + 2513, "Resurrect" + 2514, "Like raise dead, but much more effective, and works on even a dusted character. It also has a smaller chance of lowering the character's stats. It still requires Resurrection Balm to cast." + 2515, "Divine Thud" + 2516, "The most powerful offensive priest spell. It delivers a stunning blow of force to all beings within two spaces of the targeted space." + 2517, "Avatar" + 2518, "This spell temporarily makes the caster an invulnerable, incredibly powerful avatar of the gods. " + 2519, "Wall of Blades" + 2520, "This spell creates a wall of the most damaging (and long lasting) of the magic walls. Rotate the wall by hitting space." + 2521, "Word of Recall" + 2522, "This spell returns the party to Fort Emergence, where you began the game. Because of the danger of teleporting from narrow, windy tunnels, it can only be cast outdoors." + 2523, "Major Cleansing" + 2524, "This spell removes all webs and disease from the party." + 2701, "Strength" + 2702, "Measures how much brute strength the character possesses. High strength increases damage done in combat, improves odds of kicking down doors, and has other, more subtle effects." + 2703, "Dexterity" + 2704, "Measure how nimble the character is. High dexterity gives a better chance of hitting in combat (esp. with missile weapons) and makes the character harder to hit. High dexterity also makes picking locks and disarming traps easier." + 2705, "Intelligence" + 2706, "Measures mental strength and dexterity. High intelligence also makes your spells more effective, sometimes very much so. Intelligence below 4 makes your spells works poorly." + 2707, "Edged Weapons" + 2708, "Makes you better at using daggers, swords, axes, etc." + 2709, "Bashing Weapons" + 2710, "Makes you better at using clubs, maces, hammers, flails, etc." + 2711, "Pole Weapons" + 2712, "Makes you better at using spears of all sorts, halberds, etc." + 2713, "Thrown Missiles" + 2714, "Makes you better at using darts, javelins, and throwing axes." + 2715, "Archery" + 2716, "Makes you better at using a bow and arrows." + 2717, "Defense" + 2718, "This skill has three effects. It determines how well a character does at parrying, decreases the penalty in combat from bulky armor, and occasionally decreases the damage taken from enemies weapons.|" + 2719, "Mage Spells" + 2720, "Having a certain level of this skill enables you to cast mage spells of up to that level." + 2721, "Priest Spells" + 2722, "Having a certain level of this skill enables you to cast priest spells of up to that level." + 2723, "Mage Lore" + 2724, "You will occasionally need to decipher strange magical readings. This skill determines how good you are at this. If your skill is high enough, you may gain a spell or a valuable piece of information." + 2725, "Alchemy" + 2726, "You will eventually gain the ability to make magic potions. To make a given potion, however, your Alchemy skill much be above a certain level. The higher it is above this level, the better the chance of succeeding." + 2727, "Item Lore" + 2728, "Having Item Lore skill gives you a chance of having the items from slain monsters be identified when you find them. The more of this skill that is present, the higher the chance of this happening." + 2729, "Disarm Traps" + 2730, "Many chests and some corridors will have traps on them, which can be devastating. The higher this skill, the better your chance of disarming them." + 2731, "Lockpicking" + 2732, "Many towns and dungeons will have locked doors. A PC with some of this skill and lock picks equipped can try to pick them. The higher this skill, the better." + 2733, "Assassination" + 2734, "Sometimes, when a character attacks a much weaker monster, the blow will do a good deal of extra damage. The more of this skill you have, the better the chance of this happening, and the stronger the monsters it can happen to." + 2735, "Poison" + 2736, "You will find poisons, which you can put on your weapons for a extra damage. Having a few levels in this skill will make it more likely you will put the poison on at full strength, and the less likely you will nick yourself with the poison accidentally." + 2737, "Luck" + 2738, "This skill is expensive, but can be a bargain at twice the cost. Its effects are pervasive, subtle, powerful, and sometimes irreplaceable." + 6001, "No special ability" + 6002, "Throws darts (dam 1-6)" + 6003, "Shoots arrows (dam 2-12)" + 6004, "Throws spears (dam 3-18)" + 6005, "Throws rocks (dam 4-24)" + 6006, "Throws rocks (dam 5-30)" + 6007, "Throws rocks (dam 6-36)" + 6008, "Throws razordisks (4-24)" + 6009, "Petrification ray" + 6010, "Spell point drain ray" + 6011, "Heat ray" + 6012, "Invisible" + 6013, "Splits when hit" + 6014, "Mindless (resists fear)" + 6015, "Breathes stinking clouds" + 6016, "Icy touch" + 6017, "Experience draining touch" + 6018, "Icy and draining touch" + 6019, "Slowing touch" + 6020, "Shoots webs" + 6021, "Good archer (dam 7-42)" + 6022, "Steals food when hits" + 6023, "Permanent martyr's shield" + 6024, "Paralysis ray" + 6025, "Dumbfounding touch" + 6026, "Disease touch" + 6027, "Absorb spells" + 6028, "Web touch" + 6029, "Sleep touch" + 6030, "Paralysis touch" + 6031, "Petrification touch" + 6032, "Acid touch" + 6033, "Breathe sleep clouds" + 6034, "Acid spit" + 6035, "Shoot spines (dam 7-42)" + 6036, "Death touch (use with care)" + 6037, "Invulnerable (use with care)" + 6038, "Guard" + 6050, "No ability" + 6051, "Radiate fire fields" + 6052, "Radiate ice fields" + 6053, "Radiate shock fields" + 6054, "Radiate antimagic fields" + 6055, "Radiate sleep fields" + 6056, "Radiate stink clouds" + 6057, "Unused" + 6058, "Unused" + 6059, "Unused" + 6060, "Summon (%5 chance)" + 6061, "Summon (%20 chance)" + 6062, "Summon (%50 chance)" + 6063, "Unused" + 6064, "Unused" + 6065, "Death triggers scen. special" + 6080, "Unused" + 6081, "Percentage chance (1-100%)" + 6082, "Percentage chance (1-100%)" + 6083, "Percentage chance (1-100%)" + 6084, "Percentage chance (1-100%)" + 6085, "Percentage chance (1-100%)" + 6086, "Percentage chance (1-100%)" + 6087, "Unused" + 6088, "Unused" + 6089, "Unused" + 6090, "Number of creature to summon" + 6091, "Number of creature to summon" + 6092, "Number of creature to summon" + 6093, "Unused" + 6094, "Unused" + 6095, "Number of special to call" + 6130, "Hits/Swings" + 6131, "Claws" + 6132, "Bites" + 6133, "Slimes" + 6134, "Hits/Punches" + 6135, "Stings" + 6136, "Clubs" + 6137, "Burns" + 6138, "Harms" + 6139, "Stabs" + 6150, "Human" + 6151, "Reptile" + 6152, "Beast" + 6153, "Important" + 6154, "Mage" + 6155, "Priest" + 6156, "Humanoid" + 6157, "Demon" + 6158, "Undead" + 6159, "Giant" + 6160, "Slime" + 6161, "Stone" + 6162, "Bug" + 6163, "Dragon" + 6164, "Magical Creature" + 6301, "None" + 6302, "Change when step on" + 6303, "Does fire damage" + 6304, "Does cold damage" + 6305, "Does magical damage" + 6306, "Poison land" + 6307, "Diseased land" + 6308, "Crumbling terrain" + 6309, "Lockable terrain" + 6310, "Unlockable terrain" + 6311, "Unlockable/bashable" + 6312, "Is a sign" + 6313, "Call local special" + 6314, "Call scenario special" + 6315, "Is a container" + 6316, "Waterfall" + 6317, "Conveyor (north)" + 6318, "Conveyor (east)" + 6319, "Conveyor (south)" + 6320, "Conveyor (west)" + 6321, "Blocked to monsters" + 6322, "Town entrance" + 6323, "Can be used" + 6324, "Call special when used" + 6340, "Unused" + 6341, "What to change to?" + 6342, "Amount of damage done" + 6343, "Amount of damage done" + 6344, "Amount of damage done" + 6345, "Strength (1-8)" + 6346, "Strength (1-8)" + 6347, "Terrain to change to" + 6348, "Terrain to change to when locked" + 6349, "Terrain to change to when unlocked" + 6350, "Terrain to change to when unlocked" + 6351, "Unused" + 6352, "Number of special to call" + 6353, "Number of special to call" + 6354, "Unused" + 6355, "Unused" + 6356, "Unused" + 6357, "Unused" + 6358, "Unused" + 6359, "Unused" + 6360, "Unused" + 6361, "Terrain type if hidden" + 6362, "Terrain to change to when used" + 6363, "Number of scenario spec. to call" + 6380, "Unused" + 6381, "Number of sound (200 - no sound)" + 6382, "Damage multiplier" + 6383, "Damage multiplier" + 6384, "Damage multiplier" + 6385, "Percentage chance (1-100)" + 6386, "Percentage chance (1-100)" + 6387, "Unused" + 6388, "Unused" + 6389, "Difficulty (0-10)" + 6390, "Difficulty (0-10)" + 6391, "Unused" + 6392, "Unused" + 6393, "Unused" + 6394, "Unused" + 6395, "Unused" + 6396, "Unused" + 6397, "Unused" + 6398, "Unused" + 6399, "Unused" + 6400, "Unused" + 6401, "Unused" + 6402, "Number of sound (200 - no sound)" + 6403, "Unused" + 6601, "No Special" + 6602, "Set Flag" + 6603, "Increment Flag" + 6604, "Display Message" + 6605, "Secret Passage" + 6606, "Display Small Message" + 6607, "Flip Flag" + 6608, "Out Block" + 6609, "Town Block" + 6610, "Combat Block" + 6611, "Looking Block" + 6612, "Can't Enter" + 6613, "Change Time" + 6614, "Start General Timer" + 6615, "Play a Sound" + 6616, "Change Horse Possession" + 6617, "Change Boat Possession" + 6618, "Show/Hide Town" + 6619, "Major Event Has Occured" + 6620, "Forced Give" + 6621, "Buy Items of Type" + 6622, "Call Global Special" + 6623, "Set Many Flags" + 6624, "Copy Flag" + 6625, "Ritual of Sanct. Block" + 6626, "Have a Rest" + 6627, "Wandering will fight" + 6628, "End Scenario" + 6651, "Give Item" + 6652, "Give Special Item" + 6653, "One-Time Do Nothing" + 6654, "One-Time and Set" + 6655, "One-Time Text Message" + 6656, "Display Dialog (Dialog pic)" + 6657, "Display Dialog (Terrain pic)" + 6658, "Display Dialog (Monster pic)" + 6659, "Give Item (Dialog pic)" + 6660, "Give Item (Terrain pic)" + 6661, "Give Item (Monster pic)" + 6662, "One-Time Place Outdoor Enc." + 6663, "One-Time Place Town Enc." + 6664, "Trap" + 6681, "Select a PC" + 6682, "Do Damage" + 6683, "Affect Health" + 6684, "Affect Spell Points" + 6685, "Affect Experience" + 6686, "Affect Skill Points" + 6687, "Kill/Raise Dead" + 6688, "Affect Poison" + 6689, "Affect Slow/Haste" + 6690, "Affect Invulnerability" + 6691, "Affect Magic Resistance" + 6692, "Affect Webs" + 6693, "Affect Disease" + 6694, "Affect Sanctuary" + 6695, "Affect Curse/Bless" + 6696, "Affect Dumbfounding" + 6697, "Affect Sleep" + 6698, "Affect Paralysis" + 6699, "Affect Statistic" + 6700, "Give Mage Spell" + 6701, "Give Priest Spell" + 6702, "Affect Gold" + 6703, "Affect Food" + 6704, "Affect Alchemy" + 6705, "Affect Stealth" + 6706, "Affect Firewalk" + 6707, "Affect Flying" + 6731, "Stuff Done Flag?" + 6732, "Town Number?" + 6733, "Random Number?" + 6734, "Have Special Item?" + 6735, "Stuff Done Compare?" + 6736, "Terrain this type? (town)" + 6737, "Terrain this type? (out)" + 6738, "Has gold?" + 6739, "Has food?" + 6740, "Item Class on Space?" + 6741, "Have Item With Class?" + 6742, "Equipped Item With Class?" + 6743, "Has Gold? (+ take)" + 6744, "Has Food? (+ take)" + 6745, "Item Class on Space? (+ take)" + 6746, "Have Item W. Class? (+ take)" + 6747, "Equip Item W. Class? (+ take)" + 6748, "Day Reached?" + 6749, "Any Barrels?" + 6750, "Any Crates?" + 6751, "Special Thing Happened?" + 6752, "Has Cave Lore?" + 6753, "Has Woodsman?" + 6754, "Has Enough Mage Lore?" + 6755, "Text Response?" + 6756, "Stuff Done Equal?" + 6771, "Town Hostile" + 6772, "Change Terrain" + 6773, "Swap Terrain" + 6774, "Transform Terrain" + 6775, "Move Party" + 6776, "Hit Space" + 6777, "Explosion on Space" + 6778, "Lock Space" + 6779, "Unlock Space" + 6780, "Do sfx Burst" + 6781, "Make Wandering Monster" + 6782, "Place a Monster" + 6783, "Destroy Monster" + 6784, "Destroy All Monsters" + 6785, "Generic Lever" + 6786, "Generic Portal" + 6787, "Generic Button" + 6788, "Generic Stairway" + 6789, "Lever" + 6790, "Portal" + 6791, "Stairway" + 6792, "Relocate Outdoors" + 6793, "Place Item" + 6794, "Split Party" + 6795, "Reunite Party" + 6796, "Start Town Timer" + 6797, "Unused" + 6798, "Unused" + 6799, "Unused" + 6800, "Unused" + 6801, "Place Fire Wall" + 6802, "Place Force Wall" + 6803, "Place Ice Wall" + 6804, "Place Blade Wall" + 6805, "Place Stinking Cloud" + 6806, "Place Sleep Field" + 6807, "Place Quickfire" + 6808, "Place Fire Barrier" + 6809, "Place Force Barrier" + 6810, "Cleanse Rectangle" + 6811, "Place SFX" + 6812, "Place Barrels, Etc." + 6813, "Move Items" + 6814, "Destroy Items" + 6815, "Change Rectange Terrain" + 6816, "Swap Rectangle Terrain" + 6817, "Transform Rectangle Terrain" + 6818, "Lock Rectangle" + 6819, "Unlock Rectangle" + 6826, "Make Outdoor Wandering" + 6827, "Change Out Terrain" + 6828, "Place Outdoor Encounter" + 6829, "Outdoor Move Party" + 6830, "Outdoor Store" + 6901, "No ability" + 6902, "Flaming Weapon" + 6903, "Demon Slayer" + 6904, "Undead Slayer" + 6905, "Lizard Slayer" + 6906, "Giant Slayer" + 6907, "Mage Slayer" + 6908, "Priest Slayer" + 6909, "Bug Slayer" + 6910, "Acidic Weapon" + 6911, "Soulsucker" + 6912, "Drain Missiles" + 6913, "Weak Weapon" + 6914, "Causes Fear" + 6915, "Poisoned Weapon" + 6931, "Protection" + 6932, "Full Protection" + 6933, "Fire Protection" + 6934, "Cold Protection" + 6935, "Poison Protection" + 6936, "Magic Protection" + 6937, "Acid Protection" + 6938, "Skill" + 6939, "Strength" + 6940, "Dexterity" + 6941, "Intelligence" + 6942, "Accuracy" + 6943, "Thieving" + 6944, "Giant Strength" + 6945, "Lighter Object" + 6946, "Heavier Object" + 6947, "Occasional Bless" + 6948, "Occasional Haste" + 6949, "Life Saving" + 6950, "Prot. From Petrify" + 6951, "Regenerate" + 6952, "Poison Augment" + 6953, "Disease Party" + 6954, "Will" + 6955, "Free Action" + 6956, "Speed" + 6957, "Slow Wearer" + 6958, "Protection from Undead" + 6959, "Protection from Demons" + 6960, "Prot. from Humanoids" + 6961, "Prot. from Reptiles" + 6962, "Prot. from Giants" + 6963, "Prot. from Disease" + 6971, "Poison Weapon" + 6972, "Curse/Bless User" + 6973, "Cure/Cause Poison" + 6974, "Speed/Slow User" + 6975, "Add/Lose Invulnerability" + 6976, "Add/Lose Magic Res." + 6977, "Add/Lose Web" + 6978, "Cause/Cure Disease" + 6979, "Add/Lose Sanctuary" + 6980, "Cure/Cause Dumbfound" + 6981, "Add/Lose Martyr's Shield" + 6982, "Cure/Cause Sleep" + 6983, "Cure/Cause Paralysis" + 6984, "Cure/Cause Acid" + 6985, "Bliss" + 6986, "Add/Lose Experience" + 6987, "Add/Lose Skill Pts." + 6988, "Add/Lose Health" + 6989, "Add/Lose Spell Points" + 6990, "Doom" + 6991, "Light" + 6992, "Stealth" + 6993, "Firewalk" + 6994, "Flying" + 6995, "Major Healing" + 7011, "Flame" + 7012, "Fireball" + 7013, "Firestorm" + 7014, "Kill" + 7015, "Ice Bolt" + 7016, "Slow" + 7017, "Shockwave" + 7018, "Dispel Undead" + 7019, "Dispel Spirit" + 7020, "Summoning" + 7021, "Mass Summoning" + 7022, "Acid Spray" + 7023, "Stinking Cloud" + 7024, "Sleep Field" + 7025, "Venom" + 7026, "Shockstorm" + 7027, "Paralysis" + 7028, "Web Spell" + 7029, "Strengthen Target" + 7030, "Quickfire" + 7031, "Mass Charm" + 7032, "Magic Map" + 7033, "Dispel Barrier" + 7034, "Make Ice Wall" + 7035, "Charm Spell" + 7036, "Antimagic Cloud" + 7051, "Holly/Toadstool" + 7052, "Comfrey Root" + 7053, "Glowing Nettle" + 7054, "Crypt Shroom/Wormgr." + 7055, "Asptongue Mold" + 7056, "Ember Flowers" + 7057, "Graymold" + 7058, "Mandrake" + 7059, "Sapphire" + 7060, "Smoky Crystal" + 7061, "Ressurection Balm" + 7062, "Lockpicks" + 7071, "Returning" + 7072, "Lightning" + 7073, "Exploding" + 7074, "Acid" + 7075, "Slay Undead" + 7076, "Slay Demon" + 7077, "Heal Target" + 9001, "Unused" + 9002, "Value to change to" + 9003, "Increase/Decrease by" + 9004, "Unused" + 9005, "Unused" + 9006, "Unused" + 9007, "Unused" + 9008, "0 - can enter, 1 - no enter" + 9009, "0 - can enter, 1 - no enter" + 9010, "0 - can enter, 1 - no enter" + 9011, "Unused" + 9012, "0 - can enter, 1 - no enter" + 9013, "Number of moves to set forward" + 9014, "Number of moves to set the timer" + 9015, "Which sound" + 9016, "Horse to set (0 .. 29)" + 9017, "Boat to set (0 .. 29)" + 9018, "Town to show/hide" + 9019, "Number of Special Event (1 .. 10)" + 9020, "Item To Give" + 9021, "Item Class to Take Away" + 9022, "Usused" + 9023, "Value to change the 10 flags to" + 9024, "Flag to change to Part A" + 9025, "Unused" + 9026, "Number of moves that pass" + 9027, "0 - no attack, 1 - attack" + 9028, "Unused" + 9051, "Item to give" + 9052, "Num. of spec. item to give (0 .. 49)" + 9053, "Unused" + 9054, "Unused" + 9055, "Unused" + 9056, "Label of 2nd button (-1 - no button)" + 9057, "Label of 2nd button (-1 - no button)" + 9058, "Label of 2nd button (-1 - no button)" + 9059, "Item to give" + 9060, "Item to give" + 9061, "Item to give" + 9062, "Special outdoor enc. to place (0 .. 3)" + 9063, "Spec. enc. code to activate (1 .. 10)" + 9064, "Type of trap (see docs. for list)" + 9081, "0 - only living, 1 - any PC" + 9082, "Number of dice" + 9083, "Amount" + 9084, "Amount" + 9085, "Amount (0 .. 100)" + 9086, "Amount (0 .. 10)" + 9087, "0 - dead, 1 - dust, 2- stoned" + 9088, "Amount (0 .. 8)" + 9089, "Amount (0 .. 8)" + 9090, "Amount (0 .. 8)" + 9091, "Amount (0 .. 8)" + 9092, "Amount (0 .. 8)" + 9093, "Amount (0 .. 8)" + 9094, "Amount (0 .. 8)" + 9095, "Amount (0 .. 8)" + 9096, "Amount (0 .. 7)" + 9097, "Amount (0 .. 8)" + 9098, "Amount (0 .. 5000)" + 9099, "Amount (0 .. 10)" + 9100, "Which Spell (0 .. 31, see docs)" + 9101, "Which Spell (0 .. 31, see docs)" + 9102, "Amount (0 .. 25000)" + 9103, "Amount (0 .. 25000)" + 9104, "Which Recipe (0 .. 19)" + 9105, "Amount (0 .. 250)" + 9106, "Amount (0 .. 250)" + 9107, "Amount (0 .. 250)" + 9131, "If at least this value ..." + 9132, "If in this town ..." + 9133, "If random # (1 - 100) less than ..." + 9134, "If has spec. item ..." + 9135, "Stuff Done flag 2 Part A" + 9136, "X coordinate of space" + 9137, "X coordinate of space" + 9138, "If party has this much gold ..." + 9139, "If party has this much food ..." + 9140, "X coordinate of space" + 9141, "If has item of this special class ..." + 9142, "If has equipped item of this special" + 9143, "If party has this much gold ..." + 9144, "If party has this much food ..." + 9145, "X coordinate of space" + 9146, "If has item of this special class ..." + 9147, "If has equipped item of this class ..." + 9148, "If this day has been reached ..." + 9149, "Unused" + 9150, "Unused" + 9151, "If this day has been reached ..." + 9152, "Unused" + 9153, "Unused" + 9154, "If the party has this much Mage Lore" + 9155, "Number of a SCENARIO special message" + 9156, "If flag has this value ..." + 9171, "Unused" + 9172, "X coordinate of space" + 9173, "X coordinate of space" + 9174, "X coordinate of space" + 9175, "X coordinate of space" + 9176, "X coordinate of space" + 9177, "X coordinate of space" + 9178, "X coordinate of space" + 9179, "X coordinate of space" + 9180, "X coordinate of space" + 9181, "Unused" + 9182, "X coordinate of space to place" + 9183, "Type of creature to remove" + 9184, "0 - all, 1 - friendly, 2 - hostile" + 9185, "Unused" + 9186, "X coordinate to telep. to" + 9187, "Unused" + 9188, "X coordinate to go to " + 9189, "Unused" + 9190, "X coordinate to telep. to" + 9191, "X coordinate to place at" + 9192, "X coordinate of outdoor section" + 9193, "X coordinate to place at" + 9194, "X coordinate to place lone PC at" + 9195, "0 - no sound, 1 - teleport sound" + 9196, "Number of moves until event" + 9201, "Top of rectangle" + 9202, "Top of rectangle" + 9203, "Top of rectangle" + 9204, "Top of rectangle" + 9205, "Top of rectangle" + 9206, "Top of rectangle" + 9207, "Top of rectangle" + 9208, "Top of rectangle" + 9209, "Top of rectangle" + 9210, "Top of rectangle" + 9211, "Top of rectangle" + 9212, "Top of rectangle" + 9213, "Top of rectangle" + 9214, "Top of rectangle" + 9215, "Top of rectangle" + 9216, "Top of rectangle" + 9217, "Top of rectangle" + 9218, "Top of rectangle" + 9219, "Top of rectangle" + 9226, "Unused" + 9227, "X coordinate of space" + 9228, "Number of special encounter (0 .. 3)" + 9229, "X coordinate of space" + 9230, "Number of first item in store" + 9301, "Unused" + 9302, "Unused" + 9303, "0 - increase, 1 - decrease" + 9304, "Unused" + 9305, "Unused" + 9306, "Unused" + 9307, "Unused" + 9308, "Unused" + 9309, "Unused" + 9310, "Unused" + 9311, "Unused" + 9312, "Unused" + 9313, "Unused" + 9314, "Special to call when timer runs out" + 9315, "Unused" + 9316, "Unused" + 9317, "Unused" + 9318, "0 - town hidden, 1 - town visible" + 9319, "Unused" + 9320, "Unused" + 9321, "Special to call if no items taken" + 9322, "Unused" + 9323, "Unused" + 9324, "Flag to change to Part B" + 9325, "Special if not casting ritual" + 9326, "Health and spell pts. to give" + 9327, "Unused" + 9328, "Unused" + 9351, "Amount of gold to give" + 9352, "0 - give item, 1 - take away" + 9353, "Unused" + 9354, "Unused" + 9355, "Unused" + 9356, "Special if button 2 pressed" + 9357, "Special if button 2 pressed" + 9358, "Special if button 2 pressed" + 9359, "Amount of gold to give" + 9360, "Amount of gold to give" + 9361, "Amount of gold to give" + 9362, "Unused" + 9363, "Unused" + 9364, "Trap severity (0 .. 3)" + 9381, "Special if Cancel button pressed" + 9382, "Number of 'sides' on dice" + 9383, "0 - raise, 1 - lower" + 9384, "0 - raise, 1 - lower" + 9385, "0 - raise, 1 - lower" + 9386, "0 - raise, 1 - lower" + 9387, "0 - raise dead, 1 - hurt" + 9388, "0 - cure, 1 - inflict" + 9389, "0 - cure, 1 - inflict" + 9390, "0 - cure, 1 - inflict" + 9391, "0 - cure, 1 - inflict" + 9392, "0 - inflict, 1 - cure" + 9393, "0 - cure, 1 - inflict" + 9394, "0 - adds, 1 - removes" + 9395, "0 - blesses, 1 - curses" + 9396, "0 - cure, 1 - inflict" + 9397, "0 - cure, 1 - inflict" + 9398, "0 - cure, 1 - inflict" + 9399, "0 - increase, 1 - decrease" + 9400, "Unused" + 9401, "Unused" + 9402, "0 - increase, 1 - decrease" + 9403, "0 - increase, 1 - decrease" + 9404, "Unused" + 9405, "Unused" + 9406, "Unused" + 9407, "Unused" + 9431, "Call this special ..." + 9432, "Call this special ..." + 9433, "Call this special ..." + 9434, "Call this special ..." + 9435, "Stuff Done flag 2 Part B" + 9436, "Y coordinate of space" + 9437, "Y coordinate of space" + 9438, "Call this special ..." + 9439, "Call this special ..." + 9440, "Y coordinate of space" + 9441, "Call this special ..." + 9442, "Call this special ..." + 9443, "Call this special ..." + 9444, "Call this special ..." + 9445, "Y coordinate of space" + 9446, "Call this special ..." + 9447, "Call this special ..." + 9448, "Call this special ..." + 9449, "If any barrels, call this special ..." + 9450, "If any crates, call this special ..." + 9451, "And this event didn't happen before it" + 9452, "If any Cave Lore, call this special ..." + 9453, "If any Woodsman, call this special ..." + 9454, "Call this special ..." + 9455, "If answer matches, call this special" + 9456, "Call this special ..." + 9471, "Unused" + 9472, "Y coordinate of space" + 9473, "Y coordinate of space" + 9474, "Y coordinate of space" + 9475, "Y coordinate of space" + 9476, "Y coordinate of space" + 9477, "Y coordinate of space" + 9478, "Y coordinate of space" + 9479, "Y coordinate of space" + 9480, "Y coordinate of space" + 9481, "Unused" + 9482, "Y coordinate of space to place" + 9483, "Unused" + 9484, "Unused" + 9485, "If Pulled, call this special ..." + 9486, "Y coordinate to telep. to" + 9487, "If Pushed, call this special ..." + 9488, "Y coordinate to go to" + 9489, "If Pulled, call this special ..." + 9490, "Y coordinate to telep. to" + 9491, "Y coordinate to place at" + 9492, "Y coordinate of outdoor section" + 9493, "Y coordinate to place at" + 9494, "Y coordinate to place lone PC at" + 9495, "Unused" + 9496, "Call this special when time runs out" + 9501, "Left of rectangle" + 9502, "Left of rectangle" + 9503, "Left of rectangle" + 9504, "Left of rectangle" + 9505, "Left of rectangle" + 9506, "Left of rectangle" + 9507, "Left of rectangle" + 9508, "Left of rectangle" + 9509, "Left of rectangle" + 9510, "Left of rectangle" + 9511, "Left of rectangle" + 9512, "Left of rectangle" + 9513, "Left of rectangle" + 9514, "Left of rectangle" + 9515, "Left of rectangle" + 9516, "Left of rectangle" + 9517, "Left of rectangle" + 9518, "Left of rectangle" + 9519, "Left of rectangle" + 9526, "Unused" + 9527, "Y coordinate of space" + 9528, "Unused" + 9529, "Y coordinate of space" + 9530, "Store type (see docs. for list)" + 9601, "Unused" + 9602, "Unused" + 9603, "Unused" + 9604, "Unused" + 9605, "Unused" + 9606, "Unused" + 9607, "Unused" + 9608, "Unused" + 9609, "Unused" + 9610, "Unused" + 9611, "Unused" + 9612, "Unused" + 9613, "Unused" + 9614, "Unused" + 9615, "Unused" + 9616, "0 - not property, 1 - becomes property" + 9617, "0 - not property, 1 - becomes property" + 9618, "Unused" + 9619, "Unused" + 9620, "Unused" + 9621, "Amount to pay for each item" + 9622, "Unused" + 9623, "Unused" + 9624, "Unused" + 9625, "Unused" + 9626, "Unused" + 9627, "Unused" + 9628, "Unused" + 9651, "Amount of food to give" + 9652, "Unused" + 9653, "Unused" + 9654, "Unused" + 9655, "Unused" + 9656, "Label of 3rd button (-1 - no button)" + 9657, "Label of 3rd button (-1 - no button)" + 9658, "Label of 3rd button (-1 - no button)" + 9659, "Amount of food to give" + 9660, "Amount of food to give" + 9661, "Amount of food to give" + 9662, "Unused" + 9663, "Unused" + 9664, "Penalty (0 .. 100, higher is harder)" + 9681, "Unused" + 9682, "Amount of extra damage" + 9683, "Unused" + 9684, "Unused" + 9685, "Unused" + 9686, "Unused" + 9687, "Unused" + 9688, "Unused" + 9689, "Unused" + 9690, "Unused" + 9691, "Unused" + 9692, "Unused" + 9693, "Unused" + 9694, "Unused" + 9695, "Unused" + 9696, "Unused" + 9697, "Unused" + 9698, "Unused" + 9699, "Stat. to adjust (see docs. for list)" + 9700, "Unused" + 9701, "Unused" + 9702, "Unused" + 9703, "Unused" + 9704, "Unused" + 9705, "Unused" + 9706, "Unused" + 9707, "Unused" + 9731, "If less than this ..." + 9732, "Unused" + 9733, "Unused" + 9734, "Unused" + 9735, "Unused" + 9736, "If space is this terrain type ..." + 9737, "If space is this terrain type ..." + 9738, "Unused" + 9739, "Unused" + 9740, "If item of this class on space ..." + 9741, "Unused" + 9742, "Unused" + 9743, "Unused" + 9744, "Unused" + 9745, "If item of this class on space ..." + 9746, "Unused" + 9747, "Unused" + 9748, "Unused" + 9749, "Unused" + 9750, "Unused" + 9751, "Unused" + 9752, "Unused" + 9753, "Unused" + 9754, "Unused" + 9755, "Number of a SCENARIO special message" + 9756, "Unused" + 9771, "Unused" + 9772, "Terrain to change to" + 9773, "Swap this terrain ..." + 9774, "Unused" + 9775, "0 - Just move, 1 - Teleport" + 9776, "Damage to inflict (0 .. 1000)" + 9777, "Damage to inflict (0 .. 1000)" + 9778, "Unused" + 9779, "Unused" + 9780, "0 - fire, 1 - elec., 2 - telep." + 9781, "Unused" + 9782, "Number of creature to place" + 9783, "Unused" + 9784, "Unused" + 9785, "Unused" + 9786, "0 - Just move, 1 - Teleport" + 9787, "Unused" + 9788, "Number of town to place party in" + 9789, "Unused" + 9790, "0 - Just move, 1 - Teleport" + 9791, "Number of town to place party in" + 9792, "X coordinate inside section " + 9793, "Item to place" + 9794, "0 - no telep. noise, 1 - play a noise" + 9795, "Unused" + 9796, "Unused" + 9801, "Bottom of rectangle" + 9802, "Bottom of rectangle" + 9803, "Bottom of rectangle" + 9804, "Bottom of rectangle" + 9805, "Bottom of rectangle" + 9806, "Bottom of rectangle" + 9807, "Bottom of rectangle" + 9808, "Bottom of rectangle" + 9809, "Bottom of rectangle" + 9810, "Bottom of rectangle" + 9811, "Bottom of rectangle" + 9812, "Bottom of rectangle" + 9813, "Bottom of rectangle" + 9814, "Bottom of rectangle" + 9815, "Bottom of rectangle" + 9816, "Bottom of rectangle" + 9817, "Bottom of rectangle" + 9818, "Bottom of rectangle" + 9819, "Bottom of rectangle" + 9826, "Unused" + 9827, "Terrain to change to" + 9828, "Unused" + 9829, "Unused" + 9830, "Number of items in store (1 .. 40)" + 9901, "Unused" + 9902, "Unused" + 9903, "Unused" + 9904, "Unused" + 9905, "Unused" + 9906, "Unused" + 9907, "Unused" + 9908, "Unused" + 9909, "Unused" + 9910, "Unused" + 9911, "Unused" + 9912, "Unused" + 9913, "Unused" + 9914, "Unused" + 9915, "Unused" + 9916, "Unused" + 9917, "Unused" + 9918, "Unused" + 9919, "Unused" + 9920, "Special if item not given" + 9921, "Unused" + 9922, "Unused" + 9923, "Unused" + 9924, "Unused" + 9925, "Unused" + 9926, "Unused" + 9927, "Unused" + 9928, "Unused" + 9951, "Special if item not given" + 9952, "Unused" + 9953, "Unused" + 9954, "Unused" + 9955, "Unused" + 9956, "Special if button 3 pressed" + 9957, "Special if button 3 pressed" + 9958, "Special if button 3 pressed" + 9959, "Special if item IS taken" + 9960, "Special if item IS taken" + 9961, "Special if item IS taken" + 9962, "Unused" + 9963, "Unused" + 9964, "Unused" + 9965, "Unused" + 9981, "Unused" + 9982, "Type of damage (for list, see docs.)" + 9983, "Unused" + 9984, "Unused" + 9985, "Unused" + 9986, "Unused" + 9987, "Unused" + 9988, "Unused" + 9989, "Unused" + 9990, "Unused" + 9991, "Unused" + 9992, "Unused" + 9993, "Unused" + 9994, "Unused" + 9995, "Unused" + 9996, "Unused" + 9997, "Unused" + 9998, "Unused" + 9999, "Unused" + 10000, "Unused" + 10001, "Unused" + 10002, "Unused" + 10003, "Unused" + 10004, "Unused" + 10005, "Unused" + 10006, "Unused" + 10007, "Unused" + 10031, "Call this special ..." + 10032, "Unused" + 10033, "Unused" + 10034, "Unused" + 10035, "Call this special is 2nd flag lower ..." + 10036, "Call this special ..." + 10037, "Call this special ..." + 10038, "Unused" + 10039, "Unused" + 10040, "Call this special ..." + 10041, "Unused" + 10042, "Unused" + 10043, "Unused" + 10044, "Unused" + 10045, "Call this special ..." + 10046, "Unused" + 10047, "Unused" + 10048, "Unused" + 10049, "Unused" + 10050, "Unused" + 10051, "Call this special ..." + 10052, "Unused" + 10053, "Unused" + 10054, "Unused" + 10055, "If answer matches, call this special" + 10056, "Unused" + 10071, "Unused" + 10072, "Unused" + 10073, "With this terrain ..." + 10074, "Unused" + 10075, "Unused" + 10076, "Unused" + 10077, "Type of damage (for list, see docs.)" + 10078, "Unused" + 10079, "Unused" + 10080, "Unused" + 10081, "Unused" + 10082, "0 - don't force, 1 - force" + 10083, "Unused" + 10084, "Unused" + 10085, "Unused" + 10086, "Unused" + 10087, "Unused" + 10088, "What text? (0,2,4,6 up; 1,3,5,7 down)" + 10089, "Unused" + 10090, "Unused" + 10091, "If 1, always change level." + 10092, "Y coordinate inside section " + 10093, "Unused" + 10094, "Unused" + 10095, "Unused" + 10096, "Unused" + 10101, "Right of rectangle" + 10102, "Right of rectangle" + 10103, "Right of rectangle" + 10104, "Right of rectangle" + 10105, "Right of rectangle" + 10106, "Right of rectangle" + 10107, "Right of rectangle" + 10108, "Right of rectangle" + 10109, "Right of rectangle" + 10110, "Right of rectangle" + 10111, "Right of rectangle" + 10112, "Right of rectangle" + 10113, "Right of rectangle" + 10114, "Right of rectangle" + 10115, "Right of rectangle" + 10116, "Right of rectangle" + 10117, "Right of rectangle" + 10118, "Right of rectangle" + 10119, "Right of rectangle" + 10126, "Unused" + 10127, "Unused" + 10128, "Unused" + 10129, "Unused" + 10130, "Cost adjust (0 .. 6, lower = cheaper)" + 10501, "Scen name" + 10502, "Who wrote 1 " + 10503, "Who wrote 2" + 10504, "Contact info" + 10511, "Begin journal strs" + 10560, "End journal strs" + 10561, "Unused Special Item" + 10563, "Unused Special Item" + 10565, "Unused Special Item" + 10567, "Unused Special Item" + 10569, "Unused Special Item" + 10571, "Unused Special Item" + 10573, "Unused Special Item" + 10575, "Unused Special Item" + 10577, "Unused Special Item" + 10579, "Unused Special Item" + 10581, "Unused Special Item" + 10583, "Unused Special Item" + 10585, "Unused Special Item" + 10587, "Unused Special Item" + 10589, "Unused Special Item" + 10591, "Unused Special Item" + 10593, "Unused Special Item" + 10595, "Unused Special Item" + 10597, "Unused Special Item" + 10599, "Unused Special Item" + 10601, "Unused Special Item" + 10603, "Unused Special Item" + 10605, "Unused Special Item" + 10607, "Unused Special Item" + 10609, "Unused Special Item" + 10611, "Unused Special Item" + 10613, "Unused Special Item" + 10615, "Unused Special Item" + 10617, "Unused Special Item" + 10619, "Unused Special Item" + 10621, "Unused Special Item" + 10623, "Unused Special Item" + 10625, "Unused Special Item" + 10627, "Unused Special Item" + 10629, "Unused Special Item" + 10631, "Unused Special Item" + 10633, "Unused Special Item" + 10635, "Unused Special Item" + 10637, "Unused Special Item" + 10639, "Unused Special Item" + 10641, "Unused Special Item" + 10643, "Unused Special Item" + 10645, "Unused Special Item" + 10647, "Unused Special Item" + 10649, "Unused Special Item" + 10651, "Unused Special Item" + 10653, "Unused Special Item" + 10655, "Unused Special Item" + 10657, "Unused Special Item" + 10659, "Unused Special Item" + 10660, "End special item descs" + 10661, "*Begin special strs" + 10662, "*" + 10663, "*" + 10664, "*" + 10665, "*" + 10666, "*" + 10667, "*" + 10668, "*" + 10669, "*" + 10670, "*" + 10671, "*" + 10672, "*" + 10673, "*" + 10674, "*" + 10675, "*" + 10676, "*" + 10677, "*" + 10678, "*" + 10679, "*" + 10680, "*" + 10681, "*" + 10682, "*" + 10683, "*" + 10684, "*" + 10685, "*" + 10686, "*" + 10687, "*" + 10688, "*" + 10689, "*" + 10690, "*" + 10691, "*" + 10692, "*" + 10693, "*" + 10694, "*" + 10695, "*" + 10696, "*" + 10697, "*" + 10698, "*" + 10699, "*" + 10700, "*" + 10701, "*" + 10702, "*" + 10703, "*" + 10704, "*" + 10705, "*" + 10706, "*" + 10707, "*" + 10708, "*" + 10709, "*" + 10710, "*" + 10711, "*" + 10712, "*" + 10713, "*" + 10714, "*" + 10715, "*" + 10716, "*" + 10717, "*" + 10718, "*" + 10719, "*" + 10720, "*" + 10721, "*" + 10722, "*" + 10723, "*" + 10724, "*" + 10725, "*" + 10726, "*" + 10727, "*" + 10728, "*" + 10729, "*" + 10730, "*" + 10731, "*" + 10732, "*" + 10733, "*" + 10734, "*" + 10735, "*" + 10736, "*" + 10737, "*" + 10738, "*" + 10739, "*" + 10740, "*" + 10741, "*" + 10742, "*" + 10743, "*" + 10744, "*" + 10745, "*" + 10746, "*" + 10747, "*" + 10748, "*" + 10749, "*" + 10750, "*" + 10751, "*" + 10752, "*" + 10753, "*" + 10754, "*" + 10755, "*" + 10756, "*" + 10757, "*" + 10758, "*" + 10759, "*" + 10760, "*End special strs" + 10761, "From here on, reserved for furute use" + 10801, "Town name" + 10802, "Rectangle 1" + 10803, "Rectangle 2" + 10804, "Rectangle 3" + 10805, "Rectangle 4" + 10806, "Rectangle 5" + 10807, "Rectangle 6" + 10808, "Rectangle 7" + 10809, "Rectangle 8" + 10810, "Rectangle 9" + 10811, "Rectangle 10" + 10812, "Rectangle 11" + 10813, "Rectangle 12" + 10814, "Rectangle 13" + 10815, "Rectangle 14" + 10816, "Rectangle 15" + 10817, "Rectangle 16" + 10818, "Comment 1" + 10819, "Comment 2" + 10820, "Comment 3" + 10821, "*Begin special strs" + 10822, "*" + 10823, "*" + 10824, "*" + 10825, "*" + 10826, "*" + 10827, "*" + 10828, "*" + 10829, "*" + 10830, "*" + 10831, "*" + 10832, "*" + 10833, "*" + 10834, "*" + 10835, "*" + 10836, "*" + 10837, "*" + 10838, "*" + 10839, "*" + 10840, "*" + 10841, "*" + 10842, "*" + 10843, "*" + 10844, "*" + 10845, "*" + 10846, "*" + 10847, "*" + 10848, "*" + 10849, "*" + 10850, "*" + 10851, "*" + 10852, "*" + 10853, "*" + 10854, "*" + 10855, "*" + 10856, "*" + 10857, "*" + 10858, "*" + 10859, "*" + 10860, "*" + 10861, "*" + 10862, "*" + 10863, "*" + 10864, "*" + 10865, "*" + 10866, "*" + 10867, "*" + 10868, "*" + 10869, "*" + 10870, "*" + 10871, "*" + 10872, "*" + 10873, "*" + 10874, "*" + 10875, "*" + 10876, "*" + 10877, "*" + 10878, "*" + 10879, "*" + 10880, "*" + 10881, "*" + 10882, "*" + 10883, "*" + 10884, "*" + 10885, "*" + 10886, "*" + 10887, "*" + 10888, "*" + 10889, "*" + 10890, "*" + 10891, "*" + 10892, "*" + 10893, "*" + 10894, "*" + 10895, "*" + 10896, "*" + 10897, "*" + 10898, "*" + 10899, "*" + 10900, "*" + 10901, "*" + 10902, "*" + 10903, "*" + 10904, "*" + 10905, "*" + 10906, "*" + 10907, "*" + 10908, "*" + 10909, "*" + 10910, "*" + 10911, "*" + 10912, "*" + 10913, "*" + 10914, "*" + 10915, "*" + 10916, "*" + 10917, "*" + 10918, "*" + 10919, "*" + 10920, "*" + 11101, "Area name" + 11102, "Rectangle 1" + 11103, "Rectangle 2" + 11104, "Rectangle 3" + 11105, "Rectangle 4" + 11106, "Rectangle 5" + 11107, "Rectangle 6" + 11108, "Rectangle 7" + 11109, "Rectangle 8" + 11110, "Comment" + 11111, "*Begin special strs" + 11112, "*" + 11113, "*" + 11114, "*" + 11115, "*" + 11116, "*" + 11117, "*" + 11118, "*" + 11119, "*" + 11120, "*" + 11121, "*" + 11122, "*" + 11123, "*" + 11124, "*" + 11125, "*" + 11126, "*" + 11127, "*" + 11128, "*" + 11129, "*" + 11130, "*" + 11131, "*" + 11132, "*" + 11133, "*" + 11134, "*" + 11135, "*" + 11136, "*" + 11137, "*" + 11138, "*" + 11139, "*" + 11140, "*" + 11141, "*" + 11142, "*" + 11143, "*" + 11144, "*" + 11145, "*" + 11146, "*" + 11147, "*" + 11148, "*" + 11149, "*" + 11150, "*" + 11151, "*" + 11152, "*" + 11153, "*" + 11154, "*" + 11155, "*" + 11156, "*" + 11157, "*" + 11158, "*" + 11159, "*" + 11160, "*" + 11161, "*" + 11162, "*" + 11163, "*" + 11164, "*" + 11165, "*" + 11166, "*" + 11167, "*" + 11168, "*" + 11169, "*" + 11170, "*" + 11171, "*" + 11172, "*" + 11173, "*" + 11174, "*" + 11175, "*" + 11176, "*" + 11177, "*" + 11178, "*" + 11179, "*" + 11180, "*" + 11181, "*" + 11182, "*" + 11183, "*" + 11184, "*" + 11185, "*" + 11186, "*" + 11187, "*" + 11188, "*" + 11189, "*" + 11190, "*" + 11191, "*" + 11192, "*" + 11193, "*" + 11194, "*" + 11195, "*" + 11196, "*" + 11197, "*" + 11198, "*" + 11199, "*" + 11200, "*End of special strs" + 11209, "From here on, reserved for future use" + 11401, "Poison" + 11402, "Ice Bolt" + 11403, "Slow Group" + 11404, "Magic Map" + 11405, "Capture Soul" + 11406, "Simulacrum" + 11407, "Venom Arrows" + 11408, "Wall of Ice" + 11409, "Stealth" + 11410, "Major Haste" + 11411, "Firestorm" + 11412, "Dispel Barrier" + 11413, "Fire Barrier" + 11414, "Summoning" + 11415, "Shockstorm" + 11416, "Spray Fields" + 11417, "Major Poison" + 11418, "Group Fear" + 11419, "Kill" + 11420, "Paralyze" + 11421, "Daemon" + 11422, "Antimagic Cloud" + 11423, "Mindduel" + 11424, "Flight" + 11425, "Shockwave" + 11426, "Major Blessing" + 11427, "Mass Paralysis" + 11428, "Protection" + 11429, "Major Summoning" + 11430, "Force Barrier" + 11431, "Quickfire" + 11432, "Death Arrows" + 11450, "Cure Party" + 11451, "Curse All" + 11452, "Dispel Undead" + 11453, "Remove Curse" + 11454, "Sticks to Snakes" + 11455, "Martyr's Shield" + 11456, "Cleanse" + 11457, "Firewalk" + 11458, "Bless Party" + 11459, "Major Heal" + 11460, "Raise Dead" + 11461, "Flamestrike" + 11462, "Mass Sanctuary" + 11463, "Summon Host" + 11464, "Shatter" + 11465, "Dispel Fields" + 11466, "Heal All" + 11467, "Revive" + 11468, "Hyperactivity" + 11469, "Destone" + 11470, "Summon Guardian" + 11471, "Mass Charm" + 11472, "Protective Circle" + 11473, "Pestilence" + 11474, "Revive All" + 11475, "Ravage Spirit" + 11476, "Resurrect" + 11477, "Divine Thud" + 11478, "Avatar" + 11479, "Wall of Blades" + 11480, "Word of Recall" + 11481, "Major Cleansing" + 11500, "Weak Curing" + 11501, "Weak Healing" + 11502, "Weak Poison" + 11503, "Weak Speed" + 11504, "Medium Poison" + 11505, "Medium Healing" + 11506, "Strong Curing" + 11507, "Medium Speed" + 11508, "Graymold Salve" + 11509, "Weak Power" + 11510, "Potion of Clarity" + 11511, "Strong Poison" + 11512, "Strong Healing" + 11513, "Killer Poison" + 11514, "Resurrection Balm" + 11515, "Medium Power" + 11516, "Knowledge Brew" + 11517, "Strong Strength" + 11518, "Bliss" + 11519, "Strong Power" + 12001, "Regular speech" + 12002, "Unused" + 12003, "Unused" + 12004, "Unused" + 12005, "Unused" + 12006, "First part of response ..." + 12007, "Second part of response ..." + 12008, "Response depends on flag" + 12009, "Stuff Done flag Pt. A" + 12010, "Stuff Done flag Pt. B" + 12011, "Value to compare to" + 12012, "Unused" + 12013, "Response if less than or equal to" + 12014, "Response if greater than" + 12015, "Set flag to 1" + 12016, "Stuff Done flag Pt. A" + 12017, "Stuff Done flag Pt. B" + 12018, "Unused" + 12019, "Unused" + 12020, "First part of response ..." + 12021, "Second part of response ..." + 12022, "Inn" + 12023, "Cost of Inn" + 12024, "Quality of Inn (0 .. 3)" + 12025, "Move party to X" + 12026, "Move party to Y" + 12027, "Response if can afford it ..." + 12028, "Response if not enough money ..." + 12029, "Depends on Day" + 12030, "Day when response changes" + 12031, "Unused" + 12032, "Unused" + 12033, "Unused" + 12034, "Response if day not reached ..." + 12035, "Response if day reached ..." + 12036, "Depends on time and event" + 12037, "If this day has been reached ..." + 12038, "this event did not happen before it" + 12039, "(Script overflow!)" + 12040, "Unused" + 12041, "Respond with this ..." + 12042, "Otherwise respond with this ..." + 12043, "Depends on town" + 12044, "Town to check" + 12045, "Unused" + 12046, "Unused" + 12047, "Unused" + 12048, "Response if in this town ..." + 12049, "Otherwise respond ..." + 12050, "Buy Items" + 12051, "Cost adjustment (0 .. 6)" + 12052, "Number of first item in shop" + 12053, "Total number of items in shop" + 12054, "Unused" + 12055, "Name of shop" + 12056, "Unused" + 12057, "Receive Training" + 12058, "Unused" + 12059, "Unused" + 12060, "Unused" + 12061, "Unused" + 12062, "Unused" + 12063, "Unused" + 12064, "Mage Spell Shop" + 12065, "Cost adjustment (0 .. 6)" + 12066, "Number of first spell in shop" + 12067, "Total number of spells in shop" + 12068, "Unused" + 12069, "Name of shop" + 12070, "Unused" + 12071, "Priest Spell Shop" + 12072, "Cost adjustment (0 .. 6)" + 12073, "Number of first spell in shop" + 12074, "Total number of spells in shop" + 12075, "Unused" + 12076, "Name of shop" + 12077, "Unused" + 12078, "Alchemy Shop" + 12079, "Cost adjustment (0 .. 6)" + 12080, "Number of first recipe in shop" + 12081, "Total number of recipes in shop" + 12082, "Unused" + 12083, "Name of shop" + 12084, "Unused" + 12085, "Healer" + 12086, "Cost adjustment (0 .. 6)" + 12087, "Unused" + 12088, "Unused" + 12089, "Unused" + 12090, "Name of healer" + 12091, "Unused" + 12092, "Sell Weapons" + 12093, "Unused" + 12094, "Unused" + 12095, "Unused" + 12096, "Unused" + 12097, "Buyer's response" + 12098, "Unused" + 12099, "Sell Armor" + 12100, "Unused" + 12101, "Unused" + 12102, "Unused" + 12103, "Unused" + 12104, "Buyer's response" + 12105, "Unused" + 12106, "Sell All Items" + 12107, "Unused" + 12108, "Unused" + 12109, "Unused" + 12110, "Unused" + 12111, "Buyer's response" + 12112, "Unused" + 12113, "Identify Items" + 12114, "Cost to identify" + 12115, "Unused" + 12116, "Unused" + 12117, "Unused" + 12118, "Person identifying items says:" + 12119, "Unused" + 12120, "Enchant Weapons" + 12121, "Type of enchantment" + 12122, "Unused"//(Script overflow!)" + 12123, "Unused" + 12124, "Unused" + 12125, "Person augmenting items says:" + 12126, "Unused" + 12127, "Pay For Response" + 12128, "Amount of gold taken" + 12129, "Unused" + 12130, "Unused" + 12131, "Unused" + 12132, "Response if party has gold" + 12133, "Response if they don't" + 12134, "Buy response, Change Flag" + 12135, "Amount of gold taken" + 12136, "Stuff Done Flag, Pt. A" + 12137, "Stuff Done Flag, Pt. B" + 12138, "Change flag to" + 12139, "Response if party has gold" + 12140, "Response if they don't" + 12141, "Ship Shop" + 12142, "Cost of Boat" + 12143, "Number of first boat sold" + 12144, "Total number of boats sold" + 12145, "Unused" + 12146, "Response if party has gold" + 12147, "Response if they don't" + 12148, "Horse Shop" + 12149, "Cost of Horse" + 12150, "Number of first horse sold" + 12151, "Total number of horses sold" + 12152, "Unused" + 12153, "Response if party has gold" + 12154, "Response if they don't" + 12155, "Buy Special Item" + 12156, "Number of item being sold" + 12157, "Cost of item" + 12158, "Unused" + 12159, "Unused" + 12160, "Response if party buys it" + 12161, "Response if party can't afford it" + 12162, "Magic Shop" + 12163, "Cost adjustment (0 .. 6)" + 12164, "Which shop (0 .. 4)" + 12165, "Unused" + 12166, "Unused" + 12167, "Name of shop" + 12168, "Unused" + 12169, "Reveal Town Location" + 12170, "Cost to know where town is" + 12171, "Number of town to reveal" + 12172, "Unused" + 12173, "Unused" + 12174, "Response if party can pay" + 12175, "Response if party can't afford it" + 12176, "Force Conversation End" + 12177, "Unused" + 12178, "Unused" + 12179, "Unused" + 12180, "Unused" + 12181, "First part of response" + 12182, "Second part of response" + 12183, "Hostile Conversation End" + 12184, "Unused" + 12185, "Unused" + 12186, "Unused" + 12187, "Unused" + 12188, "First part of response" + 12189, "Second part of response" + 12190, "Town Hostile Conv. End" + 12191, "Unused" + 12192, "Unused" + 12193, "Unused" + 12194, "Unused" + 12195, "First part of response" + 12196, "Second part of response" + 12197, "Eliminate Creature" + 12198, "Unused" + 12199, "Unused" + 12200, "Unused" + 12201, "Unused" + 12202, "First part of response" + 12203, "Second part of response" + 12204, "Call Town Special" + 12205, "Number of town special node to call" + 12206, "Unused" + 12207, "Unused" + 12208, "Unused" + 12209, "First part of response (if no other response given in special)" + 12210, "Second part of response (if no other response given in special)" + 12211, "Call Scenario Special" + 12212, "Scenario special node number to call" + 12213, "Unused" + 12214, "Unused" + 12215, "Unused" + 12216, "First part of response (if no other response given in special)" + 12217, "Second part of response (if no other response given in special)" +} diff --git a/Win32/Scenarios Editor/TACTIONS.CPP b/Win32/Scenarios Editor/TACTIONS.CPP new file mode 100644 index 00000000..13d11eab --- /dev/null +++ b/Win32/Scenarios Editor/TACTIONS.CPP @@ -0,0 +1,3738 @@ +#include +#include +#include +#include +#include "Global.h" +#include "graphics.h" +#include "tactions.h" +#include "edsound.h" +#include "scenario.h" +#include "tfileio.h" +#include "keydlgs.h" +#include "townout.h" +#include "graphutl.h" +#include "buttonmg.h" + + +RECT world_screen; + // border rects order: top, left, bottom, right // +RECT border_rect[4]; +short current_block_edited = 0; +short current_terrain_type = 0; +short safety = 0; +location spot_hit,last_spot_hit = {-1,-1}; +creature_start_type null_monst = {0,0,{0,0},0,0,0,0,0,0}; +//creature_start_type store_monst = {0,0,{0,0},0,0,0,0,0,0}; +Boolean sign_error_received = FALSE; +short copied_spec = -1; + +Boolean good_palette_buttons[6][8] = { + {1,1,1,1,1,1,1,1}, + {1,1,1,1,1,1,0,1}, + {1,1,1,1,1,1,1,1}, + {1,1,1,0,1,1,1,1}, + {1,1,1,1,1,1,0,1}, + {1,1,1,1,1,1,1,1}}; +preset_item_type store_place_item = {{0,0},-1,0,0,0,0,0}; + +short flood_count = 0; + +RECT terrain_rects[256],terrain_rect_base = {0,0,16,16},command_rects[21]; + + +extern short ulx,uly,cen_x, cen_y, overall_mode,cur_town; +extern Boolean mouse_button_held,editing_town; +extern short cur_viewing_mode; +extern town_record_type town; +extern big_tr_type t_d; +extern short town_type; // 0 - big 1 - ave 2 - small +extern short max_dim[3],mode_count,to_create; +extern unsigned char template_terrain[64][64]; +extern short_item_record_type item_list[400]; +extern scenario_data_type scenario; +extern HWND right_sbar,mainPtr; +extern outdoor_record_type current_terrain; +extern location cur_out; +extern piles_of_stuff_dumping_type *data_store; +Boolean small_any_drawn = FALSE; +extern talking_record_type talking; +extern Boolean change_made; +extern scen_item_data_type scen_item_list; +extern piles_of_stuff_dumping_type *data_store; +extern char scen_strs[160][256]; +extern char scen_strs2[110][256]; +extern char talk_strs[170][256]; +extern char town_strs[180][256]; + +RECT left_buttons[NLS][2]; // 0 - whole, 1 - blue button +short left_button_status[NLS]; // 0 - clear, 1 - text, 2 - title text, +10 - button +short right_button_status[NRS]; +RECT right_buttons[NRSONPAGE]; +RECT palette_buttons[8][6]; +short current_rs_top = 0; + creature_start_type last_placed_monst = {0,0,{0,0},0,0,0,0,0,0,0}; + +special_node_type null_spec_node = {0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1}; +talking_node_type null_talk_node = {0,0,{120,120,120,120},{120,120,120,120},{0,0,0,0}}; + +RECT working_rect; +location last_space_hit; +Boolean erasing_mode; +unsigned char current_ground = 0; + +short special_to_paste = -1; + +void init_screen_locs() +{ + int i,j,q,r; + + for (i = 0; i < 4; i++) + border_rect[i] = world_screen; + border_rect[0].bottom = border_rect[0].top + 8; + border_rect[1].right = border_rect[1].left + 8; + border_rect[2].top = border_rect[2].bottom - 8; + border_rect[3].left = border_rect[3].right - 8; + + for (i = 0; i < 256; i++) { + terrain_rects[i] = terrain_rect_base; + OffsetRect(&terrain_rects[i],3 + (i % 17) * (terrain_rect_base.right + 1), + 3 + (i / 17) * (terrain_rect_base.bottom + 1)); + } +} + +Boolean handle_action(POINT the_point, WPARAM wparam, LPARAM lparam ) +{ + short i,j, x, y; + Boolean are_done = FALSE; + char str[256],s2[256]; + + RECT targ_rect; + Boolean need_redraw = FALSE,option_hit = FALSE; + location spot_hit; + POINT cur_point,cur_point2; + short right_top,right_hit; + short old_mode; + RECT temp_rect; + long dummy; + + Boolean to_return = FALSE; + Boolean ctrl_key = FALSE; + Boolean right_button = FALSE; + + if (lparam == -2) + option_hit = right_button = TRUE; + if (lparam != -1) { + the_point.x -= ulx; + the_point.y -= uly; + } + if (MK_CONTROL & wparam) + option_hit = ctrl_key = TRUE; + + for (i = 0; i < NLS; i++) + if ((mouse_button_held == FALSE) && (PtInRect ( &left_buttons[i][0],the_point) ) + && (left_button_status[i] >= 10)) { + draw_lb_slot(i,1); + play_sound(37); + Delay(10,&dummy); + draw_lb_slot(i,0); + if (overall_mode == 61) { + switch(i) + { + case 3: // new + build_scenario(); + if (overall_mode == 60) + set_up_main_screen(); + break; + + case 4: // edit + load_scenario(); + if (overall_mode == 60) { + set_up_main_screen(); + update_item_menu(); + } + break; + } + } + else if ((overall_mode == 60) || (overall_mode == 62)) { + switch(i) + { + case 0: + break; + + case 1: + break; + case 2: // start terrain editing + start_terrain_editing(); + break; + case 3: // start terrain editing + start_monster_editing(0); + break; + case 4: // start item editing + start_item_editing(0); + break; + case 5: // new town + if (change_made == TRUE) { + give_error("You need to save the changes made to your scenario before you can add a new town.", + "",0); + return are_done; + } + if (scenario.num_towns >= 200) { + give_error("You have reached the limit of 200 towns you can have in one scenario.", + "",0); + return are_done; + } + if (new_town(scenario.num_towns) == TRUE) + set_up_main_screen(); + break; + case 6: + SetScrollPos(right_sbar,SB_CTL,0,TRUE); + start_string_editing(0,0); + break; + case 7: + start_special_item_editing(); + break; + case 11: // pick out + if (change_made == TRUE) { + if (save_check(859) == FALSE) + break; + } + x = pick_out(cur_out); + if (x >= 0) { + spot_hit.x = x / 100; + spot_hit.y = x % 100; + load_outdoors(spot_hit,0); + augment_terrain(spot_hit); + set_up_main_screen(); + } + break; + case 12: // edit outdoors + start_out_edit(); + mouse_button_held = FALSE; + return FALSE; + break; + case 16: // pick town + if (change_made == TRUE) { + if (save_check(859) == FALSE) + break; + } + x = pick_town_num(855,cur_town); + if (x >= 0) { + load_town(x); + set_up_main_screen(); + start_town_edit(); + mouse_button_held = FALSE; + return FALSE; + } + break; + case 17: // edit town + start_town_edit(); + mouse_button_held = FALSE; + return FALSE; + break; + case 18: + start_dialogue_editing(0); + break; + + } + } + if ((overall_mode < 60) && (i == NLS - 1)) { + set_cursor(0); + set_up_main_screen(); + } + mouse_button_held = FALSE; + } + + if (overall_mode == 60) { + right_top = GetScrollPos(right_sbar,SB_CTL); + for (i = 0; i < NRSONPAGE; i++) + if ((mouse_button_held == FALSE) && (PtInRect (&right_buttons[i],the_point) ) + && (right_button_status[i + right_top] > 0)) { + + right_hit = right_button_status[i + right_top]; + j = right_hit % 1000; + //flash_rect(left_buttons[i][0]); + draw_rb_slot(i + right_top,1); + play_sound(37); + Delay(10,&dummy); + draw_rb_slot(i + right_top,0); + change_made = TRUE; + switch(right_hit / 1000) + { + case 1: + edit_ter_type(j); + update_item_menu(); + break; + case 2: + edit_monst_type(j); + update_item_menu(); + start_monster_editing(1); + break; + case 3: + edit_item_type(j); + update_item_menu(); + start_item_editing(1); + break; + case 4: + if (option_hit == TRUE) { + scenario.scen_specials[j] = null_spec_node; + } + else edit_spec_enc(j,0,0); + start_special_editing(0,1); + break; + case 5: + if (option_hit == TRUE) { + current_terrain.specials[j] = null_spec_node; + } + else edit_spec_enc(j,1,0); + start_special_editing(1,1); + break; + case 6: + if (option_hit == TRUE) { + town.specials[j] = null_spec_node; + } + else edit_spec_enc(j,2,0); + start_special_editing(2,1); + break; + case 7: + if (option_hit == TRUE) { + get_str(s2,35,j + 1); + if (j < 160) + strcpy(scen_strs[j],(char *) s2); + else strcpy(scen_strs2[j - 160],(char *) s2); + } + else edit_text_str(j,0); + start_string_editing(0,1); + break; + + case 8: + if (option_hit == TRUE) { + get_str(s2,37,j + 1); + strcpy(data_store->out_strs[j],(char *) s2); + } + else edit_text_str(j,1); + start_string_editing(1,1); + break; + case 9: + if (option_hit == TRUE) { + get_str(s2,36,j + 1); + strcpy(town_strs[j],(char *) s2); + } + else edit_text_str(j,2); + start_string_editing(2,1); + break; + case 10: + edit_spec_item(j); + start_special_item_editing(); + break; + case 12: + edit_talk_node(j,0); + start_dialogue_editing(1); + break; + case 13: + edit_basic_dlog(j); + start_dialogue_editing(1); + break; + } + //draw_rb_slot(i + right_top,0); + mouse_button_held = FALSE; + } + } + if ((overall_mode < 60) //&& (PtInRect (the_point, &world_screen)) + && (the_point.x > world_screen.left + 8) && (the_point.x < world_screen.right - 8) + && (the_point.y > world_screen.top + 8) && (the_point.y < world_screen.bottom - 8) ) { + if (cur_viewing_mode == 0) { + i = (the_point.x - TER_RECT_UL_X - 8) / 28; + j = (the_point.y - TER_RECT_UL_Y - 8) / 36; + + spot_hit.x = cen_x + i - 4; + spot_hit.y = cen_y + j - 4; + if ((i < 0) || (i > 8) || (j < 0) || (j > 8)) + spot_hit.x = -1; + } + else { + + i = (the_point.x - TER_RECT_UL_X - 8) / 4; + j = (the_point.y - TER_RECT_UL_Y - 8) / 4; + spot_hit.x = i; spot_hit.y = j; + } + + if ((mouse_button_held == TRUE) && (spot_hit.x == last_spot_hit.x) && + (spot_hit.y == last_spot_hit.y)) + return are_done; + else last_spot_hit = spot_hit; + if (mouse_button_held == FALSE) + last_spot_hit = spot_hit; + + old_mode = overall_mode; + change_made = TRUE; + + if ((spot_hit.x < 0) || (spot_hit.x > ((editing_town == TRUE) ? max_dim[town_type] - 1 : 47)) || + (spot_hit.y < 0) || (spot_hit.y > ((editing_town == TRUE) ? max_dim[town_type] - 1 : 47))) ; + else switch (overall_mode) { + case 0: + if (((mouse_button_held == FALSE) && + (((editing_town == TRUE) && (t_d.terrain[spot_hit.x][spot_hit.y] == current_terrain_type)) || + ((editing_town == FALSE) && (current_terrain.terrain[spot_hit.x][spot_hit.y] == current_terrain_type)) || + ((is_mountain(spot_hit.x,spot_hit.y)) && (current_terrain_type >= 22) + && (current_terrain_type <= 35) && (current_terrain_type != 23)) || + ((is_erasable_water(spot_hit.x,spot_hit.y)) && (current_terrain_type >= 50)&& (current_terrain_type <= 62)) || + ((is_correctable_wall((short) spot_hit.x,(short) spot_hit.y)) + && (current_terrain_type >= 5) && (current_terrain_type <= 21) && (scenario.ter_types[current_terrain_type].blockage == 5)) || + ((is_hill(spot_hit.x,spot_hit.y)) && (current_terrain_type >= 36) && (current_terrain_type <= 49) + && (current_terrain_type != 37)))) || + ((mouse_button_held == TRUE) && (erasing_mode == TRUE))) { + set_terrain(spot_hit,current_ground); + set_cursor(0); + erasing_mode = TRUE; + mouse_button_held = TRUE; + } + else + { + mouse_button_held = TRUE; + set_cursor(0); + set_terrain(spot_hit,current_terrain_type); + erasing_mode = FALSE; + } + break; + + case 1: case 3: case 9: case 35: case 36: + if (mouse_button_held == TRUE) + break; + if (mode_count == 2) { + working_rect.left = spot_hit.x; + working_rect.top = spot_hit.y; + mode_count = 1; + set_cursor(6); + set_string("Now select lower right corner",""); + break; + } + working_rect.right = spot_hit.x; + working_rect.bottom = spot_hit.y; + if ((overall_mode == 1) || (overall_mode == 36)) { + change_rect_terrain(working_rect,current_terrain_type,20,0); + } + else if (overall_mode == 35) { + change_rect_terrain(working_rect,current_terrain_type,20,1); + } + else if (overall_mode == 9) { + town.in_town_rect = working_rect; + } + else { + if (editing_town == TRUE) { + for (x = 0; x < 16; x++) + if (t_d.room_rect[x].right == 0) { + t_d.room_rect[x] = working_rect; + sprintf(town_strs[x + 1],""); + if (edit_area_rect_str(x,1) == FALSE) + t_d.room_rect[x].right = 0; + x = 500; + } + } + if (editing_town == FALSE) { + for (x = 0; x < 8; x++) + if (current_terrain.info_rect[x].right == 0) { + current_terrain.info_rect[x] = working_rect; + sprintf(data_store->out_strs[x + 1],""); + if (edit_area_rect_str(x,0) == FALSE) + current_terrain.info_rect[x].right = 0; + x = 500; + } + + } + if (x < 500) + give_error("You have placed the maximum number of area rectangles (16 in town, 8 outdoors).","",0); + } + overall_mode = 0; + set_cursor(0); + break; + case 2: + if (mouse_button_held == TRUE) + break; + if (editing_town == FALSE) { + current_terrain.wandering_locs[mode_count - 1].x = spot_hit.x; + current_terrain.wandering_locs[mode_count - 1].y = spot_hit.y; + } + if (editing_town == TRUE) { + town.wandering_locs[mode_count - 1].x = spot_hit.x; + town.wandering_locs[mode_count - 1].y = spot_hit.y; + } + mode_count--; + switch (mode_count) { + case 3: set_string("Place second wandering monster arrival point","");break; + case 2: set_string("Place third wandering monster arrival point","");break; + case 1: set_string("Place fourth wandering monster arrival point","");break; + case 0: + overall_mode = 0; + set_cursor(0); + set_string("Drawing mode",""); + break; + } + break; + case 6: + break; + + case 29: + mouse_button_held = TRUE; + change_circle_terrain(spot_hit,4,current_terrain_type,20); + break; + case 30: + mouse_button_held = TRUE; + change_circle_terrain(spot_hit,1,current_terrain_type,20); + break; + case 31: + mouse_button_held = TRUE; + shy_change_circle_terrain(spot_hit,4,current_terrain_type,1); + break; + case 32: + mouse_button_held = TRUE; + shy_change_circle_terrain(spot_hit,2,current_terrain_type,1); + break; + case 37: // erase + change_circle_terrain(spot_hit,2,current_ground,20); + mouse_button_held = TRUE; + break; + case 4: + for (x = 0; x < 64; x++) + if (town.preset_items[x].item_code < 0) { + town.preset_items[x].item_loc.x = spot_hit.x; + town.preset_items[x].item_loc.y = spot_hit.y; + town.preset_items[x].item_code = mode_count; + town.preset_items[x].ability = -1; + if ((scen_item_list.scen_items[mode_count].variety == 3) || + (scen_item_list.scen_items[mode_count].variety == 11)) + town.preset_items[x].ability = get_ran(1,4,6); + //town.preset_items[x].charges = 0; + town.preset_items[x].always_there = 0; + town.preset_items[x].property = 0; + town.preset_items[x].contained = container_there(town.preset_items[x].item_loc); + store_place_item = town.preset_items[x]; + x = 70; + } + if (x == 64) + give_error("You can only have 64 preset items in each town.","",0); + + overall_mode = 0; + set_cursor(0); + set_string("Drawing mode",""); + break; + case 5: + for (x = 0; x < 64; x++) + if ((spot_hit.x == town.preset_items[x].item_loc.x) && + (spot_hit.y == town.preset_items[x].item_loc.y) && (town.preset_items[x].item_code >= 0)) { + edit_placed_item(x); + store_place_item = town.preset_items[x]; + } + overall_mode = 0; + set_cursor(0); + break; + case 7: + overall_mode = 0; + set_cursor(0); + break; + case 8: + if (last_placed_monst.number == 0) { + give_error("Either no monster has been placed, or the last time you tried to place a monster the operation failed.","",0); + break; + } + for (i = 0; i < 60; i++) + if (t_d.creatures[i].number == 0) { + t_d.creatures[i] = last_placed_monst; + t_d.creatures[i].start_loc = spot_hit; + if ((i >= 30) && (scenario.town_size[cur_town] == 2)) { + give_error("Small towns can have at most 30 preset monsters.","",0); // error + t_d.creatures[i].number = 0; + } + else if ((i >= 40) && (scenario.town_size[cur_town] == 1)) { + give_error("Medium towns can have at most 40 preset monsters.","",0); // error + t_d.creatures[i].number = 0; + } + i = 60; + } + overall_mode = 0; + set_cursor(0); + break; + case 28: + for (i = 0; i < 60; i++) + if (t_d.creatures[i].number == 0) { + t_d.creatures[i].start_loc = spot_hit; + t_d.creatures[i].number = mode_count; + t_d.creatures[i].start_attitude = + scenario.scen_monsters[mode_count].default_attitude; + t_d.creatures[i].mobile = 1; + t_d.creatures[i].time_flag = 0; + t_d.creatures[i].extra1 = 0; + t_d.creatures[i].extra2 = 0; + t_d.creatures[i].spec1 = -1; + t_d.creatures[i].spec2 = -1; + t_d.creatures[i].spec_enc_code = 0; + t_d.creatures[i].time_code = 0; + t_d.creatures[i].monster_time = 0; + t_d.creatures[i].personality = -1; + t_d.creatures[i].special_on_kill = -1; + t_d.creatures[i].facial_pic = scenario.scen_monsters[mode_count].default_facial_pic; + if ((i >= 30) && (scenario.town_size[cur_town] == 2)) { + give_error("Small towns can have at most 30 preset monsters.","",0); // error + t_d.creatures[i].number = 0; + } + else if ((i >= 40) && (scenario.town_size[cur_town] == 1)) { + give_error("Medium towns can have at most 40 preset monsters.","",0); // error + t_d.creatures[i].number = 0; + } + last_placed_monst = t_d.creatures[i]; + + i = 70; + } + if ((i < 70) && (scenario.town_size[cur_town] == 0)) { + give_error("Large towns can have at most 60 preset monsters.","",0); // error + } + overall_mode = 0; + set_cursor(0); + break; + + case 10: case 11: case 12: case 13: + town.start_locs[overall_mode - 10].x = spot_hit.x; + town.start_locs[overall_mode - 10].y = spot_hit.y; + set_cursor(0); + overall_mode = 0; + break; + case 20: + make_web(spot_hit.x,spot_hit.y); overall_mode = 0; break; + case 21: + make_crate(spot_hit.x,spot_hit.y); overall_mode = 0; break; + case 22: + make_barrel(spot_hit.x,spot_hit.y); overall_mode = 0; break; + case 23: + make_fire_barrier(spot_hit.x,spot_hit.y); overall_mode = 0; break; + case 24: + make_force_barrier(spot_hit.x,spot_hit.y); overall_mode = 0; break; + case 25: + make_quickfire(spot_hit.x,spot_hit.y); overall_mode = 0; break; + + case 26: + take_quickfire(spot_hit.x,spot_hit.y); + take_force_barrier(spot_hit.x,spot_hit.y); + take_fire_barrier(spot_hit.x,spot_hit.y); + take_barrel(spot_hit.x,spot_hit.y); + take_crate(spot_hit.x,spot_hit.y); + take_web(spot_hit.x,spot_hit.y); + for (i = 0; i < 8; i++) + take_sfx(spot_hit.x,spot_hit.y,i); + set_cursor(0); + overall_mode = 0; + break; + case 33: + make_sfx(spot_hit.x,spot_hit.y,mode_count); overall_mode = 0; break; + case 34: + if (editing_town == TRUE) + set_new_terrain(t_d.terrain[spot_hit.x][spot_hit.y]); + else set_new_terrain(current_terrain.terrain[spot_hit.x][spot_hit.y]); + set_cursor(0); + overall_mode = 0; + break; + case 46: + if (store_place_item.item_code < 0) { + give_error("Either no item has been placed, or the last time you tried to place an item the operation failed.","",0); + break; + } + for (x = 0; x < 64; x++) + if (town.preset_items[x].item_code < 0) { + town.preset_items[x] = store_place_item; + town.preset_items[x].item_loc.x = spot_hit.x; + town.preset_items[x].item_loc.y = spot_hit.y; + + town.preset_items[x].contained = container_there(town.preset_items[x].item_loc); + x = 64; + } + set_cursor(0); + overall_mode = 0; + break; + case 38: //edit sign + if (editing_town == TRUE) { + for (x = 0; x < 15; x++) + if ((town.sign_locs[x].x == spot_hit.x) && (town.sign_locs[x].y == spot_hit.y)) { + edit_sign(x,scenario.ter_types[t_d.terrain[spot_hit.x][spot_hit.y]].picture); + x = 30; + } + if (x == 15) { + give_error("Either this space is not a sign, or you have already placed too many signs on this level.", + "",0); + } + } + if (editing_town == FALSE) { + for (x = 0; x < 8; x++) + if ((current_terrain.sign_locs[x].x == spot_hit.x) && (current_terrain.sign_locs[x].y == spot_hit.y)) { + edit_sign(x,scenario.ter_types[current_terrain.terrain[spot_hit.x][spot_hit.y]].picture); + x = 30; + } + if (x == 8) { + give_error("Either this space is not a sign, or you have already placed too many signs on this level.", + "",0); + } + } + set_cursor(0); + overall_mode = 0; + break; + case 39: //edit monst + for (x = 0; x < 60; x++) + if (monst_on_space(spot_hit,x) == TRUE) { + edit_placed_monst(x); + last_placed_monst = t_d.creatures[x]; + } + set_cursor(0); + overall_mode = 0; + break; + case 40: //make special + place_edit_special(spot_hit); + set_cursor(0); + overall_mode = 0; + break; + case 41: //copy special + if (editing_town == TRUE) { + for (x = 0; x < 50; x++) + if ((town.special_locs[x].x == spot_hit.x) && (town.special_locs[x].y == spot_hit.y)) { + copied_spec = town.spec_id[x]; + x = 500; + } + } + if (editing_town == FALSE) { + for (x = 0; x < 18; x++) + if ((current_terrain.special_locs[x].x == spot_hit.x) && (current_terrain.special_locs[x].y == spot_hit.y)) { + copied_spec = current_terrain.special_id[x]; + x = 500; + } + } + if (x < 500) + give_error("There wasn't a special on that spot.","",0); + set_cursor(0); + overall_mode = 0; + break; + case 42: //paste special + if (copied_spec < 0) { + give_error("You need to select a special to copy first.","",0); + break; + } + if (editing_town == TRUE) { + for (x = 0; x < 50; x++) + if (town.special_locs[x].x == 100) { + town.special_locs[x] = spot_hit; + town.spec_id[x] = copied_spec ; + x = 500; + } + } + if (editing_town == FALSE) { + if ((spot_hit.x == 0) || (spot_hit.x == 47) || (spot_hit.y == 0) || (spot_hit.y == 47)) { + fancy_choice_dialog(870,0); + break; + } + for (x = 0; x < 18; x++) + if (current_terrain.special_locs[x].x == 100) { + current_terrain.special_locs[x] = spot_hit; + current_terrain.special_id[x] = copied_spec ; + x = 500; + } + } + + if (x < 500) + give_error("Each town can have at most 50 locations with special encounters. Each outdoor section can have at most 18. You'll need to erase some special spaces before you can place more.","",0); + + set_cursor(0); + overall_mode = 0; + break; + case 43: //erase special + if (editing_town == TRUE) { + for (x = 0; x < 50; x++) + if ((town.special_locs[x].x == spot_hit.x) && (town.special_locs[x].y == spot_hit.y)) { + town.special_locs[x].x = 100; + x = 500; + } + } + if (editing_town == FALSE) { + for (x = 0; x < 18; x++) + if ((current_terrain.special_locs[x].x == spot_hit.x) && (current_terrain.special_locs[x].y == spot_hit.y)) { + current_terrain.special_locs[x].x = 100; + x = 500; + } + } + set_cursor(0); + overall_mode = 0; + break; + case 44: //edit special + set_special(spot_hit); + set_cursor(0); + overall_mode = 0; + break; + case 45: //edit town entry + town_entry(spot_hit); + overall_mode = 0; + set_cursor(0); + break; + case 47: //edit out start loc + if (editing_town == TRUE) { + set_string("You must be outdoors to do this...",""); + break; + } + if (fancy_choice_dialog(864,0) == 2) + break; + if ((spot_hit.x != minmax(4,43,spot_hit.x)) || + (spot_hit.y != minmax(4,43,spot_hit.y))) { + give_error("You can't put the starting location this close to the edge of an outdoor section. It has to be at least 4 spaces away.","",0); + break; + } + scenario.out_sec_start.x = cur_out.x; + scenario.out_sec_start.y = cur_out.y; + scenario.out_start = spot_hit; + set_cursor(0); + overall_mode = 0; + break; + case 48: //delete monst + for (x = 0; x < 60; x++) + if (monst_on_space(spot_hit,x) == TRUE) { + t_d.creatures[x].number = 0; + t_d.creatures[x].start_loc.x = 0; + t_d.creatures[x].start_loc.y = 0; + } + set_cursor(0); + overall_mode = 0; + break; + case 49: // delete item + for (x = 0; x < 64; x++) + if ((spot_hit.x == town.preset_items[x].item_loc.x) && + (spot_hit.y == town.preset_items[x].item_loc.y) && (town.preset_items[x].item_code >= 0)) { + town.preset_items[x].item_code = -1; + } + set_cursor(0); + overall_mode = 0; + break; + } + if ((overall_mode == 0) && (old_mode != 0)) + set_string("Drawing mode",""); + draw_terrain(); + + } + if (overall_mode < 60) { + if ((PtInRect (&border_rect[0],the_point )) & (cen_y > ((editing_town == TRUE) ? 4 : 3))) { + cen_y--; + if (ctrl_key == TRUE) + cen_y = ((editing_town == TRUE) ? 4 : 3); + need_redraw = TRUE; + mouse_button_held = TRUE; + } + if ((PtInRect (&border_rect[1],the_point )) & (cen_x > ((editing_town == TRUE) ? 4 : 3))) { + cen_x--; + if (ctrl_key == TRUE) + cen_x = ((editing_town == TRUE) ? 4 : 3); + need_redraw = TRUE; + mouse_button_held = TRUE; + } + if ((PtInRect (&border_rect[2],the_point )) & (cen_y < ((editing_town == TRUE) ? max_dim[town_type] - 5 : 44))) { + cen_y++; + if (ctrl_key == TRUE) + cen_y = (editing_town == TRUE) ? max_dim[town_type] - 5 : 44; + need_redraw = TRUE; + mouse_button_held = TRUE; + } + if ((PtInRect (&border_rect[3],the_point )) & (cen_x < ((editing_town == TRUE) ? max_dim[town_type] - 5 : 44))) { + cen_x++; + if (ctrl_key == TRUE) + cen_x = (editing_town == TRUE) ? max_dim[town_type] - 5 : 44; + need_redraw = TRUE; + mouse_button_held = TRUE; + } + if (need_redraw == TRUE) { + draw_terrain(); + place_just_location(); + need_redraw = FALSE; + } + } + + if ((mouse_button_held == FALSE) && ((overall_mode < 60) || (overall_mode == 62))) { + cur_point = the_point; + cur_point.x -= RIGHT_AREA_UL_X; + cur_point.y -= RIGHT_AREA_UL_Y; + + for (i = 0; i < 256; i++) + if (PtInRect(&terrain_rects[i],cur_point)) { + temp_rect = terrain_rects[i]; + OffsetRect(&temp_rect,RIGHT_AREA_UL_X, RIGHT_AREA_UL_Y ); + flash_rect(temp_rect); + if (overall_mode < 60) { + set_new_terrain(i); + } + else { + edit_ter_type(i); + set_up_terrain_buttons(); + } + place_location(); + } + cur_point2 = cur_point; + cur_point2.x -= 5; + cur_point2.y -= terrain_rects[255].bottom + 5; + for (i = 0; i < 8; i++) + for (j = 0; j < 6; j++) { + if ((good_palette_buttons[j][i] > 0) && (mouse_button_held == FALSE) && (PtInRect(&palette_buttons[i][j],cur_point2)) + && ((j < 3) || (editing_town == TRUE)) && (overall_mode < 60)) { + temp_rect = palette_buttons[i][j]; + OffsetRect(&temp_rect,RIGHT_AREA_UL_X + 5, RIGHT_AREA_UL_Y + terrain_rects[255].bottom + 5); + flash_rect(temp_rect); + switch (i + 100 * j) { + case 0: + set_string("Drawing mode"," "); + overall_mode = 0; + set_cursor(0); + break; + case 1: + set_string("Paintbrush (large)",""); + overall_mode = 28 + i; + set_cursor(2); + break; + case 2: + set_string("Paintbrush (small)",""); + set_cursor(2); + overall_mode = 28 + i; + break; + case 3: + set_string("Spraycan (large)",""); + set_cursor(3); + overall_mode = 28 + i; + break; + case 4: + set_string("Spraycan (small)",""); + set_cursor(3); + overall_mode = 28 + i; + break; + case 5: + set_string("Eyedropper","Select terrain to draw"); + set_cursor(1); + overall_mode = 34; + break; + case 6: + overall_mode = 35; + mode_count = 2; + set_cursor(5); + set_string("Fill rectangle (hollow)","Select upper left corner"); + break; + case 7: + overall_mode = 36; + mode_count = 2; + set_cursor(5); + set_string("Fill rectangle (solid)","Select upper left corner"); + break; + case 100: // switch view + cur_viewing_mode = 1 - cur_viewing_mode; + need_redraw = TRUE; + break; + case 101: + set_string("Erase space","Select space to clear"); + overall_mode = 37; + set_cursor(4); + break; + case 102: + set_string("Edit sign","Select sign to edit"); + set_cursor(7); + overall_mode = 38; + break; + case 103: + overall_mode = 3; + mode_count = 2; + set_cursor(5); + set_string("Create room rectangle","Select upper left corner"); + break; + case 104: + overall_mode = 2; + mode_count = 4; + set_cursor(7); + set_string("Place first wandering monster arrival point",""); + break; + case 105: // replace terrain + swap_terrain(); + need_redraw = TRUE; + mouse_button_held = FALSE; + break; + // case 106: blank + case 107: + if (editing_town == TRUE) { + set_string("Can only set town entrances outdoors",""); + break; + } + set_string("Set town entrance","Select town to edit"); + set_cursor(7); + overall_mode = 45; + break; + + case 200: + if (editing_town == FALSE) { + set_string("Edit placed item","Not while outdoors."); + break; + } + set_string("Edit placed item","Select item to edit"); + set_cursor(7); + overall_mode = 5; + break; + case 201: + if (editing_town == FALSE) { + set_string("Place same item","Not while outdoors."); + break; + } + set_string("Place same item","Select location"); + set_cursor(7); + overall_mode = 46; + break; + case 202: + if (editing_town == FALSE) { + set_string("Delete an item","Not while outdoors."); + break; + } + set_string("Delete an item","Select item"); + set_cursor(7); + overall_mode = 49; + break; + case 203: + set_string("Create/Edit special","Select special location"); + set_cursor(7); + overall_mode = 40; + break; + case 204: + set_string("Copy special","Select special to copy"); + set_cursor(7); + overall_mode = 41; + break; + case 205: + if (special_to_paste < 0) { + set_string("Can't paste special","No special to paste"); + } + set_string("Paste special","Select location to paste"); + overall_mode = 42; + set_cursor(7); + break; + case 206: + set_string("Erase special","Select special to erase"); + overall_mode = 43; + set_cursor(4); + break; + case 207: + set_string("Set/place special","Select special location"); + set_cursor(7); + overall_mode = 44; + break; + + case 300: + set_string("Edit creature","Select creature to edit"); + set_cursor(7); + overall_mode = 39; + break; + case 301: + set_string("Place same creature","Select creature location"); + set_cursor(7); + overall_mode = 8; + break; + case 302: + set_string("Delete a creature","Select creature"); + set_cursor(4); + overall_mode = 48; + break; +// case 303: blank + case 304: + set_string("Place north entrace","Select entrance location"); + set_cursor(7); + overall_mode = 10; + break; + case 305: + set_string("Place west entrace","Select entrance location"); + set_cursor(7); + overall_mode = 13; + break; + case 306: + set_string("Place south entrace","Select entrance location"); + set_cursor(7); + overall_mode = 12; + break; + case 307: + set_string("Place east entrace","Select entrance location"); + set_cursor(7); + overall_mode = 11; + break; + case 400: + set_string("Place web","Select location"); + overall_mode = 20; + set_cursor(0); + break; + case 401: + set_string("Place crate","Select location"); + overall_mode = 21; + set_cursor(0); + break; + case 402: + set_string("Place barrel","Select location"); + overall_mode = 22; + set_cursor(0); + break; + case 403: + set_string("Place fire barrier","Select location"); + overall_mode = 23; + set_cursor(0); + break; + case 404: + set_string("Place force barrier","Select location"); + overall_mode = 24; + set_cursor(0); + break; + case 405: + set_string("Place quickfire","Select location"); + overall_mode = 25; + set_cursor(0); + break; +// case 406: blank + case 407: + set_string("Clear space","Select space to clear"); + overall_mode = 26; + set_cursor(4); + break; + case 500: + set_string("Place small blood stain","Select stain location"); + overall_mode = 33; mode_count = 0; + set_cursor(0); + break; + case 501: + set_string("Place ave. blood stain","Select stain location"); + overall_mode = 33; mode_count = 1; + set_cursor(0); + break; + case 502: + set_string("Place large blood stain","Select stain location"); + overall_mode = 33; mode_count = 2; + set_cursor(0); + break; + case 503: + set_string("Place small slime pool","Select slime location"); + overall_mode = 33; mode_count = 3; + set_cursor(0); + break; + case 504: + set_string("Place large slime pool","Select slime location"); + overall_mode = 33; mode_count = 4; + set_cursor(0); + break; + case 505: + set_string("Place ash","Select ash location"); + overall_mode = 33; mode_count = 5; + set_cursor(0); + break; + case 506: + set_string("Place bones","Select bones location"); + overall_mode = 33; mode_count = 6; + set_cursor(0); + break; + case 507: + set_string("Place rocks","Select rocks location"); + overall_mode = 33; mode_count = 7; + set_cursor(0); + break; + } + } + } + } + if (need_redraw == TRUE) { + draw_main_screen(); + draw_terrain(); + } + + return are_done; +} + +void flash_rect(RECT to_flash) +{ + int i; + long dummy; + HDC hdc; + + hdc = GetDC(mainPtr); + SetViewportOrgEx(hdc,ulx,uly,NULL); + InvertRect (hdc,&to_flash); + play_sound(37); + Delay(5,&dummy); + InvertRect (hdc,&to_flash); + fry_dc(mainPtr,hdc); +} + +void swap_terrain() +{ + short a,b,c,i,j; + unsigned char ter; + + change_ter(&a,&b,&c); + if (a < 0) return; + + for (i = 0; i < ((editing_town == TRUE) ? max_dim[town_type] : 48); i++) + for (j = 0; j < ((editing_town == TRUE) ? max_dim[town_type] : 48); j++) + { + ter = (editing_town == TRUE) ? t_d.terrain[i][j] : current_terrain.terrain[i][j]; + if ((ter == a) && (get_ran(1,1,100) <= c)) { + if (editing_town == TRUE) + t_d.terrain[i][j] = b; + else current_terrain.terrain[i][j] = b; + } + } + +} + +void set_new_terrain(unsigned char selected_terrain) +{ + current_terrain_type = selected_terrain; + redraw_selected_ter(); + if (selected_terrain < 2) + current_ground = 0; + else if (selected_terrain < 5) + current_ground = 2; +} + +Boolean control_key_down() +{ + // is control key down? + Boolean control_down = FALSE; + BYTE cBuf[256]; + GetKeyboardState(cBuf); + if (cBuf[VK_CONTROL] & 0x80) + control_down = TRUE; + return control_down; + +} + +Boolean handle_syskeystroke(WPARAM wParam, LPARAM lParam,short *handled) +{ + UINT kp[10] = {VK_NUMPAD0,VK_NUMPAD1, VK_NUMPAD2, VK_NUMPAD3, VK_NUMPAD4, + VK_NUMPAD5, VK_NUMPAD6, VK_NUMPAD7, VK_NUMPAD8, VK_NUMPAD9}; + + POINT terrain_click[10] = {{150,185},{7,359},{50,359},{270,359}, + {7,50},{150,206},{270,50}, + {7,27},{50,27},{275,27}}; + POINT pass_point; + Boolean are_done = FALSE; + short i; + if (overall_mode >= 60) + return are_done; + + for (i = 0; i < 10; i++) + if (wParam == kp[i]) { + if (i == 0) { + *handled = 1; + return handle_keystroke((UINT) 'z',-1); + } + else { + pass_point.x = terrain_click[i].x; + pass_point.y = terrain_click[i].y; + wParam = 0; + FlushEvents(0); + if (GetKeyState(VK_CONTROL) < 0) { + wParam = wParam | MK_CONTROL; + } + are_done = handle_action(pass_point,wParam,-1); + mouse_button_held = FALSE; + return are_done; + + } + } + return are_done; +} + +Boolean handle_keystroke(WPARAM wParam, LPARAM lParam) +{ + Boolean are_done = FALSE; + POINT pass_point; + short i,j,k,l,dum; + long i2,j2,k2,l2,dum2; + long dummy; + short the_type,store_ter; + DWORD s1; + UINT s2,s3; + bool ctrl_key = (GetKeyState( VK_CONTROL ) & 0x8000) != 0; // check MSB for current key state + Boolean dialog_grabbed_key = FALSE; + char chr; + + store_ter = current_terrain_type; + chr = (char) wParam; + + switch(chr) + { + case'A': + pass_point.x = RIGHT_AREA_UL_X + 6 + palette_buttons[0][0].left; + pass_point.y = RIGHT_AREA_UL_Y + 6 + terrain_rects[255].bottom + palette_buttons[0][0].top; + are_done = handle_action(pass_point,wParam,-1); + break; + + case'B': + pass_point.x = RIGHT_AREA_UL_X + 6 + palette_buttons[1][0].left; + pass_point.y = RIGHT_AREA_UL_Y + 6 + terrain_rects[255].bottom + palette_buttons[1][0].top; + are_done = handle_action(pass_point,wParam,-1); + break; + + case'C': + pass_point.x = RIGHT_AREA_UL_X + 6 + palette_buttons[2][0].left; + pass_point.y = RIGHT_AREA_UL_Y + 6 + terrain_rects[255].bottom + palette_buttons[2][0].top; + are_done = handle_action(pass_point,wParam,-1); + break; + + case'D': + pass_point.x = RIGHT_AREA_UL_X + 6 + palette_buttons[3][0].left; + pass_point.y = RIGHT_AREA_UL_Y + 6 + terrain_rects[255].bottom + palette_buttons[3][0].top; + are_done = handle_action(pass_point,wParam,-1); + break; + + case'E': + pass_point.x = RIGHT_AREA_UL_X + 6 + palette_buttons[4][0].left; + pass_point.y = RIGHT_AREA_UL_Y + 6 + terrain_rects[255].bottom + palette_buttons[4][0].top; + are_done = handle_action(pass_point,wParam,-1); + break; + + case'F': + pass_point.x = RIGHT_AREA_UL_X + 6 + palette_buttons[5][0].left; + pass_point.y = RIGHT_AREA_UL_Y + 6 + terrain_rects[255].bottom + palette_buttons[5][0].top; + are_done = handle_action(pass_point,wParam,-1); + break; + + case'G': + pass_point.x = RIGHT_AREA_UL_X + 6 + palette_buttons[6][0].left; + pass_point.y = RIGHT_AREA_UL_Y + 6 + terrain_rects[255].bottom + palette_buttons[6][0].top; + are_done = handle_action(pass_point,wParam,-1); + break; + + case'H': + pass_point.x = RIGHT_AREA_UL_X + 6 + palette_buttons[7][0].left; + pass_point.y = RIGHT_AREA_UL_Y + 6 + terrain_rects[255].bottom + palette_buttons[7][0].top; + are_done = handle_action(pass_point,wParam,-1); + break; + + case'I': + pass_point.x = RIGHT_AREA_UL_X + 6 + palette_buttons[0][1].left; + pass_point.y = RIGHT_AREA_UL_Y + 6 + terrain_rects[255].bottom + palette_buttons[0][1].top; + are_done = handle_action(pass_point,wParam,-1); + break; + + case'J': + pass_point.x = RIGHT_AREA_UL_X + 6 + palette_buttons[1][1].left; + pass_point.y = RIGHT_AREA_UL_Y + 6 + terrain_rects[255].bottom + palette_buttons[1][1].top; + are_done = handle_action(pass_point,wParam,-1); + break; + + case'K': + pass_point.x = RIGHT_AREA_UL_X + 6 + palette_buttons[2][1].left; + pass_point.y = RIGHT_AREA_UL_Y + 6 + terrain_rects[255].bottom + palette_buttons[2][1].top; + are_done = handle_action(pass_point,wParam,-1); + break; + + case'L': + pass_point.x = RIGHT_AREA_UL_X + 6 + palette_buttons[3][1].left; + pass_point.y = RIGHT_AREA_UL_Y + 6 + terrain_rects[255].bottom + palette_buttons[3][1].top; + are_done = handle_action(pass_point,wParam,-1); + break; + + case'M': + pass_point.x = RIGHT_AREA_UL_X + 6 + palette_buttons[4][1].left; + pass_point.y = RIGHT_AREA_UL_Y + 6 + terrain_rects[255].bottom + palette_buttons[4][1].top; + are_done = handle_action(pass_point,wParam,-1); + break; + + case'N': + pass_point.x = RIGHT_AREA_UL_X + 6 + palette_buttons[5][1].left; + pass_point.y = RIGHT_AREA_UL_Y + 6 + terrain_rects[255].bottom + palette_buttons[5][1].top; + are_done = handle_action(pass_point,wParam,-1); + break; + + case'O': + pass_point.x = RIGHT_AREA_UL_X + 6 + palette_buttons[6][1].left; + pass_point.y = RIGHT_AREA_UL_Y + 6 + terrain_rects[255].bottom + palette_buttons[6][1].top; + are_done = handle_action(pass_point,wParam,-1); + break; + + case'P': + pass_point.x = RIGHT_AREA_UL_X + 6 + palette_buttons[7][1].left; + pass_point.y = RIGHT_AREA_UL_Y + 6 + terrain_rects[255].bottom + palette_buttons[7][1].top; + are_done = handle_action(pass_point,wParam,-1); + break; + + case'Q': + pass_point.x = RIGHT_AREA_UL_X + 6 + palette_buttons[0][2].left; + pass_point.y = RIGHT_AREA_UL_Y + 6 + terrain_rects[255].bottom + palette_buttons[0][2].top; + are_done = handle_action(pass_point,wParam,-1); + break; + + case'R': + pass_point.x = RIGHT_AREA_UL_X + 6 + palette_buttons[1][2].left; + pass_point.y = RIGHT_AREA_UL_Y + 6 + terrain_rects[255].bottom + palette_buttons[1][2].top; + are_done = handle_action(pass_point,wParam,-1); + break; + + case'S': + pass_point.x = RIGHT_AREA_UL_X + 6 + palette_buttons[2][2].left; + pass_point.y = RIGHT_AREA_UL_Y + 6 + terrain_rects[255].bottom + palette_buttons[2][2].top; + are_done = handle_action(pass_point,wParam,-1); + break; + + case'T': + pass_point.x = RIGHT_AREA_UL_X + 6 + palette_buttons[3][2].left; + pass_point.y = RIGHT_AREA_UL_Y + 6 + terrain_rects[255].bottom + palette_buttons[3][2].top; + are_done = handle_action(pass_point,wParam,-1); + break; + + case'U': + pass_point.x = RIGHT_AREA_UL_X + 6 + palette_buttons[4][2].left; + pass_point.y = RIGHT_AREA_UL_Y + 6 + terrain_rects[255].bottom + palette_buttons[4][2].top; + are_done = handle_action(pass_point,wParam,-1); + break; + + case'V': + pass_point.x = RIGHT_AREA_UL_X + 6 + palette_buttons[5][2].left; + pass_point.y = RIGHT_AREA_UL_Y + 6 + terrain_rects[255].bottom + palette_buttons[5][2].top; + are_done = handle_action(pass_point,wParam,-1); + break; + + case'W': + pass_point.x = RIGHT_AREA_UL_X + 6 + palette_buttons[6][2].left; + pass_point.y = RIGHT_AREA_UL_Y + 6 + terrain_rects[255].bottom + palette_buttons[6][2].top; + are_done = handle_action(pass_point,wParam,-1); + break; + + case'X': + pass_point.x = RIGHT_AREA_UL_X + 6 + palette_buttons[7][2].left; + pass_point.y = RIGHT_AREA_UL_Y + 6 + terrain_rects[255].bottom + palette_buttons[7][2].top; + are_done = handle_action(pass_point,wParam,-1); + break; + + + case 'Y': + for (i = 0; i < 64; i++) { + if ((town.preset_items[i].item_loc.x < 0) || + (town.preset_items[i].item_loc.y < 0)) + town.preset_items[i].item_code = -1; + if (town.preset_items[i].item_code >= 0) { + edit_placed_item(i); + //town.preset_items[i] = edit_item(town.preset_items[i]); + } + } + break; + + case '1': case '2': case '3': case '4': case '5': case '6': + pass_point.x = RIGHT_AREA_UL_X + 6 + palette_buttons[chr - 49][4].left; + pass_point.y = RIGHT_AREA_UL_Y + 6 + terrain_rects[255].bottom + palette_buttons[chr - 48][4].top; + are_done = handle_action(pass_point,wParam,-1); + break; + case '8': + pass_point.x = RIGHT_AREA_UL_X + 6 + palette_buttons[7][4].left; + pass_point.y = RIGHT_AREA_UL_Y + 6 + terrain_rects[255].bottom + palette_buttons[7][4].top; + are_done = handle_action(pass_point,wParam,-1); + break; + case ',': + set_string("Edit creature","Select creature to edit"); + overall_mode = 39; + break; + case '.': + set_string("Place same creature","Select creature location"); + overall_mode = 8; + break; + case'/': + pass_point.x = RIGHT_AREA_UL_X + 6 + palette_buttons[2][3].left; + pass_point.y = RIGHT_AREA_UL_Y + 6 + terrain_rects[255].bottom + palette_buttons[2][3].top; + are_done = handle_action(pass_point,wParam,-1); + break; + + case'!': + pass_point.x = RIGHT_AREA_UL_X + 6 + palette_buttons[0][5].left; + pass_point.y = RIGHT_AREA_UL_Y + 6 + terrain_rects[255].bottom + palette_buttons[0][5].top; + are_done = handle_action(pass_point,wParam,-1); + break; + + case'@': + pass_point.x = RIGHT_AREA_UL_X + 6 + palette_buttons[1][5].left; + pass_point.y = RIGHT_AREA_UL_Y + 6 + terrain_rects[255].bottom + palette_buttons[1][5].top; + are_done = handle_action(pass_point,wParam,-1); + break; + + case'#': + pass_point.x = RIGHT_AREA_UL_X + 6 + palette_buttons[2][5].left; + pass_point.y = RIGHT_AREA_UL_Y + 6 + terrain_rects[255].bottom + palette_buttons[2][5].top; + are_done = handle_action(pass_point,wParam,-1); + break; + + case'$': + pass_point.x = RIGHT_AREA_UL_X + 6 + palette_buttons[3][5].left; + pass_point.y = RIGHT_AREA_UL_Y + 6 + terrain_rects[255].bottom + palette_buttons[3][5].top; + are_done = handle_action(pass_point,wParam,-1); + break; + + case'%': + pass_point.x = RIGHT_AREA_UL_X + 6 + palette_buttons[4][5].left; + pass_point.y = RIGHT_AREA_UL_Y + 6 + terrain_rects[255].bottom + palette_buttons[4][5].top; + are_done = handle_action(pass_point,wParam,-1); + break; + + case'^': + pass_point.x = RIGHT_AREA_UL_X + 6 + palette_buttons[5][5].left; + pass_point.y = RIGHT_AREA_UL_Y + 6 + terrain_rects[255].bottom + palette_buttons[5][5].top; + are_done = handle_action(pass_point,wParam,-1); + break; + + case'&': + pass_point.x = RIGHT_AREA_UL_X + 6 + palette_buttons[6][5].left; + pass_point.y = RIGHT_AREA_UL_Y + 6 + terrain_rects[255].bottom + palette_buttons[6][5].top; + are_done = handle_action(pass_point,wParam,-1); + break; + + case'*': + pass_point.x = RIGHT_AREA_UL_X + 6 + palette_buttons[7][5].left; + pass_point.y = RIGHT_AREA_UL_Y + 6 + terrain_rects[255].bottom + palette_buttons[7][5].top; + are_done = handle_action(pass_point,wParam,-1); + break; + + default: + Boolean ctrl = control_key_down(); + if ((chr == 4) && (ctrl)) { + if (editing_town) + edit_town_details(); + else outdoor_details(); + break; + } + + if ((chr >= 97) && (chr <= 122)) { + for (i = 0; i < 256; i++) { + j = current_terrain_type + i + 1; + j = j % 256; + if (scenario.ter_types[j].shortcut_key == chr) { + set_new_terrain(j); + i = 256; + } + } + + } + break; + + } + if (store_ter != current_terrain_type) + draw_terrain(); + mouse_button_held = FALSE; +} + + +void modify_lists() +{ + set_up_lights(); +} + +void set_up_lights() +{ + + short i,j,rad; + location where,l; +location light_locs[40]; +short num_lights = 0; +Boolean where_lit[64][64]; + + + // Find bonfires, braziers, etc. + num_lights = 0; + for (i = 0; i < 64; i++) + for (j = 0; j < 64; j++) + where_lit[i][j] = 0; + + for (i = 0; i < max_dim[town_type]; i++) + for (j = 0; j < max_dim[town_type]; j++) { + l.x = i; l.y = j; + rad = scenario.ter_types[t_d.terrain[i][j]].light_radius; + if (rad > 0) { + for (where.x = max(0,i - rad); where.x < min(max_dim[town_type],i + rad + 1); where.x++) + for (where.y = max(0,j - rad); where.y < min(max_dim[town_type],j + rad + 1); where.y++) + if ((where_lit[where.x][where.y] == 0) && (dist(where,l) <= rad) && (can_see(l,where,0) < 5)) + where_lit[where.x][where.y] = 1; + } + } + for (i = 0; i < 8; i++) + for (j = 0; j < 64; j++) + t_d.lighting[i][j] = 0; + for (where.x = 0; where.x < max_dim[town_type]; where.x++) + for (where.y = 0; where.y < max_dim[town_type]; where.y++) { + if (where_lit[where.x][where.y] > 0) { + t_d.lighting[where.x / 8][where.y] = t_d.lighting[where.x / 8][where.y] | (char) (s_pow(2,where.x % 8)); + } + } + +} + + + + +Boolean is_wall(short i,short j) +{ + + unsigned char ter,walls[3] = {77,77,224}; + Boolean answer = FALSE; + short k,pic; + + ter = (editing_town == TRUE) ? t_d.terrain[i][j] : current_terrain.terrain[i][j]; + pic = scenario.ter_types[ter].picture; + + if ((editing_town == TRUE) && ((i < 0) || (i > max_dim[town_type] - 1) || (j < 0) || (j > max_dim[town_type] - 1))) + return TRUE; + if ((editing_town == FALSE) && ((i < 0) || (i > 47) || (j < 0) || (j > 47))) + return TRUE; + if ((ter < 22) && (ter > 4)) + return TRUE; + if ((pic >= 5) && (pic <= 17)) + return TRUE; + if ((pic >= 88) && (pic <= 120)) + return TRUE; + if ((pic >= 240) && (pic <= 243)) + return TRUE; + if (pic == 405) + return TRUE; +// for (k = 0; k < 3 ; k++) +// if (t_d.terrain[i][j] == walls[k]) +// answer = TRUE; + return answer; + +} + +Boolean is_correctable_wall(short i,short j) +{ + + unsigned char ter,walls[13] = {5,6,8,9,11,12, + 14,15,17,18,19,20,21}; + Boolean answer = FALSE; + short k; + + ter = (editing_town == TRUE) ? t_d.terrain[i][j] : current_terrain.terrain[i][j]; + if ((editing_town == TRUE) && ((i < 0) || (i > max_dim[town_type] - 1) || (j < 0) || (j > max_dim[town_type] - 1))) + return FALSE; + if ((editing_town == FALSE) && ((i < 0) || (i > 47) || (j < 0) || (j > 47))) + return FALSE; + for (k = 0; k < 13 ; k++) + if (ter == walls[k]) + answer = TRUE; + return answer; + +} + +Boolean is_mountain(short i,short j) +{ + + Boolean answer = FALSE; + short k,pic; + unsigned char ter; + + ter = (editing_town == TRUE) ? t_d.terrain[i][j] : current_terrain.terrain[i][j]; + pic = scenario.ter_types[ter].picture; + if ((editing_town == TRUE) && ((i < 0) || (i > max_dim[town_type] - 1) || (j < 0) || (j > max_dim[town_type] - 1))) + return TRUE; + if ((editing_town == FALSE) && ((i < 0) || (i > 47) || (j < 0) || (j > 47))) + return TRUE; + if ((ter >= 22) && (ter <= 35)) + answer = TRUE; + if ((pic >= 18) && + (pic <= 31) ) return TRUE; + if (pic == 192) return TRUE; + if (pic == 193) return TRUE; + if (pic == 195) return TRUE; + if (pic == 194) return TRUE; + return answer; + +} +Boolean is_hill(short i,short j) +{ + + Boolean answer = FALSE; + short k,pic; + unsigned char ter; + + ter = (editing_town == TRUE) ? t_d.terrain[i][j] : current_terrain.terrain[i][j]; + pic = scenario.ter_types[ter].picture; + if ((editing_town == TRUE) && ((i < 0) || (i > max_dim[town_type] - 1) || (j < 0) || (j > max_dim[town_type] - 1))) + return TRUE; + if ((editing_town == FALSE) && ((i < 0) || (i > 47) || (j < 0) || (j > 47))) + return TRUE; + if ((ter >= 36) && (ter <= 49)) + answer = TRUE; + if (((pic >= 32) && + (pic <= 45)) + || (pic == 204) + || (pic == 212) + ) + answer = TRUE; + return answer; + +} +Boolean is_hill_or_mountain(short i,short j) +{ + if (is_hill(i,j)) + return TRUE; + if (is_mountain(i,j)) + return TRUE; + return FALSE; +} +Boolean is_erasable_water(short i,short j) +{ + + Boolean answer = FALSE; + short k,pic; + unsigned char ter; + + ter = (editing_town == TRUE) ? t_d.terrain[i][j] : current_terrain.terrain[i][j]; + pic = scenario.ter_types[ter].picture; + if ((editing_town == TRUE) && ((i < 0) || (i > max_dim[town_type] - 1) || (j < 0) || (j > max_dim[town_type] - 1))) + return FALSE; + if ((editing_town == FALSE) && ((i < 0) || (i > 47) || (j < 0) || (j > 47))) + return FALSE; + if ((ter >= 50) && + (ter <= 62)) + answer = TRUE; + + return answer; +} +Boolean is_water(short i,short j) +{ + + Boolean answer = FALSE; + short k,pic; + unsigned char ter; + + ter = (editing_town == TRUE) ? t_d.terrain[i][j] : current_terrain.terrain[i][j]; + pic = scenario.ter_types[ter].picture; + if ((editing_town == TRUE) && ((i < 0) || (i > max_dim[town_type] - 1) || (j < 0) || (j > max_dim[town_type] - 1))) + return TRUE; + if ((editing_town == FALSE) && ((i < 0) || (i > 47) || (j < 0) || (j > 47))) + return TRUE; + if ((pic >= 46) && + (pic <= 66)) + answer = TRUE; + + return answer; +} +Boolean is_correctable_water(short i,short j) +{ + Boolean answer = FALSE; + short k,pic; + unsigned char ter; + + ter = (editing_town == TRUE) ? t_d.terrain[i][j] : current_terrain.terrain[i][j]; + pic = scenario.ter_types[ter].picture; + if ((editing_town == TRUE) && ((i < 0) || (i > max_dim[town_type] - 1) || (j < 0) || (j > max_dim[town_type] - 1))) + return FALSE; + if ((editing_town == FALSE) && ((i < 0) || (i > 47) || (j < 0) || (j > 47))) + return FALSE; + if ((ter >= 50) && + (ter <= 62)) + answer = TRUE; + + return answer; +} + +void shy_change_circle_terrain(location center,short radius,unsigned char terrain_type,short probability) +// prob is 0 - 20, 0 no, 20 always +{ +location l; +short i,j; + unsigned char ter; + +for (i = 0; i < ((editing_town == TRUE) ? max_dim[town_type] : 48); i++) + for (j = 0; j < ((editing_town == TRUE) ? max_dim[town_type] : 48); j++) { + l.x = i; + l.y = j; + ter = (editing_town == TRUE) ? t_d.terrain[i][j] : current_terrain.terrain[i][j]; + if ((dist(center,l) <= radius) && (get_ran(1,1,20) <= probability) + && (ter < 5)) + set_terrain(l,terrain_type); + } +} + +void change_circle_terrain(location center,short radius,unsigned char terrain_type,short probability) +// prob is 0 - 20, 0 no, 20 always +{ +location l; +short i,j; + +for (i = 0; i < ((editing_town == TRUE) ? max_dim[town_type] : 48); i++) + for (j = 0; j < ((editing_town == TRUE) ? max_dim[town_type] : 48); j++) { + l.x = i; + l.y = j; + if ((dist(center,l) <= radius) && (get_ran(1,1,20) <= probability)) + set_terrain(l,terrain_type); + } +} + +void change_rect_terrain(RECT r,unsigned char terrain_type,short probability,Boolean hollow) +// prob is 0 - 20, 0 no, 20 always +{ +location l; +short i,j; + +for (i = 0; i < ((editing_town == TRUE) ? max_dim[town_type] : 48); i++) + for (j = 0; j < ((editing_town == TRUE) ? max_dim[town_type] : 48); j++) { + l.x = i; + l.y = j; + if ((i >= r.left) && (i <= r.right) && (j >= r.top) && (j <= r.bottom) + && ((hollow == FALSE) || (i == r.left) || (i == r.right) || (j == r.top) || (j == r.bottom)) + && ((hollow == TRUE) || (get_ran(1,1,20) <= probability))) + set_terrain(l,terrain_type); + } +} + + +void frill_up_terrain() +{ + short i,j; + unsigned char terrain_type; + + for (i = 0; i < ((editing_town == TRUE) ? max_dim[town_type] : 48); i++) + for (j = 0; j < ((editing_town == TRUE) ? max_dim[town_type] : 48); j++) { + terrain_type = (editing_town == TRUE) ? t_d.terrain[i][j] : current_terrain.terrain[i][j]; + + if ((terrain_type == 2) && (get_ran(1,1,20) < 3)) + terrain_type = 3; + if ((terrain_type == 2) && (get_ran(1,1,20) < 2)) + terrain_type = 4; + if ((terrain_type == 0) && (get_ran(1,1,20) < 2)) + terrain_type = 1; + if ((terrain_type == 36) && (get_ran(1,1,20) < 5)) + terrain_type = 37; + if (editing_town == TRUE) + t_d.terrain[i][j] = terrain_type; + else current_terrain.terrain[i][j] = terrain_type; + } + draw_terrain(); +} + +void unfrill_terrain() +{ + short i,j; + unsigned char terrain_type; + + for (i = 0; i < ((editing_town == TRUE) ? max_dim[town_type] : 48); i++) + for (j = 0; j < ((editing_town == TRUE) ? max_dim[town_type] : 48); j++) { + terrain_type = (editing_town == TRUE) ? t_d.terrain[i][j] : current_terrain.terrain[i][j]; + if (terrain_type == 3) + terrain_type = 2; + if (terrain_type == 4) + terrain_type = 2; + if (terrain_type == 1) + terrain_type = 0; + if (terrain_type == 37) + terrain_type = 36; + if (editing_town == TRUE) + t_d.terrain[i][j] = terrain_type; + else current_terrain.terrain[i][j] = terrain_type; + } + draw_terrain(); +} + +void set_terrain(location l,unsigned char terrain_type) +{ + short i,j,which_sign = -1; + unsigned char ter; + location l2; + + i = l.x; j = l.y; + //if ((l.x < 0) || (l.x > max_dim[town_type] - 1) || (l.y < 0) || (l.y > max_dim[town_type] - 1)) + // return; + if ((editing_town == TRUE) && ((i < 0) || (i > max_dim[town_type] - 1) || (j < 0) || (j > max_dim[town_type] - 1))) + return ; + if ((editing_town == FALSE) && ((i < 0) || (i > 47) || (j < 0) || (j > 47))) + return ; + + if (editing_town == TRUE) + t_d.terrain[i][j] = terrain_type; + else current_terrain.terrain[i][j] = terrain_type; + l2 = l; + + if (terrain_type == 85) { + l2.x++; + if (editing_town == TRUE) + t_d.terrain[l2.x][l2.y] = 86; + else current_terrain.terrain[l2.x][l2.y] = 86; + } + if (terrain_type == 86) { + l2.x--; + if (editing_town == TRUE) + t_d.terrain[l2.x][l2.y] = 85; + else current_terrain.terrain[l2.x][l2.y] = 85; + } + if (terrain_type == 88) { + l2.x++; + if (editing_town == TRUE) + t_d.terrain[l2.x][l2.y] = 89; + else current_terrain.terrain[l2.x][l2.y] = 89; + } + if (terrain_type == 89) { + l2.x--; + if (editing_town == TRUE) + t_d.terrain[l2.x][l2.y] = 88; + else current_terrain.terrain[l2.x][l2.y] = 88; + } + + if (is_mountain(l.x,l.y)) + for (i = l.x - 1; i < l.x + 2; i++) + for (j = l.y - 1; j < l.y + 2; j++) { + if ((i < 0) || (i > ((editing_town == TRUE) ? max_dim[town_type] - 1 : 47)) + || (j < 0) || (j > ((editing_town == TRUE) ? max_dim[town_type] - 1 : 47))) + ; + else { + l2.x = i; + l2.y = j; + ter = (editing_town == TRUE) ? t_d.terrain[l2.x][l2.y] : current_terrain.terrain[l2.x][l2.y]; + if ((!is_mountain(l2.x,l2.y)) && (ter < 5)) { + if (editing_town == TRUE) + t_d.terrain[l2.x][l2.y] = 36; + else current_terrain.terrain[l2.x][l2.y] = 36; + } + } + } + + adjust_space(l); + l.x--; + adjust_space(l); + + l.x += 2; + adjust_space(l); + + l.x--; + l.y--; + adjust_space(l); + + l.y+= 2; + adjust_space(l); + l.y--; + + if ((scenario.ter_types[terrain_type].special == 11) && (editing_town == TRUE)) { /// it's a sign + for (i = 0; i < 15; i++) + if (which_sign < 0) { + if ((town.sign_locs[i].x == l.x) && (town.sign_locs[i].y == l.y)) + which_sign = i; + } + for (i = 0; i < 15; i++) + if (which_sign < 0) { + if (town.sign_locs[i].x == 100) + which_sign = i; + else { + ter = t_d.terrain[town.sign_locs[i].x][town.sign_locs[i].y]; + if (scenario.ter_types[ter].special != 11) + which_sign = i; + } + } + if (which_sign >= 0) { + town.sign_locs[which_sign] = l; + edit_sign(which_sign,scenario.ter_types[terrain_type].picture); + sign_error_received = FALSE; + } + else { + t_d.terrain[l.x][l.y] = current_ground; + if (sign_error_received == FALSE) { + give_error("Towns can have at most 15 signs. Outdoor sections can have at most 8. When the party looks at this sign, they will get no message.","",0); + sign_error_received = TRUE; + } + } + mouse_button_held = FALSE; + } + if ((scenario.ter_types[terrain_type].special == 11) && (editing_town == FALSE)) { /// it's a sign + if ((l.x == 0) || (l.x == 47) || (l.y == 0) || (l.y == 47)) { + fancy_choice_dialog(870,0); + mouse_button_held = FALSE; + return; + } + for (i = 0; i < 8; i++) + if (which_sign < 0) { + if ((current_terrain.sign_locs[i].x == l.x) && (current_terrain.sign_locs[i].y == l.y)) + which_sign = i; + } + for (i = 0; i < 8; i++) + if (which_sign < 0) { + if (current_terrain.sign_locs[i].x == 100) + which_sign = i; + else { + ter = current_terrain.terrain[current_terrain.sign_locs[i].x][current_terrain.sign_locs[i].y]; + if (scenario.ter_types[ter].special != 11) + which_sign = i; + } + } + if (which_sign >= 0) { + current_terrain.sign_locs[which_sign] = l; + edit_sign(which_sign,scenario.ter_types[terrain_type].picture); + sign_error_received = FALSE; + } + else { + current_terrain.terrain[l.x][l.y] = current_ground; + if (sign_error_received == FALSE) { + give_error("Towns can have at most 15 signs. Outdoor sections can have at most 8. When the party looks at this sign, they will get no message.","",0); + sign_error_received = TRUE; + } + } + mouse_button_held = FALSE; + } +} + +Boolean fix_rubble(location l) +{ + unsigned char terrain_type; + + if ((l.x < 0) || (l.y > max_dim[town_type] - 1) || (l.y < 0) || (l.y > max_dim[town_type] - 1)) + return FALSE; + terrain_type = t_d.terrain[l.x][l.y]; + if ((terrain_type == 85) && (t_d.terrain[l.x + 1][l.y] != 86)) { + t_d.terrain[l.x][l.y] = 0; + return TRUE; + } + if ((terrain_type == 86) && (t_d.terrain[l.x - 1][l.y] != 85)) { + t_d.terrain[l.x][l.y] = 0; + return TRUE; + } + if ((terrain_type == 88) && (t_d.terrain[l.x + 1][l.y] != 89)) { + t_d.terrain[l.x][l.y] = 2; + return TRUE; + } + if ((terrain_type == 89) && (t_d.terrain[l.x - 1][l.y] != 88)) { + t_d.terrain[l.x][l.y] = 2; + return TRUE; + } + return FALSE; +} + +Boolean fix_cave(location l) +{ + unsigned char ter_to_fix; + unsigned char store_ter; + short i,j; + + if ((l.x < 0) || (l.y > max_dim[town_type] - 1) || (l.y < 0) || (l.y > max_dim[town_type] - 1)) + return FALSE; + i = l.x; j = l.y; + store_ter = t_d.terrain[l.x][l.y]; + + if (is_correctable_wall(i,j) == TRUE) { +/* if (((l.x == 0) || (l.x == max_dim[town_type] - 1)) && ((l.y == 0) || (l.y == max_dim[town_type] - 1))) + ter_to_fix = 2; + else if ((l.x == 0) || (l.x == max_dim[town_type] - 1)) { + if (is_wall(i,j-1)) { + if (is_wall(i,j+1)) { + ter_to_fix = 2; + } + else ter_to_fix = 3; + } + else ter_to_fix = 9; + } + else if ((l.y == 0) || (l.y == max_dim[town_type] - 1)) { + if (is_wall(i - 1,j)) { + if (is_wall(i + 1,j)) { + ter_to_fix = 2; + } + else ter_to_fix = 6; + } + else ter_to_fix = 12; + + } + else { // not edge +*/ +if (is_wall(i-1,j) == FALSE) +{ + if (is_wall(i,j-1) == FALSE) + { + ter_to_fix = 11; + } + else + { + if (is_wall(i,j+1) == FALSE) + ter_to_fix = 14; + else ter_to_fix = 12; + } + + + +} + +else // wall(i-1,j) == TRUE + +{ + if (is_wall(i+1,j) == FALSE) + { + if (is_wall(i, j-1) == FALSE) + ter_to_fix = 8; + else if (is_wall(i,j+1) == FALSE) + ter_to_fix = 5; + else ter_to_fix = 6; + + } + + else //wall(i+1,j) == TRUE + + { + if (is_wall(i, j-1) == FALSE) + ter_to_fix = 9; + else if (is_wall(i,j+1) == FALSE) + ter_to_fix = 3; + else if (is_wall(i-1,j-1) == FALSE) + ter_to_fix = 16; + else if(is_wall(i-1,j+1) == FALSE) + ter_to_fix = 15; + else if (is_wall(i+1,j-1) == FALSE) + ter_to_fix = 17; + else if (is_wall(i+1,j+1) == FALSE) + ter_to_fix = 18; + else ter_to_fix = 2; + + + + } + +} +//} + ter_to_fix += 3; + t_d.terrain[i][j] = ter_to_fix; + } + + if (store_ter == t_d.terrain[l.x][l.y]) + return FALSE; + else return TRUE; + +} + + +Boolean fix_mountain(location l) +{ + unsigned char ter_to_fix; + unsigned char store_ter; + short i,j; + + if ((l.x < 0) || (l.y > max_dim[town_type] - 1) || (l.y < 0) || (l.y > max_dim[town_type] - 1)) + return FALSE; + i = l.x; j = l.y; + store_ter = t_d.terrain[l.x][l.y]; + + if ((store_ter >= 22) && + (store_ter <= 35) && (store_ter != 23)) { + if (((l.x == 0) || (l.x == max_dim[town_type] - 1)) && ((l.y == 0) || (l.y == max_dim[town_type] - 1))) + ter_to_fix = 22; + else if ((l.x == 0) || (l.x == max_dim[town_type] - 1)) { + if (is_mountain(i,j-1)) { + if (is_mountain(i,j+1)) { + ter_to_fix = 22; + } + else ter_to_fix = 24; + } + else ter_to_fix = 28; + } + else if ((l.y == 0) || (l.y == max_dim[town_type] - 1)) { + if (is_mountain(i - 1,j)) { + if (is_mountain(i + 1,j)) { + ter_to_fix = 22; + } + else ter_to_fix = 26; + } + else ter_to_fix = 30; + + } + else { // not edge + +if (is_mountain(i-1,j) == FALSE) +{ + if (is_mountain(i,j-1) == FALSE) + { + ter_to_fix = 29; + } + else + { + if (is_mountain(i,j+1) == FALSE) + ter_to_fix = 31; + else ter_to_fix = 30; + } + + + +} + +else // wall(i-1,j) == TRUE + +{ + if (is_mountain(i+1,j) == FALSE) + { + if (is_mountain(i, j-1) == FALSE) + ter_to_fix = 27; + else if (is_mountain(i,j+1) == FALSE) + ter_to_fix = 25; + else ter_to_fix = 26; + + } + + else //wall(i+1,j) == TRUE + + { + if (is_mountain(i, j-1) == FALSE) + ter_to_fix = 28; + else if (is_mountain(i,j+1) == FALSE) + ter_to_fix = 24; + else if (is_mountain(i-1,j-1) == FALSE) + ter_to_fix = 33; + else if(is_mountain(i-1,j+1) == FALSE) + ter_to_fix = 32; + else if (is_mountain(i+1,j-1) == FALSE) + ter_to_fix = 34; + else if (is_mountain(i+1,j+1) == FALSE) + ter_to_fix = 35; + else ter_to_fix = 22; + + + + } + +} +} + t_d.terrain[i][j] = ter_to_fix; + } + + if (store_ter == t_d.terrain[l.x][l.y]) + return FALSE; + else return TRUE; + +} + +Boolean fix_hill(location l) +{ + unsigned char ter_to_fix; + unsigned char store_ter; + short i,j; + + if ((l.x < 0) || (l.y > max_dim[town_type] - 1) || (l.y < 0) || (l.y > max_dim[town_type] - 1)) + return FALSE; + i = l.x; j = l.y; + store_ter = t_d.terrain[l.x][l.y]; + + if ((t_d.terrain[l.x][l.y] >= 36) && + (t_d.terrain[l.x][l.y] <= 49) ) { + if (((l.x == 0) || (l.x == max_dim[town_type] - 1)) && ((l.y == 0) || (l.y == max_dim[town_type] - 1))) + ter_to_fix = 22; + else if ((l.x == 0) || (l.x == max_dim[town_type] - 1)) { + if (is_hill_or_mountain(i,j-1)) { + if (is_hill_or_mountain(i,j+1)) { + ter_to_fix = 22; + } + else ter_to_fix = 24; + } + else ter_to_fix = 28; + } + else if ((l.y == 0) || (l.y == max_dim[town_type] - 1)) { + if (is_hill_or_mountain(i - 1,j)) { + if (is_hill_or_mountain(i + 1,j)) { + ter_to_fix = 22; + } + else ter_to_fix = 26; + } + else ter_to_fix = 30; + + } + else { // not edge + +if (is_hill_or_mountain(i-1,j) == FALSE) +{ + if (is_hill_or_mountain(i,j-1) == FALSE) + { + ter_to_fix = 29; + } + else + { + if (is_hill_or_mountain(i,j+1) == FALSE) + ter_to_fix = 31; + else ter_to_fix = 30; + } + + + +} + +else // wall(i-1,j) == TRUE + +{ + if (is_hill_or_mountain(i+1,j) == FALSE) + { + if (is_hill_or_mountain(i, j-1) == FALSE) + ter_to_fix = 27; + else if (is_hill_or_mountain(i,j+1) == FALSE) + ter_to_fix = 25; + else ter_to_fix = 26; + + } + + else //wall(i+1,j) == TRUE + + { + if (is_hill_or_mountain(i, j-1) == FALSE) + ter_to_fix = 28; + else if (is_hill_or_mountain(i,j+1) == FALSE) + ter_to_fix = 24; + else if (is_hill_or_mountain(i-1,j-1) == FALSE) + ter_to_fix = 33; + else if(is_hill_or_mountain(i-1,j+1) == FALSE) + ter_to_fix = 32; + else if (is_hill_or_mountain(i+1,j-1) == FALSE) + ter_to_fix = 34; + else if (is_hill_or_mountain(i+1,j+1) == FALSE) + ter_to_fix = 35; + else ter_to_fix = 22; + + + + } + +} +} + ter_to_fix += 14; + //if ((ter_to_fix == 36) && (get_ran(1,0,15) == 5)) + // ter_to_fix++; + if ((t_d.terrain[i][j] != 37) || (ter_to_fix != 36)) + t_d.terrain[i][j] = ter_to_fix; + } + + if (store_ter == t_d.terrain[l.x][l.y]) + return FALSE; + else return TRUE; + +} + +Boolean fix_water(location l) +{ + unsigned char ter_to_fix; + unsigned char store_ter; + short i,j; + + if ((l.x < 0) || (l.y > max_dim[town_type] - 1) || (l.y < 0) || (l.y > max_dim[town_type] - 1)) + return FALSE; + i = l.x; j = l.y; + store_ter = t_d.terrain[l.x][l.y]; + + if (is_correctable_water(l.x,l.y)) { + if (((l.x == 0) || (l.x == max_dim[town_type] - 1)) && ((l.y == 0) || (l.y == max_dim[town_type] - 1))) + ter_to_fix = 22; + else if ((l.x == 0) || (l.x == max_dim[town_type] - 1)) { + if (is_water(i,j-1)) { + if (is_water(i,j+1)) { + ter_to_fix = 22; + } + else ter_to_fix = 24; + } + else ter_to_fix = 28; + } + else if ((l.y == 0) || (l.y == max_dim[town_type] - 1)) { + if (is_water(i - 1,j)) { + if (is_water(i + 1,j)) { + ter_to_fix = 22; + } + else ter_to_fix = 26; + } + else ter_to_fix = 30; + + } + else { // not edge + +if (is_water(i-1,j) == FALSE) +{ + if (is_water(i,j-1) == FALSE) + { + ter_to_fix = 29; + } + else + { + if (is_water(i,j+1) == FALSE) + ter_to_fix = 31; + else ter_to_fix = 30; + } + + + +} + +else // wall(i-1,j) == TRUE + +{ + if (is_water(i+1,j) == FALSE) + { + if (is_water(i, j-1) == FALSE) + ter_to_fix = 27; + else if (is_water(i,j+1) == FALSE) + ter_to_fix = 25; + else ter_to_fix = 26; + + } + + else //wall(i+1,j) == TRUE + + { + if (is_water(i, j-1) == FALSE) + ter_to_fix = 28; + else if (is_water(i,j+1) == FALSE) + ter_to_fix = 24; + else if (is_water(i-1,j-1) == FALSE) + ter_to_fix = 33; + else if(is_water(i-1,j+1) == FALSE) + ter_to_fix = 32; + else if (is_water(i+1,j-1) == FALSE) + ter_to_fix = 34; + else if (is_water(i+1,j+1) == FALSE) + ter_to_fix = 35; + else ter_to_fix = 22; + + + + } + +} +} + ter_to_fix += 27; + if (ter_to_fix == 49) + ter_to_fix++; + t_d.terrain[i][j] = ter_to_fix; + } + + if (store_ter == t_d.terrain[l.x][l.y]) + return FALSE; + else return TRUE; + +} + +// begin out +Boolean out_fix_rubble(location l) +{ + unsigned char terrain_type; + + if ((l.x < 0) || (l.y > 47) || (l.y < 0) || (l.y > 47)) + return FALSE; + terrain_type = current_terrain.terrain[l.x][l.y]; + if ((terrain_type == 85) && (current_terrain.terrain[l.x + 1][l.y] != 86)) { + current_terrain.terrain[l.x][l.y] = 0; + return TRUE; + } + if ((terrain_type == 86) && (current_terrain.terrain[l.x - 1][l.y] != 85)) { + current_terrain.terrain[l.x][l.y] = 0; + return TRUE; + } + if ((terrain_type == 88) && (current_terrain.terrain[l.x + 1][l.y] != 89)) { + current_terrain.terrain[l.x][l.y] = 2; + return TRUE; + } + if ((terrain_type == 89) && (current_terrain.terrain[l.x - 1][l.y] != 88)) { + current_terrain.terrain[l.x][l.y] = 2; + return TRUE; + } + return FALSE; +} + +Boolean out_fix_cave(location l) +{ + unsigned char ter_to_fix; + unsigned char store_ter; + short i,j; + + if ((l.x < 0) || (l.y > 47) || (l.y < 0) || (l.y > 47)) + return FALSE; + i = l.x; j = l.y; + store_ter = current_terrain.terrain[l.x][l.y]; + + if (is_correctable_wall(i,j) == TRUE) { + if (((l.x == 0) || (l.x == 47)) && ((l.y == 0) || (l.y == 47))) + ter_to_fix = 2; + else if ((l.x == 0) || (l.x == 47)) { + if (is_wall(i,j-1)) { + if (is_wall(i,j+1)) { + ter_to_fix = 2; + } + else ter_to_fix = 3; + } + else ter_to_fix = 9; + } + else if ((l.y == 0) || (l.y == 47)) { + if (is_wall(i - 1,j)) { + if (is_wall(i + 1,j)) { + ter_to_fix = 2; + } + else ter_to_fix = 6; + } + else ter_to_fix = 12; + + } + else { // not edge + +if (is_wall(i-1,j) == FALSE) +{ + if (is_wall(i,j-1) == FALSE) + { + ter_to_fix = 11; + } + else + { + if (is_wall(i,j+1) == FALSE) + ter_to_fix = 14; + else ter_to_fix = 12; + } + + + +} + +else // wall(i-1,j) == TRUE + +{ + if (is_wall(i+1,j) == FALSE) + { + if (is_wall(i, j-1) == FALSE) + ter_to_fix = 8; + else if (is_wall(i,j+1) == FALSE) + ter_to_fix = 5; + else ter_to_fix = 6; + + } + + else //wall(i+1,j) == TRUE + + { + if (is_wall(i, j-1) == FALSE) + ter_to_fix = 9; + else if (is_wall(i,j+1) == FALSE) + ter_to_fix = 3; + else if (is_wall(i-1,j-1) == FALSE) + ter_to_fix = 16; + else if(is_wall(i-1,j+1) == FALSE) + ter_to_fix = 15; + else if (is_wall(i+1,j-1) == FALSE) + ter_to_fix = 17; + else if (is_wall(i+1,j+1) == FALSE) + ter_to_fix = 18; + else ter_to_fix = 2; + + + + } + +} +} + ter_to_fix += 3; + current_terrain.terrain[i][j] = ter_to_fix; + } + + if (store_ter == current_terrain.terrain[l.x][l.y]) + return FALSE; + else return TRUE; + +} + + +Boolean out_fix_mountain(location l) +{ + unsigned char ter_to_fix; + unsigned char store_ter; + short i,j; + + if ((l.x < 0) || (l.y > 47) || (l.y < 0) || (l.y > 47)) + return FALSE; + i = l.x; j = l.y; + store_ter = current_terrain.terrain[l.x][l.y]; + + if ((store_ter >= 22) && + (store_ter <= 35) && (store_ter != 23)) { + if (((l.x == 0) || (l.x == 47)) && ((l.y == 0) || (l.y == 47))) + ter_to_fix = 22; + else if ((l.x == 0) || (l.x == 47)) { + if (is_mountain(i,j-1)) { + if (is_mountain(i,j+1)) { + ter_to_fix = 22; + } + else ter_to_fix = 24; + } + else ter_to_fix = 28; + } + else if ((l.y == 0) || (l.y == 47)) { + if (is_mountain(i - 1,j)) { + if (is_mountain(i + 1,j)) { + ter_to_fix = 22; + } + else ter_to_fix = 26; + } + else ter_to_fix = 30; + + } + else { // not edge + +if (is_mountain(i-1,j) == FALSE) +{ + if (is_mountain(i,j-1) == FALSE) + { + ter_to_fix = 29; + } + else + { + if (is_mountain(i,j+1) == FALSE) + ter_to_fix = 31; + else ter_to_fix = 30; + } + + + +} + +else // wall(i-1,j) == TRUE + +{ + if (is_mountain(i+1,j) == FALSE) + { + if (is_mountain(i, j-1) == FALSE) + ter_to_fix = 27; + else if (is_mountain(i,j+1) == FALSE) + ter_to_fix = 25; + else ter_to_fix = 26; + + } + + else //wall(i+1,j) == TRUE + + { + if (is_mountain(i, j-1) == FALSE) + ter_to_fix = 28; + else if (is_mountain(i,j+1) == FALSE) + ter_to_fix = 24; + else if (is_mountain(i-1,j-1) == FALSE) + ter_to_fix = 33; + else if(is_mountain(i-1,j+1) == FALSE) + ter_to_fix = 32; + else if (is_mountain(i+1,j-1) == FALSE) + ter_to_fix = 34; + else if (is_mountain(i+1,j+1) == FALSE) + ter_to_fix = 35; + else ter_to_fix = 22; + + + + } + +} +} + current_terrain.terrain[i][j] = ter_to_fix; + } + + if (store_ter == current_terrain.terrain[l.x][l.y]) + return FALSE; + else return TRUE; + +} + +Boolean out_fix_hill(location l) +{ + unsigned char ter_to_fix; + unsigned char store_ter; + short i,j; + + if ((l.x < 0) || (l.y > 47) || (l.y < 0) || (l.y > 47)) + return FALSE; + i = l.x; j = l.y; + store_ter = current_terrain.terrain[l.x][l.y]; + + if ((current_terrain.terrain[l.x][l.y] >= 36) && + (current_terrain.terrain[l.x][l.y] <= 49) ) { + if (((l.x == 0) || (l.x == 47)) && ((l.y == 0) || (l.y == 47))) + ter_to_fix = 22; + else if ((l.x == 0) || (l.x == 47)) { + if (is_hill_or_mountain(i,j-1)) { + if (is_hill_or_mountain(i,j+1)) { + ter_to_fix = 22; + } + else ter_to_fix = 24; + } + else ter_to_fix = 28; + } + else if ((l.y == 0) || (l.y == 47)) { + if (is_hill_or_mountain(i - 1,j)) { + if (is_hill_or_mountain(i + 1,j)) { + ter_to_fix = 22; + } + else ter_to_fix = 26; + } + else ter_to_fix = 30; + + } + else { // not edge + +if (is_hill_or_mountain(i-1,j) == FALSE) +{ + if (is_hill_or_mountain(i,j-1) == FALSE) + { + ter_to_fix = 29; + } + else + { + if (is_hill_or_mountain(i,j+1) == FALSE) + ter_to_fix = 31; + else ter_to_fix = 30; + } + + + +} + +else // wall(i-1,j) == TRUE + +{ + if (is_hill_or_mountain(i+1,j) == FALSE) + { + if (is_hill_or_mountain(i, j-1) == FALSE) + ter_to_fix = 27; + else if (is_hill_or_mountain(i,j+1) == FALSE) + ter_to_fix = 25; + else ter_to_fix = 26; + + } + + else //wall(i+1,j) == TRUE + + { + if (is_hill_or_mountain(i, j-1) == FALSE) + ter_to_fix = 28; + else if (is_hill_or_mountain(i,j+1) == FALSE) + ter_to_fix = 24; + else if (is_hill_or_mountain(i-1,j-1) == FALSE) + ter_to_fix = 33; + else if(is_hill_or_mountain(i-1,j+1) == FALSE) + ter_to_fix = 32; + else if (is_hill_or_mountain(i+1,j-1) == FALSE) + ter_to_fix = 34; + else if (is_hill_or_mountain(i+1,j+1) == FALSE) + ter_to_fix = 35; + else ter_to_fix = 22; + + + + } + +} +} + ter_to_fix += 14; + //if ((ter_to_fix == 36) && (get_ran(1,0,15) == 5)) + // ter_to_fix++; + if ((current_terrain.terrain[i][j] != 37) || (ter_to_fix != 36)) + current_terrain.terrain[i][j] = ter_to_fix; + } + + if (store_ter == current_terrain.terrain[l.x][l.y]) + return FALSE; + else return TRUE; + +} + +Boolean out_fix_water(location l) +{ + unsigned char ter_to_fix; + unsigned char store_ter; + short i,j; + + if ((l.x < 0) || (l.y > 47) || (l.y < 0) || (l.y > 47)) + return FALSE; + i = l.x; j = l.y; + store_ter = current_terrain.terrain[l.x][l.y]; + + if (is_correctable_water(l.x,l.y)) { + if (((l.x == 0) || (l.x == 47)) && ((l.y == 0) || (l.y == 47))) + ter_to_fix = 22; + else if ((l.x == 0) || (l.x == 47)) { + if (is_water(i,j-1)) { + if (is_water(i,j+1)) { + ter_to_fix = 22; + } + else ter_to_fix = 24; + } + else ter_to_fix = 28; + } + else if ((l.y == 0) || (l.y == 47)) { + if (is_water(i - 1,j)) { + if (is_water(i + 1,j)) { + ter_to_fix = 22; + } + else ter_to_fix = 26; + } + else ter_to_fix = 30; + + } + else { // not edge + +if (is_water(i-1,j) == FALSE) +{ + if (is_water(i,j-1) == FALSE) + { + ter_to_fix = 29; + } + else + { + if (is_water(i,j+1) == FALSE) + ter_to_fix = 31; + else ter_to_fix = 30; + } + + + +} + +else // wall(i-1,j) == TRUE + +{ + if (is_water(i+1,j) == FALSE) + { + if (is_water(i, j-1) == FALSE) + ter_to_fix = 27; + else if (is_water(i,j+1) == FALSE) + ter_to_fix = 25; + else ter_to_fix = 26; + + } + + else //wall(i+1,j) == TRUE + + { + if (is_water(i, j-1) == FALSE) + ter_to_fix = 28; + else if (is_water(i,j+1) == FALSE) + ter_to_fix = 24; + else if (is_water(i-1,j-1) == FALSE) + ter_to_fix = 33; + else if(is_water(i-1,j+1) == FALSE) + ter_to_fix = 32; + else if (is_water(i+1,j-1) == FALSE) + ter_to_fix = 34; + else if (is_water(i+1,j+1) == FALSE) + ter_to_fix = 35; + else ter_to_fix = 22; + + + + } + +} +} + ter_to_fix += 27; + if (ter_to_fix == 49) + ter_to_fix++; + current_terrain.terrain[i][j] = ter_to_fix; + } + + if (store_ter == current_terrain.terrain[l.x][l.y]) + return FALSE; + else return TRUE; + +} +// end out + +void adjust_space(location l) +{ + Boolean needed_change = FALSE; + location l2; + short i,j; + + i = l.x; j = l.y; + if ((editing_town == TRUE) && ((i < 0) || (i > max_dim[town_type] - 1) || (j < 0) || (j > max_dim[town_type] - 1))) + return ; + if ((editing_town == FALSE) && ((i < 0) || (i > 47) || (j < 0) || (j > 47))) + return ; + + if (editing_town == TRUE) { + if (fix_rubble(l) == TRUE) + needed_change = TRUE; + if (fix_cave(l) == TRUE) + needed_change = TRUE; + if (fix_mountain(l) == TRUE) + needed_change = TRUE; + if (fix_hill(l) == TRUE) + needed_change = TRUE; + if (fix_water(l) == TRUE) + needed_change = TRUE; + } + if (editing_town == FALSE) { + if (out_fix_rubble(l) == TRUE) + needed_change = TRUE; + if (out_fix_cave(l) == TRUE) + needed_change = TRUE; + if (out_fix_mountain(l) == TRUE) + needed_change = TRUE; + if (out_fix_hill(l) == TRUE) + needed_change = TRUE; + if (out_fix_water(l) == TRUE) + needed_change = TRUE; + } + + if (needed_change == TRUE) { + l2 = l; + l2.x--; + adjust_space(l2); + l2.x += 2; + adjust_space(l2); + l2.x--; + l2.y--; + adjust_space(l2); + l2.y += 2; + adjust_space(l2); + } + +} + +Boolean is_lava(short x,short y) +{ + if ((coord_to_ter(x,y) == 75) || (coord_to_ter(x,y) == 76)) + return TRUE; + else return FALSE; +} + +unsigned char coord_to_ter(short x,short y) +{ + unsigned char what_terrain; + + if (editing_town == TRUE) + what_terrain = t_d.terrain[x][y]; + else what_terrain = current_terrain.terrain[x][y]; + + return what_terrain; +} + +short get_obscurity(short x,short y) +{ + unsigned char what_terrain; + short store; + + what_terrain = coord_to_ter(x,y); + + store = scenario.ter_types[what_terrain].blockage; + if ((store == 1) || (store == 5)) + return 5; + if (store == 4) + return 1; + return 0; +} + + +short can_see(location p1,location p2,short mode) +//mode; // 0 - normal 1 - counts 1 for blocked spaces or lava (used for party placement in + // town combat) + // 2 - no light check +{ + short dx,dy,count,storage = 0; + + if (p1.y == p2.y) { + if (p1.x > p2.x) { + for (count = p2.x + 1; count < p1.x; count++) { + storage = storage + get_obscurity(count, p1.y); + if (((scenario.ter_types[coord_to_ter(count,p1.y)].blockage > 2) || (is_lava(count,p1.y) == TRUE)) && (mode == 1)) + return 5; + } + } + else { + for (count = p1.x + 1; count < p2.x; count++) { + + storage = storage + get_obscurity(count, p1.y); + if (((scenario.ter_types[coord_to_ter(count,p1.y)].blockage > 2) || (is_lava(count,p1.y) == TRUE)) && (mode == 1)) + return 5; + } + } + return storage; + } + if (p1.x == p2.x) { + if (p1.y > p2.y) { + for (count = p1.y - 1; count > p2.y; count--) { + storage = storage + get_obscurity(p1.x, count); + if (((scenario.ter_types[coord_to_ter(p1.x,count)].blockage > 2) || (is_lava(p1.x,count) == TRUE)) && (mode == 1)) + return 5; + } + } + else { + for (count = p1.y + 1; count < p2.y; count++) { + storage = storage + get_obscurity(p1.x, count); + if (((scenario.ter_types[coord_to_ter(p1.x,count)].blockage > 2) || (is_lava(p1.x,count) == TRUE)) && (mode == 1)) + return 5; + } + } + return storage; + } + dx = p2.x - p1.x; + dy = p2.y - p1.y; + + if (abs(dy) > abs(dx)) { + if (p2.y > p1.y) { + for (count = 1; count < dy; count++) { + storage = storage + get_obscurity(p1.x + (count * dx) / dy, p1.y + count); + if ( ((scenario.ter_types[coord_to_ter(p1.x + (count * dx) / dy,p1.y + count)].blockage > 2) || + (is_lava(p1.x + (count * dx) / dy,p1.y + count) == TRUE)) + && (mode == 1)) + return 5; + } + } + else { + for (count = -1; count > dy; count--) { + storage = storage + get_obscurity(p1.x + (count * dx) / dy, p1.y + count); + if ( ((scenario.ter_types[coord_to_ter(p1.x + (count * dx) / dy, p1.y + count)].blockage > 2) || + (is_lava(p1.x + (count * dx) / dy, p1.y + count) == TRUE)) + && (mode == 1)) + return 5; + } + } + return storage; + } + if (abs(dy) <= abs(dx)) { + if (p2.x > p1.x) { + for (count = 1; count < dx; count++) { + storage = storage + get_obscurity(p1.x + count, p1.y + (count * dy) / dx); + if (((scenario.ter_types[coord_to_ter(p1.x + count,p1.y + (count * dy) / dx)].blockage > 2) || + (is_lava(p1.x + count,p1.y + (count * dy) / dx) == TRUE)) + && (mode == 1)) + return 5; + } + } + else { + for (count = -1; count > dx; count--) { + storage = storage + get_obscurity(p1.x + count, p1.y + (count * dy) / dx); + if ( ((scenario.ter_types[coord_to_ter(p1.x + count,p1.y + (count * dy) / dx)].blockage > 2) || + (is_lava(p1.x + count,p1.y + (count * dy) / dx) == TRUE)) + && (mode == 1)) + return 5; + } + } + return storage; + } + if (storage > 5) + return 5; + else return storage; +} + +Boolean place_item(location spot_hit,short which_item,short property,short always,short odds) +// odds 0 - 100, with 100 always +{ + + short x; + + if ((which_item < 0) || (which_item > 399)) + return TRUE; + if (scen_item_list.scen_items[which_item].variety == 0) + return TRUE; + if (get_ran(1,1,100) > odds) + return FALSE; + for (x = 0; x < 64; x++) + if (town.preset_items[x].item_code < 0) { + town.preset_items[x].item_loc.x = spot_hit.x; + town.preset_items[x].item_loc.y = spot_hit.y; + town.preset_items[x].item_code = which_item; + town.preset_items[x].ability = -1; + if ((scen_item_list.scen_items[which_item].variety == 3) || + (scen_item_list.scen_items[which_item].variety == 11)) + town.preset_items[x].ability = get_ran(1,4,6); + + //town.preset_items[x].charges = 0; + town.preset_items[x].always_there = always; + town.preset_items[x].property = property; + town.preset_items[x].contained = container_there(town.preset_items[x].item_loc); + return TRUE; + } + return FALSE; +} + +void place_items_in_town() +{ + location l; + short i,j,k,x; + Boolean place_failed = FALSE; + + for (i = 0; i < max_dim[town_type];i++) + for (j = 0; j < max_dim[town_type];j++) { + l.x = i; l.y = j; + + for (k = 0; k < 10; k++) + if (t_d.terrain[i][j] == scenario.storage_shortcuts[k].ter_type) { + for (x = 0; x < 10; x++) + if (place_item(l,scenario.storage_shortcuts[k].item_num[x], + scenario.storage_shortcuts[k].property,FALSE, + scenario.storage_shortcuts[k].item_odds[x]) == FALSE) + place_failed = TRUE; + } + } + if (place_failed == TRUE) + give_error("Not all of the random items could be placed. The preset item per town limit of 64 was reached.","",0); + draw_terrain(); +} + +void place_edit_special(location loc) +{ + short i,spec; + + if (editing_town == TRUE) { + for (i = 0; i < 50; i++) + if ((town.special_locs[i].x == loc.x) && (town.special_locs[i].y == loc.y)) { + edit_spec_enc(town.spec_id[i],2,0); + i = 500; + } + if (i < 500) { // new special + spec = get_fresh_spec(2); + if (spec < 0) { + give_error("You are out of special nodes in this town. Select Edit Special Nodes from the Town menu to clear out some of the special nodes.","",0); + return; + } + for (i = 0; i < 50; i++) + if (town.special_locs[i].x == 100) { + town.special_locs[i] = loc; + town.spec_id[i] = spec; + edit_spec_enc(spec,2,0); + + if (town.specials[spec].pic < 0) + town.special_locs[i].x = 100; + i = 500; + } + if (i < 500) { + give_error("Each town can have at most 50 locations with special encounters. You'll need to erase some special spaces before you can place more.","",0); + return; + } + } + } + + if (editing_town == FALSE) { + if ((loc.x == 0) || (loc.x == 47) || (loc.y == 0) || (loc.y == 47)) { + fancy_choice_dialog(870,0); + return; + } + for (i = 0; i < 18; i++) + if ((current_terrain.special_locs[i].x == loc.x) && (current_terrain.special_locs[i].y == loc.y)) { + edit_spec_enc(current_terrain.special_id[i],1,0); + i = 500; + } + if (i < 500) { // new special + spec = get_fresh_spec(1); + if (spec < 0) { + give_error("You are out of special nodes in this outdoor section. Select Edit Special Nodes from the Outdoor menu to clear out some of the special nodes.","",0); + return; + } + for (i = 0; i < 18; i++) + if (current_terrain.special_locs[i].x == 100) { + current_terrain.special_locs[i] = loc; + current_terrain.special_id[i] = spec; + edit_spec_enc(spec,1,0); + + if (current_terrain.specials[spec].pic < 0) + current_terrain.special_locs[i].x = 100; + i = 500; + } + if (i < 500) { + give_error("Each outdoor can have at most 18 locations with special encounters. You'll need to erase some special spaces before you can place more.","",0); + return; + } + } + } + +} + +void set_special(location spot_hit) +{ + short x,y; + + if (editing_town == TRUE) { + for (x = 0; x < 50; x++) + if ((town.special_locs[x].x == spot_hit.x) && (town.special_locs[x].y == spot_hit.y)) { + y = edit_special_num(2,town.spec_id[x]); + if (y >= 0) town.spec_id[x] = y; + x = 500; + } + if (x < 500) { + for (x = 0; x < 50; x++) + if (town.special_locs[x].x == 100) { + y = edit_special_num(2,0); + if (y >= 0) { + town.special_locs[x] = spot_hit; + town.spec_id[x] = y; + } + x = 500; + } + if (x < 500) + give_error("Each town can have at most 50 locations with special encounters. Each outdoor section can have at most 18. You'll need to erase some special spaces before you can place more.","",0); + } + } + if (editing_town == FALSE) { + if ((spot_hit.x == 0) || (spot_hit.x == 47) || (spot_hit.y == 0) || (spot_hit.y == 47)) { + fancy_choice_dialog(870,0); + return; + } + for (x = 0; x < 18; x++) + if ((current_terrain.special_locs[x].x == spot_hit.x) && (current_terrain.special_locs[x].y == spot_hit.y)) { + y = edit_special_num(1,current_terrain.special_id[x]); + if (y >= 0) current_terrain.special_id[x] = y; + x = 500; + } + if (x < 500) { + for (x = 0; x < 18; x++) + if (current_terrain.special_locs[x].x == 100) { + y = edit_special_num(1,current_terrain.special_id[x]); + if (y >= 0) { + current_terrain.special_locs[x] = spot_hit; + current_terrain.special_id[x] = y; + } + x = 500; + } + if (x < 500) + give_error("Each town can have at most 50 locations with special encounters. Each outdoor section can have at most 18. You'll need to erase some special spaces before you can place more.","",0); + } + } + +} + +void town_entry(location spot_hit) +{ + short x,y; + unsigned char ter; + + ter = current_terrain.terrain[spot_hit.x][spot_hit.y]; + if (scenario.ter_types[ter].special != 21) { + give_error("This space isn't a town entrance. Town entrances are marked by a small brown castle icon.","",0); + return; + } + // clean up old town entrys + for (x = 0; x < 8; x++) + if (current_terrain.exit_locs[x].x < 100) { + ter = current_terrain.terrain[current_terrain.exit_locs[x].x][current_terrain.exit_locs[x].y]; + if (scenario.ter_types[ter].special != 21) + current_terrain.exit_locs[x].x = 100; + } + y = -2; + for (x = 0; x < 8; x++) + if ((current_terrain.exit_locs[x].x == spot_hit.x) && (current_terrain.exit_locs[x].y == spot_hit.y)) { + y = pick_town_num(856,current_terrain.exit_dests[x]); + if (y >= 0) current_terrain.exit_dests[x] = y; + } + if (y == -2) { + for (x = 0; x < 8; x++) + if (current_terrain.exit_locs[x].x == 100) { + y = pick_town_num(856,0); + if (y >= 0) { + current_terrain.exit_dests[x] = y; + current_terrain.exit_locs[x] = spot_hit; + } + x = 500; + } + if (y == -2) + give_error("You can't set more than 8 town entrances in any outdoor section.","",0); + } +} + +// is slot >= 0, force that slot +// if -1, use 1st free slot +void set_up_start_screen() +{ + set_lb(0,2,"Blades of Exile",0); + set_lb(1,2,"Scenario Editor",0); + //set_lb(3,2,"by Jeff Vogel",0); + set_lb(3,11,"Make New Scenario",0); + set_lb(4,11,"Load Scenario",0); + set_lb(7,1,"To find out how to use the",0); + set_lb(8,1,"editor, select Getting Started ",0); + set_lb(9,1,"from the Help menu.",0); + set_lb(NLS - 5,1,"Be sure to read the file Blades",0); + set_lb(NLS - 4,1,"of Exile License. Using this",0); + set_lb(NLS - 3,1,"program implies that you agree ",0); + set_lb(NLS - 2,1,"with the terms of the license.",0); + //set_lb(NLS - 2,1,"Copyright 1997, Spiderweb Software",0); + //set_lb(NLS - 1,1,"All rights reserved.",0); + set_lb(NLS - 1,1,"Copyright 1997, All rights reserved.",0); +} + +void set_up_main_screen() +{ + char message[50]; + + reset_lb(); + reset_rb(); + set_lb(-1,2,"Blades of Exile",0); + set_lb(-1,1,"Scenario Options",0); + set_lb(-1,11,"Edit Terrain Types",0); + set_lb(-1,11,"Edit Monsters",0); + set_lb(-1,11,"Edit Items",0); + set_lb(-1,11,"Create New Town",0); + set_lb(-1,11,"Edit Scenario Text",0); + set_lb(-1,11,"Edit Special Items",0); + set_lb(-1,1,"",0); + set_lb(-1,1,"Outdoors Options",0); + sprintf((char *) message," Section x = %d, y = %d",(short) cur_out.x,(short) cur_out.y); + set_lb(-1,1,(char *) message,0); + set_lb(-1,11,"Load New Section",0); + set_lb(-1,11,"Edit Outdoor Terrain",0); + set_lb(-1,1,"",0); + set_lb(-1,1,"Town/Dungeon Options",0); + sprintf((char *) message," Town %d: %s",cur_town,town_strs[0]); + set_lb(-1,1,(char *) message,0); + set_lb(-1,11,"Load Another Town",0); + set_lb(-1,11,"Edit Town Terrain",0); + set_lb(-1,11,"Edit Town Dialogue",0); + //set_lb(NLS - 2,1,"Copyright 1997",0); + set_lb(NLS - 1,1,"Copyright 1997, All rights reserved.",0); + overall_mode = 60; + ShowScrollBar(right_sbar,SB_CTL,TRUE); + shut_down_menus(4); + shut_down_menus(3); + //DrawMenuBar(); + redraw_screen(); + //draw_main_screen(); +} + +void start_town_edit() +{ + short i,j; + char message[50]; + small_any_drawn = FALSE; + cen_x = max_dim[town_type] / 2; cen_y = max_dim[town_type] / 2; + reset_lb(); + set_lb(0,2,"Editing town",0); + sprintf((char *) message,"Editing Town %d: %s",cur_town,town_strs[0]); + set_lb(NLS -2,1,(char *) message,0); + set_lb(NLS - 1,11,"Back to Main Menu",0); + overall_mode = 0; + editing_town = TRUE; + set_up_terrain_buttons(); + shut_down_menus(4); + shut_down_menus(2); + //DrawMenuBar(); + ShowScrollBar(right_sbar,SB_CTL,FALSE); + redraw_screen(); + set_string("Drawing mode",""); + place_location(); + copied_spec = -1; + for (i = 0; i < max_dim[town_type]; i++) + for (j = 0; j < max_dim[town_type]; j++) + if (t_d.terrain[i][j] == 0) + current_ground = 0; + else if (t_d.terrain[i][j] == 2) + current_ground = 2; +} + +void start_out_edit() +{ + short i,j; + char message[50]; + char out_strs[0]; + small_any_drawn = FALSE; + cen_x = 24; cen_y = 24; + reset_lb(); + set_lb(0,2,"Editing outdoors",0); + sprintf((char *) message,"X = %d, Y = %d: %s",(short) cur_out.x,(short) cur_out.y,data_store->out_strs[0]); + set_lb(NLS -2,1,(char *) message,0); + set_lb(NLS - 1,11,"Back to Main Menu",0); + overall_mode = 0; + editing_town = FALSE; + set_up_terrain_buttons(); + ShowScrollBar(right_sbar,SB_CTL,FALSE); + shut_down_menus(4); + shut_down_menus(1); + //DrawMenuBar(); + redraw_screen(); + set_string("Drawing mode",""); + place_location(); + copied_spec = -1; + for (i = 0; i < 48; i++) + for (j = 0; j < 48; j++) + if (current_terrain.terrain[i][j] == 0) + current_ground = 0; + else if (current_terrain.terrain[i][j] == 2) + current_ground = 2; +} + +// mode 0 - initial shut down, 1 - no town, 2 - no out, 3 - no town or out 4 - all menus on +void shut_down_menus(short mode) +{ + HMENU menu; + short i; + short scen_items[18] = {101,103,104,105,106, 109,110,112,113,114, 115,116,117,118,119, 120,111, 121}; + short town_items[17] = {201,202,203,204,205, 206,208,209,210,213, 214,215,216, 217,218,219,220}; + short out_items[10] = {301,302,303,304,305,306,308,311,312,313}; + menu = GetMenu(mainPtr); + //menu[i] = GetSubMenu(big_menu,5 + i); + + if (mode == 0) { + EnableMenuItem(menu,2,MF_GRAYED | MF_BYCOMMAND); + for (i = 0; i < 18; i++) + EnableMenuItem(menu,scen_items[i],MF_GRAYED | MF_BYCOMMAND); + for (i = 0; i < 17; i++) + EnableMenuItem(menu,town_items[i],MF_GRAYED | MF_BYCOMMAND); + for (i = 0; i < 10; i++) + EnableMenuItem(menu,out_items[i],MF_GRAYED | MF_BYCOMMAND); + for (i = 0; i < 10; i++) + EnableMenuItem(menu,401+i,MF_GRAYED | MF_BYCOMMAND); + //for (i = 600; i < 1000; i++) { + // EnableMenuItem(menu,i,MF_GRAYED | MF_BYCOMMAND); + // } + //for (i = 1000; i < 1256; i++) { + // EnableMenuItem(menu,i,MF_GRAYED | MF_BYCOMMAND); + // } + } + if (mode == 4) { + EnableMenuItem(menu,1,MF_ENABLED | MF_BYCOMMAND); + EnableMenuItem(menu,2,MF_ENABLED | MF_BYCOMMAND); + EnableMenuItem(menu,3,MF_ENABLED | MF_BYCOMMAND); + EnableMenuItem(menu,5,MF_ENABLED | MF_BYCOMMAND); + for (i = 0; i < 18; i++) + EnableMenuItem(menu,scen_items[i],MF_ENABLED | MF_BYCOMMAND); + for (i = 0; i < 17; i++) + EnableMenuItem(menu,town_items[i],MF_ENABLED | MF_BYCOMMAND); + for (i = 0; i < 10; i++) + EnableMenuItem(menu,out_items[i],MF_ENABLED | MF_BYCOMMAND); + for (i = 0; i < 10; i++) + EnableMenuItem(menu,401+i,MF_ENABLED | MF_BYCOMMAND); + //for (i = 600; i < 1000; i++) { + // EnableMenuItem(menu,i,MF_ENABLED | MF_BYCOMMAND); + // } + //for (i = 1000; i < 1256; i++) { + // EnableMenuItem(menu,i,MF_ENABLED | MF_BYCOMMAND); + // } + + } + if ((mode == 1) || (mode == 3)) { + for (i = 0; i < 9; i++) + EnableMenuItem(menu,town_items[i],MF_GRAYED | MF_BYCOMMAND); + //for (i = 600; i < 1000; i++) { + // EnableMenuItem(menu,i,MF_GRAYED | MF_BYCOMMAND); + // } + //for (i = 1000; i < 1256; i++) { + // EnableMenuItem(menu,i,MF_GRAYED | MF_BYCOMMAND); + // } + } + if ((mode == 2) || (mode == 3)) { + for (i = 0; i < 7; i++) + EnableMenuItem(menu,out_items[i],MF_GRAYED | MF_BYCOMMAND); + } +} + +void start_terrain_editing() +{ + short i; + char str[256]; + + ShowScrollBar(right_sbar,SB_CTL,FALSE); + overall_mode = 62; + set_up_terrain_buttons(); + place_location(); + + set_lb(NLS - 3,0,"",1); +/* SetControlValue(right_sbar,0); + + reset_rb(); + SetControlMaximum(right_sbar,256 - NRSONPAGE); + for (i = 0; i < 256; i++) { + sprintf((char *) str,"%d - %s",i,(char *) scen_item_list.ter_names[i]); + set_rb(i,1000 + i,(char *) str,0); + } + for (i = 0; i < NRSONPAGE; i++) + draw_rb_slot(i); */ +} + +void start_monster_editing(short just_redo_text) +{ + short i; + char str[256]; + Boolean draw_full = FALSE; + + if (overall_mode == 62) + draw_full = TRUE; + if (just_redo_text == 0) { + overall_mode = 60; + ShowScrollBar(right_sbar,SB_CTL,TRUE); + SetScrollPos(right_sbar,SB_CTL,0,TRUE); + + reset_rb(); + SetScrollRange(right_sbar,SB_CTL,0,255 - NRSONPAGE,TRUE); + } + for (i = 0; i < 256; i++) { + sprintf((char *) str,"%d - %s",i,(char *) scen_item_list.monst_names[i]); + set_rb(i,2000 + i,(char *) str,0); + } + if (draw_full == TRUE) + redraw_screen(); + else for (i = 0; i < NRSONPAGE; i++) + draw_rb_slot(i,0); + set_lb(NLS - 3,0,"",1); +} + +Boolean monst_on_space(location loc,short m_num) +{ + short i,j; + + if (editing_town == FALSE) + return FALSE; + if (t_d.creatures[m_num].number == 0) + return FALSE; + if ((loc.x - t_d.creatures[m_num].start_loc.x >= 0) && + (loc.x - t_d.creatures[m_num].start_loc.x <= scenario.scen_monsters[t_d.creatures[m_num].number].x_width - 1) && + (loc.y - t_d.creatures[m_num].start_loc.y >= 0) && + (loc.y - t_d.creatures[m_num].start_loc.y <= scenario.scen_monsters[t_d.creatures[m_num].number].y_width - 1)) + return TRUE; + return FALSE; + +} + +void start_item_editing(short just_redo_text) +{ + short i; + char str[256]; + Boolean draw_full = FALSE; + + if (just_redo_text == 0) { + if (overall_mode < 60) + set_up_main_screen(); + if (overall_mode == 62) + draw_full = TRUE; + overall_mode = 60; + ShowScrollBar(right_sbar,SB_CTL,TRUE); + SetScrollPos(right_sbar,SB_CTL,0,TRUE); + + reset_rb(); + SetScrollRange(right_sbar,SB_CTL,0,400 - NRSONPAGE,TRUE); + } + for (i = 0; i < 400; i++) { + sprintf((char *) str,"%d - %s",i,(char *) scen_item_list.scen_items[i].full_name); + set_rb(i,3000 + i,(char *) str,0); + } + if (draw_full == TRUE) + redraw_screen(); + else for (i = 0; i < NRSONPAGE; i++) + draw_rb_slot(i,0); + set_lb(NLS - 3,0,"",1); +} + +void start_special_item_editing() +{ + short i; + char str[256]; + Boolean draw_full = FALSE; + + if (overall_mode < 60) + set_up_main_screen(); + if (overall_mode == 62) + draw_full = TRUE; + overall_mode = 60; + SetScrollPos(right_sbar,SB_CTL,0,TRUE); + + SetScrollRange(right_sbar,SB_CTL,0,50 - NRSONPAGE,TRUE); + reset_rb(); + for (i = 0; i < 50; i++) { + sprintf((char *) str,"%d - %s",i,(char *) scen_strs[60 + i * 2]); + set_rb(i,10000 + i,(char *) str,0); + } + if (draw_full == TRUE) + redraw_screen(); + else for (i = 0; i < NRSONPAGE; i++) + draw_rb_slot(i,0); + set_lb(NLS - 3,0,"",1); +} + +// mode 0 - scen 1 - out 2 - town +// if just_redo_text not 0, simply need to update text portions +void start_string_editing(short mode,short just_redo_text) +{ + short i,pos; + char str[256]; + short num_strs[3] = {260,108,140}; + Boolean draw_full = FALSE; + + if (just_redo_text == 0) { + if (overall_mode < 60) + set_up_main_screen(); + if (overall_mode == 62) + draw_full = TRUE; + overall_mode = 60; + ShowScrollBar(right_sbar,SB_CTL,TRUE); + SetScrollPos(right_sbar,SB_CTL,0,TRUE); + + reset_rb(); + SetScrollRange(right_sbar,SB_CTL,0,num_strs[mode] - NRSONPAGE,TRUE); + + } + for (i = 0; i < num_strs[mode]; i++) { + switch (mode) { + case 0: + if (i < 160) + sprintf((char *) str,"%d - %-30.30s",i,(char *) scen_strs[i]); + else sprintf((char *) str,"%d - %-30.30s",i,(char *) scen_strs2[i - 160]); + set_rb(i,7000 + i,(char *) str,0); + break; + case 1: + sprintf((char *) str,"%d - %-30.30s",i,(char *) data_store->out_strs[i]); + set_rb(i,8000 + i,(char *) str,0); + break; + case 2: + sprintf((char *) str,"%d - %-30.30s",i,(char *) town_strs[i]); + set_rb(i,9000 + i,(char *) str,0); + break; + } + } + + pos = GetScrollPos(right_sbar,SB_CTL); + if (draw_full == TRUE) + redraw_screen(); + else for (i = 0; i < NRSONPAGE; i++) + draw_rb_slot(i + pos,0); + set_lb(NLS - 3,1,"Control-click to clear",1); +} + +// mode 0 - scen 1 - out 2 - town +// if just_redo_text not 0, simply need to update text portions +void start_special_editing(short mode,short just_redo_text) +{ + short i; + char str[256],s2[256]; + short num_specs[3] = {256,60,100}; + Boolean draw_full = FALSE; + + if (just_redo_text == 0) { + if (overall_mode < 60) + set_up_main_screen(); + if (overall_mode == 62) + draw_full = TRUE; + overall_mode = 60; + ShowScrollBar(right_sbar,SB_CTL,TRUE); + + reset_rb(); + SetScrollRange(right_sbar,SB_CTL,0,num_specs[mode] - NRSONPAGE,TRUE); + + } + + for (i = 0; i < num_specs[mode]; i++) { + switch (mode) { + case 0: + get_str(s2,22,scenario.scen_specials[i].type + 1); + sprintf((char *) str,"%d - %-30.30s",i,(char *) s2); + set_rb(i,4000 + i,(char *) str,0); + break; + case 1: + get_str(s2,22,current_terrain.specials[i].type + 1); + sprintf((char *) str,"%d - %-30.30s",i,(char *) s2); + set_rb(i,5000 + i,(char *) str,0); + break; + case 2: + get_str(s2,22,town.specials[i].type + 1); + sprintf((char *) str,"%d - %-30.30s",i,(char *) s2); + set_rb(i,6000 + i,(char *) str,0); + break; + } + } + if (draw_full == TRUE) + redraw_screen(); + else for (i = 0; i < NRSONPAGE; i++) + draw_rb_slot(i,0); + set_lb(NLS - 3,1,"Control-click to clear",1); +} + +// if restoring is 1, this is just a redraw, so don't move scroll bar position +void start_dialogue_editing(short restoring) +{ + short i,j; + char str[256]; + char s[15] = " , "; + Boolean draw_full = FALSE; + + if (overall_mode < 60) + set_up_main_screen(); + if (overall_mode == 62) + draw_full = TRUE; + overall_mode = 60; + ShowScrollBar(right_sbar,SB_CTL,TRUE); + + if (restoring == 0) { + SetScrollPos(right_sbar,SB_CTL,0,TRUE); + reset_rb(); + SetScrollRange(right_sbar,SB_CTL,0,70 - NRSONPAGE,TRUE); + } + for (i = 0; i < 10; i++) { + sprintf((char *) str,"Personality %d - %s",i + cur_town * 10, + (char *) talk_strs[i]); + set_rb(i,13000 + i,(char *) str,0); + } + for (i = 0; i < 60; i++) { + for (j = 0; j < 4; j++) { + s[j] = talking.talk_nodes[i].link1[j]; + s[j + 6] = talking.talk_nodes[i].link2[j]; + } + sprintf((char *) str,"Node %d - Per. %d, %s",i, + talking.talk_nodes[i].personality,s); + set_rb(10 + i,12000 + i,(char *) str,0); + } + if (draw_full == TRUE) + redraw_screen(); + else for (i = 0; i < NRSONPAGE; i++) + draw_rb_slot(i,0); + set_lb(NLS - 3,0,"",1); +} + +Boolean save_check(short which_dlog) +{ + short choice; + + if (change_made == FALSE) + return TRUE; + change_made = FALSE; + choice = fancy_choice_dialog(which_dlog,0); + if (choice == 3) + return TRUE; + if (choice == 2) + return FALSE; + modify_lists(); + save_scenario(); + return TRUE; +} + +void update_item_menu() +{ + short i,j; + HMENU menu[13],big_menu; + char item_name[256]; + + big_menu = GetMenu(mainPtr); + + for (i = 0; i < 13; i++) + menu[i] = GetSubMenu(big_menu,5 + i); + +// for (i = 0; i < 400; i++) +// DeleteMenu(big_menu,600 + i,MF_BYCOMMAND); + + for (j = 0; j < 8; j++) { + for (i = 0; i < 50; i++) { + DeleteMenu(menu[j],0,MF_BYPOSITION); + } + if (overall_mode < 61) { + for (i = 0; i < 50; i++) { + sprintf((char *) item_name, "%d - %s",i + j * 50,scen_item_list.scen_items[i + j * 50].full_name); + if ((i % 25 == 0) && (i > 0)) + AppendMenu(menu[j],MF_MENUBREAK | MF_BYCOMMAND | MF_ENABLED | MF_STRING, 600 + (50 * j) + i, item_name); + else AppendMenu(menu[j],MF_BYCOMMAND | MF_ENABLED | MF_STRING, 600 + (50 * j) + i, item_name); + } + } + } + + for (j = 0; j < 5; j++) { + for (i = 0; i < 51; i++) { + DeleteMenu(menu[j + 8],0,MF_BYPOSITION); + } + if (overall_mode < 61) { + for (i = 0; i < 51; i++) { + sprintf((char *) item_name, "%d - %s",(51 * j) + i + 1,scen_item_list.monst_names[(51 * j) + i + 1]); + if ((i % 26 == 0) && (i > 0)) + AppendMenu(menu[j + 8],MF_MENUBREAK | MF_BYCOMMAND | MF_ENABLED | MF_STRING, 1001 + (51 * j) + i, item_name); + else AppendMenu(menu[j + 8],MF_BYCOMMAND | MF_ENABLED | MF_STRING, 1001 + (51 * j) + i, item_name); + } + } + } +/* + for (j = 0; j < 4; j++) { + for (i = 0; i < 50; i++) { + DeleteMenu(menu[j + 13],0,MF_BYPOSITION); + } + if (overall_mode < 61) { + for (i = 0; i < 50; i++) { + if ((i % 25 == 0) && (i > 0)) + AppendMenu(menu[j + 13],MF_MENUBREAK | MF_BYCOMMAND | MF_ENABLED | MF_STRING,1400 + (50 * j) + i, item_name); + else + AppendMenu(menu[j + 13],MF_BYCOMMAND | MF_ENABLED | MF_STRING, 1400 + (50 * j) + i, item_name); + if ((i + 50 * j) < scenario.num_towns) { + load_town(i + 50 * j); + sprintf((char *) item_name, "%d - %s",i + j * 50,town_strs[0]); + } + if ((i + 50 * j) >= scenario.num_towns) { + sprintf((char *) item_name, "%d - Town does not exist",i + j * 50); + } + } + } + } + +*/ +} + diff --git a/Win32/Scenarios Editor/TACTIONS.H b/Win32/Scenarios Editor/TACTIONS.H new file mode 100644 index 00000000..eb938903 --- /dev/null +++ b/Win32/Scenarios Editor/TACTIONS.H @@ -0,0 +1,60 @@ +void init_screen_locs(); +Boolean handle_action(POINT the_point, WPARAM wparam, LPARAM lparam); +void flash_rect(RECT to_flash); +void swap_terrain(); +void set_new_terrain(unsigned char selected_terrain); +Boolean handle_syskeystroke(WPARAM wparam, LPARAM lparam,short *handled); +Boolean handle_keystroke(WPARAM wparam, LPARAM lparam); +preset_item_type edit_item(preset_item_type item); +void modify_lists(); +void set_up_lights(); +Boolean is_wall(short i,short j); +Boolean is_correctable_wall(short i,short j); +Boolean is_mountain(short i,short j); +Boolean is_hill(short i,short j); +Boolean is_hill_or_mountain(short i,short j); +Boolean is_water(short i,short j); +Boolean is_correctable_water(short i,short j); +void shy_change_circle_terrain(location center,short radius,unsigned char terrain_type,short probability); +void change_circle_terrain(location center,short radius,unsigned char terrain_type,short probability); +void change_rect_terrain(RECT r,unsigned char terrain_type,short probability,Boolean hollow); +void frill_up_terrain(); +void unfrill_terrain(); +void set_terrain(location l,unsigned char terrain_type); +Boolean fix_rubble(location l); +Boolean fix_cave(location l); +Boolean fix_mountain(location l); +Boolean fix_hill(location l); +Boolean fix_water(location l); +Boolean out_fix_rubble(location l); +Boolean out_fix_cave(location l); +Boolean out_fix_mountain(location l); +Boolean out_fix_hill(location l); +Boolean out_fix_water(location l); +void adjust_space(location l); +Boolean is_lava(short x,short y); +unsigned char coord_to_ter(short x,short y); +short get_obscurity(short x,short y); +short can_see(location p1,location p2,short mode); +Boolean place_item(location spot_hit,short which_item,short property,short always,short odds); +void place_items_in_town(); +void set_up_start_screen(); +void set_up_main_screen(); +void start_town_edit(); +void start_out_edit(); +void shut_down_menus(short mode); +void start_terrain_editing(); +void start_monster_editing(short just_redo_text); +void start_item_editing(short just_redo_text); +void start_special_item_editing(); +void start_string_editing(short mode,short just_redo_text); +void start_special_editing(short mode,short just_redo_text); +void town_entry(location spot_hit); +void start_dialogue_editing(short restoring); +Boolean is_erasable_water(short i,short j); + +Boolean monst_on_space(location loc,short m_num); +void place_edit_special(location loc); +void set_special(location spot_hit); +Boolean save_check(short which_dlog); +void update_item_menu(); diff --git a/Win32/Scenarios Editor/TFILEIO.CPP b/Win32/Scenarios Editor/TFILEIO.CPP new file mode 100644 index 00000000..860d6adf --- /dev/null +++ b/Win32/Scenarios Editor/TFILEIO.CPP @@ -0,0 +1,2263 @@ +#include +#include +#include "string.h" +#include "Global.h" +#include "stdio.h" +#include "tfileio.h" +#include "keydlgs.h" +#include "graphics.h" +#include "scenario.h" +#include "edsound.h" +#include "graphutl.h" + +#define DONE_BUTTON_ITEM 1 +#define NIL 0L + +extern char szBladBase[128]; // blscened.cpp + +extern scenario_data_type scenario; +extern HDC main_dc; + +ave_tr_type ave_t; +tiny_tr_type tiny_t; + scenario_data_type *temp_scenario; + +HWND the_dialog; +extern HWND mainPtr; +extern town_record_type town; +extern big_tr_type t_d; +extern short town_type, max_dim[3]; // 0 - big 1 - ave 2 - small +extern short cur_town,overall_mode; +extern location cur_out; +extern piles_of_stuff_dumping_type *data_store; +extern talking_record_type talking; +extern outdoor_record_type current_terrain; +extern unsigned char borders[4][50]; +extern Boolean change_made; +extern scen_item_data_type scen_item_list; +extern char scen_strs[160][256]; +extern char scen_strs2[110][256]; +extern char talk_strs[170][256]; +extern char town_strs[180][256]; +extern HBITMAP spec_scen_g; +extern HBITMAP spec_scen_zoom_g; +extern char current_string[256] ; +short specials_res_id,data_dump_file_id; +char start_name[256]; +short start_volume,data_volume,jl = 0; +long start_dir,data_dir; +// outdoor_record_type current_terrain; +Boolean cur_scen_is_win = TRUE; +talking_record_type *dummy_talk_ptr; +town_record_type *dummy_town_ptr; +extern char file_path_name[256]; + +// Big waste! +char last_load_file[63] = "newscen.exs"; +char szFileName [128] = "newscen.exs"; +char szFileName2 [128] = "tempscen.exs"; +char szTitleName [128] = "newscen.exs"; +OPENFILENAME ofn; + OFSTRUCT store; +Boolean suppress_load_file_name = FALSE; + +void print_write_position (); + +void Get_Path(char* path){ + +char file_path[256]=""; // initialization +GetModuleFileName(NULL,file_path,256); // get path to the executable + +int i=255; // initialize the first while loop +while(file_path[i] != '\\') + { + i--; // find the last '\' in the path to the executable + } // in order to get rid of 'blades of exile.exe' + + +int j=0; // initialize the second loop + +for(j=0;jout_strs[i]); + + for (i = 0; i < 300; i++) + scenario.scen_str_len[i] = 0; + for (i = 0; i < 160; i++) + scenario.scen_str_len[i] = strlen(scen_strs[i]); + for (i = 160; i < 270; i++) + scenario.scen_str_len[i] = strlen(scen_strs2[i - 160]); + scenario.last_town_edited = cur_town; + scenario.last_out_edited = cur_out; + + // now write scenario data + scenario.flag1 = 20; + scenario.flag2 = 40; + scenario.flag3 = 60; + scenario.flag4 = 80; /// these mean made on PC + + len = sizeof(scenario_data_type); // scenario data + if ((error = FSWrite(dummy_f, &len, (char *) &scenario)) != 0) { + SysBeep(2); _lclose(scen_f); _lclose(dummy_f);oops_error(15); + return; + } + + len = sizeof(scen_item_data_type); // item data + if ((error = FSWrite(dummy_f, &len, (char *) &(scen_item_list))) != 0) { + SysBeep(2); _lclose(scen_f); _lclose(dummy_f);oops_error(16); + return; + } + for (i = 0; i < 270; i++) { // scenario strings + len = (long) scenario.scen_str_len[i]; + if ( i < 160) { + if ((error = FSWrite(dummy_f, &len, (char *) &(scen_strs[i]))) != 0) { + SysBeep(2); _lclose(scen_f); _lclose(dummy_f);oops_error(17); + return; + } + } + else { + if ((error = FSWrite(dummy_f, &len, (char *) &(scen_strs2[i - 160]))) != 0) { + SysBeep(2); _lclose(scen_f); _lclose(dummy_f);oops_error(17); + return; + } + } + } + + SetFPos(scen_f,1,scen_ptr_move); + + // OK ... scenario written. Now outdoors. + num_outdoors = scenario.out_width * scenario.out_height; + for (i = 0; i < num_outdoors; i++) + if (i == out_num) { + // write outdoors + for (j = 0; j < 180; j++) + current_terrain.strlens[j] = 0; + for (j = 0; j < 120; j++) + current_terrain.strlens[j] = strlen(data_store->out_strs[j]); + len = sizeof(outdoor_record_type); + error = FSWrite(dummy_f, &len, (char *) ¤t_terrain); + if (error != 0) {_lclose(scen_f); _lclose(dummy_f);oops_error(18);} + + for (j = 0; j < 120; j++) { + len = (long) current_terrain.strlens[j]; + FSWrite(dummy_f, &len, (char *) &(data_store->out_strs[j])); + } + + SetFPos(scen_f,3,save_out_size); + } + else { + len = (long) (scenario.out_data_size[i][0]) + (long) (scenario.out_data_size[i][1]); + error = FSRead(scen_f, &len, buffer); + dummy_out_ptr = (outdoor_record_type *) buffer; + port_out(dummy_out_ptr); + if (error != 0) {_lclose(scen_f); _lclose(dummy_f);oops_error(19);} + if ((error = FSWrite(dummy_f, &len, buffer)) != 0) { + SysBeep(2); _lclose(scen_f); _lclose(dummy_f);oops_error(20); + return; + } + } + + // now, finally, write towns. + for (k = 0; k < scenario.num_towns; k++) + if (k == cur_town) { + for (i = 0; i < 180; i++) + town.strlens[i] = 0; + for (i = 0; i < 140; i++) + town.strlens[i] = strlen(town_strs[i]); + + // write towns + len = sizeof(town_record_type); + error = FSWrite(dummy_f, &len, (char *) &town); + if (error != 0) {_lclose(scen_f); _lclose(dummy_f);oops_error(21);} + + switch (scenario.town_size[cur_town]) { + case 0: + len = sizeof(big_tr_type); + FSWrite(dummy_f, &len, (char *) &t_d); + break; + + case 1: + for (i = 0; i < 48; i++) + for (j = 0; j < 48; j++) { + ave_t.terrain[i][j] = t_d.terrain[i][j]; + ave_t.lighting[i / 8][j] = t_d.lighting[i / 8][j]; + } + for (i = 0; i < 16; i++) { + ave_t.room_rect[i] = t_d.room_rect[i]; + } + for (i = 0; i < 40; i++) { + ave_t.creatures[i] = t_d.creatures[i]; + } + len = sizeof(ave_tr_type); + FSWrite(dummy_f, &len, (char *) &ave_t); + break; + + + case 2: + for (i = 0; i < 32; i++) + for (j = 0; j < 32; j++) { + tiny_t.terrain[i][j] = t_d.terrain[i][j]; + tiny_t.lighting[i / 8][j] = t_d.lighting[i / 8][j]; + } + for (i = 0; i < 16; i++) { + tiny_t.room_rect[i] = t_d.room_rect[i]; + } + for (i = 0; i < 30; i++) { + tiny_t.creatures[i] = t_d.creatures[i]; + } + len = sizeof(tiny_tr_type); + FSWrite(dummy_f, &len, (char *) &tiny_t); + break; + } + for (j = 0; j < 140; j++) { + len = (long) town.strlens[j]; + FSWrite(dummy_f, &len, (char *) &(town_strs[j])); + } + + for (i = 0; i < 200; i++) + talking.strlens[i] = 0; + for (i = 0; i < 170; i++) + talking.strlens[i] = strlen(talk_strs[i]); + len = sizeof(talking_record_type); + error = FSWrite(dummy_f, &len, (char *) &talking); + if (error != 0) {_lclose(scen_f); _lclose(dummy_f);oops_error(22);} + for (j = 0; j < 170; j++) { + len = (long) talking.strlens[j]; + FSWrite(dummy_f, &len, (char *) &(talk_strs[j])); + } + + SetFPos(scen_f,3,save_town_size); + } + else { /// load unedited town into buffer and save, doing translataions when necessary + + len = (long) (sizeof(town_record_type)); + error = FSRead(scen_f, &len, buffer); + if (error != 0) {_lclose(scen_f); _lclose(dummy_f);oops_error(24);} + dummy_town_ptr = (town_record_type *) buffer; + port_dummy_town(); + if ((error = FSWrite(dummy_f, &len, buffer)) != 0) {_lclose(scen_f); _lclose(dummy_f);oops_error(23);return;} + + if (scenario.town_size[k] == 0) + len = (long) ( sizeof(big_tr_type)); + else if (scenario.town_size[k] == 1) + len = (long) ( sizeof(ave_tr_type)); + else len = (long) ( sizeof(tiny_tr_type)); + error = FSRead(scen_f, &len, buffer); + if (error != 0) {_lclose(scen_f); _lclose(dummy_f);oops_error(24);} + port_dummy_t_d(scenario.town_size[k],buffer); + if ((error = FSWrite(dummy_f, &len, buffer)) != 0) {_lclose(scen_f); _lclose(dummy_f);oops_error(23);return;} + + len = (long) (scenario.town_data_size[k][1]) + + (long) (scenario.town_data_size[k][2]); + error = FSRead(scen_f, &len, buffer); + if (error != 0) {_lclose(scen_f); _lclose(dummy_f);oops_error(24);} + if ((error = FSWrite(dummy_f, &len, buffer)) != 0) {_lclose(scen_f); _lclose(dummy_f);oops_error(23);return;} + + len = (long) (scenario.town_data_size[k][3]); + error = FSRead(scen_f, &len, buffer); + if (error != 0) {_lclose(scen_f); _lclose(dummy_f);oops_error(24);} + dummy_talk_ptr = (talking_record_type *) buffer; + port_dummy_talk_nodes(); + if ((error = FSWrite(dummy_f, &len, buffer)) != 0) {_lclose(scen_f); _lclose(dummy_f);oops_error(23);return;} + len = (long) (scenario.town_data_size[k][4]); + error = FSRead(scen_f, &len, buffer); + if (error != 0) {_lclose(scen_f); _lclose(dummy_f);oops_error(24);} + if ((error = FSWrite(dummy_f, &len, buffer)) != 0) {_lclose(scen_f); _lclose(dummy_f);oops_error(23);return;} + } + + change_made = FALSE; + + + // now, everything is moved over. Delete the original, and move everything from the + // dummy into a new original + error = _lclose(scen_f); + if (error != 0) {_lclose(scen_f); _lclose(dummy_f);oops_error(25);} + cur_scen_is_win = TRUE; + + if (OpenFile(szFileName,&store,OF_DELETE) == HFILE_ERROR) { + oops_error(101); + return; + } + if (-1 == (scen_f = _lcreat(szFileName,0))) { + oops_error(100); + return; + } + total_file_size = _llseek(dummy_f,0,2); + SetFPos(dummy_f,1,0); + + while (total_file_size > 0) { + if (total_file_size >= 60000) + len = 60000; + else len = total_file_size; + error = FSRead(dummy_f, &len, buffer); + if (error != 0) {_lclose(scen_f); _lclose(dummy_f);oops_error(102);} + if ((error = FSWrite(scen_f, &len, buffer)) != 0) {_lclose(scen_f); _lclose(dummy_f);oops_error(103);return;} + total_file_size -= len; + } + error = _lclose(dummy_f); + error = _lclose(scen_f); + if (error != 0) {_lclose(scen_f); _lclose(dummy_f);oops_error(26);} + OpenFile(szFileName2,&store,OF_DELETE); + GlobalUnlock(temp_buffer); + GlobalFree(temp_buffer); + +} + +void load_scenario() +{ + short i,j,k,l; + Boolean file_ok = FALSE; + HANDLE file_id; + short error; + DWORD dwByteRead, len; + + ofn.hwndOwner = mainPtr; + ofn.lpstrFile = szFileName; + ofn.lpstrFileTitle = szTitleName; + ofn.Flags = 0; + + if (GetOpenFileName(&ofn) == 0) + return; + + SetCurrentDirectory(file_path_name); + + file_id = CreateFile(szFileName, GENERIC_READ, FILE_SHARE_READ, NULL, + OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (file_id == INVALID_HANDLE_VALUE) + { + oops_error(28); + beep(); + return; + } + + if (ReadFile(file_id, &scenario, sizeof(scenario_data_type), &dwByteRead, NULL) == FALSE) + { + CloseHandle(file_id); + oops_error(30); + return; + } + + if ((scenario.flag1 == 10) && (scenario.flag2 == 20) + && (scenario.flag3 == 30) + && (scenario.flag4 == 40)) { + cur_scen_is_win = FALSE; + file_ok = TRUE; + port_scenario(); + } + if ((scenario.flag1 == 20) && (scenario.flag2 == 40) + && (scenario.flag3 == 60) + && (scenario.flag4 == 80)) { + + cur_scen_is_win = TRUE; + file_ok = TRUE; + } + if (file_ok == FALSE) { + CloseHandle(file_id); + give_error("This is not a legitimate Blades of Exile scenario.","",0); + return; + } + + len = sizeof(scen_item_data_type); // item data + + if (ReadFile(file_id, &scen_item_list, sizeof(scen_item_data_type), &dwByteRead, NULL) == FALSE) + { + CloseHandle(file_id); + oops_error(30); + return; + } + + port_item_list(); + for (i = 0; i < 270; i++) { + len = scenario.scen_str_len[i]; + if (i < 160) { + ReadFile(file_id, &(scen_strs[i]), len, &dwByteRead, NULL); + scen_strs[i][len] = 0; + } + else { + ReadFile(file_id, &(scen_strs2[i - 160]), len, &dwByteRead, NULL); + scen_strs2[i - 160][len] = 0; + } + } + + CloseHandle(file_id); + + //store_file_reply = file_to_load; + overall_mode = 60; + change_made = FALSE; + load_town(scenario.last_town_edited); + //load_town(0); + load_outdoors(scenario.last_out_edited,0); + load_spec_graphics(); + augment_terrain(scenario.last_out_edited); +} + +//extern GWorldPtr spec_scen_g; +void load_spec_graphics() +{ + short i,file_num; + char file_name[256]; + + if (spec_scen_g != NULL) { + DeleteObject(spec_scen_g); + spec_scen_g = NULL; + } + + //build_scen_file_name(file_name); + sprintf(file_name,"%s",szFileName); + for (i = 0; i < 256; i++) { + if (file_name[i] == '.') { + file_name[i + 1] = 'b'; + file_name[i + 2] = 'm'; + file_name[i + 3] = 'p'; + i = 256; + } + } + suppress_load_file_name = TRUE; + spec_scen_g = ReadBMP(file_name); + suppress_load_file_name = FALSE; + + +/* if (spec_scen_zoom_g != NULL) { + DeleteObject(spec_scen_zoom_g); + spec_scen_zoom_g = NULL; + } + + //build_scen_file_name(file_name); + sprintf(file_name,"%szoom",szFileName); + for (i = 0; i < 256; i++) { + if (file_name[i] == '.') { + file_name[i + 1] = 'b'; + file_name[i + 2] = 'm'; + file_name[i + 3] = 'p'; + i = 256; + } + } + suppress_load_file_name = TRUE; + spec_scen_zoom_g = ReadBMP(file_name); + suppress_load_file_name = FALSE; + */ +} + + +void augment_terrain(location to_create) +{ + location to_load; + short i,j; + + for (i = 0 ; i < 4; i++) + for (j = 0 ; j < 50; j++) + borders[i][j] = 90; + + to_load = to_create; + if (to_create.y > 0) { + to_load.y--; + load_outdoors(to_load, 1); + } + to_load = to_create; + if (to_create.y < scenario.out_height - 1) { + to_load.y++; + load_outdoors(to_load, 3); + } + + to_load = to_create; + if (to_create.x < scenario.out_width - 1) { + to_load.x++; + load_outdoors(to_load, 2); + } + to_load = to_create; + if (to_create.x > 0) { + to_load.x--; + load_outdoors(to_load, 4); + } +} + +//mode -> 0 - primary load 1 - add to top 2 - right 3 - bottom 4 - left +void load_outdoors(location which_out,short mode) +{ + short i,j,k,file_id; + long len,len_to_jump,store; + short out_sec_num; + outdoor_record_type store_out; + short error; + + if (overall_mode == 61) + return; + + file_id = _lopen(szFileName,OF_READ | OF_SHARE_DENY_WRITE); + if (file_id == HFILE_ERROR) { + oops_error(31); + beep(); + return; + } + + out_sec_num = scenario.out_width * which_out.y + which_out.x; + + len_to_jump = sizeof(scenario_data_type); + len_to_jump += sizeof(scen_item_data_type); + for (i = 0; i < 300; i++) + len_to_jump += (long) scenario.scen_str_len[i]; + store = 0; + for (i = 0; i < out_sec_num; i++) + for (j = 0; j < 2; j++) + store += (long) (scenario.out_data_size[i][j]); + len_to_jump += store; + + error = SetFPos (file_id, 1, len_to_jump); + if (error != 0) {_lclose(file_id);oops_error(32);} + + len = sizeof(outdoor_record_type); + error = FSRead(file_id, &len, (char *) &store_out); + if (error != 0) {_lclose(file_id);oops_error(33);} + + if (mode == 0) { + current_terrain = store_out; + port_out(¤t_terrain); + for (i = 0; i < 120; i++) { + len = (long) (current_terrain.strlens[i]); + FSRead(file_id, &len, (char *) &(data_store->out_strs[i])); + data_store->out_strs[i][len] = 0; + } + cur_out = which_out; + } + + if (mode == 1) + for (j = 0; j < 48; j++) { + borders[0][j] = store_out.terrain[j][47]; + } + if (mode == 2) + for (j = 0; j < 48; j++) { + borders[1][j] = store_out.terrain[0][j]; + } + if (mode == 3) + for (j = 0; j < 48; j++) { + borders[2][j] = store_out.terrain[j][0]; + } + if (mode == 4) + for (j = 0; j < 48; j++) { + borders[3][j] = store_out.terrain[47][j]; + } + + + error = _lclose(file_id); + if (error != 0) {_lclose(file_id);oops_error(33);} + +} + +void load_town(short which_town) +{ + short i,j,k,file_id; + long len,len_to_jump = 0,store; + short error; + + + if (overall_mode == 61) + return; + + file_id = _lopen(szFileName,OF_READ | OF_SHARE_DENY_WRITE); + if (file_id == HFILE_ERROR) { + oops_error(34); + beep(); + return; + } + + len_to_jump = sizeof(scenario_data_type); + len_to_jump += sizeof(scen_item_data_type); + for (i = 0; i < 300; i++) + len_to_jump += (long) scenario.scen_str_len[i]; + store = 0; + for (i = 0; i < 100; i++) + for (j = 0; j < 2; j++) + store += (long) (scenario.out_data_size[i][j]); + for (i = 0; i < which_town; i++) + for (j = 0; j < 5; j++) + store += (long) (scenario.town_data_size[i][j]); + len_to_jump += store; + + error = SetFPos (file_id, 1, len_to_jump); + if (error != 0) {_lclose(file_id);oops_error(35);} + + len = sizeof(town_record_type); + + error = FSRead(file_id, &len , (char *) &town); + port_town(); + if (error != 0) {_lclose(file_id);oops_error(36);} + + switch (scenario.town_size[which_town]) { + case 0: + len = sizeof(big_tr_type); + FSRead(file_id, &len, (char *) &t_d); + port_t_d(); + break; + + case 1: + len = sizeof(ave_tr_type); + FSRead(file_id, &len, (char *) &ave_t); + for (i = 0; i < 48; i++) + for (j = 0; j < 48; j++) { + t_d.terrain[i][j] = ave_t.terrain[i][j]; + t_d.lighting[i / 8][j] = ave_t.lighting[i / 8][j]; + } + for (i = 0; i < 16; i++) { + t_d.room_rect[i] = ave_t.room_rect[i]; + } + for (i = 0; i < 40; i++) { + t_d.creatures[i] = ave_t.creatures[i]; + } + port_t_d(); + for (i = 40; i < 60; i++) { + t_d.creatures[i].number = 0; + } + break; + + case 2: + len = sizeof(tiny_tr_type); + FSRead(file_id,&len , (char *) &tiny_t); + for (i = 0; i < 32; i++) + for (j = 0; j < 32; j++) { + t_d.terrain[i][j] = tiny_t.terrain[i][j]; + t_d.lighting[i / 8][j] = tiny_t.lighting[i / 8][j]; + } + for (i = 0; i < 16; i++) { + t_d.room_rect[i] = tiny_t.room_rect[i]; + } + for (i = 0; i < 30; i++) { + t_d.creatures[i] = tiny_t.creatures[i]; + } + port_t_d(); + for (i = 30; i < 60; i++) { + t_d.creatures[i].number = 0; + } + break; + } + + + for (i = 0; i < 140; i++) { + len = (long) (town.strlens[i]); + FSRead(file_id, &len, (char *) &(town_strs[i])); + town_strs[i][len] = 0; + } + + len = sizeof(talking_record_type); + error = FSRead(file_id, &len , (char *) &talking); + if (error != 0) {_lclose(file_id);oops_error(37);} + port_talk_nodes(); + + for (i = 0; i < 170; i++) { + len = (long) (talking.strlens[i]); + FSRead(file_id, &len, (char *) &(talk_strs[i])); + talk_strs[i][len] = 0; + } + + town_type = scenario.town_size[which_town]; + cur_town = which_town; + error = _lclose(file_id); + if (error != 0) {_lclose(file_id);oops_error(38);} +} + +// if which_town is -1, load town from base +void import_town(short which_town) +{ + short i,j,k,l; + HFILE file_id; + Boolean file_ok = FALSE; + short error; + long len,len_to_jump = 0,store; + DWORD buf_len = 100000; + char *buffer = NULL; + char szFileName3 [128] = "scen.exs"; + HGLOBAL temp_buffer; + + if (which_town >= 0) { + ofn.hwndOwner = mainPtr; + ofn.lpstrFile = szFileName3; + ofn.lpstrFileTitle = szTitleName; + ofn.Flags = 0; + + if (GetOpenFileName(&ofn) == 0) + return; + } + else { +// sprintf((char *) szFileName3,".\\scenarios\\BLADBASE.EXS"); + strncpy(szFileName3, szBladBase, 128); + which_town = 0; + } + + SetCurrentDirectory(file_path_name); + + file_id = _lopen(szFileName3,OF_READ | OF_SHARE_DENY_WRITE); + if (file_id == HFILE_ERROR) { + oops_error(42); beep(); + return; + } + + temp_buffer = GlobalAlloc(GMEM_FIXED,buf_len); + if (temp_buffer == NULL) { + _lclose(file_id); oops_error(41); + return; + } + buffer = (char *) GlobalLock(temp_buffer); + if (buffer == NULL) { + _lclose(file_id); oops_error(41); + return; + } + + len = (long) sizeof(scenario_data_type); + if ((error = FSRead(file_id, &len, buffer)) != 0){ + _lclose(file_id); oops_error(43); return; + } + temp_scenario = (scenario_data_type *) buffer; + + if (temp_scenario->town_size[which_town] != scenario.town_size[cur_town]) { + give_error("Oops ... the town in the selected scenario and the current town are different sizes. Import failed.","",0); + GlobalUnlock(temp_buffer); GlobalFree(temp_buffer); _lclose(file_id); + return; + } + if (which_town >= temp_scenario->num_towns) { + give_error("Oops ... the selected scenario doesn't have enough towns. The town you selected doesn't exist inside this scenario.","",0); + GlobalUnlock(temp_buffer); GlobalFree(temp_buffer); _lclose(file_id); + return; + } + + if ((temp_scenario->flag1 == 20) && (temp_scenario->flag2 == 40) + && (temp_scenario->flag3 == 60) + && (temp_scenario->flag4 == 80)) { + file_ok = TRUE; + } + if (file_ok == FALSE) { + GlobalUnlock(temp_buffer); GlobalFree(temp_buffer); _lclose(file_id); give_error("This is not a legitimate Blades of Exile scenario. If it is a scenario, note that it needs to have been saved by the Windows scenario editor.","",0); return; + } + + len_to_jump = sizeof(scenario_data_type); + len_to_jump += sizeof(scen_item_data_type); + for (i = 0; i < 300; i++) + len_to_jump += (long) temp_scenario->scen_str_len[i]; + store = 0; + for (i = 0; i < 100; i++) + for (j = 0; j < 2; j++) + store += (long) (temp_scenario->out_data_size[i][j]); + for (i = 0; i < which_town; i++) + for (j = 0; j < 5; j++) + store += (long) (temp_scenario->town_data_size[i][j]); + len_to_jump += store; + error = SetFPos (file_id, 1, len_to_jump); + if (error != 0) {_lclose(file_id);oops_error(44);} + + len = sizeof(town_record_type); + error = FSRead(file_id, &len , (char *) &town); + if (error != 0) {_lclose(file_id);oops_error(45);} + + switch (temp_scenario->town_size[which_town]) { + case 0: + len = sizeof(big_tr_type); + FSRead(file_id, &len, (char *) &t_d); + break; + + case 1: + len = sizeof(ave_tr_type); + FSRead(file_id, &len, (char *) &ave_t); + for (i = 0; i < 48; i++) + for (j = 0; j < 48; j++) { + t_d.terrain[i][j] = ave_t.terrain[i][j]; + t_d.lighting[i / 8][j] = ave_t.lighting[i / 8][j]; + } + for (i = 0; i < 16; i++) { + t_d.room_rect[i] = ave_t.room_rect[i]; + } + for (i = 0; i < 40; i++) { + t_d.creatures[i] = ave_t.creatures[i]; + } + for (i = 40; i < 60; i++) { + t_d.creatures[i].number = 0; + } + break; + + case 2: + len = sizeof(tiny_tr_type); + FSRead(file_id,&len , (char *) &tiny_t); + for (i = 0; i < 32; i++) + for (j = 0; j < 32; j++) { + t_d.terrain[i][j] = tiny_t.terrain[i][j]; + t_d.lighting[i / 8][j] = tiny_t.lighting[i / 8][j]; + } + for (i = 0; i < 16; i++) { + t_d.room_rect[i] = tiny_t.room_rect[i]; + } + for (i = 0; i < 30; i++) { + t_d.creatures[i] = tiny_t.creatures[i]; + } + for (i = 30; i < 60; i++) { + t_d.creatures[i].number = 0; + } + break; + } + + for (i = 0; i < 140; i++) { + len = (long) (town.strlens[i]); + FSRead(file_id, &len, (char *) &(town_strs[i])); + town_strs[i][len] = 0; + } + + len = sizeof(talking_record_type); + error = FSRead(file_id, &len , (char *) &talking); + if (error != 0) {_lclose(file_id);oops_error(46);} + + for (i = 0; i < 170; i++) { + len = (long) (talking.strlens[i]); + FSRead(file_id, &len, (char *) &(talk_strs[i])); + talk_strs[i][len] = 0; + } + + error = _lclose(file_id); + if (error != 0) {_lclose(file_id);oops_error(47);} + GlobalUnlock(temp_buffer); + GlobalFree(temp_buffer); +} + +// When this is called, the current town is the town to make town 0. +void make_new_scenario(char *file_name,short out_width,short out_height,short making_warriors_grove, + short use_grass,char *title) +{ + short i,j,k,num_outdoors; + HFILE dummy_f,file_id; + DWORD buf_len = 100000; + short error; + short out_num; + long len,scen_ptr_move = 0,save_town_size = 0,save_out_size = 0; + location loc; + short x,y; + HGLOBAL temp_buffer; + char *buffer; + + // Step 1 - load scenario file from scenario base. It contains all the monsters and + // items done up properly! +// if (HFILE_ERROR == (file_id = _lopen(".\\scenarios\\BLADBASE.EXS", OF_READ | OF_SHARE_EXCLUSIVE))) { + if (HFILE_ERROR == (file_id = _lopen(szBladBase, OF_READ | OF_SHARE_EXCLUSIVE))) { + //give_error("Could not find the file 'Blades of Exile Base', which needs to be in the Scenario Editor folder. If you no longer have it, you need to redownload Blades of Exile.","",0); + give_error("The Blades Editor is having trouble finding the file 'bladbase.exs'.", + "Please check approporiate settings in 'blades.ini'.",0); + file_name[0] = 0; + return; + } + +// strcpy((char *) szFileName, file_name); + sprintf(szFileName, "scenarios\\%s", file_name); + + temp_buffer = GlobalAlloc(GMEM_FIXED,buf_len); + if (temp_buffer == NULL) { + _lclose(file_id); oops_error(114); + return; + } + buffer = (char *) GlobalLock(temp_buffer); + if (buffer == NULL) { + _lclose(file_id); oops_error(114); + return; + } + + len = (long) sizeof(scenario_data_type); + if ((error = FSRead(file_id, &len, (char *) &scenario)) != 0){ + _lclose(file_id); oops_error(82); return; + } + + len = sizeof(scen_item_data_type); // item data + if ((error = FSRead(file_id, &len, (char *) &(scen_item_list))) != 0){ + _lclose(file_id); oops_error(83); return; + } + for (i = 0; i < 270; i++) { + len = (long) (scenario.scen_str_len[i]); + if (i < 160) { + FSRead(file_id, &len, (char *) &(scen_strs[i])); + scen_strs[i][len] = 0; + } + else { + FSRead(file_id, &len, (char *) &(scen_strs2[i - 160])); + scen_strs2[i - 160][len] = 0; + } + } + strcpy((char *) scen_strs[0],(char *) title); + scenario.scen_str_len[0] = strlen(title); + scen_strs[0][scenario.scen_str_len[0]] = 0; + _lclose(file_id); + + //OK. FIrst find out what file name we're working with, and make the dummy file + // which we'll build the new scenario in Blades of Exile Base + if (HFILE_ERROR == (dummy_f = _lcreat(szFileName, 0))) { + oops_error(111); + return; + } + + + scenario.prog_make_ver[0] = 1; + scenario.prog_make_ver[1] = 0; + scenario.prog_make_ver[2] = 0; + cur_town = 0; + town_type = 1; + scenario.num_towns = 1; + scenario.town_size[0] = 1; + scenario.out_width = out_width; + scenario.out_height = out_height; + cur_out.x = 0; + cur_out.y = 0; + scenario.last_out_edited = cur_out; + + // We're finally set up. Let's first set up the new scenario field + // We need the new info for the current town and outdoors, which may have been changed + scenario.town_data_size[cur_town][0] = sizeof(town_record_type); + if (scenario.town_size[cur_town] == 0) + scenario.town_data_size[cur_town][0] += sizeof(big_tr_type); + else if (scenario.town_size[cur_town] == 1) + scenario.town_data_size[cur_town][0] += sizeof(ave_tr_type); + else scenario.town_data_size[cur_town][0] += sizeof(tiny_tr_type); + scenario.town_data_size[cur_town][1] = 0; + for (i = 0; i < 60; i++) + scenario.town_data_size[cur_town][1] += strlen(town_strs[i]); + scenario.town_data_size[cur_town][2] = 0; + for (i = 60; i < 140; i++) + scenario.town_data_size[cur_town][2] += strlen(town_strs[i]); + scenario.town_data_size[cur_town][3] = sizeof(talking_record_type); + for (i = 0; i < 80; i++) + scenario.town_data_size[cur_town][3] += strlen(talk_strs[i]); + scenario.town_data_size[cur_town][4] = 0; + for (i = 80; i < 170; i++) + scenario.town_data_size[cur_town][4] += strlen(talk_strs[i]); + + num_outdoors = scenario.out_width * scenario.out_height; + for (i = 0; i < num_outdoors; i++) { + scenario.out_data_size[i][0] = sizeof(outdoor_record_type); + scenario.out_data_size[i][1] = 0; + for (j = 0; j < 120; j++) + scenario.out_data_size[i][1] += strlen(data_store->out_strs[j]); + } + + for (i = 0; i < 300; i++) + scenario.scen_str_len[i] = 0; + for (i = 0; i < 160; i++) + scenario.scen_str_len[i] = strlen(scen_strs[i]); + for (i = 160; i < 270; i++) + scenario.scen_str_len[i] = strlen(scen_strs2[i - 160]); + scenario.last_town_edited = cur_town; + scenario.last_out_edited = cur_out; + + // now write scenario data + scenario.flag1 = 20; + scenario.flag2 = 40; + scenario.flag3 = 60; + scenario.flag4 = 80; /// these mean made on mac + + len = sizeof(scenario_data_type); // scenario data + scen_ptr_move += len; + if ((error = FSWrite(dummy_f, &len, (char *) &scenario)) != 0) { + _lclose(dummy_f); + oops_error(3); + return; + } + len = sizeof(scen_item_data_type); // item data + scen_ptr_move += len; + if ((error = FSWrite(dummy_f, &len, (char *) &(scen_item_list))) != 0) { + _lclose(dummy_f); + oops_error(4); + return; + } + for (i = 0; i < 270; i++) { // scenario strings + len = (long) scenario.scen_str_len[i]; + scen_ptr_move += len; + if (i < 160) { + if ((error = FSWrite(dummy_f, &len, (char *) &(scen_strs[i]))) != 0) { + _lclose(dummy_f);oops_error(5); + return; + } + } + else { + if ((error = FSWrite(dummy_f, &len, (char *) &(scen_strs2[i - 160]))) != 0) { + _lclose(dummy_f);oops_error(5); + return; + } + } + } + + + // OK ... scenario written. Now outdoors. + num_outdoors = scenario.out_width * scenario.out_height; + for (i = 0; i < num_outdoors; i++) + { + loc.x = i % scenario.out_width; + loc.y = i / scenario.out_width; + + for (x = 0; x < 48; x++) + for (y = 0; y < 48; y++) { + current_terrain.terrain[x][y] = (use_grass > 0) ? 2 : 0; + + if ((x < 4) && (loc.x == 0)) + current_terrain.terrain[x][y] = (use_grass > 0) ? 22 : 5; + if ((y < 4) && (loc.y == 0)) + current_terrain.terrain[x][y] = (use_grass > 0) ? 22 : 5; + if ((x > 43) && (loc.x == scenario.out_width - 1)) + current_terrain.terrain[x][y] = (use_grass > 0) ? 22 : 5; + if ((y > 43) && (loc.y == scenario.out_height - 1)) + current_terrain.terrain[x][y] = (use_grass > 0) ? 22 : 5; + if ((i == 0) && (making_warriors_grove > 0)) { + current_terrain.terrain[24][24] = (use_grass > 0) ? 234 : 232; + current_terrain.exit_locs[0].x = 24; + current_terrain.exit_locs[0].y = 24; + current_terrain.exit_dests[0] = 0; + } + else current_terrain.exit_locs[0].x = 100; + } + + // write outdoors + for (j = 0; j < 180; j++) + current_terrain.strlens[j] = 0; + for (j = 0; j < 120; j++) + current_terrain.strlens[j] = strlen(data_store->out_strs[j]); + len = sizeof(outdoor_record_type); + error = FSWrite(dummy_f, &len, (char *) ¤t_terrain); + if (error != 0) {_lclose(dummy_f);oops_error(6);} + + for (j = 0; j < 120; j++) { + len = (long) current_terrain.strlens[j]; + error = FSWrite(dummy_f, &len, (char *) &(data_store->out_strs[j])); + if (error != 0) {_lclose(dummy_f);oops_error(7);} + } + + } + + + // now, finally, write towns. + for (k = 0; k < scenario.num_towns; k++) + { + for (i = 0; i < 180; i++) + town.strlens[i] = 0; + for (i = 0; i < 140; i++) + town.strlens[i] = strlen(town_strs[i]); + + // write towns + len = sizeof(town_record_type); + error = FSWrite(dummy_f, &len, (char *) &town); + if (error != 0) {_lclose(dummy_f);oops_error(8);} + + switch (scenario.town_size[cur_town]) { + case 0: + len = sizeof(big_tr_type); + FSWrite(dummy_f, &len, (char *) &t_d); + break; + + case 1: + for (i = 0; i < 48; i++) + for (j = 0; j < 48; j++) { + ave_t.terrain[i][j] = t_d.terrain[i][j]; + ave_t.lighting[i / 8][j] = t_d.lighting[i / 8][j]; + } + for (i = 0; i < 16; i++) { + ave_t.room_rect[i] = t_d.room_rect[i]; + } + for (i = 0; i < 40; i++) { + ave_t.creatures[i] = t_d.creatures[i]; + } + len = sizeof(ave_tr_type); + FSWrite(dummy_f, &len, (char *) &ave_t); + break; + + + case 2: + for (i = 0; i < 32; i++) + for (j = 0; j < 32; j++) { + tiny_t.terrain[i][j] = t_d.terrain[i][j]; + tiny_t.lighting[i / 8][j] = t_d.lighting[i / 8][j]; + } + for (i = 0; i < 16; i++) { + tiny_t.room_rect[i] = t_d.room_rect[i]; + } + for (i = 0; i < 30; i++) { + tiny_t.creatures[i] = t_d.creatures[i]; + } + len = sizeof(tiny_tr_type); + FSWrite(dummy_f, &len, (char *) &tiny_t); + break; + } + for (j = 0; j < 140; j++) { + len = (long) town.strlens[j]; + FSWrite(dummy_f, &len, (char *) &(town_strs[j])); + } + + for (i = 0; i < 200; i++) + talking.strlens[i] = 0; + for (i = 0; i < 170; i++) + talking.strlens[i] = strlen(talk_strs[i]); + len = sizeof(talking_record_type); + error = FSWrite(dummy_f, &len, (char *) &talking); + if (error != 0) {_lclose(dummy_f);oops_error(9);} + for (j = 0; j < 170; j++) { + len = (long) talking.strlens[j]; + FSWrite(dummy_f, &len, (char *) &(talk_strs[j])); + } + + } + + + change_made = TRUE; + // now, everything is moved over. Delete the original, and rename the dummy + error = _lclose(dummy_f); + if (error != 0) {_lclose(dummy_f);oops_error(10);} + + GlobalUnlock(temp_buffer); + GlobalFree(temp_buffer); +} + +void oops_error(short error) +{ + char error_str[256]; + + SysBeep(50); + SysBeep(50); + SysBeep(50); + sprintf((char *) error_str,"You may need more memory ... run the editor with no other programs running. Be sure to back your scenario up often. Error number: %d.",error); + give_error("The program encountered an error while loading/saving/creating the scenario. To prevent future problems, the program will now terminate. Trying again may solve the problem.",(char *) error_str,0); + PostQuitMessage(0); +} + +void start_data_dump() +{ + short i,j; + char get_text[280]; + HFILE data_dump_file_id; + long len; + location out_sec; + if (HFILE_ERROR == (data_dump_file_id = _lcreat("Scendata.txt", 0))) { + SysBeep(50); + return; + } + + SetFPos (data_dump_file_id, 2, 0); + + sprintf((char *)get_text,"Scenario data for %s:\n",scen_strs[0]); + len = (long) (strlen((char *)get_text)); + FSWrite(data_dump_file_id, &len, (char *) get_text); + sprintf((char *)get_text,"\nTerrain types for %s:\n",scen_strs[0]); + len = (long) (strlen((char *)get_text)); + FSWrite(data_dump_file_id, &len, (char *) get_text); + for (i = 0; i < 256; i++) { + sprintf((char *)get_text," Terrain type %d: %s\n",i,scen_item_list.ter_names[i]); + len = (long) (strlen((char *)get_text)); + FSWrite(data_dump_file_id, &len, (char *) get_text); + } + sprintf((char *)get_text,"\nMonster types for %s:\n",scen_strs[0]); + len = (long) (strlen((char *)get_text)); + FSWrite(data_dump_file_id, &len, (char *) get_text); + for (i = 0; i < 256; i++) { + sprintf((char *)get_text," Monster type %d: %s\n",i,scen_item_list.monst_names[i]); + len = (long) (strlen((char *)get_text)); + FSWrite(data_dump_file_id, &len, (char *) get_text); + } + sprintf((char *)get_text,"\nItem types for %s:\n",scen_strs[0]); + len = (long) (strlen((char *)get_text)); + FSWrite(data_dump_file_id, &len, (char *) get_text); + for (i = 0; i < 400; i++) { + sprintf((char *)get_text," Item type %d: %s\n",i,scen_item_list.scen_items[i].full_name); + len = (long) (strlen((char *)get_text)); + FSWrite(data_dump_file_id, &len, (char *) get_text); + } + sprintf((char *)get_text,"\n\nNames of the Outdoor Sections in %s:\n",scen_strs[0]); + len = (long) (strlen((char *)get_text)); + FSWrite(data_dump_file_id, &len, (char *) get_text); + for (out_sec.y = 0; out_sec.y < scenario.out_height ; out_sec.y++) + for (out_sec.x = 0; out_sec.x < scenario.out_width ; out_sec.x++) { + load_outdoors(out_sec,0); + sprintf((char *)get_text," Section X = %d, Y = %d: %s \n",(short) out_sec.x,(short) out_sec.y,data_store->out_strs[0]); + len = (long) (strlen((char *)get_text)); + FSWrite(data_dump_file_id, &len, (char *) get_text); + } + sprintf((char *)get_text,"\nNames of the towns in %s:\n",scen_strs[0]); + len = (long) (strlen((char *)get_text)); + FSWrite(data_dump_file_id, &len, (char *) get_text); + for (j = 0; j < scenario.num_towns; j++) { + load_town(j); + sprintf((char *)get_text," Town %d: %s\n",j,town_strs[0]); + len = (long) (strlen((char *)get_text)); + FSWrite(data_dump_file_id, &len, (char *) get_text); + } + sprintf((char *)get_text,"\n Outdoor Start Zone: X = %d, Y = %d\n",scenario.out_sec_start.x,scenario.out_sec_start.y); + len = (long) (strlen((char *)get_text)); + FSWrite(data_dump_file_id, &len, (char *) get_text); + sprintf((char *)get_text," Outdoor Start Location: X = %d, Y = %d\n",scenario.out_start.x,scenario.out_start.y); + len = (long) (strlen((char *)get_text)); + FSWrite(data_dump_file_id, &len, (char *) get_text); + sprintf((char *)get_text," Starting Town: = %d\n",scenario.which_town_start); + len = (long) (strlen((char *)get_text)); + FSWrite(data_dump_file_id, &len, (char *) get_text); + sprintf((char *)get_text," Starting Town Location: X = %d, Y = %d\n",scenario.where_start.x,scenario.where_start.y); + len = (long) (strlen((char *)get_text)); + FSWrite(data_dump_file_id, &len, (char *) get_text); + sprintf((char *)get_text," Last Outdoor Zone Edited: X = %d, Y = %d\n",scenario.last_out_edited.x,scenario.last_out_edited.y); + len = (long) (strlen((char *)get_text)); + FSWrite(data_dump_file_id, &len, (char *) get_text); + sprintf((char *)get_text," Last Town Edited: = %d\n\n\n",scenario.last_town_edited); + len = (long) (strlen((char *)get_text)); + FSWrite(data_dump_file_id, &len, (char *) get_text); + sprintf((char *)get_text,"Names of the Special Items in %s:\n",scen_strs[0]); + len = (long) (strlen((char *)get_text)); + FSWrite(data_dump_file_id, &len, (char *) get_text); + + for (short i = 0; i < 50; i++) { + sprintf((char *)get_text,"Special Item \"%d \"%s \"%s\n",i,scen_strs[60 + i * 2],scen_strs[61 + i * 2]); + len = (long) (strlen((char *)get_text)); + FSWrite(data_dump_file_id, &len, (char *) get_text); + } + + sprintf((char *)get_text,"\n\nLocations of Town Entrances in %s:\n",scen_strs[0]); + len = (long) (strlen((char *)get_text)); + FSWrite(data_dump_file_id, &len, (char *) get_text); + for (out_sec.y = 0; out_sec.y < scenario.out_height ; out_sec.y++) + for (out_sec.x = 0; out_sec.x < scenario.out_width ; out_sec.x++) { + load_outdoors(out_sec,0); + sprintf((char *)get_text,"\n\n Section X = %d, Y = %d: %s\n",(short) out_sec.x,(short) out_sec.y,data_store->out_strs[0]); + len = (long) (strlen((char *)get_text)); + FSWrite(data_dump_file_id, &len, (char *) get_text); + for (short i = 0; i < 8; i++) { + if ((current_terrain.exit_locs[i].x != 100) && (current_terrain.exit_locs[i].y != 0)) { + sprintf((char *)get_text,"Town entrance %d, town %d, x = %d, y = %d\n",i,current_terrain.exit_dests[i],current_terrain.exit_locs[i].x,current_terrain.exit_locs[i].y); + len = (long) (strlen((char *)get_text)); + FSWrite(data_dump_file_id, &len, (char *) get_text); + } + } + } + out_sec.x = scenario.last_out_edited.x; + out_sec.y = scenario.last_out_edited.y; + load_outdoors(out_sec,0); + load_town(scenario.last_town_edited); + + _lclose(data_dump_file_id); + +} + +void start_shopping_data_dump() +{ + short i; + short j; + short count; + char res[256]; + char get_text[280]; + HFILE data_dump_file_id; + long len; + location out_sec; + if (HFILE_ERROR == (data_dump_file_id = _lcreat("Scenario Shopping.txt", 0))) { + SysBeep(50); + return; + } + + SetFPos (data_dump_file_id, 2, 0); + + sprintf(get_text,"Scenario shopping data printout for %s:\n",scen_strs[0]); + len = (long) (strlen(get_text)); + FSWrite(data_dump_file_id, &len, get_text); + sprintf(get_text,"\nList of outdoor stores:\n"); + len = (long) (strlen(get_text)); + FSWrite(data_dump_file_id, &len, get_text); + for (out_sec.x = 0; out_sec.x < scenario.out_width ; (out_sec.x)++) + for (out_sec.y = 0; out_sec.y < scenario.out_height ; (out_sec.y)++) { + count = 0; + load_outdoors(out_sec,0); + sprintf(get_text,"\n Section X = %d, Y = %d: %s \n",(short) out_sec.x,(short) out_sec.y,data_store->out_strs[0]); + len = (long) (strlen(get_text)); + FSWrite(data_dump_file_id, &len, get_text); + for (i = 0; i < 60; i++) { + if (current_terrain.specials[i].type == 229) { + count++; + sprintf(get_text,"\n Number of node : %d\n",i); + len = (long) (strlen(get_text)); + FSWrite(data_dump_file_id, &len, get_text); + sprintf(get_text," Name of Store : %s\n",data_store->out_strs[current_terrain.specials[i].m1+10]); + len = (long) (strlen(get_text)); + FSWrite(data_dump_file_id, &len, get_text); + + switch(current_terrain.specials[i].ex1b){ + case 0: + sprintf(get_text," Store type : 0 - Items\n"); + break; + + case 1: + sprintf(get_text," Store type : 1 - Mage spells\n"); + break; + + case 2: + sprintf(get_text," Store type : 2 - Priest spells\n"); + break; + + case 3: + sprintf(get_text," Store type : 3 - Alchemy\n"); + break; + + case 4: + sprintf(get_text," Store type : 4 - Healing\n"); + break; + + } + + len = (long) (strlen(get_text)); + FSWrite(data_dump_file_id, &len, get_text); + sprintf(get_text," Number of first item in store : %d, full name : %s\n",current_terrain.specials[i].ex1a, scen_item_list.scen_items[current_terrain.specials[i].ex1a].full_name); + len = (long) (strlen(get_text)); + FSWrite(data_dump_file_id, &len, get_text); + sprintf(get_text," Number of items in store : %d\n",current_terrain.specials[i].ex2a); + len = (long) (strlen(get_text)); + FSWrite(data_dump_file_id, &len, get_text); + sprintf(get_text," Cost adjust (0 .. 6, lower = cheaper) : %d\n",current_terrain.specials[i].ex2b); + len = (long) (strlen(get_text)); + FSWrite(data_dump_file_id, &len, get_text); + } + } + if(count == 0) + sprintf(get_text,"\n -- No shop found.\n"); + else if (count == 1) + sprintf(get_text,"\n -- Found 1 shop.\n"); + else + sprintf(get_text,"\n -- Found %d shops.\n",count); + len = (long) (strlen(get_text)); + FSWrite(data_dump_file_id, &len, get_text); + } + + sprintf(get_text,"\nList of town stores:\n"); + len = (long) (strlen(get_text)); + FSWrite(data_dump_file_id, &len, get_text); + + for (j = 0; j < scenario.num_towns; j++) { + count = 0; + load_town(j); + sprintf((char *)get_text,"\n Town %d: %s\n",j,town_strs[0]); + len = (long) (strlen((char *)get_text)); + FSWrite(data_dump_file_id, &len, (char *) get_text); + for (i = 0; i < 60; i++) { + if (talking.talk_nodes[i].type == 3 || (talking.talk_nodes[i].type >= 7 && talking.talk_nodes[i].type <= 17) || (talking.talk_nodes[i].type >= 20 && talking.talk_nodes[i].type <= 23)) { + count++; + sprintf(get_text,"\n Number of talking node : %d\n",i); + len = (long) (strlen(get_text)); + FSWrite(data_dump_file_id, &len, get_text); + GetIndString(res,40,1+talking.talk_nodes[i].type *7); + sprintf(get_text," Store type : %s\n",res); + len = (long) (strlen(get_text)); + FSWrite(data_dump_file_id, &len, get_text); + + switch(talking.talk_nodes[i].type){ + + case 3: + sprintf(get_text," Cost of Inn : %d\n",talking.talk_nodes[i].extras[0]); + len = (long) (strlen(get_text)); + FSWrite(data_dump_file_id, &len, get_text); + sprintf(get_text," Quality of Inn (0 .. 3) : %d\n",talking.talk_nodes[i].extras[1]); + len = (long) (strlen(get_text)); + FSWrite(data_dump_file_id, &len, get_text); + sprintf(get_text," Move party to X : %d\n",talking.talk_nodes[i].extras[2]); + len = (long) (strlen(get_text)); + FSWrite(data_dump_file_id, &len, get_text); + sprintf(get_text," Move party to Y : %d\n",talking.talk_nodes[i].extras[3]); + len = (long) (strlen(get_text)); + FSWrite(data_dump_file_id, &len, get_text); + break; + + case 7: + sprintf(get_text," Name of Store : %s\n",talk_strs[2*i+40]); + len = (long) (strlen(get_text)); + FSWrite(data_dump_file_id, &len, get_text); + sprintf(get_text," Number of first item in store : %d, full name : %s\n",talking.talk_nodes[i].extras[1], scen_item_list.scen_items[talking.talk_nodes[i].extras[1]].full_name); + len = (long) (strlen(get_text)); + FSWrite(data_dump_file_id, &len, get_text); + sprintf(get_text," Number of items in shop : %d\n",talking.talk_nodes[i].extras[2]); + len = (long) (strlen(get_text)); + FSWrite(data_dump_file_id, &len, get_text); + sprintf(get_text," Cost adjust (0 .. 6, lower = cheaper) : %d\n",talking.talk_nodes[i].extras[0]); + len = (long) (strlen(get_text)); + FSWrite(data_dump_file_id, &len, get_text); + break; + + case 9: + sprintf(get_text," Name of Store : %s\n",talk_strs[2*i+40]); + len = (long) (strlen(get_text)); + FSWrite(data_dump_file_id, &len, get_text); + GetIndString(res,38,1+talking.talk_nodes[i].extras[1]); + sprintf(get_text," Number of first spell in shop : %d, name : %s\n",talking.talk_nodes[i].extras[1], res); + len = (long) (strlen(get_text)); + FSWrite(data_dump_file_id, &len, get_text); + sprintf(get_text," Number of spells in shop : %d\n",talking.talk_nodes[i].extras[2]); + len = (long) (strlen(get_text)); + FSWrite(data_dump_file_id, &len, get_text); + sprintf(get_text," Cost adjust (0 .. 6, lower = cheaper) : %d\n",talking.talk_nodes[i].extras[0]); + len = (long) (strlen(get_text)); + FSWrite(data_dump_file_id, &len, get_text); + break; + + case 10: + sprintf(get_text," Name of Store : %s\n",talk_strs[2*i+40]); + len = (long) (strlen(get_text)); + FSWrite(data_dump_file_id, &len, get_text); + GetIndString(res,38,50+talking.talk_nodes[i].extras[1]); + sprintf(get_text," Number of first spell in shop : %d, name : %s\n",talking.talk_nodes[i].extras[1], res); + len = (long) (strlen(get_text)); + FSWrite(data_dump_file_id, &len, get_text); + sprintf(get_text," Number of spells in shop : %d\n",talking.talk_nodes[i].extras[2]); + len = (long) (strlen(get_text)); + FSWrite(data_dump_file_id, &len, get_text); + sprintf(get_text," Cost adjust (0 .. 6, lower = cheaper) : %d\n",talking.talk_nodes[i].extras[0]); + len = (long) (strlen(get_text)); + FSWrite(data_dump_file_id, &len, get_text); + break; + + case 11: + sprintf(get_text," Name of Store : %s\n",talk_strs[2*i+40]); + len = (long) (strlen(get_text)); + FSWrite(data_dump_file_id, &len, get_text); + GetIndString(res,38,100+talking.talk_nodes[i].extras[1]); + sprintf(get_text," Cost adjust (0 .. 6, lower = cheaper) : %d\n",talking.talk_nodes[i].extras[0]); + len = (long) (strlen(get_text)); + FSWrite(data_dump_file_id, &len, get_text); + sprintf(get_text," Number of first recipe in shop : %d, name : %s\n",talking.talk_nodes[i].extras[1], res); + len = (long) (strlen(get_text)); + FSWrite(data_dump_file_id, &len, get_text); + sprintf(get_text," Number of recipes in shop : %d\n",talking.talk_nodes[i].extras[2]); + len = (long) (strlen(get_text)); + FSWrite(data_dump_file_id, &len, get_text); + break; + + case 12: + sprintf(get_text," Name of healer : %s\n",talk_strs[2*i+40]); + len = (long) (strlen(get_text)); + FSWrite(data_dump_file_id, &len, get_text); + sprintf(get_text," Cost adjust (0 .. 6, lower = cheaper) : %d\n",talking.talk_nodes[i].extras[0]); + len = (long) (strlen(get_text)); + FSWrite(data_dump_file_id, &len, get_text); + break; + + case 16: + sprintf(get_text," Cost to identify : %d\n",talking.talk_nodes[i].extras[0]); + len = (long) (strlen(get_text)); + FSWrite(data_dump_file_id, &len, get_text); + break; + + case 17: + sprintf(get_text," Type of enchantment : %d\n",talking.talk_nodes[i].extras[0]); + len = (long) (strlen(get_text)); + FSWrite(data_dump_file_id, &len, get_text); + break; + + case 20: + sprintf(get_text," Cost of Boat : %d\n",talking.talk_nodes[i].extras[0]); + len = (long) (strlen(get_text)); + FSWrite(data_dump_file_id, &len, get_text); + sprintf(get_text," Number of first boat sold : %d\n",talking.talk_nodes[i].extras[1]); + len = (long) (strlen(get_text)); + FSWrite(data_dump_file_id, &len, get_text); + sprintf(get_text," Total number of boats sold : %d\n",talking.talk_nodes[i].extras[2]); + len = (long) (strlen(get_text)); + FSWrite(data_dump_file_id, &len, get_text); + break; + + case 21: + sprintf(get_text," Cost of Horse : %d\n",talking.talk_nodes[i].extras[0]); + len = (long) (strlen(get_text)); + FSWrite(data_dump_file_id, &len, get_text); + sprintf(get_text," Number of first horse sold : %d\n",talking.talk_nodes[i].extras[1]); + len = (long) (strlen(get_text)); + FSWrite(data_dump_file_id, &len, get_text); + sprintf(get_text," Total number of horses sold : %d\n",talking.talk_nodes[i].extras[2]); + len = (long) (strlen(get_text)); + FSWrite(data_dump_file_id, &len, get_text); + break; + + case 22: + sprintf(get_text," Number of item being sold : %d\n",talking.talk_nodes[i].extras[0]); + len = (long) (strlen(get_text)); + FSWrite(data_dump_file_id, &len, get_text); + sprintf(get_text," Cost of item : %d\n",talking.talk_nodes[i].extras[1]); + len = (long) (strlen(get_text)); + FSWrite(data_dump_file_id, &len, get_text); + break; + + + case 23: + sprintf(get_text," Name of Store : %s\n",talk_strs[2*i+40]); + len = (long) (strlen(get_text)); + FSWrite(data_dump_file_id, &len, get_text); + sprintf(get_text," Cost adjust (0 .. 6, lower = cheaper) : %d\n",talking.talk_nodes[i].extras[0]); + len = (long) (strlen(get_text)); + FSWrite(data_dump_file_id, &len, get_text); + sprintf(get_text," Which shop (0 .. 4) : %d\n",talking.talk_nodes[i].extras[1]); + len = (long) (strlen(get_text)); + FSWrite(data_dump_file_id, &len, get_text); + break; + } + } + } + + if(count == 0) + sprintf(get_text,"\n -- No shop found.\n"); + else if (count == 1) + sprintf(get_text,"\n -- Found 1 shop.\n"); + else + sprintf(get_text,"\n -- Found %d shops.\n",count); + len = (long) (strlen(get_text)); + FSWrite(data_dump_file_id, &len, get_text); + } + + sprintf(get_text,"\n -------- End of file."); + len = (long) (strlen(get_text)); + FSWrite(data_dump_file_id, &len, get_text); + + out_sec.x = scenario.last_out_edited.x; + out_sec.y = scenario.last_out_edited.y; + load_outdoors(out_sec,0); + load_town(scenario.last_town_edited); + + _lclose(data_dump_file_id); + +} + +void scen_text_dump() +{ + short i,j; + HFILE data_dump_file_id; + char get_text[300]; + long len; + location out_sec; + + if (HFILE_ERROR == (data_dump_file_id = _lcreat("Scentext.txt", 0))) { + SysBeep(50); + return; + } + + SetFPos (data_dump_file_id, 2, 0); + + sprintf((char *)get_text,"\nScenario Text Write Up for %s:\n",scen_strs[0]); + len = (long) (strlen((char *)get_text)); + FSWrite(data_dump_file_id, &len, (char *) get_text); + sprintf((char *)get_text,"\nScenario Text for %s:\n",scen_strs[0]); + len = (long) (strlen((char *)get_text)); + FSWrite(data_dump_file_id, &len, (char *) get_text); + for (i = 0; i < 260; i++) + if (((i < 160) ? scen_strs[i][0] : scen_strs2[i - 160][0]) != '*') { + if (i < 160) + sprintf((char *)get_text," Message %d: %s\n",i,scen_strs[i]); + else sprintf((char *)get_text," Message %d: %s\n",i,scen_strs2[i - 160]); + len = (long) (strlen((char *)get_text)); + FSWrite(data_dump_file_id, &len, (char *) get_text); + } + + sprintf((char *)get_text,"\n\nOutdoor Sections Text for %s:",scen_strs[0]); + len = (long) (strlen((char *)get_text)); + FSWrite(data_dump_file_id, &len, (char *) get_text); + for (out_sec.y = 0; out_sec.y < scenario.out_height ; out_sec.y++) + for (out_sec.x = 0; out_sec.x < scenario.out_width ; out_sec.x++) { + sprintf((char *)get_text,"\n\n Section X = %d, Y = %d: \n",(short) out_sec.x,(short) out_sec.y); + len = (long) (strlen((char *)get_text)); + FSWrite(data_dump_file_id, &len, (char *) get_text); + load_outdoors(out_sec,0); + for (i = 0; i < 108; i++) + if (data_store->out_strs[i][0] != '*') { + sprintf((char *)get_text," Message %d: %s\n",i,data_store->out_strs[i]); + len = (long) (strlen((char *)get_text)); + FSWrite(data_dump_file_id, &len, (char *) get_text); + } + } + + sprintf((char *)get_text,"\n\nTown Text for %s:",scen_strs[0]); + len = (long) (strlen((char *)get_text)); + FSWrite(data_dump_file_id, &len, (char *) get_text); + for (j = 0; j < scenario.num_towns; j++) { + load_town(j); + sprintf((char *)get_text,"\n\n Town %d: %s\n",j,town_strs[0]); + len = (long) (strlen((char *)get_text)); + FSWrite(data_dump_file_id, &len, (char *) get_text); + sprintf((char *)get_text,"\n Town Messages:\n"); + len = (long) (strlen((char *)get_text)); + FSWrite(data_dump_file_id, &len, (char *) get_text); + for (i = 0; i < 135; i++) + if (town_strs[i][0] != '*') { + sprintf((char *)get_text," Message %d: %s\n",i,town_strs[i]); + len = (long) (strlen((char *)get_text)); + FSWrite(data_dump_file_id, &len, (char *) get_text); + } + sprintf((char *)get_text,"\n Dialog for Town %d: %s\n",j,town_strs[0]); + len = (long) (strlen((char *)get_text)); + FSWrite(data_dump_file_id, &len, (char *) get_text); + for (i = 0; i < 10; i++) { + sprintf((char *)get_text," Personality %d name: %s\n",j * 10 + i,talk_strs[i]); + len = (long) (strlen((char *)get_text)); + FSWrite(data_dump_file_id, &len, (char *) get_text); + sprintf((char *)get_text," Personality %d look: %s\n",j * 10 + i,talk_strs[i + 10]); + len = (long) (strlen((char *)get_text)); + FSWrite(data_dump_file_id, &len, (char *) get_text); + sprintf((char *)get_text," Personality %d ask name: %s\n",j * 10 + i,talk_strs[i + 20]); + len = (long) (strlen((char *)get_text)); + FSWrite(data_dump_file_id, &len, (char *) get_text); + sprintf((char *)get_text," Personality %d ask job: %s\n",j * 10 + i,talk_strs[i + 30]); + len = (long) (strlen((char *)get_text)); + FSWrite(data_dump_file_id, &len, (char *) get_text); + sprintf((char *)get_text," Personality %d confused: %s\n",j * 10 + i,talk_strs[i + 160]); + len = (long) (strlen((char *)get_text)); + FSWrite(data_dump_file_id, &len, (char *) get_text); + } + for (i = 40; i < 160; i++) + if (strlen((char *) (talk_strs[i])) > 0) { + sprintf((char *)get_text," Node %d: %s\n",(i - 40) / 2,talk_strs[i]); + len = (long) (strlen((char *)get_text)); + FSWrite(data_dump_file_id, &len, (char *) get_text); + } + sprintf((char *)get_text,"\n"); + len = (long) (strlen((char *)get_text)); + FSWrite(data_dump_file_id, &len, (char *) get_text); + } + out_sec.x = scenario.last_out_edited.x; + out_sec.y = scenario.last_out_edited.y; + load_outdoors(out_sec,0); + load_town(scenario.last_town_edited); + + _lclose(data_dump_file_id); + +} +void port_talk_nodes() +{ + short i,j,k,l; + + if (cur_scen_is_win == TRUE) + return; + for (i = 0; i < 60; i++) { + flip_short(&talking.talk_nodes[i].personality); + flip_short(&talking.talk_nodes[i].type); + flip_short(&talking.talk_nodes[i].extras[0]); + flip_short(&talking.talk_nodes[i].extras[1]); + flip_short(&talking.talk_nodes[i].extras[2]); + flip_short(&talking.talk_nodes[i].extras[3]); + } +} + +void port_town() +{ + short i,j,k,l; + + if (cur_scen_is_win == TRUE) + return; + flip_short(&town.town_chop_time); + flip_short(&town.town_chop_key); + flip_short(&town.lighting); + for (i =0 ; i < 4; i++) + flip_short(&town.exit_specs[i]); + flip_rect(&town.in_town_rect); + for (i =0 ; i < 64; i++) { + flip_short(&town.preset_items[i].item_code); + flip_short(&town.preset_items[i].ability); + } + for (i =0 ; i < 50; i++) { + flip_short(&town.preset_fields[i].field_type); + } + flip_short(&town.max_num_monst); + flip_short(&town.spec_on_entry); + flip_short(&town.spec_on_entry_if_dead); + for (i =0 ; i < 8; i++) + flip_short(&town.timer_spec_times[i]); + for (i =0 ; i < 8; i++) + flip_short(&town.timer_specs[i]); + flip_short(&town.difficulty); + for (i =0 ; i < 100; i++) + flip_spec_node(&town.specials[i]); + +} + +void port_dummy_town() +{ + short i,j,k,l; + + if (cur_scen_is_win == TRUE) + return; + flip_short(&dummy_town_ptr->town_chop_time); + flip_short(&dummy_town_ptr->town_chop_key); + flip_short(&dummy_town_ptr->lighting); + for (i =0 ; i < 4; i++) + flip_short(&dummy_town_ptr->exit_specs[i]); + flip_rect(&dummy_town_ptr->in_town_rect); + for (i =0 ; i < 64; i++) { + flip_short(&dummy_town_ptr->preset_items[i].item_code); + flip_short(&dummy_town_ptr->preset_items[i].ability); + } + for (i =0 ; i < 50; i++) { + flip_short(&dummy_town_ptr->preset_fields[i].field_type); + } + flip_short(&dummy_town_ptr->max_num_monst); + flip_short(&dummy_town_ptr->spec_on_entry); + flip_short(&dummy_town_ptr->spec_on_entry_if_dead); + for (i =0 ; i < 8; i++) + flip_short(&dummy_town_ptr->timer_spec_times[i]); + for (i =0 ; i < 8; i++) + flip_short(&dummy_town_ptr->timer_specs[i]); + flip_short(&dummy_town_ptr->difficulty); + for (i =0 ; i < 100; i++) + flip_spec_node(&dummy_town_ptr->specials[i]); + +} + +void port_dummy_t_d(short size,char *buffer) +{ + short i,j,k,l; + big_tr_type *d1; + ave_tr_type *d2; + tiny_tr_type *d3; + + if (cur_scen_is_win == TRUE) + return; + + switch (size) { + case 0: + d1 = (big_tr_type *) buffer; + for (i =0 ; i < 16; i++) + flip_rect(&d1->room_rect[i]); + for (i =0 ; i < 60; i++) { + flip_short(&d1->creatures[i].spec1); + flip_short(&d1->creatures[i].spec2); + flip_short(&d1->creatures[i].monster_time); + flip_short(&d1->creatures[i].personality); + flip_short(&d1->creatures[i].special_on_kill); + flip_short(&d1->creatures[i].facial_pic); + } + break; + case 1: + d2 = (ave_tr_type *) buffer; + for (i =0 ; i < 16; i++) + flip_rect(&d2->room_rect[i]); + for (i =0 ; i < 40; i++) { + flip_short(&d2->creatures[i].spec1); + flip_short(&d2->creatures[i].spec2); + flip_short(&d2->creatures[i].monster_time); + flip_short(&d2->creatures[i].personality); + flip_short(&d2->creatures[i].special_on_kill); + flip_short(&d2->creatures[i].facial_pic); + } + break; + case 2: + d3 = (tiny_tr_type *) buffer; + for (i =0 ; i < 16; i++) + flip_rect(&d3->room_rect[i]); + for (i =0 ; i < 30; i++) { + flip_short(&d3->creatures[i].spec1); + flip_short(&d3->creatures[i].spec2); + flip_short(&d3->creatures[i].monster_time); + flip_short(&d3->creatures[i].personality); + flip_short(&d3->creatures[i].special_on_kill); + flip_short(&d3->creatures[i].facial_pic); + } + break; + } +} + +void port_dummy_talk_nodes() +{ + short i,j,k,l; + + if (cur_scen_is_win == TRUE) + return; + for (i = 0; i < 60; i++) { + flip_short(&dummy_talk_ptr->talk_nodes[i].personality); + flip_short(&dummy_talk_ptr->talk_nodes[i].type); + flip_short(&dummy_talk_ptr->talk_nodes[i].extras[0]); + flip_short(&dummy_talk_ptr->talk_nodes[i].extras[1]); + flip_short(&dummy_talk_ptr->talk_nodes[i].extras[2]); + flip_short(&dummy_talk_ptr->talk_nodes[i].extras[3]); + } +} + +void port_t_d() +{ + short i,j,k,l; + if (cur_scen_is_win == TRUE) + return; + + for (i =0 ; i < 16; i++) + flip_rect(&t_d.room_rect[i]); + for (i =0 ; i < 60; i++) { + flip_short(&t_d.creatures[i].spec1); + flip_short(&t_d.creatures[i].spec2); + flip_short(&t_d.creatures[i].monster_time); + flip_short(&t_d.creatures[i].personality); + flip_short(&t_d.creatures[i].special_on_kill); + flip_short(&t_d.creatures[i].facial_pic); + + } +} + +void port_scenario() +{ + short i,j,k,l; + + if (cur_scen_is_win == TRUE) + return; + + flip_short(&scenario.flag_a); + flip_short(&scenario.flag_b); + flip_short(&scenario.flag_c); + flip_short(&scenario.flag_d); + flip_short(&scenario.flag_e); + flip_short(&scenario.flag_f); + flip_short(&scenario.flag_g); + flip_short(&scenario.flag_h); + flip_short(&scenario.flag_i); + flip_short(&scenario.intro_mess_pic); + flip_short(&scenario.intro_mess_len); + flip_short(&scenario.which_town_start); + for (i = 0; i < 200; i++) + for (j = 0; j < 5; j++) + flip_short(&scenario.town_data_size[i][j]); + for (i = 0; i < 10; i++) + flip_short(&scenario.town_to_add_to[i]); + for (i = 0; i < 10; i++) + for (j = 0; j < 2; j++) + flip_short(&scenario.flag_to_add_to_town[i][j]); + for (i = 0; i < 100; i++) + for (j = 0; j < 2; j++) + flip_short(&scenario.out_data_size[i][j]); + for (i = 0; i < 3; i++) + flip_rect(&scenario.store_item_rects[i]); + for (i = 0; i < 3; i++) + flip_short(&scenario.store_item_towns[i]); + for (i = 0; i < 50; i++) + flip_short(&scenario.special_items[i]); + for (i = 0; i < 50; i++) + flip_short(&scenario.special_item_special[i]); + flip_short(&scenario.rating); + flip_short(&scenario.uses_custom_graphics); + for (i = 0; i < 256; i++) { + flip_short(&scenario.scen_monsters[i].health); + flip_short(&scenario.scen_monsters[i].m_health); + flip_short(&scenario.scen_monsters[i].max_mp); + flip_short(&scenario.scen_monsters[i].mp); + flip_short(&scenario.scen_monsters[i].a[1]); + flip_short(&scenario.scen_monsters[i].a[0]); + flip_short(&scenario.scen_monsters[i].a[2]); + flip_short(&scenario.scen_monsters[i].morale); + flip_short(&scenario.scen_monsters[i].m_morale); + flip_short(&scenario.scen_monsters[i].corpse_item); + flip_short(&scenario.scen_monsters[i].corpse_item_chance); + flip_short(&scenario.scen_monsters[i].picture_num); + } + + for (i = 0; i < 256; i++) { + flip_short(&scenario.ter_types[i].picture); + } + for (i = 0; i < 30; i++) { + flip_short(&scenario.scen_boats[i].which_town); + } + for (i = 0; i < 30; i++) { + flip_short(&scenario.scen_horses[i].which_town); + } + for (i = 0; i < 20; i++) + flip_short(&scenario.scenario_timer_times[i]); + for (i = 0; i < 20; i++) + flip_short(&scenario.scenario_timer_specs[i]); + for (i = 0; i < 256; i++) { + flip_spec_node(&scenario.scen_specials[i]); + } + for (i = 0; i < 10; i++) { + flip_short(&scenario.storage_shortcuts[i].ter_type); + flip_short(&scenario.storage_shortcuts[i].property); + for (j = 0; j < 10; j++) { + flip_short(&scenario.storage_shortcuts[i].item_num[j]); + flip_short(&scenario.storage_shortcuts[i].item_odds[j]); + } + } + flip_short(&scenario.last_town_edited); +} + + +void port_item_list() +{ + short i,j,k,l; + + if (cur_scen_is_win == TRUE) + return; + + for (i = 0; i < 400; i++) { + flip_short(&(scen_item_list.scen_items[i].variety)); + flip_short(&(scen_item_list.scen_items[i].item_level)); + flip_short(&(scen_item_list.scen_items[i].value)); + } +} + +void port_out(outdoor_record_type *out) +{ + short i,j,k,l; + + if (cur_scen_is_win == TRUE) + return; + + for (i = 0; i < 4; i++) { + flip_short(&(out->wandering[i].spec_on_meet)); + flip_short(&(out->wandering[i].spec_on_win)); + flip_short(&(out->wandering[i].spec_on_flee)); + flip_short(&(out->wandering[i].cant_flee)); + flip_short(&(out->wandering[i].end_spec1)); + flip_short(&(out->wandering[i].end_spec2)); + flip_short(&(out->special_enc[i].spec_on_meet)); + flip_short(&(out->special_enc[i].spec_on_win)); + flip_short(&(out->special_enc[i].spec_on_flee)); + flip_short(&(out->special_enc[i].cant_flee)); + flip_short(&(out->special_enc[i].end_spec1)); + flip_short(&(out->special_enc[i].end_spec2)); + } + for (i = 0; i < 8; i++) + flip_rect(&(out->info_rect[i])); + for (i = 0; i < 60; i++) + flip_spec_node(&(out->specials[i])); +} + +void flip_spec_node(special_node_type *spec) +{ + flip_short(&(spec->type)); + flip_short(&(spec->sd1)); + flip_short(&(spec->sd2)); + flip_short(&(spec->pic)); + flip_short(&(spec->m1)); + flip_short(&(spec->m2)); + flip_short(&(spec->ex1a)); + flip_short(&(spec->ex1b)); + flip_short(&(spec->ex2a)); + flip_short(&(spec->ex2b)); + flip_short(&(spec->jumpto)); +} + +void flip_short(short *s) +{ + char store,*s1, *s2; + + s1 = (char *) s; + s2 = s1 + 1; + store = *s1; + *s1 = *s2; + *s2 = store; + +} + +void alter_rect(RECT *r) +{ + short a; + + a = r->top; + r->top = r->left; + r->left = a; + a = r->bottom; + r->bottom = r->right; + r->right = a; +} + +void flip_rect(RECT *s) +{ + flip_short((short *) &(s->top)); + flip_short((short *) &(s->bottom)); + flip_short((short *) &(s->left)); + flip_short((short *) &(s->right)); + alter_rect(s); + } + +short FSWrite(HFILE file,long *len,char *buffer) +{ + long error = 0; + + if ((error = _lwrite(file, (char *) buffer, (UINT) (*len))) == HFILE_ERROR) + return -1; + return 0; +} + +short FSRead(HFILE file,long *len,char *buffer) +{ + long error = 0; + + if ((error = _lread(file, (char *) buffer, (UINT) (*len))) == HFILE_ERROR) + return -1; + return 0; +} + +short SetFPos(HFILE file, short mode, long len) +{ + long error = 0; + + switch (mode) { + case 1: error = _llseek(file,len,0); break; + case 2: error = _llseek(file,len,2); break; + case 3: error = _llseek(file,len,1); break; + } + + if (error == HFILE_ERROR) + return -1; + return 0; +} + +void flip_rect(RECT16 *s) +{ + flip_short((short *) &(s->top)); + flip_short((short *) &(s->bottom)); + flip_short((short *) &(s->left)); + flip_short((short *) &(s->right)); + alter_rect(s); +} + +void alter_rect(RECT16 *r) +{ + short a; + + a = r->top; + r->top = r->left; + r->left = a; + a = r->bottom; + r->bottom = r->right; + r->right = a; +} + +/* +void import_outdoors(location which_out) +{ + short i,j,k,l; + HFILE file_id; + Boolean file_ok = FALSE; + short error; + long len,len_to_jump = 0,store; + DWORD buf_len = 100000; + char *buffer = NULL; + char szFileName3 [128] = "scen.exs"; + HGLOBAL temp_buffer; + short out_sec_num; + outdoor_record_type store_out; + + if (overall_mode == 61) + return; + + file_id = _lopen(szFileName,OF_READ | OF_SHARE_DENY_WRITE); + if (file_id == HFILE_ERROR) { + oops_error(31); + beep(); + return; + } + + out_sec_num = scenario.out_width * which_out.y + which_out.x; + + + if (out_sec_num >= 0) { + ofn.hwndOwner = mainPtr; + ofn.lpstrFile = szFileName3; + ofn.lpstrFileTitle = szTitleName; + ofn.Flags = 0; + + if (GetOpenFileName(&ofn) == 0) + return; + } + else { +// sprintf((char *) szFileName3,".\\scenarios\\BLADBASE.EXS"); + strncpy(szFileName3, szBladBase, 128); + which_town = 0; + } + + SetCurrentDirectory(file_path_name); + + file_id = _lopen(szFileName3,OF_READ | OF_SHARE_DENY_WRITE); + if (file_id == HFILE_ERROR) { + oops_error(42); beep(); + return; + } + + temp_buffer = GlobalAlloc(GMEM_FIXED,buf_len); + if (temp_buffer == NULL) { + _lclose(file_id); oops_error(41); + return; + } + buffer = (char *) GlobalLock(temp_buffer); + if (buffer == NULL) { + _lclose(file_id); oops_error(41); + return; + } + + len = (long) sizeof(scenario_data_type); + if ((error = FSRead(file_id, &len, buffer)) != 0){ + _lclose(file_id); oops_error(43); return; + } + temp_scenario = (scenario_data_type *) buffer; + + if ((which.out.x >= temp_scenario->out_width) || (which.out.y >= temp_scenario->out_height)) { + give_error("Oops ... the selected scenario doesn't have those dimensions. The zone you selected doesn't exist inside this scenario.","",0); + GlobalUnlock(temp_buffer); GlobalFree(temp_buffer); _lclose(file_id); + return; + } + + if ((temp_scenario->flag1 == 20) && (temp_scenario->flag2 == 40) + && (temp_scenario->flag3 == 60) + && (temp_scenario->flag4 == 80)) { + file_ok = TRUE; + } + if (file_ok == FALSE) { + GlobalUnlock(temp_buffer); GlobalFree(temp_buffer); _lclose(file_id); give_error("This is not a legitimate Blades of Exile scenario. If it is a scenario, note that it needs to have been saved by the Windows scenario editor.","",0); + return; + } + len_to_jump = sizeof(scenario_data_type); + len_to_jump += sizeof(scen_item_data_type); + for (i = 0; i < 300; i++) + len_to_jump += (long) scenario.scen_str_len[i]; + store = 0; + for (i = 0; i < out_sec_num; i++) + for (j = 0; j < 2; j++) + store += (long) (scenario.out_data_size[i][j]); + len_to_jump += store; + + error = SetFPos (file_id, 1, len_to_jump); + if (error != 0) {_lclose(file_id);oops_error(32);} + + len = sizeof(outdoor_record_type); + error = FSRead(file_id, &len, (char *) &store_out); + if (error != 0) {_lclose(file_id);oops_error(33);} + + if (mode == 0) { + current_terrain = store_out; + port_out(¤t_terrain); + for (i = 0; i < 120; i++) { + len = (long) (current_terrain.strlens[i]); + FSRead(file_id, &len, (char *) &(data_store->out_strs[i])); + data_store->out_strs[i][len] = 0; + } + + } + + if (mode == 0) { + cur_out = which_out; + } + + if (mode == 1) + for (j = 0; j < 48; j++) { + borders[0][j] = store_out.terrain[j][47]; + } + if (mode == 2) + for (j = 0; j < 48; j++) { + borders[1][j] = store_out.terrain[0][j]; + } + if (mode == 3) + for (j = 0; j < 48; j++) { + borders[2][j] = store_out.terrain[j][0]; + } + if (mode == 4) + for (j = 0; j < 48; j++) { + borders[3][j] = store_out.terrain[47][j]; + } + + + error = _lclose(file_id); + if (error != 0) {_lclose(file_id);oops_error(33);} + +} +*/ diff --git a/Win32/Scenarios Editor/TFILEIO.H b/Win32/Scenarios Editor/TFILEIO.H new file mode 100644 index 00000000..7beb1510 --- /dev/null +++ b/Win32/Scenarios Editor/TFILEIO.H @@ -0,0 +1,37 @@ +#ifndef _TFILEIO_H + #define _TFILEIO_H + +void Get_Path(char* path); +void file_initialize(); +void save_scenario(); +void load_scenario(); +void load_spec_graphics(); +void augment_terrain(location to_create); +void load_outdoors(location which_out,short mode); +void load_town(short which_town); +void import_town(short which_town); +void oops_error(short error); +void start_data_dump(); +void start_shopping_data_dump(); +void scen_text_dump(); +void port_talk_nodes(); +void port_town(); +void port_dummy_town(); +void port_dummy_t_d(short size,char *buffer); +void port_dummy_talk_nodes(); +void port_t_d(); +void port_scenario(); +void port_item_list(); +void port_out(outdoor_record_type *out); +void flip_spec_node(special_node_type *spec); +void flip_short(short *s); +void alter_rect(RECT *r); +void flip_rect(RECT *s); +short FSWrite(HFILE file,long *len,char *buffer); +short FSRead(HFILE file,long *len,char *buffer); +short SetFPos(HFILE file, short mode, long len); +void make_new_scenario(char *file_name,short out_width,short out_height,short making_warriors_grove, + short use_grass,char *title); +void flip_rect(RECT16 *s); +void alter_rect(RECT16 *r); +#endif diff --git a/Win32/Scenarios Editor/townout.cpp b/Win32/Scenarios Editor/townout.cpp new file mode 100644 index 00000000..09570604 --- /dev/null +++ b/Win32/Scenarios Editor/townout.cpp @@ -0,0 +1,1862 @@ +#include +#include +#include +#include "global.h" +#include "graphics.h" +#include "dlogtool.h" +#include "townout.h" +#include "keydlgs.h" +#include "tfileio.h" + +typedef char Str255[255]; +extern char town_strs[180][256]; +extern char talk_strs[170][256]; +extern scen_item_data_type scen_item_list; + +extern short cen_x, cen_y, overall_mode; +extern Boolean mouse_button_held,dialog_not_toast,editing_town; +extern short cur_viewing_mode; +extern town_record_type town; +extern big_tr_type t_d; +extern short town_type; // 0 - big 1 - ave 2 - small +extern short max_dim[3],mode_count,to_create,cur_town; +extern unsigned char template_terrain[64][64]; +extern short_item_record_type item_list[400]; +extern scenario_data_type scenario; +extern special_node_type null_spec_node; +extern talking_node_type null_talk_node; +extern piles_of_stuff_dumping_type *data_store; +extern outdoor_record_type current_terrain; +extern unsigned char borders[4][50]; +extern pascal Boolean cd_event_filter(); +extern location cur_out; +extern talking_record_type talking; + +creature_start_type store_placed_monst,store_placed_monst2; +short store_which_placed_monst; +preset_item_type store_placed_item; +short store_which_placed_item,store_which_sign; +extern short dialog_answer; +short store_whigh_dlog; +short str_do_delete[16]; +short a,b,c; +short store_which_out_wand,store_out_wand_mode; +out_wandering_type store_out_wand; + +char *day_str_1[] = {"Unused","Day creature appears","Day creature disappears", + "Unused","Unused","Unused","Unused","Unused"}; +char *day_str_2[] = {"Unused","Event code (0 - no event)","Event code (0 - no event)", + "Unused","Unused","Unused", + "Event code (0 - no event)","Event code (0 - no event)"}; + +short store_which_talk_node,last_talk_node[60]; +talking_node_type store_talk_node; +location store_cur_loc; + +void init_town(short size) +{ + short i,j,s; + location d_loc = {100,0}; + RECT d_rect = {0,0,0,0}; + wandering_type d_wan = {0,0,0,0}; + creature_start_type dummy_creature = {0,0,{0,0},0,0,0,0,0,0,0,0,0,0,0,0}; + preset_item_type null_item = {{0,0},-1,0,0,0,0,0}; + Str255 temp_str; + + town.town_chop_time = -1; + town.town_chop_key = -1; + for (i = 0; i < 4; i++) { + town.wandering[i] = d_wan; + town.wandering_locs[i] = d_loc; + } + for (i = 0; i < 50; i++) { + town.special_locs[i] = d_loc; + town.special_locs[i].x = 100; + //town.spec_id[i] = -1; + town.spec_id[i] = 0xFF; + } + town.lighting = 0; + for (i = 0; i < 4; i++) { + town.start_locs[i] = d_loc; + town.exit_specs[i] = -1; + town.exit_locs[i].x = -1; + town.exit_locs[i].y = -1; + } + s = max_dim[size]; + town.start_locs[0].x = s / 2; + town.start_locs[0].y = 4; + town.start_locs[2].x = s / 2; + town.start_locs[2].y = s - 5; + town.start_locs[1].x = s - 5; + town.start_locs[1].y = s / 2; + town.start_locs[3].x = 4; + town.start_locs[3].y = s / 2; + town.in_town_rect.top = 3; + town.in_town_rect.bottom = s - 4; + town.in_town_rect.left = 3; + town.in_town_rect.right = s - 4; + for (i = 0; i < 64; i++) + town.preset_items[i] = null_item; + town.max_num_monst = 30000; + for (i = 0; i < 50; i++) + town.preset_fields[i].field_type = 0; + town.spec_on_entry = -1; + town.spec_on_entry_if_dead = -1; + for (i = 0; i < 15; i++) { + town.sign_locs[i] = d_loc; + town.sign_locs[i].x = 100; + } + for (i = 0; i < 8; i++) { + town.timer_spec_times[i] = 0; + town.timer_specs[i] = -1; + } + for (i = 0; i < 100; i++) { + town.specials[i] = null_spec_node; + } + town.specials1 = 0; + town.specials2 = 0; + town.res1 = 0; + town.res2 = 0; + town.difficulty = 0; + for (i = 0; i < 180; i++) { + get_str(temp_str,36,i + 1); + sprintf((char *)town_strs[i], "%s", temp_str); + town.strlens[i] = strlen(town_strs[i]); + } + + + + + for (i = 0; i < 16; i++) { + t_d.room_rect[i] = d_rect; + //sprintf((char *) t_d.room_string[i], ""); + } + for (i = 0; i < 64; i++) + for (j = 0; j < 64; j++) { + t_d.terrain[i][j] = scenario.default_ground * 2; + t_d.lighting[i / 8][j] = 0; + } + + for (i = 0; i < 60; i++) { + t_d.creatures[i] = dummy_creature; + } + + for(i = 0; i < 200; i++) + talking.strlens[i] = 0; + for(i = 0; i < 170; i++) + if (i < 10) + sprintf(talk_strs[i],"Unused"); + else sprintf(talk_strs[i],""); + for(i = 0; i < 60; i++) { + talking.talk_nodes[i].personality = -1; + talking.talk_nodes[i].type = 0; + talking.talk_nodes[i].extras[0] = 0; + talking.talk_nodes[i].extras[1] = 0; + talking.talk_nodes[i].extras[2] = 0; + talking.talk_nodes[i].extras[3] = -1; + for (j = 0; j < 4; j++) { + talking.talk_nodes[i].link1[j] = 'x'; + talking.talk_nodes[i].link2[j] = 'x'; + } + } + +} + +void init_out() +{ + short i,j; + location d_loc = {100,0}; + out_wandering_type d_monst = {{0,0,0,0,0,0,0},{0,0,0},-1,-1,-1,0,-1,-1}; + RECT d_rect = {0,0,0,0}; + location locs[4] = {{8,8},{32,8},{8,32},{32,32}}; + Str255 temp_str; + + for (i = 0; i < 48; i++) + for (j = 0; j < 48; j++) { + current_terrain.terrain[i][j] = 0; + } + for (i = 0; i < 4; i++) + for (j = 0; j < 50; j++) + borders[i][j] = 90; + + for (i = 0; i < 18; i++) { + current_terrain.special_locs[i] = d_loc; + current_terrain.special_id[i] = 0; + } + for (i = 0; i < 8; i++) { + current_terrain.exit_locs[i] = d_loc; + current_terrain.exit_dests[i] = 0; + current_terrain.sign_locs[i] = d_loc; + current_terrain.sign_locs[i].x = 100; + current_terrain.info_rect[i] = d_rect; + } + for (i = 0; i < 4; i++) { + current_terrain.wandering[i] = d_monst; + current_terrain.wandering_locs[i] = locs[i]; + current_terrain.special_enc[i] = d_monst; + } + + for (i = 0; i < 120; i++) { + get_str(temp_str,37,i + 1); + sprintf((char *)data_store->out_strs[i], "%s", temp_str); + current_terrain.strlens[i] = strlen((char *) data_store->out_strs[i]); + } + for (i = 0; i < 60; i++) { + current_terrain.specials[i] = null_spec_node; + } + +} + +void put_placed_monst_in_dlog() +{ + Str255 str; + short i; + + cdsin(837,24,store_which_placed_monst); + csit(837,7,scen_item_list.monst_names[store_placed_monst.number]); + cd_set_led_range(837,14,17,store_placed_monst.start_attitude); + cd_set_led_range(837,18,19,store_placed_monst.mobile); + CDSN(837,2,store_placed_monst.personality); + CDSN(837,3,store_placed_monst.facial_pic); + if ((store_placed_monst.facial_pic < 1) || (store_placed_monst.facial_pic >= 1000)) + csp(837,11,950); + else csp(837,11,store_placed_monst.facial_pic + 1000); +} +Boolean get_placed_monst_in_dlog() +{ + Str255 str; + short i; + + store_placed_monst.start_attitude = cd_get_led_range(837,14,17); + store_placed_monst.mobile = cd_get_led_range(837,18,19); + store_placed_monst.personality = CDGN(837,2); + store_placed_monst.facial_pic = CDGN(837,3); + // later + t_d.creatures[store_which_placed_monst] = store_placed_monst; + return TRUE; +} + +void edit_placed_monst_event_filter (short item_hit) +{ + Str255 str; + short i; + creature_start_type store_m; + + switch (item_hit) { + case 20: + if (get_placed_monst_in_dlog() == FALSE) + break; + dialog_not_toast = FALSE; + break; + case 21: + dialog_not_toast = FALSE; + break; + case 6: // choose m type + if (get_placed_monst_in_dlog() == FALSE) + break; + i = choose_text_res(-1,1,255,store_placed_monst.number,837,"Choose Which Monster:"); + if (i >= 0) { + store_placed_monst.number = i; + put_placed_monst_in_dlog(); + } + break; + case 12: // facial pic + if (get_placed_monst_in_dlog() == FALSE) + break; + i = choose_graphic(1001,1084,store_placed_monst.facial_pic + 1000,837); + if (i >= 0) { + store_placed_monst.facial_pic = i - 1000; + } + else break; + put_placed_monst_in_dlog(); + break; + case 25: //advanced + store_m = edit_placed_monst_adv(store_placed_monst); + if (store_m.number != 0) + store_placed_monst = store_m; + break; + default: + cd_hit_led_range(837,14,17,item_hit); + cd_hit_led_range(837,18,19,item_hit); + break; + } +} + +void edit_placed_monst(short which_m) +{ + + short item_hit,i,store_dialog_answer; + Str255 temp_str; + char *attitude[4] = {"Friendly, Docile","Hostile, Type A","Friendly, Will Fight","Hostile, Type B"}; + + store_placed_monst = t_d.creatures[which_m]; + store_which_placed_monst = which_m; + + cd_create_dialog_parent_num(837,0); + + put_placed_monst_in_dlog(); + + cd_add_label(837,18,"No",13); + cd_add_label(837,19,"Yes",13); + + for (i = 0; i < 4; i++) + cd_add_label(837,14 + i,attitude[i],57); + + while (dialog_not_toast) + ModalDialog(); + + cd_kill_dialog(837,0); + +} + +void put_placed_monst_adv_in_dlog() +{ + Str255 str; + short i; + + cdsin(838,20,store_which_placed_monst); + csit(838,9,scen_item_list.monst_names[store_placed_monst2.number]); + for (i = 22; i < 30; i++) + cd_set_led(838,i,0); + if (store_placed_monst2.time_flag < 3) + cd_set_led(838,22 + store_placed_monst2.time_flag,1); + else cd_set_led(838,21 + store_placed_monst2.time_flag,1); + csit(838,11,day_str_1[(store_placed_monst2.time_flag < 3) ? store_placed_monst2.time_flag : store_placed_monst2.time_flag - 1]); + csit(838,12,day_str_2[(store_placed_monst2.time_flag < 3) ? store_placed_monst2.time_flag : store_placed_monst2.time_flag - 1]); + CDSN(838,2,store_placed_monst2.monster_time); + CDSN(838,3,store_placed_monst2.time_code); + cd_set_led_range(838,30,40,(short) store_placed_monst2.spec_enc_code); + CDSN(838,4,store_placed_monst2.special_on_kill); + CDSN(838,5,store_placed_monst2.spec1); + CDSN(838,6,store_placed_monst2.spec2); +} +Boolean get_placed_monst_adv_in_dlog() +{ + Str255 str; + short i; + + store_placed_monst2.time_flag = cd_get_led_range(838,22,29); + if (store_placed_monst2.time_flag > 2) + store_placed_monst2.time_flag++; + store_placed_monst2.monster_time = CDGN(838,2); + if (cre(store_placed_monst2.monster_time,0,1000,"Given day must be from 0 to 1000.","",838) > 0) return FALSE; + store_placed_monst2.time_code = CDGN(838,3); + if (cre(store_placed_monst2.time_code,0,10,"Event code must be 0 (for no event) or from 1 to 10.","",838) > 0) return FALSE; + store_placed_monst2.special_on_kill = CDGN(838,4); + if (cre(store_placed_monst2.special_on_kill,-1,99,"Town special node number must be from 0 to 99 (or -1 for no special).","",838) > 0) return FALSE; + store_placed_monst2.spec1 = CDGN(838,5); + if (cre(store_placed_monst2.spec1,-1,299,"First part of special flag must be -1 (if this is to be ignored) or from 0 to 299.","",838) > 0) return FALSE; + store_placed_monst2.spec2 = CDGN(838,6); + if (cre(store_placed_monst2.spec2,-1,9,"Second part of special flag must be -1 (if this is to be ignored) or from 0 to 9.","",838) > 0) return FALSE; + + store_placed_monst2.spec_enc_code = cd_get_led_range(838,30,40); + return TRUE; +} + +void edit_placed_monst_adv_event_filter (short item_hit) +{ + Str255 str; + short i; + + switch (item_hit) { + case 16: + if (get_placed_monst_adv_in_dlog() == FALSE) + break; + dialog_not_toast = FALSE; + break; + case 17: + store_placed_monst2.number = 0; + dialog_not_toast = FALSE; + break; + + default: + cd_hit_led_range(838,22,29,item_hit); + cd_hit_led_range(838,30,40,item_hit); + if ((item_hit >= 22) && (item_hit <= 29)) { + csit(838,11,day_str_1[item_hit - 22]); + csit(838,12,day_str_2[item_hit - 22]); + } + break; + } +} + +creature_start_type edit_placed_monst_adv(creature_start_type monst_record) +{ + + short item_hit,i,store_dialog_answer; + Str255 temp_str; + char *time_labels[] = {"Always here","Appear on given day","Disappear on day", + "Sometimes here A","Sometimes here B","Sometimes here C", + "Appear when event","Disappear when event"}; + + store_placed_monst2 = monst_record; + + cd_create_dialog_parent_num(838,837); + + put_placed_monst_adv_in_dlog(); + + for (i = 0; i < 8; i++) + cd_add_label(838,22 + i,time_labels[i],57); + cd_add_label(838,30,"None",18); + for (i = 0; i < 10; i++) { + sprintf((char *) temp_str,"%d",i + 1); + cd_add_label(838,31 + i,(char *) temp_str,18); + } + + while (dialog_not_toast) + ModalDialog(); + + cd_kill_dialog(838,0); + return store_placed_monst2; +} + +void put_placed_item_in_dlog() +{ + Str255 str; + short i; + + cdsin(836,17,store_which_placed_item); + sprintf((char *) str,"X = %d, Y = %d",store_placed_item.item_loc.x,store_placed_item.item_loc.y); + csit(836,22,(char *) str); + csit(836,15,scen_item_list.scen_items[store_placed_item.item_code].full_name); + CDSN(836,2,store_placed_item.ability); + if (store_placed_item.always_there == TRUE) + cd_set_led(836,12,1); + else cd_set_led(836,12,0); + if (store_placed_item.property == TRUE) + cd_set_led(836,13,1); + else cd_set_led(836,13,0); + if (store_placed_item.contained == TRUE) + cd_set_led(836,14,1); + else cd_set_led(836,14,0); + + i = scen_item_list.scen_items[store_placed_item.item_code].graphic_num; + if (i >= 1000) + csp(836,4,950); + else csp(836,4,1800 + i); +} +Boolean get_placed_item_in_dlog() +{ + Str255 str; + short i; + + store_placed_item.ability = CDGN(836,2); + if ((store_placed_item.ability < -1) || (store_placed_item.ability > 2500)) { + give_error("Number of charges/amount of gold or food must be from 0 to 2500." + ,"If an item with charges (not gold or food) leave this at -1 for the item to have the default number of charges.",836); + return FALSE; + } + i = scen_item_list.scen_items[store_placed_item.item_code].variety; + if ((store_placed_item.ability == 0) && ((i == 3) || (i == 11))) { + give_error("You must assign gold or food an amount of at least 1.","",836); + return FALSE; + } + store_placed_item.always_there = cd_get_led(836,12); + store_placed_item.property = cd_get_led(836,13); + store_placed_item.contained = cd_get_led(836,14); + + town.preset_items[store_which_placed_item] = store_placed_item; + return TRUE; +} + +void edit_placed_item_event_filter (short item_hit) +{ + Str255 str; + short i; + creature_start_type store_m; + + switch (item_hit) { + case 3: + if (get_placed_item_in_dlog() == FALSE) + break; + dialog_not_toast = FALSE; + break; + case 20: + dialog_not_toast = FALSE; + break; + case 18: + i = choose_text_res(-2,0,399,store_placed_item.item_code,836,"Place which item?"); + if (i >= 0) { + store_placed_item.item_code = i; + put_placed_item_in_dlog(); + } + break; + + default: + for (i = 12; i <= 14; i++) + cd_flip_led(836,i,item_hit); + break; + } +} + +void edit_placed_item(short which_i) +{ + + short item_hit,i,store_dialog_answer; + Str255 temp_str; + + store_placed_item = town.preset_items[which_i]; + store_which_placed_item = which_i; + + cd_create_dialog_parent_num(836,0); + + cd_activate_item(836,19,0); + put_placed_item_in_dlog(); + + while (dialog_not_toast) + ModalDialog(); + + cd_kill_dialog(836,0); + +} + +void edit_sign_event_filter (short item_hit) +{ + short i; + Boolean had1 = FALSE, had2 = FALSE; + + switch (item_hit) { + case 9: case 4: + if (editing_town == FALSE) + CDGT(831,2,data_store->out_strs[100 + store_which_sign]); + else CDGT(831,2,town_strs[120 + store_which_sign]); + if (item_hit == 9) + dialog_not_toast = FALSE; + else { + if (item_hit == 3) + store_which_sign--; + else store_which_sign++; + if (store_which_sign < 0) + store_which_sign = (editing_town == TRUE) ? 14 : 7; + if (store_which_sign > (editing_town == TRUE) ? 14 : 7) + store_which_sign = 0; + } + break; + case 3: + dialog_not_toast = FALSE; + break; + } + cdsin(831,5,store_which_sign); + if (editing_town == FALSE) + CDST(831,2,data_store->out_strs[100 + store_which_sign]); + else CDST(831,2,town_strs[120 + store_which_sign]); +} + +void edit_sign(short which_sign,short picture) +{ + + short item_hit; + Str255 sign_text; + location view_loc; + Boolean sound_done = FALSE; + + store_which_sign = which_sign; + + cd_create_dialog_parent_num(831,0); + + if (picture >= 1000) + csp(831,6,950); + else if (picture >= 400) + csp(831,6,picture - 100); + else csp(831,6,picture); + + cdsin(831,5,store_which_sign); + if (editing_town == FALSE) + CDST(831,2,data_store->out_strs[100 + store_which_sign]); + else CDST(831,2,town_strs[120 + store_which_sign]); + //cd_activate_item(831,3,0); + //cd_activate_item(831,4,0); + while (dialog_not_toast) + ModalDialog(); + + cd_kill_dialog(831,0); +} + +Boolean save_out_strs() +{ + Str255 str; + short i; + + for (i = 0; i < 8; i++) { + CDGT(850,2 + i,(char *) str); + sprintf((char *)data_store->out_strs[i + 1],"%-29.29s",str); + if (str_do_delete[i] > 0) + current_terrain.info_rect[i].right = 0; + } + return TRUE; +} + +void put_out_strs_in_dlog() +{ + Str255 str; + short i; + + for (i = 0; i < 8; i++) { + if ((current_terrain.info_rect[i].right == 0) || (str_do_delete[i] > 0)) { + sprintf((char *) str,"Not yet placed."); + cd_activate_item(850,25 + i,0); + } + else sprintf((char *) str,"X = %d, Y = %d",current_terrain.info_rect[i].left, + current_terrain.info_rect[i].top); + csit(850,13 + i,(char *) str); + CDST(850,2 + i,data_store->out_strs[i + 1]); + } + +} + +void edit_out_strs_event_filter (short item_hit) +{ + Str255 str; + short i; + + switch (item_hit) { + case 10: + if (save_out_strs() == TRUE) + dialog_not_toast = FALSE; + break; + case 11: + dialog_not_toast = FALSE; + break; + default: + if ((item_hit >= 25) && (item_hit <= 32)) { + //sprintf((char *)data_store->out_strs[item_hit - 25 + 1],""); + CDST(850,2 + item_hit - 25,""); + str_do_delete[item_hit - 25] = 1; + put_out_strs_in_dlog(); + } + break; + } +} + +void edit_out_strs() +// ignore parent in Mac version +{ + short out_strs_hit,i,store_dialog_answer; + Str255 temp_str; + + for (i = 0; i < 8; i++) + str_do_delete[i] = 0; + + cd_create_dialog_parent_num(850,0); + + put_out_strs_in_dlog(); + + while (dialog_not_toast) + ModalDialog(); + + cd_kill_dialog(850,0); +} + + +Boolean save_town_strs() +{ + Str255 str; + short i; + + for (i = 0; i < 16; i++) { + CDGT(839,2 + i,(char *) str); + sprintf((char *)town_strs[i + 1],"%-29.29s",str); + if (str_do_delete[i] > 0) + t_d.room_rect[i].right = 0; + } + return TRUE; +} + +void put_town_strs_in_dlog() +{ + Str255 str; + short i; + + for (i = 0; i < 16; i++) { + if ((t_d.room_rect[i].right == 0) || (str_do_delete[i] > 0)) { + sprintf((char *) str,"Not yet placed."); + cd_activate_item(839,41 + i,0); + } + else sprintf((char *) str,"X = %d, Y = %d",t_d.room_rect[i].left, + t_d.room_rect[i].top); + csit(839,21 + i,(char *) str); + CDST(839,2 + i,town_strs[i + 1]); + } + +} + +void edit_town_strs_event_filter (short item_hit) +{ + Str255 str; + short i; + + switch (item_hit) { + case 18: + if (save_town_strs() == TRUE) + dialog_not_toast = FALSE; + break; + case 19: + dialog_not_toast = FALSE; + break; + default: + if ((item_hit >= 41) && (item_hit <= 56)) { + //sprintf((char *)town_strs[item_hit - 41 + 1],""); + CDST(839,2 + item_hit - 41,""); + str_do_delete[item_hit - 41] = 1; + put_town_strs_in_dlog(); + } + break; + } +} + +void edit_town_strs() +// ignore parent in Mac version +{ + short town_strs_hit,i,store_dialog_answer; + Str255 temp_str; + + for (i = 0; i < 16; i++) + str_do_delete[i] = 0; + + cd_create_dialog_parent_num(839,0); + + put_town_strs_in_dlog(); + + while (dialog_not_toast) + ModalDialog(); + + cd_kill_dialog(839,0); +} + + + +void pick_town_num_event_filter (short item_hit) +{ + Str255 str; + short i; + + switch (item_hit) { + case 3: + dialog_answer = CDGN(store_whigh_dlog,2); + if ((dialog_answer < 0) || (dialog_answer >= scenario.num_towns)) { + give_error("This number is out of the correct range. (0 to the number of towns minus 1)","",store_whigh_dlog); + break; + } + dialog_not_toast = FALSE; + break; + case 4: + dialog_answer = -1; + dialog_not_toast = FALSE; + break; + + } +} + +short pick_town_num(short which_dlog,short def) +// ignore parent in Mac version +{ + short town_strs_hit,i,store_dialog_answer; + Str255 temp_str,str2; + + store_whigh_dlog = which_dlog; + + cd_create_dialog_parent_num(store_whigh_dlog,0); + + CDSN(store_whigh_dlog,2,def); + cd_get_item_text(which_dlog,7,(char *) temp_str); + sprintf((char *) str2,"%s (0 - %d)",(char *) temp_str,scenario.num_towns - 1); + csit(which_dlog,7,(char *) str2); + + while (dialog_not_toast) + ModalDialog(); + + cd_kill_dialog(store_whigh_dlog,0); + return dialog_answer; +} + +void change_ter_event_filter (short item_hit) +{ + Str255 str; + short i; + + switch (item_hit) { + case 5: + a = CDGN(857,2); + b = CDGN(857,3); + c = CDGN(857,4); + if (cre(a,0,255,"Both terrain types must be from 0 to 255.","",857) == TRUE) break; + if (cre(b,0,255,"Both terrain types must be from 0 to 255.","",857) == TRUE) break; + if (cre(c,0,100,"The Chance must be from 0 to 100.","",857) == TRUE) break; + + dialog_not_toast = FALSE; + break; + case 6: + a = -1; b = -1; c = -1; + dialog_not_toast = FALSE; + break; + case 10: case 11: + i = CDGN(857,item_hit - 8); + i = choose_text_res(-4,0,255,i,857,"Which Terrain?"); + if (i >= 0) + CDSN(857,item_hit - 8,i); + break; + } +} + +void change_ter(short *change_from,short *change_to,short *chance) +// ignore parent in Mac version +{ + short town_strs_hit,i,store_dialog_answer; + Str255 temp_str; + + cd_create_dialog_parent_num(857,0); + + CDSN(857,2,0); + CDSN(857,3,0); + CDSN(857,4,100); + + while (dialog_not_toast) + ModalDialog(); + + *change_from = a; + *change_to = b; + *chance = c; + + cd_kill_dialog(857,0); +} + +void outdoor_details_event_filter (short item_hit) +{ + Str255 str; + short i; + + switch (item_hit) { + case 3: + CDGT(851,2,(char *) str); + str[29] = 0; + sprintf(data_store->out_strs[0],"%s",(char *) str); + dialog_not_toast = FALSE; + break; + + } +} + +void outdoor_details() +// ignore parent in Mac version +{ + short town_strs_hit,i,store_dialog_answer; + Str255 temp_str; + + + cd_create_dialog_parent_num(851,0); + + CDST(851,2,data_store->out_strs[0]); + sprintf((char *) temp_str,"X = %d, Y = %d",cur_out.x,cur_out.y); + csit(851,8,(char *) temp_str); + + while (dialog_not_toast) + ModalDialog(); + + cd_kill_dialog(851,0); +} + +void put_out_wand_in_dlog() +{ + Str255 str; + short i; + + cdsin(852,45,store_which_out_wand); + for (i = 0; i < 7; i++) + if (store_out_wand.monst[i] == 0) + csit(852, i + 7, "Empty"); + else { + get_str(str,-1,store_out_wand.monst[i]); + csit(852,i + 7,(char *) str); + } + for (i = 0; i < 3; i++) + if (store_out_wand.friendly[i] == 0) + csit(852, i + 7 + 7, "Empty"); + else { + get_str(str,-1,store_out_wand.friendly[i]); + csit(852,i + 7 + 7,(char *) str); + } + if (store_out_wand.cant_flee % 10 == 1) + cd_set_led(852,51,1); + else cd_set_led(852,51,0); + if (store_out_wand.cant_flee >= 10) + cd_set_led(852,53,1); + else cd_set_led(852,53,0); + CDSN(852,2,store_out_wand.spec_on_meet); + CDSN(852,3,store_out_wand.spec_on_win); + CDSN(852,4,store_out_wand.spec_on_flee); + CDSN(852,5,store_out_wand.end_spec1); + CDSN(852,6,store_out_wand.end_spec2); +} +Boolean get_out_wand_in_dlog() +{ + Str255 str; + short i; + + store_out_wand.spec_on_meet = CDGN(852,2); + store_out_wand.spec_on_win = CDGN(852,3); + store_out_wand.spec_on_flee = CDGN(852,4); + store_out_wand.end_spec1 = CDGN(852,5); + store_out_wand.end_spec2 = CDGN(852,6); + if (cre(store_out_wand.end_spec1, + -1,299,"First part of Stuff Done flag must be from 0 to 299 (or -1 if it's not used).","",852) == TRUE) return FALSE; + if (cre(store_out_wand.end_spec2, + -1,9,"Second part of Stuff Done flag must be from 0 to 9 (or -1 if it's not used).","",852) == TRUE) return FALSE; + if (cre(store_out_wand.spec_on_meet, + -1,59,"Outdoor Special Nodes run from 0 to 59 (or -1 if not used).","",852) == TRUE) return FALSE; + if (cre(store_out_wand.spec_on_win, + -1,59,"Outdoor Special Nodes run from 0 to 59 (or -1 if not used).","",852) == TRUE) return FALSE; + if (cre(store_out_wand.spec_on_flee, + -1,59,"Outdoor Special Nodes run from 0 to 59 (or -1 if not used).","",852) == TRUE) return FALSE; + + store_out_wand.cant_flee = 0; + if (cd_get_led(852,53) > 0) + store_out_wand.cant_flee += 10; + if (cd_get_led(852,51) > 0) + store_out_wand.cant_flee += 1; + + if (store_out_wand_mode == 0) + current_terrain.wandering[store_which_out_wand] = store_out_wand; + else current_terrain.special_enc[store_which_out_wand] = store_out_wand; + return TRUE; +} + +void edit_out_wand_event_filter (short item_hit) +{ + Str255 str; + short i,spec; + creature_start_type store_m; + + switch (item_hit) { + case 17: + if (get_out_wand_in_dlog() == FALSE) + break; + dialog_not_toast = FALSE; + break; + case 18: + dialog_not_toast = FALSE; + break; + case 19: + if (get_out_wand_in_dlog() == FALSE) break; + store_which_out_wand--; + if (store_which_out_wand < 0) store_which_out_wand = 3; + store_out_wand = (store_out_wand_mode == 0) ? + current_terrain.wandering[store_which_out_wand] : current_terrain.special_enc[store_which_out_wand]; + put_out_wand_in_dlog(); + break; + case 20: + if (get_out_wand_in_dlog() == FALSE) break; + store_which_out_wand++; + if (store_which_out_wand > 3) store_which_out_wand = 0; + store_out_wand = (store_out_wand_mode == 0) ? + current_terrain.wandering[store_which_out_wand] : current_terrain.special_enc[store_which_out_wand]; + put_out_wand_in_dlog(); + break; + + case 31: case 32: case 33: + if (get_out_wand_in_dlog() == FALSE) + break; + spec = CDGN(852,item_hit - 29); + if ((spec < 0) || (spec >= 60)) { + spec = get_fresh_spec(1); + if (spec < 0) { + give_error("You can't create a new special encounter because there are no more free special nodes.", + "To free a special node, set its type to No Special and set its Jump To special to -1.",852); + break; + } + CDSN(852,item_hit - 29,spec); + } + edit_spec_enc(spec,1,852); + if ((spec >= 0) && (spec < 60) && (current_terrain.specials[spec].pic < 0)) + CDSN(852,item_hit - 29,-1); + if (get_out_wand_in_dlog() == FALSE) + break; + break; + default: + if (get_out_wand_in_dlog() == FALSE) + break; + cd_flip_led(852,51,item_hit); + cd_flip_led(852,53,item_hit); + if ((item_hit >= 21) && (item_hit <= 27)) { + i = choose_text_res(-1,0,255,store_out_wand.monst[item_hit - 21],852,"Choose Which Monster:"); + if (i >= 0) store_out_wand.monst[item_hit - 21] = i; + put_out_wand_in_dlog(); + } + if ((item_hit >= 28) && (item_hit <= 30)) { + i = choose_text_res(-1,0,255,store_out_wand.friendly[item_hit - 28],852,"Choose Which Monster:"); + if (i >= 0) store_out_wand.friendly[item_hit - 28] = i; + put_out_wand_in_dlog(); + } + break; + } +} + +// mode 0 - wandering 1 - special +void edit_out_wand(short mode) +{ + + short item_hit,i,store_dialog_answer; + Str255 temp_str; + + store_which_out_wand = 0; + store_out_wand_mode = mode; + store_out_wand = (store_out_wand_mode == 0) ? current_terrain.wandering[0] : current_terrain.special_enc[0]; + + cd_create_dialog_parent_num(852,0); + + if (mode == 1) + csit(852,47,"Outdoor Special Encounter:"); + + put_out_wand_in_dlog(); + + while (dialog_not_toast) + ModalDialog(); + + cd_kill_dialog(852,0); + +} + +Boolean save_town_details() +{ + Str255 str; + short i; + + CDGT(832,2,(char *) str); + sprintf(town_strs[0],"%-29.29s",str); + town.town_chop_time = CDGN(832,3); + if (cre(town.town_chop_time,-1,10000,"The day the town becomes abandoned must be from 0 to 10000 (or -1 if it doesn't)." + ,"",832) == TRUE) return FALSE; + town.town_chop_key = CDGN(832,4); + if (cre(town.town_chop_key,-1,10,"The event which prevents the town from becoming abandoned must be from 1 to 10 (-1 or 0 for none)." + ,"",832) == TRUE) return FALSE; + town.lighting = cd_get_led_range(832,19,22); + town.max_num_monst = CDGN(832,5); + town.difficulty = CDGN(832,6); + if (cre(town.difficulty,0,10,"The town difficulty must be between 0 (easiest) and 10 (hardest)." + ,"",832) == TRUE) return FALSE; + + return TRUE; +} + +void put_town_details_in_dlog() +{ + Str255 str; + short i; + + CDST(832,2,town_strs[0]); + CDSN(832,3,town.town_chop_time); + CDSN(832,4,town.town_chop_key); + cd_set_led_range(832,19,22,town.lighting); + CDSN(832,5,town.max_num_monst); + CDSN(832,6,town.difficulty); + +} + +void edit_town_details_event_filter (short item_hit) +{ + Str255 str; + short i; + + switch (item_hit) { + case 7: + if (save_town_details() == TRUE) + dialog_not_toast = FALSE; + break; + default: + cd_hit_led_range(832,19,22,item_hit); + break; + } +} + +void edit_town_details() +// ignore parent in Mac version +{ + short town_details_hit,i,store_dialog_answer; + Str255 temp_str; + + cd_create_dialog_parent_num(832,0); + + put_town_details_in_dlog(); + + while (dialog_not_toast) + ModalDialog(); + + cd_kill_dialog(832,0); +} + +Boolean save_town_events() +{ + Str255 str; + short i; + + for (i = 0; i < 8; i++) { + town.timer_spec_times[i] = CDGN(833,2 + i); + town.timer_specs[i] = CDGN(833,10 + i); + if (cre(town.timer_specs[i],-1,99,"The town special nodes must be between 0 at 99 (or -1 for no special)." + ,"",833) == TRUE) return FALSE; + } + return TRUE; +} + +void put_town_events_in_dlog() +{ + Str255 str; + short i; + + for (i = 0; i < 8; i++) { + CDSN(833,2 + i,town.timer_spec_times[i]); + CDSN(833,10 + i,town.timer_specs[i]); + } + +} + +void edit_town_events_event_filter (short item_hit) +{ + Str255 str; + short i,spec; + + switch (item_hit) { + case 18: + if (save_town_events() == TRUE) + dialog_not_toast = FALSE; + break; + default: + if ((item_hit >= 26) && (item_hit <= 33)) { + if (save_town_events() == FALSE) + break; + spec = CDGN(833,item_hit - 26 + 10); + if ((spec < 0) || (spec > 99)) { + spec = get_fresh_spec(2); + if (spec < 0) { + give_error("You can't create a new special encounter because there are no more free special nodes.", + "To free a special node, set its type to No Special and set its Jump To special to -1.",833); + break; + } + CDSN(833,item_hit - 26 + 10,spec); + } + edit_spec_enc(spec,2,833); + if ((spec >= 0) && (spec < 100) && (town.specials[spec].pic < 0)) + CDSN(833,item_hit - 26 + 10,-1); + } + break; + } +} + +void edit_town_events() +// ignore parent in Mac version +{ + short advanced_town_hit,i,store_dialog_answer; + Str255 temp_str; + + + cd_create_dialog_parent_num(833,0); + + put_town_events_in_dlog(); + + while (dialog_not_toast) + ModalDialog(); + + cd_kill_dialog(833,0); +} + +Boolean save_advanced_town() +{ + Str255 str; + short i; + + for (i = 0; i < 4; i++) { + town.exit_specs[i] = CDGN(834,2 + i); + if (cre(town.exit_specs[i],-1,99,"The town exit specials must be between 0 at 99 (or -1 for no special)." + ,"",834) == TRUE) return FALSE; + town.exit_locs[i].x = CDGN(834,8 + i * 2); + if (cre(town.exit_locs[i].x,-1,47,"The town exit coordinates must be from 0 to 47 (or -1 if you want them ignored)." + ,"",834) == TRUE) return FALSE; + town.exit_locs[i].y = CDGN(834,9 + i * 2); + if (cre(town.exit_locs[i].y,-1,47,"The town exit coordinates must be from 0 to 47 (or -1 if you want them ignored)." + ,"",834) == TRUE) return FALSE; + } + town.spec_on_entry = CDGN(834,6); + town.spec_on_entry_if_dead = CDGN(834,7); + if (cre(town.spec_on_entry,-1,99,"The town entry specials must be from 0 to 99 (or -1 for no special)." + ,"",834) == TRUE) return FALSE; + if (cre(town.spec_on_entry_if_dead,-1,99,"The town entry specials must be from 0 to 99 (or -1 for no special)." + ,"",834) == TRUE) return FALSE; + scenario.town_hidden[cur_town] = cd_get_led(834,37); + return TRUE; +} + +void put_advanced_town_in_dlog() +{ + Str255 str; + short i; + + for (i = 0; i < 4; i++) { + CDSN(834,2 + i,town.exit_specs[i]); + CDSN(834,8 + i * 2,town.exit_locs[i].x); + CDSN(834,9 + i * 2,town.exit_locs[i].y); + } + CDSN(834,6,town.spec_on_entry); + CDSN(834,7,town.spec_on_entry_if_dead); + cd_set_led(834,37,scenario.town_hidden[cur_town]); + +} + +void edit_advanced_town_event_filter (short item_hit) +{ + Str255 str; + short i,spec; + + switch (item_hit) { + case 16: + if (save_advanced_town() == TRUE) + dialog_not_toast = FALSE; + break; + case 17: + dialog_not_toast = FALSE; + break; + case 37: + cd_flip_led(834,37,item_hit); + break; + } +} + +void edit_advanced_town() +// ignore parent in Mac version +{ + short advanced_town_hit,i,store_dialog_answer; + Str255 temp_str; + + + cd_create_dialog_parent_num(834,0); + + put_advanced_town_in_dlog(); + + while (dialog_not_toast) + ModalDialog(); + + cd_kill_dialog(834,0); +} + +Boolean save_town_wand() +{ + Str255 str; + short i,j; + + for (i = 0; i < 4; i++) + for (j = 0; j < 4; j++) + { + town.wandering[i].monst[j] = CDGN(835,2 + i * 4 + j); + if (cre(town.wandering[i].monst[j],0,255,"Wandering monsters must all be from 0 to 255 (0 means no monster)." + ,"",835) == TRUE) return FALSE; + } + + return TRUE; +} + +void put_town_wand_in_dlog() +{ + Str255 str; + short i,j; + + for (i = 0; i < 4; i++) + for (j = 0; j < 4; j++) + { + CDSN(835,2 + i * 4 + j,town.wandering[i].monst[j]); + } + +} + +void edit_town_wand_event_filter (short item_hit) +{ + Str255 str; + short i,j,spec; + + switch (item_hit) { + case 18: + if (save_town_wand() == TRUE) + dialog_not_toast = FALSE; + break; + case 27: case 28: case 29: case 30: + for (i = 0; i < 4; i++) { + j = choose_text_res(-1,0,255,town.wandering[item_hit - 27].monst[i],835,"Choose Which Monster:"); + if (j < 0) + i = 5; + else { + CDSN(835,2 + (item_hit - 27) * 4 + i,j); + } + } + break; + } +} + +void edit_town_wand() +// ignore parent in Mac version +{ + short town_wand_hit,i,store_dialog_answer; + Str255 temp_str; + + + cd_create_dialog_parent_num(835,0); + + put_town_wand_in_dlog(); + + while (dialog_not_toast) + ModalDialog(); + + cd_kill_dialog(835,0); +} + +Boolean save_basic_dlog() +{ + Str255 str; + short i,j; + + CDGT(821,2,talk_strs[store_which_talk_node]); + talk_strs[store_which_talk_node][30] = 0; + CDGT(821,3,talk_strs[160 + store_which_talk_node]); + CDGT(821,4,talk_strs[10 + store_which_talk_node]); + CDGT(821,5,talk_strs[20 + store_which_talk_node]); + CDGT(821,6,talk_strs[30 + store_which_talk_node]); + + return TRUE; +} + +void put_basic_dlog_in_dlog() +{ + Str255 str; + short i,j; + + cdsin(821,14,store_which_talk_node + cur_town * 10); + CDST(821,2,talk_strs[store_which_talk_node]); + CDST(821,3,talk_strs[160 + store_which_talk_node]); + CDST(821,4,talk_strs[10 + store_which_talk_node]); + CDST(821,5,talk_strs[20 + store_which_talk_node]); + CDST(821,6,talk_strs[30 + store_which_talk_node]); + +} + +void edit_basic_dlog_event_filter (short item_hit) +{ + Str255 str; + short i,j,spec; + + switch (item_hit) { + case 7: + if (save_basic_dlog() == TRUE) + dialog_not_toast = FALSE; + break; + case 8: + dialog_not_toast = FALSE; + break; + case 9: + if (save_basic_dlog() == FALSE) break; + store_which_talk_node--; + if (store_which_talk_node < 0) store_which_talk_node = 9; + put_basic_dlog_in_dlog(); + break; + case 10: + if (save_basic_dlog() == FALSE) break; + store_which_talk_node++; + if (store_which_talk_node > 9) store_which_talk_node = 0; + put_basic_dlog_in_dlog(); + break; + } +} + +void edit_basic_dlog(short which_node) +// ignore parent in Mac version +{ + short basic_dlog_hit,i,store_dialog_answer; + Str255 temp_str; + + store_which_talk_node = which_node; + + cd_create_dialog_parent_num(821,0); + + cd_attach_key(821,10,0); + cd_attach_key(821,9,0); + + put_basic_dlog_in_dlog(); + + while (dialog_not_toast) + ModalDialog(); + + cd_kill_dialog(821,0); +} + +Boolean save_talk_node() +{ + Str255 str; + short i; + + + store_talk_node.personality = CDGN(817,2); + if ((store_talk_node.personality >= 0) && + ((store_talk_node.personality < cur_town * 10) || (store_talk_node.personality >= (cur_town + 1) * 10))) { + sprintf((char *) str,"The legal range for personalities in this town is from %d to %d.", + cur_town * 10,cur_town * 10 + 9,817); + give_error("Personalities in talk nodes must be -1 (for unused node), -2 (all personalities use) or in the legal range of personalities in this town.", + (char *) str,817); + return FALSE; + } + CDGT(817,3,(char *) str); + for (i = 0; i < 4; i++) { + store_talk_node.link1[i] = str[i]; + if ((str[i] < 97) || (str[i] > 122)) { + give_error("The words this node is the response to must be at least 4 characters long, and all characters must be lower case letters.", + "",817); + return FALSE; + } + } + CDGT(817,4,(char *) str); + for (i = 0; i < 4; i++) { + store_talk_node.link2[i] = str[i]; + if ((str[i] < 97) || (str[i] > 122)) { + give_error("The words this node is the response to must be at least 4 characters long, and all characters must be lower case letters.", + "",817); + return FALSE; + } + } + for (i = 0; i < 4; i++) + store_talk_node.extras[i] = CDGN(817,5 + i); + + switch (store_talk_node.type) { + case 1: case 2: + if (cre(store_talk_node.extras[0],0,299,"First part of Stuff Done flag must be from 0 to 299.","",817) > 0) return FALSE; + if (cre(store_talk_node.extras[1],0,9,"Second part of Stuff Done flag must be from 0 to 9.","",817) > 0) return FALSE; + break; + case 3: + if (cre(store_talk_node.extras[0],0,1000,"Inn cost must be from 0 to 1000.","",817) > 0) return FALSE; + if (cre(store_talk_node.extras[1],0,3,"Inn quality must be from 0 to 3.","",817) > 0) return FALSE; + break; + case 5: + if (cre(store_talk_node.extras[1],0,9,"Event must be from 0 to 9. (0 means no event)","",817) > 0) return FALSE; + break; + case 6: + if (cre(store_talk_node.extras[0],0,199,"Town number must be from 0 to 199.","",817) > 0) return FALSE; + break; + case 7: case 9: case 10: case 11: case 12: + if (cre(store_talk_node.extras[0],0,6,"Cost adjustment must be from 0 (cheapest) to 6 (most expensive).","",817) > 0) return FALSE; + break; + case 17: + if (cre(store_talk_node.extras[0],0,6,"Enchantment type must be from 0 to 6. See the documentation for a list of possible abilities.","",817) > 0) return FALSE; + break; + case 19: case 23: + if (cre(store_talk_node.extras[1],0,299,"First part of Stuff Done flag must be from 0 to 299.","",817) > 0) return FALSE; + if (cre(store_talk_node.extras[2],0,9,"Second part of Stuff Done flag must be from 0 to 9.","",817) > 0) return FALSE; + break; + case 20: case 21: + if (cre(store_talk_node.extras[1],0,29,"The first boat/horse must be in the legal range (0 - 29).","",817) > 0) return FALSE; + break; + case 22: + if (cre(store_talk_node.extras[0],0,49,"The special item must be in the legal range (0 - 49).","",817) > 0) return FALSE; + break; + case 29: + if (cre(store_talk_node.extras[0],-1,99,"The town special node called must be in the legal range (0 - 99), or -1 for No Special.","",817) > 0) return FALSE; + break; + case 30: + if (cre(store_talk_node.extras[0],-1,255,"The scenario special node called must be in the legal range (0 - 255), or -1 for No Special.","",817) > 0) return FALSE; + break; + } + + CDGT(817,9,talk_strs[40 + store_which_talk_node * 2]); + CDGT(817,10,talk_strs[40 + store_which_talk_node * 2 + 1]); + + talking.talk_nodes[store_which_talk_node] = store_talk_node; + + return TRUE; +} + +void put_talk_node_in_dlog() +{ + Str255 str; + short i; + + CDSN(817,2,store_talk_node.personality); + str[4] = 0; + for (i = 0; i < 4; i++) + str[i] = store_talk_node.link1[i]; + CDST(817,3,(char *) str); + for (i = 0; i < 4; i++) + str[i] = store_talk_node.link2[i]; + CDST(817,4,(char *) str); + get_str(str,40,store_talk_node.type * 7 + 1); + csit(817,15,(char *) str); + get_str(str,40,store_talk_node.type * 7 + 2); + csit(817,16,(char *) str); + get_str(str,40,store_talk_node.type * 7 + 3); + csit(817,17,(char *) str); + get_str(str,40,store_talk_node.type * 7 + 4); + csit(817,18,(char *) str); + get_str(str,40,store_talk_node.type * 7 + 5); + csit(817,19,(char *) str); + get_str(str,40,store_talk_node.type * 7 + 6); + csit(817,20,(char *) str); + get_str(str,40,store_talk_node.type * 7 + 7); + csit(817,21,(char *) str); + for (i = 0; i < 4; i++) + CDSN(817,5 + i,store_talk_node.extras[i]); + CDST(817,9,talk_strs[40 + store_which_talk_node * 2]); + CDST(817,10,talk_strs[40 + store_which_talk_node * 2 + 1]); + + if ((store_talk_node.type == 7) || (store_talk_node.type == 9) || + (store_talk_node.type == 10) || (store_talk_node.type == 11)) + cd_activate_item(817,37,1); + else cd_activate_item(817,37,0); + if (last_talk_node[0] >= 0) + cd_activate_item(817,13,1); + else cd_activate_item(817,13,0); + if ((store_talk_node.type != 29) && (store_talk_node.type != 30)) + cd_activate_item(817,38,0); + else cd_activate_item(817,38,1); + +} + +void edit_talk_node_event_filter (short item_hit) +{ + Str255 str; + short i,j,node_to_change_to = -1,spec; + + switch (item_hit) { + case 11: + if (save_talk_node() == TRUE) + dialog_not_toast = FALSE; + break; + case 13: //go_back + if (save_talk_node() == FALSE) + break; + for (i = 0; i < 60; i++) + if (last_talk_node[i] < 0) { + node_to_change_to = last_talk_node[i - 1]; + if (i > 0) + last_talk_node[i - 1] = -1; + i = 256; + } + break; + case 12: + + dialog_not_toast = FALSE; break; + case 14: + if (save_talk_node() == FALSE) + break; + + spec = -1; + for (j = 0; j < 60; j++) + if ((talking.talk_nodes[j].personality < 0) && (talking.talk_nodes[j].extras[3] < 0)) { + spec = j; + j = 60; + } + + if (spec < 0) { + give_error("You have used all 60 available talk nodes. To create fresh dialogue, go back and reuse and old one.", + "",817); + break; + } + + for (i = 0; i < 60; i++) + if (last_talk_node[i] < 0) { + last_talk_node[i] = store_which_talk_node; + node_to_change_to = spec; + i = 60; + } + break; + + case 28: + if (save_talk_node() == FALSE) + break; + i = choose_text_res(-5,0,30,store_talk_node.type,817,"What Talking Node type?"); + if (i >= 0) { + store_talk_node.type = i; + if ((store_talk_node.type == 29) || (store_talk_node.type == 30)) + store_talk_node.extras[0] = -1; + put_talk_node_in_dlog(); + } + + break; + case 37: + i = CDGN(817,6); + if (store_talk_node.type == 9) { + i = choose_text_res(38,1,32,i + 1,817,"What is the first spell in the shop?"); + if (i >= 0) + CDSN(817,6,i - 1); + } + else if (store_talk_node.type == 10) { + i = choose_text_res(38,50,81,i + 50,817,"What is the first spell in the shop?"); + if (i >= 0) + CDSN(817,6,i - 50); + } + else if (store_talk_node.type == 11) { + i = choose_text_res(38,100,119,i + 100,817,"What is the first recipe in the shop?"); + if (i >= 0) + CDSN(817,6,i - 100); + } + else { + i = choose_text_res(-2,0,399,i,817,"What is the first item in the shop?"); + if (i >= 0) + CDSN(817,6,i); + } + break; + case 38: + if (save_talk_node() == FALSE) + break; + spec = CDGN(817,5); + if ((spec < 0) || (spec >= 100)) { + if (store_talk_node.type == 29) + spec = get_fresh_spec(2); + else spec = get_fresh_spec(0); + if (spec < 0) { + give_error("You can't create a new special encounter because there are no more free special nodes.", + "To free a special node, set its type to No Special and set its Jump To special to -1.",817); + break; + } + CDSN(817,5,spec); + } + if (store_talk_node.type == 29) + edit_spec_enc(spec,2,817); + else edit_spec_enc(spec,0,817); + if (store_talk_node.type == 29) { + if ((spec >= 0) && (spec < 100) && (town.specials[spec].pic < 0)) + CDSN(817,5,-1); + } + else { + if ((spec >= 0) && (spec < 256) && (scenario.scen_specials[spec].pic < 0)) + CDSN(817,5,-1); + } + if (save_talk_node() == FALSE) + break; + break; + } + if (node_to_change_to >= 0) { + store_which_talk_node = node_to_change_to; + store_talk_node = talking.talk_nodes[store_which_talk_node]; + if (store_talk_node.extras[3] < 0) + store_talk_node.extras[3] = 0; + put_talk_node_in_dlog(); + } +} + +void edit_talk_node(short which_node,short parent_num) +// ignore parent in Mac version +{ + short talk_node_hit,i,store_dialog_answer; + Str255 temp_str; + + store_which_talk_node = which_node; + for (i = 0; i < 60; i++) + last_talk_node[i] = -1; + //last_talk_node[0] = store_which_mode * 1000 + store_which_talk_node; + store_talk_node = talking.talk_nodes[store_which_talk_node]; + if (store_talk_node.extras[3] < 0) + store_talk_node.extras[3] = 0; + + cd_create_dialog_parent_num(817,parent_num); + + cd_activate_item(817,13,0); + cd_activate_item(817,37,0); + + if ((store_talk_node.type != 29) && (store_talk_node.type != 30)) + cd_activate_item(817,38,0); + else cd_activate_item(817,38,1); + put_talk_node_in_dlog(); + + while (dialog_not_toast) + ModalDialog(); + + cd_kill_dialog(817,0); +} + +void pick_out_event_filter (short item_hit) +{ + Str255 temp_str; + short i,j,spec; + + switch (item_hit) { + case 2: + dialog_answer = store_cur_loc.x * 100 + store_cur_loc.y; + dialog_not_toast = FALSE; + break; + case 3: + dialog_answer = -1; + dialog_not_toast = FALSE; + break; + case 12: + if (store_cur_loc.x == 0) SysBeep(20); + else store_cur_loc.x--; + break; + case 13: + if (store_cur_loc.x >= scenario.out_width - 1) SysBeep(20); + else store_cur_loc.x++; + break; + case 14: + if (store_cur_loc.y == 0) SysBeep(20); + else store_cur_loc.y--; + break; + case 15: + if (store_cur_loc.y >= scenario.out_height - 1) SysBeep(20); + else store_cur_loc.y++; + break; + } + sprintf((char *) temp_str,"X = %d",store_cur_loc.x); + csit(854,8,(char *) temp_str); + sprintf((char *) temp_str,"Y = %d",store_cur_loc.y); + csit(854,11,(char *) temp_str); +} + +short pick_out(location default_loc) +// ignore parent in Mac version +{ + short basic_dlog_hit,i,store_dialog_answer; + Str255 temp_str; + + store_cur_loc = default_loc; + + cd_create_dialog_parent_num(854,0); + + cdsin(854,7,scenario.out_width); + cdsin(854,10,scenario.out_height); + sprintf((char *) temp_str,"X = %d",store_cur_loc.x); + csit(854,8,(char *) temp_str); + sprintf((char *) temp_str,"Y = %d",store_cur_loc.y); + csit(854,11,(char *) temp_str); + + while (dialog_not_toast) + ModalDialog(); + + cd_kill_dialog(854,0); + return dialog_answer; +} + +void new_town_event_filter (short item_hit) +{ + Str255 temp_str; + short i,j,spec; + + switch (item_hit) { + case 3: + dialog_answer = 1; + dialog_not_toast = FALSE; + break; + case 23: + dialog_answer = -1; + dialog_not_toast = FALSE; + break; + default: + cd_hit_led_range(830,11,13,item_hit); + cd_hit_led_range(830,18,20,item_hit); + break; + } + +} + +Boolean new_town(short which_town) +// ignore parent in Mac version +{ + short basic_dlog_hit,i,j,store_dialog_answer; + Str255 temp_str; + short size = 0,preset = 0; + + + cd_create_dialog_parent_num(830,0); + + cdsin(830,22,which_town); + cd_set_led(830,12,1); + cd_set_led(830,18,1); + sprintf((char *) temp_str,"Town name"); + CDST(830,2,(char *) temp_str); + + while (dialog_not_toast) + ModalDialog(); + + size = cd_get_led_range(830,11,13); + preset = cd_get_led_range(830,18,20); + CDGT(830,2,(char *) temp_str); + temp_str[30] = 0; + cd_kill_dialog(830,0); + if (dialog_answer < 0) + return FALSE; + + scenario.num_towns++; + scenario.town_size[which_town] = size; + scenario.town_hidden[which_town] = 0; + cur_town = which_town; + scenario.last_town_edited = cur_town; + init_town(size); + strcpy(town_strs[0],(char *) temp_str); + town_type = size; + + for (i = 0; i < max_dim[size]; i++) + for (j = 0; j < max_dim[size]; j++) + switch (preset) { + case 0: + t_d.terrain[i][j] = 0; + break; + case 1: + t_d.terrain[i][j] = 2; + break; + case 2: + t_d.terrain[i][j] = 2; + if (get_ran(1,0,8) == 0) + t_d.terrain[i][j] = 3; + else if (get_ran(1,0,10) == 0) + t_d.terrain[i][j] = 4; + break; + } + + return TRUE; +} + +// before calling this, be sure to do all checks to make sure it's safe. +void delete_last_town() +{ + scenario.num_towns--; + scenario.town_size[scenario.num_towns] = 0; + scenario.town_hidden[scenario.num_towns] = 0; + scenario.town_data_size[scenario.num_towns][0] = 0; + scenario.town_data_size[scenario.num_towns][1] = 0; + scenario.town_data_size[scenario.num_towns][2] = 0; + scenario.town_data_size[scenario.num_towns][3] = 0; + scenario.town_data_size[scenario.num_towns][4] = 0; + save_scenario(); +} + +void pick_import_town_event_filter (short item_hit) +{ + Str255 str; + short i; + + switch (item_hit) { + case 3: + dialog_answer = CDGN(store_whigh_dlog,2); + if (dialog_answer < 0) { + give_error("This number is out of the correct range. It must be at least 0.","",store_whigh_dlog); + break; + } + dialog_not_toast = FALSE; + break; + case 8: + dialog_answer = -1; + dialog_not_toast = FALSE; + break; + + } +} + +short pick_import_town(short which_dlog,short def) +// ignore parent in Mac version +{ + short town_strs_hit,i,store_dialog_answer; + Str255 temp_str,str2; + + store_whigh_dlog = which_dlog; + + cd_create_dialog_parent_num(store_whigh_dlog,0); + + CDSN(store_whigh_dlog,2,0); + + while (dialog_not_toast) + ModalDialog(); + + cd_kill_dialog(store_whigh_dlog,0); + return dialog_answer; +} + + diff --git a/Win32/Scenarios Editor/townout.h b/Win32/Scenarios Editor/townout.h new file mode 100644 index 00000000..fb30517e --- /dev/null +++ b/Win32/Scenarios Editor/townout.h @@ -0,0 +1,62 @@ +void init_town(short size); +void init_out(); +void edit_placed_monst(short which_m); +void edit_placed_monst_event_filter (short item_hit); +Boolean get_placed_monst_in_dlog(); +void put_placed_monst_in_dlog(); +creature_start_type edit_placed_monst_adv(creature_start_type monst_record); +void edit_placed_monst_adv_event_filter (short item_hit); +Boolean get_placed_monst_adv_in_dlog(); +void put_placed_monst_adv_in_dlog(); +void edit_sign(short which_sign,short picture); +void edit_sign_event_filter (short item_hit); +Boolean save_out_strs(); +void put_out_strs_in_dlog(); +void edit_out_strs_event_filter (short item_hit); +void edit_out_strs(); +Boolean save_town_strs(); +void put_town_strs_in_dlog(); +void edit_town_strs_event_filter (short item_hit); +void edit_town_strs(); +void pick_town_num_event_filter (short item_hit); +short pick_town_num(short which_dlog,short def); +void change_ter(short *change_from,short *change_to,short *chance); +void change_ter_event_filter (short item_hit); +void edit_out_wand(short mode); +void edit_out_wand_event_filter (short item_hit); +Boolean get_out_wand_in_dlog(); +void put_out_wand_in_dlog(); +void outdoor_details_event_filter (short item_hit); +void outdoor_details(); +void edit_town_details(); +void edit_town_details_event_filter (short item_hit); +void put_town_details_in_dlog(); +Boolean save_town_details(); +void edit_town_events(); +void edit_town_events_event_filter (short item_hit); +void put_town_events_in_dlog(); +Boolean save_town_events(); +void edit_advanced_town(); +void edit_advanced_town_event_filter (short item_hit); +void put_advanced_town_in_dlog(); +Boolean save_advanced_town(); +void edit_basic_dlog(short which_node); +void edit_basic_dlog_event_filter (short item_hit); +void put_basic_dlog_in_dlog(); +Boolean save_basic_dlog(); +void edit_talk_node(short which_node,short parent_num); +void edit_talk_node_event_filter (short item_hit); +void put_talk_node_in_dlog(); +Boolean save_talk_node(); +void pick_out_event_filter (short item_hit); +short pick_out(location default_loc); +void pick_import_town_event_filter (short item_hit); +short pick_import_town(short which_dlog,short def); +Boolean new_town(short which_town); +void new_town_event_filter (short item_hit); +void edit_placed_item_event_filter (short item_hit); +void edit_placed_item(short which_i); + +void delete_last_town(); +void edit_town_wand_event_filter (short item_hit); +void edit_town_wand();