From f688cd3f7ed3bedb5a637bb7a5c4d561a51c0086 Mon Sep 17 00:00:00 2001 From: Chokboyz Date: Thu, 16 Jul 2009 23:31:09 +0000 Subject: [PATCH] Initial Classic BoE version 1.0 import : Changelog : Classic Blades of Exile version 1.0 : - Added a new item ability : Call a scenario special when using the item. The special called is specified by the ability strength. The type of scenario to call depends of the magic_use_type (the boxes from help pc (0) to harm all (4)) : 0 is only local, 1 is town local and out global, 2 is town global and out local and 3 is only global. If the number of charge is greater than 0, then using the item takes one charge. If not, the item can be used at will. - Changed the "Set SDF" debug command to display the value of the specified SDF if value to set it to is -1 (BoA style). - Added a missing compatibility switch from the introduced "Specials interrupt wait/rest" feature. - Misc. battlefield adjustment (forest battlefield doesn't show a road anymore, road battlefields appear correctly, cave bridge now has cave trims, ...) - Fixed a bug where an absent boat or horse could prevent a pc from entering a square while in outdoor combat. - Trims now use the next terrain type (cave, grass, mountain) when drawn. - Fixed a potential negative pointer to an array. - Readded Spidweb logo intro sound. - Event Timers will now triggers even when resting (compatibility switch available) - Stairway can now be called in any mode except outdoor : town, looking, talking, even fighting (put in fight mode at destination). - The three basics scenarios are no longer listed in the custom scenario list. - Talking mode : fixed a typo which would prevent the keyword "name" from giving the name dialogue. Added the keywords "buy" (for purchase) and "bye" to end conversation. - Time for event timers is now taken into account correctly while resting Outdoor/ in Inn / via "Have a Rest Node". The "Change Time" node is unchanged. - Added a preference to show a talk entry field next to "Ask About" (like in older Exiles) for direct typing. - Fixed clipping error in the main menu screen for high resolutions. - Added the Ctrl+N shortcut who was advertised but not working. - Gold is now updated after training. - If not using special messages, a "Move Party" node won't mess with talking responses anymore. - Affect Gold/Food nodes could give more gold/food than the maximum allowed. Fixed. - Deleted a check that was destroying items with "type Flag" 15 first. - Calling add_string_to_buf() with an empty string now does nothing. Classic Scenario Editor version 1.0 : - Added a switch to the Scenario Details to bypass the automatic difficulty adjust - Added the ability to play sound asynchronously (use -sound_number instead of sound_number). - If a custom monster pic was shown in the monster dialog and a non-custom monster was loaded via the arrows, the pic was always drawn from the custom sheet. Fixed. - Cancelling while choosing an item ability won't reset the item ability to "No ability" anymore. - Added a "Change Town Lightning" node. (StarEye a.k.a *i) - Loading a town in the main menu won't get into editing mode automatically anymore. - Added an option in the Town Advanced details to prevent the mapping (like in older Exiles). - Added a "Display picture" node, that living up to its name, displays a picture. Bitmaps (BMP) are the only supported format but image can be of any size (be warned that if the image is larger/wider than the screen, it will be streched to fit, meaning a (potentially substancial) loss of quality). The name of the file is search in the scenario special strings (160 to 259) as specified in the node ex1a field. The format must be "[eventual path]filename.bmp". The base search folder is "[folder_the_scenario_is_in]/scenario_name.exr/". - Corrected the "Type Flag" description text (is between 0 and 255). - Modified the "Has Enough Mage Lore?" node into a general statistic check node. (StarEye a.k.a *i) Here is a description of fields : ex1a: how much of skill ex1b: special to call if enough ex2a: skill index (-1 defaults to mage lore to preserve compatibility) 0 - 18 corresponding skill, 19 - Current Health, 20 - Max Health, 21 - Current Spell Points, 22 - Max Spell Points, 23 - Experience, 24 - Skill points, 25 - Level. ex2b: 0, others - cumulative, 1 - highest, 2 - average, 3 - lowest, 10 + x - that PC. (-1 defaults to mage lore to preserve compatibility) - Added a "Has enough species ?" node, which checks if the party has (at least) a specified number of character with a given race. (StarEye a.k.a *i) - Modified the "Give ... spells" nodes to either take (spec.1b = 0) or give (spec.1b = 1) spells and have access to low level spells (spec.1a = 100 + spell_number, with 0 <= spell_number <= 29 ) (StarEye a.k.a *i) - Added an option in Town Advanced Details to prevent Magic Mapping from being cast (already included in the Map Unavailable option). - Added an option in Town Advanced Details that specifies a town special to call if the town becomes hostile (for compatibility reasons the special 0 can't be called in legacy scenarios). - Added a "Change Creature Attitude" node in Town specs : spec.ex1a is the number of the monster in the current town and ex.1b is the attitude to set it to (0 - Friendly, Docile, 1 - Hostile, Type A, 2 - Friendly, Will fight, 3 - Hostile, Type B). - Modified the "Make town hostile" node to "Set Town Attitude". Spec.ex1a is 0 for hostile, 1 for friendly. The dead part (2) is currently non functionnal. Classic Character Editor version 1.1 : - The party is in info bar has been extended an placed under the main window (now that subfolders can used, the scen_name can be pretty long) - In Edit skill, you could decrease health and spell points to negative values. Fixed. Chokboyz git-svn-id: http://openexile.googlecode.com/svn/trunk@113 4ebdad44-0ea0-11de-aab3-ff745001d230 --- Blades of Exile Char Editor/BLADPCED.CPP | 2 +- Blades of Exile Char Editor/BLADPCED.RC | 2 +- Blades of Exile Char Editor/Changes_CE.txt | 34 +- Blades of Exile Char Editor/EDACTION.CPP | 4 +- Blades of Exile/ACTIONS.CPP | 92 ++- Blades of Exile/BLADES.CPP | 6 +- Blades of Exile/BLADES.RC | 1 + Blades of Exile/COMBAT.CPP | 22 +- Blades of Exile/CONSTS.H | 11 +- Blades of Exile/Changes.txt | 124 +++- Blades of Exile/DLGUTILS.CPP | 112 +++- Blades of Exile/DLOGTOOL.CPP | 168 +++++- Blades of Exile/DLOGTOOL.H | 3 + Blades of Exile/FILEIO.CPP | 55 +- Blades of Exile/GAMEDLOG.RC | 34 +- Blades of Exile/GLOBAL.H | 18 +- Blades of Exile/GLOBVAR.CPP | 11 +- Blades of Exile/GLOBVAR.H | 10 +- Blades of Exile/GRAPHICS.CPP | 184 ++++-- Blades of Exile/GRAPHUTL.CPP | 20 +- Blades of Exile/GRAPHUTL.H | 1 + Blades of Exile/ITEMS.CPP | 48 +- Blades of Exile/ITEMS.H | 2 +- Blades of Exile/MONSTER.CPP | 10 +- Blades of Exile/NEWGRAPH.CPP | 9 +- Blades of Exile/PARTY.CPP | 52 +- Blades of Exile/PC.CPP | 2 +- Blades of Exile/SPECIALS.CPP | 668 ++++++++++++++++++--- Blades of Exile/SPECIALS.H | 2 +- Blades of Exile/TEXT.CPP | 2 + Blades of Exile/TOWN.CPP | 48 +- Scenario Editor/BLSCENED.CPP | 4 +- Scenario Editor/BLSCENED.RC | 12 +- Scenario Editor/Changes_SE.txt | 134 +++++ Scenario Editor/GAMEDLOG.RC | 18 +- Scenario Editor/GLOBAL.H | 6 +- Scenario Editor/GRAPHICS.CPP | 8 - Scenario Editor/KEYDLGS.CPP | 8 +- Scenario Editor/SCENARIO.CPP | 25 +- Scenario Editor/STRINGS.RC | 54 +- Scenario Editor/TACTIONS.CPP | 2 +- Scenario Editor/TFILEIO.CPP | 2 +- Scenario Editor/townout.cpp | 22 +- 43 files changed, 1668 insertions(+), 384 deletions(-) create mode 100644 Scenario Editor/Changes_SE.txt diff --git a/Blades of Exile Char Editor/BLADPCED.CPP b/Blades of Exile Char Editor/BLADPCED.CPP index 7fabdcc2..1c4bd81f 100644 --- a/Blades of Exile Char Editor/BLADPCED.CPP +++ b/Blades of Exile Char Editor/BLADPCED.CPP @@ -175,7 +175,7 @@ int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR, int nCm } mainPtr = CreateWindow (szAppName, - "Blades of Exile Editor", + "Classic Blades of Exile Character Editor 1.1", WS_OVERLAPPEDWINDOW, 0, 0, diff --git a/Blades of Exile Char Editor/BLADPCED.RC b/Blades of Exile Char Editor/BLADPCED.RC index 6f7754c9..d7eed3a3 100644 --- a/Blades of Exile Char Editor/BLADPCED.RC +++ b/Blades of Exile Char Editor/BLADPCED.RC @@ -748,7 +748,7 @@ STYLE WS_POPUP | WS_DLGFRAME { LTEXT "1_63", 1, 434, 268, 61, 20 LTEXT "5_716", 2, 6, 6, 36, 36 - LTEXT "Classic Blades of Exile Character Editor v1.0.0 |Released under the GNU General Public License, version 2.", 3, 50, 6, 358, 34 + LTEXT "Classic Blades of Exile Character Editor v1.1 |Released under the GNU General Public License, version 2.", 3, 50, 6, 358, 34 LTEXT "Comments and questions? Feel free to express yourself on the Irony Central Board: http://www.ironycentral.com/forum/", 5, 50, 178, 354, 32 LTEXT "Spiderweb Software web page: http://www.spidweb.com", 6, 60, 211, 354, 53 LTEXT "The Blades of Exile Editor was originally created by Spiderweb Software - _Where our aberrations become your reality._ ||_Blades of Exile_ and Spiderweb Software are trademarks of Spiderweb Software.", 7, 50, 91, 410, 51 diff --git a/Blades of Exile Char Editor/Changes_CE.txt b/Blades of Exile Char Editor/Changes_CE.txt index 3db5a6e4..b6594407 100644 --- a/Blades of Exile Char Editor/Changes_CE.txt +++ b/Blades of Exile Char Editor/Changes_CE.txt @@ -1,12 +1,19 @@ Changes : -Beta 1 -- The editor now display the filename of the scenario you are in. -- The editor now get the list of items from the scenario you're in. If not in a scenario, bladbase.exs is used. (clicking a item with food (resp. gold) type will give a random (1-20) amount of food (resp. gold).) -- References to registration and shareware are removed. -- Status Screen now show Food, Gold and Day. -- Corrected the garbled status due to a non-alive character (Ishad Nha) -Beta 2 +Version 1.1 : + +- The party is in info bar has been extended an placed under the main window (now that subfolders can used, the scen_name can be pretty long) +- In Edit skill, you could decrease health and spell points to negative values. Fixed. + +Version 1.0 : + +- The character editor now search the right help file. +- If sounds are desactivated in the game, they will now be desactivated in the character editor as well. +- Reorganised menus. +- Implemented a "Save as" option. "Save" now overwrite the loaded file. + +Beta 2 : + - Corrected the edit day option so that it sets the day to the one specified and not to the day after. - Fixed the saving function : now changes can be saved outdoors (that was crashing at save stored_items making give_map non functional). That also fixes the stored items arrays being filled with items from current town. @@ -14,8 +21,11 @@ That also fixes the stored items arrays being filled with items from current tow - Giving PC items from a Mac made scenario doesn't crash the game anymore (overall Mac scenario support added) - Cleaned the ressource file. The executable is now smaller. - On give items : the editor now tries to load the bladbase.exs file if the scenario file is not found. If can't locate the bladbase, the items menus are grayed. -Version 1.0 : -- The character editor now search the right help file. -- If sounds are desactivated in the game, they will now be desactivated in the character editor as well. -- Reorganised menus. -- Implemented a "Save as" option. "Save" now overwrite the loaded file. \ No newline at end of file + +Beta 1 : + +- The editor now display the filename of the scenario you are in. +- The editor now get the list of items from the scenario you're in. If not in a scenario, bladbase.exs is used. (clicking a item with food (resp. gold) type will give a random (1-20) amount of food (resp. gold).) +- References to registration and shareware are removed. +- Status Screen now show Food, Gold and Day. +- Corrected the garbled status due to a non-alive character (Ishad Nha) \ No newline at end of file diff --git a/Blades of Exile Char Editor/EDACTION.CPP b/Blades of Exile Char Editor/EDACTION.CPP index 13a82b0c..11e0e9cc 100644 --- a/Blades of Exile Char Editor/EDACTION.CPP +++ b/Blades of Exile Char Editor/EDACTION.CPP @@ -449,7 +449,7 @@ Boolean spend_xp_event_filter (short item_hit) case 3: case 4: - if ((store_h >= 250) && (item_hit == 4)) + if (((store_h >= 250) && (item_hit == 4)) ||((store_h <= 2) && (item_hit == 3))) play_sound(0); else { if (item_hit == 3) { @@ -477,7 +477,7 @@ Boolean spend_xp_event_filter (short item_hit) break; case 5: case 6: - if ((store_sp >= 150) && (item_hit == 6)) + if (((store_sp >= 150) && (item_hit == 6)) || ((store_sp <= 0) && (item_hit == 5))) play_sound(0); else { if (item_hit == 5) { diff --git a/Blades of Exile/ACTIONS.CPP b/Blades of Exile/ACTIONS.CPP index 1634ce65..d4c265e9 100644 --- a/Blades of Exile/ACTIONS.CPP +++ b/Blades of Exile/ACTIONS.CPP @@ -169,7 +169,7 @@ Boolean handle_action(POINT the_point, WPARAM wparam, LPARAM lparam ) 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 find_direction_from,ter_looked_at,button_hit = 12; short store_sp[6]; char str[60]; @@ -187,7 +187,7 @@ Boolean handle_action(POINT the_point, WPARAM wparam, LPARAM lparam ) ctrl_key = TRUE; for (i = 0; i < 20; i++) - special_queue[i] = -1; + special_queue[i].queued_special = -1; end_scenario = FALSE; // Now split off the extra stuff, like talking and shopping. @@ -350,7 +350,7 @@ Boolean handle_action(POINT the_point, WPARAM wparam, LPARAM lparam ) i = 200; add_string_to_buf(" Monsters nearby."); } - if(timed_special_happened){ + if(timed_special_happened && PSD[309][4] == 1){ i=200; add_string_to_buf(" Rest interrupted."); } @@ -359,11 +359,38 @@ Boolean handle_action(POINT the_point, WPARAM wparam, LPARAM lparam ) put_pc_screen(); } if (i == 50) { + if(PSD[309][6] == 1){ + for(i=0; i < 115; i++){ + party.age += 10; + // Specials countdowns + if ((party.age % 500 == 0) && (get_ran(1,0,5) == 3) && (adven.hasAbil(52) == true)) { + i = 200; + adven.disease(2); + } + // Plants and magic shops + if (party.age % 4000 == 0) refresh_store_items(); + + timed_special_happened = special_increase_age(0); + + if(timed_special_happened && PSD[309][4] == 1){ + i=200; + add_string_to_buf(" Rest interrupted."); + } + } + if(i == 115){ + add_string_to_buf(" Rest successful. "); + adven.heal(get_ran(5,1,10)); + adven.restoreSP(50); + put_pc_screen(); + } + } + else{ 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; @@ -576,14 +603,11 @@ Boolean handle_action(POINT the_point, WPARAM wparam, LPARAM lparam ) // Begin: Moving if ((right_button == FALSE) && (overall_mode == MODE_COMBAT)) { - store_cur_pc = current_pc; if (pc_combat_move(destination) == TRUE) { center = pc_pos[current_pc]; did_something = TRUE; update_explored(destination); } - if(store_cur_pc != current_pc) - did_something = TRUE; //pc dead by backshot need_redraw = TRUE; menu_activate(1); } @@ -1108,7 +1132,7 @@ Boolean handle_action(POINT the_point, WPARAM wparam, LPARAM lparam ) j = get_ran(1,1,160 - c_town.difficulty); if (j == 10) create_wand_monst(); - if(timed_special_happened){ + if(timed_special_happened && PSD[309][4] == 1){ i = 200; add_string_to_buf(" Waiting interrupted."); } @@ -1141,15 +1165,24 @@ Boolean handle_action(POINT the_point, WPARAM wparam, LPARAM lparam ) // 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) { + if (special_queue[i].queued_special >= 0) { s3 = 0; switch (i) { case 0: - run_special(5,2,special_queue[0],c_town.p_loc,&s1,&s2,&s3); + run_special(5,2,special_queue[0].queued_special,c_town.p_loc,&s1,&s2,&s3); break; case 1: - run_special(6,2,special_queue[1],party.p_loc,&s1,&s2,&s3); + run_special(6,2,special_queue[1].queued_special,party.p_loc,&s1,&s2,&s3); break; + default: + long store_time = party.age; + party.age = special_queue[i].trigger_time; +// Call run_special() with the other data from special_queue[i] (which is a pending_special_type struct) + run_special(special_queue[i].mode, special_queue[i].type, special_queue[i].queued_special, special_queue[i].where, &s1, &s2, &s3); + party.age = max(party.age, store_time); + queue_position--; //free the queue slot + break; + } if (s3 > 0) initiate_redraw(); @@ -1175,7 +1208,6 @@ Boolean handle_action(POINT the_point, WPARAM wparam, LPARAM lparam ) 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; } @@ -1328,7 +1360,7 @@ void check_cd_event(HWND hwnd,UINT message, WPARAM wparam, LPARAM lparam) 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 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; @@ -1640,15 +1672,15 @@ Boolean handle_keystroke(WPARAM wParam, LPARAM lParam) // case 'A': Alchemy case 'B': // Leave town if (in_scen_debug) { - party.stuff_done[304][0] = 0; - for(i=0;i<6;i++) - if(adven[i].main_status > 9) - adven[i].main_status -= 10; - if(overall_mode == MODE_OUTDOORS){ + if(overall_mode != MODE_TOWN){ add_string_to_buf("Debug - Leave Town: You're not in town !"); print_buf(); break; } + party.stuff_done[304][0] = 0; + for(i=0;i<6;i++) + if(adven[i].main_status > 9) + adven[i].main_status -= 10; overall_mode = MODE_OUTDOORS; position_party(party.outdoor_corner.x,party.outdoor_corner.y,party.p_loc.x,party.p_loc.y); clear_map(); @@ -1761,26 +1793,29 @@ Boolean handle_keystroke(WPARAM wParam, LPARAM lParam) 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.", + 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; + loc = party.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); + sprintf ((char *) c_line, "Debug: You're outside at x %d, y %d.",x,y); } + if(is_combat()){ + loc = pc_pos[current_pc]; + sprintf (c_line, "Debug: You're in combat at x %d, y %d.", loc.x, loc.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); +// sprintf(buf,"Party Age : %d, Ctown ploc : x = %d, y = %d", party.age, center.x, center.y); + sprintf(buf,"Town chop time : %d, chop key : %d",c_town.town.town_chop_time, c_town.town.town_chop_key); give_error(buf,"",0); -/* char buf[256]; - sprintf(buf,"Scen name = %s",party.scen_name);*/ break; case 'Q': // Magic map if (in_scen_debug) { @@ -1832,9 +1867,14 @@ Boolean handle_keystroke(WPARAM wParam, LPARAM lParam) 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); + display_strings("Enter Stuff Done Flag Part Value (outrageous values are a sure way to crash, or at least broke, the game)|Entering -1 show the value of the specified SDF.","",0,0,0,0,"Which value ?",-1,130,0); get_text_response(873,response,0); x = atoi(response); + if(x == -1){ + sprintf(response,"SDF[%d][%d] = %d",i,j,party.stuff_done[i][j]); + give_error(response,"",0); + } + else party.stuff_done[i][j]=x; } } @@ -2303,7 +2343,7 @@ void increase_age() } dump_gold(1); - timed_special_happened = special_increase_age(); + timed_special_happened = special_increase_age(0); push_things(); if (is_town()) process_fields(); diff --git a/Blades of Exile/BLADES.CPP b/Blades of Exile/BLADES.CPP index 66189bf9..99cdd26e 100644 --- a/Blades of Exile/BLADES.CPP +++ b/Blades of Exile/BLADES.CPP @@ -176,8 +176,8 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR, int nCmd RegisterClass(&wndclass2); - mainPtr = CreateWindow (szAppName, "Classic Blades of Exile Beta 2", - WS_OVERLAPPEDWINDOW, + mainPtr = CreateWindow (szAppName, "Classic Blades of Exile 1.0", + WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN, 0, 0, 588, @@ -326,7 +326,7 @@ long CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) // First, handle window size GetWindowRect(mainPtr,&wind_rect); - switch (display_mode) { + switch (display_mode) { //case 0 is center case 1: store_ulx = 0; store_uly = 0; break; diff --git a/Blades of Exile/BLADES.RC b/Blades of Exile/BLADES.RC index 4e86f6e6..07fbde68 100644 --- a/Blades of Exile/BLADES.RC +++ b/Blades of Exile/BLADES.RC @@ -104,6 +104,7 @@ ACCELERATORS_1 ACCELERATORS "^Q", 8, ASCII "^M", 84, ASCII "^A", 81, ASCII + "^N", 4, ASCII } 89 CURSOR "resources/ul.cur" diff --git a/Blades of Exile/COMBAT.CPP b/Blades of Exile/COMBAT.CPP index 64080987..f48d4562 100644 --- a/Blades of Exile/COMBAT.CPP +++ b/Blades of Exile/COMBAT.CPP @@ -46,6 +46,7 @@ void start_outdoor_combat(outdoor_creature_type encounter,unsigned char in_which 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);//// @@ -185,7 +186,7 @@ Boolean pc_combat_move(location destination) 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(); + set_town_status(0); if (s2 == 2) { last_attacked[current_pc] = monst_hit; pc_attack(current_pc,monst_hit); @@ -229,7 +230,7 @@ Boolean pc_combat_move(location destination) draw_terrain(0); } if (s1 != current_pc) - return FALSE; + return TRUE; } // move if still alive @@ -894,7 +895,7 @@ void do_combat_cast(location target) 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(); + set_town_status(0); store_sound = (spell_being_cast >= 50) ? 24 : 25; switch (spell_being_cast) { case 68: // spray acid @@ -1301,6 +1302,7 @@ void fire_missile(location target) // 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 @@ -1316,8 +1318,14 @@ Boolean combat_next_step() pick_next_pc(); if (current_pc != store_pc) to_return = TRUE; - center = pc_pos[current_pc]; - + + if(overall_mode == MODE_OUTDOORS) // has combat ended ? (stairway node) + center = party.p_loc; + else if (overall_mode == MODE_TOWN) + center = c_town.p_loc; + else + center = pc_pos[current_pc]; + adjust_spell_menus(); if ((combat_active_pc == 6) && (current_pc != store_pc)) { @@ -1441,7 +1449,7 @@ void combat_run_monst() } - timed_special_happened = special_increase_age(); + timed_special_happened = special_increase_age(0); push_things(); if (party.age % 2 == 0) do_poison(); @@ -3660,7 +3668,7 @@ void end_combat() adven[i].status[3] = 0; } if (which_combat_type == 0) { - overall_mode = 0; + overall_mode = MODE_OUTDOORS; } combat_active_pc = 6; current_pc = store_current_pc; diff --git a/Blades of Exile/CONSTS.H b/Blades of Exile/CONSTS.H index bd31f6cb..35adea3a 100644 --- a/Blades of Exile/CONSTS.H +++ b/Blades of Exile/CONSTS.H @@ -24,12 +24,6 @@ #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 @@ -61,7 +55,7 @@ #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). +#define MAIN_STATUS_SPLIT 10 // split from party, added to previous status (e.g 11 is splitted and alive : waiting for the active pc to return). /* adven[i].skills */ //complete @@ -511,7 +505,8 @@ #define SPELL_TARGET 2 #define SPELL_FANCY_TARGET 3 -#define SDF_IS_PARTY_SLIPT 304][0 +/* stuff done flags */ +#define SDF_IS_PARTY_SPLIT 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 diff --git a/Blades of Exile/Changes.txt b/Blades of Exile/Changes.txt index 173d785c..a59fa627 100644 --- a/Blades of Exile/Changes.txt +++ b/Blades of Exile/Changes.txt @@ -44,7 +44,67 @@ Bug Fixes : - 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. + +Beta 2 : + +- Giant Strength ability and Skill ability now use the ability strength rather than the item level to calculate effect. +- Won't take damage when moving boats over damaging terrains (fire, cold, magic, poison, disease) anymore. +- Won't take damage when horses refuses to enter a damaging terrain (fire, cold, magic) anymore. +- Horses won't enter damaging terrains (fire, cold, magic) or "horse blocking" terrains when outdoors anymore. +- Boom effects won't be displayed at random places when being damaged outdoors anymore. +- Damage won't be displayed in boom animation when attacking invulnerable monsters when they are in fact unharmed ... +- The first pc won't become active with 0 AP anymore when a pc get killed by backshots. +- All terrains and monsters sheets now loaded in memory to bypass storage sheet. That should speed up the game and fix some graphical oddities. Mac and Windows graphics can now be swapped on the fly (i.e without restarting the game). That also removes any graphical limitation in the game. +- In the same way, PC graphics will now be drawn directly to the game gworld. +- You can't end the scenario via a special node if the party is dead anymore (prevent saving an "all dead" party) +- Fixed the town loading behavior so that Empties won't appear in Place Town Encounters anymore. +- Cleaned the ressource file (smaller executable). +- Changed the "force place monster" function to preferably flush a summoned monster if flushing is needed. Also prevent a potential infinite loop if trying to force place a monster and all the 60 monsters of a town have a life flag. +- Tweaked exploding arrows firing animation to be smoother (arrow fired, then explosion). +- Added a safety check to monsters with Absorb Spells ability to prevent negative health. +- The spell usable Stinking Cloud ability was protecting against acid instead of the Protection from Acid ability. Fixed. +- The Protection from Disease item ability should now works to the full extent. +- Removed a check on the item graphic when deciding whether to play the"swallow" sound; now checks only for item variety. (Celtic Minstrel) +- Corrected the code so that the party cannot be split again if already split. +- Various messages code cleaning/fixing (Celtic Minstrel) +- Removed the 50 node limit. To prevent infinite loop an interrupt sequence has been implemented (Ctrl-C). +- Jobs dialog reimplemented. +- Cave Bridges battlefield should now appears instead of basic cave floor. +- Wall trims are now working. +- Slowdowns due to trims drawing (animated water, ...) should be fixed now. +- Scenarios in subfolders (under Scenarios/) are now found. +- No more limit for the number of listed scenarios. +- Clicking '?' icon on shopping and talk mode now gives help, even if in 'No instant help' mode. +- 'Burma Shave' Easter Egg readded. +- Debug Mode : ghost mode implemented. + +Version 1.0 : + +- Added a new item ability : Call a scenario special when using the item. The special called is specified by the ability strength. +The type of scenario to call depends of the magic_use_type (the boxes from help pc (0) to harm all (4)) : 0 is only local, 1 is town local and out global, +2 is town global and out local and 3 is only global. +If the number of charge is greater than 0, then using the item takes one charge. If not, the item can be used at will. +- Changed the "Set SDF" debug command to display the value of the specified SDF if value to set it to is -1 (BoA style). +- Added a missing compatibility switch from the introduced "Specials interrupt wait/rest" feature. +- Misc. battlefield adjustment (forest battlefield doesn't show a road anymore, road battlefields appear correctly, cave bridge now has cave trims, ...) +- Fixed a bug where an absent boat or horse could prevent a pc from entering a square while in outdoor combat. +- Trims now use the next terrain type (cave, grass, mountain) when drawn. +- Fixed a potential negative pointer to an array. +- Readded Spidweb logo intro sound. +- Event Timers will now triggers even when resting (compatibility switch available) +- Stairway can now be called in any mode except outdoor : town, looking, talking, even fighting (put in fight mode at destination). +- The three basics scenarios are no longer listed in the custom scenario list. +- Talking mode : fixed a typo which would prevent the keyword "name" from giving the name dialogue. Added the keywords "buy" (for purchase) and "bye" to end conversation. +- Time for event timers is now taken into account correctly while resting Outdoor/ in Inn / via "Have a Rest Node". The "Change Time" node is unchanged. +- Added a preference to show a talk entry field next to "Ask About" (like in older Exiles) for direct typing. +- Fixed clipping error in the main menu screen for high resolutions. +- Added the Ctrl+N shortcut who was advertised but not working. +- Gold is now updated after training. +- If not using special messages, a "Move Party" node won't mess with talking responses anymore. +- Affect Gold/Food nodes could give more gold/food than the maximum allowed. Fixed. +- Deleted a check that was destroying items with "type Flag" 15 first. +- Calling add_string_to_buf() with an empty string now does nothing. + Changes : - Created a compatibility menu @@ -59,7 +119,7 @@ Changes : - 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) + - Anama references removed (was able to gain Anama's bonus against demons when the right SDF was set and suffers Anama's wrath for learning Mage Spells if 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 : @@ -115,27 +175,34 @@ Compatibility Switches : ToDo : -- elim_monst() function is now unused. -- Complete MIXED_D.BMP (ppats ...) +//- Jobs page ? <= not in Classic BoE +//- Check Spell on space Node ? <= not for now +//- Implement new trims method. <= not in Classic BoE + +System Shock 2 + + +/* => should be done +- Changing Terrain with different light radius will have no effect. The town will remember the value of the original terrain, and display the light radius for that terrain, regardless of what it mutates into. I have been told this effect may work on MACs, I can say for certain it will NOT work on PCs. - 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. +/*- 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 +/*- 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. +/*- 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 +- On an unrelated note... Is it possible to alter any member functions that call add_string_to_buf so that they return the string to add instead of adding it themselves? That's what I'm going to do when I get there (and already have done with the splitting functions). Since add_string_to_buffer only exists in the game (and not the editors), it's necessary in order to be able to use the exact same code for all three. (Unless we do some conditional compilation stuff, I suppose.) +- Check Trait Node ? +- Just wondering, did you implement this yet? I'll be doing it soon if I haven't already (I suspect I added the code to set it when enchanting a weapons but forgot to add the code to check it when deducting a charge from an item). +- Add a "strong_barrier" field to match Mac behavior. 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 ? @@ -179,4 +246,37 @@ void Paint(HWND hWnd, HDC hDC) graphics.DrawImage(pImage, rect); delete pImage; -} \ No newline at end of file +} + +// Load our PNG image +CImage img; +img.Load("circle.png"); +// Get dimensions +int iWidth = img.GetWidth(); +int iHeight = img.GetHeight(); +// Make mem DC + mem bitmap +HDC hdcScreen = GetDC(NULL); +HDC hDC = CreateCompatibleDC(hdcScreen); +HBITMAP hBmp = CreateCompatibleBitmap(hdcScreen, iWidth, iHeight); +HBITMAP hBmpOld = (HBITMAP)SelectObject(hDC, hBmp); +// Draw image to memory DC +img.Draw(hDC, 0, 0, iWidth, iHeight, 0, 0, iWidth, iHeight); + +// Call UpdateLayeredWindow +BLENDFUNCTION blend = {0}; +blend.BlendOp = AC_SRC_OVER; +blend.SourceConstantAlpha = 255; +blend.AlphaFormat = AC_SRC_ALPHA; +POINT ptPos = {0, 0}; +SIZE sizeWnd = {iWidth, iHeight}; +POINT ptSrc = {0, 0}; +UpdateLayeredWindow(hWnd, hdcScreen, &ptPos, &sizeWnd, hDC, &ptSrc, 0, &blend, ULW_ALPHA); + +SelectObject(hDC, hBmpOld); +DeleteObject(hBmp); +DeleteDC(hDC); +ReleaseDC(NULL, hdcScreen);Because I’m using CImage, you need to include the atlimage.h header. + +That’s all that is required for the basics of UpdateLayeredWindow. + +NOTE: The example above does not include any error checking. That is left for the reader as an exercise. \ No newline at end of file diff --git a/Blades of Exile/DLGUTILS.CPP b/Blades of Exile/DLGUTILS.CPP index a446e580..89359d4d 100644 --- a/Blades of Exile/DLGUTILS.CPP +++ b/Blades of Exile/DLGUTILS.CPP @@ -23,7 +23,7 @@ #define NUM_HINTS 30 -extern BOOL fry_startup; +extern BOOL play_startup; /* shop_type: @@ -41,6 +41,9 @@ void start_shop_mode(short shop_type,short shop_min,short shop_max,short cost_ad { RECT area_rect; + if(PSD[307][1] == 1) + ShowWindow(talk_edit_box, SW_HIDE); + if (shop_max < shop_min) shop_max = shop_min; //// store_cost_mult = cost_adj; @@ -75,6 +78,9 @@ void end_shop_mode() { RECT dummy_rect = {0,0,0,0}; + if(PSD[307][1] == 1) + ShowWindow(talk_edit_box, SW_SHOW); + ShowScrollBar(shop_sbar,SB_CTL,FALSE); if (store_pre_shop_mode == 20) { sprintf((char *)old_str1,"You conclude your business."); @@ -415,7 +421,7 @@ void set_up_shop_array() void start_talk_mode(short m_num,short personality,unsigned char monst_type,short store_face_pic)//// { - RECT area_rect; + RECT area_rect, talk_edit_box_rect; char place_string1[256] = ""; char place_string2[256] = ""; @@ -426,7 +432,20 @@ void start_talk_mode(short m_num,short personality,unsigned char monst_type,shor 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); + talk_gworld = CreateCompatibleBitmap(main_dc,area_rect.right,area_rect.bottom); + + if(PSD[307][1] == 1){ + talk_edit_box_rect = preset_words[8].word_rect; + OffsetRect(&talk_edit_box_rect,ulx,uly+3); + talk_edit_box = CreateWindow("edit",NULL,WS_CHILD | WS_BORDER | WS_VISIBLE, + talk_edit_box_rect.left+125,talk_edit_box_rect.top, + 140, + 20, + mainPtr,(HMENU) 160,(HINSTANCE) store_hInstance,NULL); + store_edit_parent = mainPtr; + old_edit_proc = (WNDPROC) (GetWindowLong(talk_edit_box,GWL_WNDPROC)); + SetWindowLong(talk_edit_box,GWL_WNDPROC,(LONG) edit_proc); + } // first make sure relevant talk strs are loaded in if (personality / 10 != cur_town_talk_loaded) @@ -458,10 +477,16 @@ void start_talk_mode(short m_num,short personality,unsigned char monst_type,shor void end_talk_mode() { + DeleteObject(talk_gworld); talk_gworld = NULL; + if((PSD [307][1] == 1) && (talk_edit_box != NULL)){ + DestroyWindow(talk_edit_box); + talk_edit_box = NULL; + } - overall_mode = store_pre_talk_mode; + overall_mode = store_pre_talk_mode; + create_clip_region(); if (overall_mode == 2) overall_mode = 1; @@ -469,10 +494,14 @@ void end_talk_mode() center = c_town.p_loc; update_explored(center); } + stat_screen_mode = 0; - put_item_screen(stat_window,0); + + put_item_screen(stat_window,0); put_pc_screen(); redraw_screen(0); + + } void handle_talk_event(POINT p) @@ -537,6 +566,28 @@ void handle_talk_event(POINT p) break; case 6: // quit end_talk_mode(); + + if(talk_end_forced == 10){ // party is in inn + talk_end_forced = TRUE; // safety set + for(j=0; j < 700; j++){ + party.age++; + // Specials countdowns + if ((party.age % 500 == 0) && (get_ran(1,0,5) == 3) && (adven.hasAbil(52) == true)) { + j = 900; + adven.disease(2); + } + // Plants and magic shops + if (party.age % 4000 == 0) refresh_store_items(); + + timed_special_happened = special_increase_age(0); + + if(timed_special_happened && PSD[309][4] == 1){ + j = 900; + add_string_to_buf(" Rest interrupted."); + print_buf(); + } + } + } return; break; default: @@ -556,6 +607,13 @@ void handle_talk_event(POINT p) i = 100; } } + if(strcmp(talk_edit_string,"") != 0){ + for(j = 0; j < 4; j++) + asked[j] = talk_edit_string[j]; + talk_edit_string[0] = '\0'; + i = 100; + } + if (i == 50) // no event return; if (force_special == 9) { @@ -566,7 +624,7 @@ void handle_talk_event(POINT p) asked[3] = place_string1[3]; } - if ((asked[0] == 'n') && (asked[1] == 'a') &&(asked[2] == 'm') &&(asked[3] == 'a')) { + if ((asked[0] == 'n') && (asked[1] == 'a') &&(asked[2] == 'm') &&(asked[3] == 'e')) { force_special = 2; } if ((asked[0] == 'l') && (asked[1] == 'o') &&(asked[2] == 'o') &&(asked[3] == 'k')) { @@ -576,6 +634,12 @@ void handle_talk_event(POINT p) ((asked[0] == 'w') && (asked[1] == 'o') &&(asked[2] == 'r')&&(asked[3] == 'k')) ) { force_special = 3; } + if((asked[0] == 'b') && (asked[1] == 'u') && (asked[2] == 'y')) + force_special = 4; + if((asked[0] == 'b') && (asked[1] == 'y') && (asked[2] == 'e')){ + end_talk_mode(); + return; + } if (force_special > 0) { switch (force_special) { @@ -678,13 +742,23 @@ void handle_talk_event(POINT p) talk_end_forced = TRUE; party.gold -= a; put_pc_screen(); - adven.heal(30 * b); + if(PSD[309][6] == 1){ + talk_end_forced = 10; + adven.heal(30 * b); + adven.restoreSP(25 * b); + c_town.p_loc.x = c; + c_town.p_loc.y = d; + center = c_town.p_loc; + } + else{ + 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; @@ -724,6 +798,7 @@ void handle_talk_event(POINT p) spend_xp(get_pc,1, 0); } sprintf((char *) place_string1, "You conclude your training."); + put_pc_screen(); return; case 9: case 10: case 11: @@ -892,7 +967,7 @@ void handle_talk_event(POINT p) talk_end_forced = TRUE; break; case 27: - make_town_hostile(); + set_town_status(0); talk_end_forced = TRUE; break; case 28: @@ -939,7 +1014,6 @@ void handle_talk_event(POINT p) 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) @@ -995,7 +1069,7 @@ Boolean prefs_event_filter (short item_hit) 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: + case 50: case 52: case 54: case 56: case 60: 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; @@ -1035,10 +1109,11 @@ Boolean prefs_event_filter (short item_hit) 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); + play_startup = cd_get_led(1099,54); party.stuff_done[305][7] = cd_get_led(1099,56); + party.stuff_done[307][1] = cd_get_led(1099,60); - if(party.stuff_done[307][0] != cd_get_led(1099,58)){//changed graphic mode (Mac vs Windows) ? + if(party.stuff_done[307][0] != cd_get_led(1099,58)){ //changed graphic mode (Mac vs Windows) ? party.stuff_done[307][0] = cd_get_led(1099,58);//adjust the graphic mode SDF swap_platform_graphics();//swap graphics redraw_screen(0);//redraw screen with new graphics @@ -1096,9 +1171,10 @@ void pick_preferences() 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,54,(play_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_led(1099,60,(party.stuff_done[307][1] != 0) ? 1 : 0);// talk edit box appearing ? cd_set_flag(1099,3,1); if (PSD[306][6] == 3) cd_set_led(1099,47,1); @@ -1132,7 +1208,7 @@ Boolean compatibility_event_filter (short item_hit) break; - case 7: case 9: case 11: case 13: + case 7: case 9: case 11: case 13: case 15: case 17: case 19: cd_set_led(1100,item_hit,1 - cd_get_led(1100,item_hit)); break; } @@ -1143,6 +1219,9 @@ Boolean compatibility_event_filter (short item_hit) 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); + party.stuff_done[309][4]=cd_get_led(1100,15); + party.stuff_done[309][5]=cd_get_led(1100,17); + party.stuff_done[309][6]=cd_get_led(1100,19); } build_data_file(1); } @@ -1161,6 +1240,9 @@ void pick_compatibility() 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 + cd_set_led(1100,15,(party.stuff_done[309][4] != 0) ? 1 : 0);// party.stuff_done[309][4] special_interrupt + cd_set_led(1100,17,(party.stuff_done[309][5] != 0) ? 1 : 0);// party.stuff_done[309][5] stairway_everywhere + cd_set_led(1100,19,(party.stuff_done[309][6] != 0) ? 1 : 0);// party.stuff_done[309][6] resting_checks_timers if (party.help_received[110] == 0) { cd_initial_draw(1100); diff --git a/Blades of Exile/DLOGTOOL.CPP b/Blades of Exile/DLOGTOOL.CPP index 263c1735..c3c9cd98 100644 --- a/Blades of Exile/DLOGTOOL.CPP +++ b/Blades of Exile/DLOGTOOL.CPP @@ -7,6 +7,8 @@ #include "dlogtool.h" #include "text.h" #include "locutils.h" +#include "dlgutils.h" +#include "infodlgs.h" #include "globvar.h" @@ -69,6 +71,21 @@ void cd_init_dialogs() long CALLBACK fresh_edit_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { + if(hwnd == talk_edit_box){ + switch (message) { + case WM_KEYDOWN: + if (wParam == VK_RETURN){// talk edit box + POINT p = {-1,-1}; + GetWindowText(talk_edit_box,talk_edit_string,40); + SetWindowText(talk_edit_box,""); + FlushEvents(0); + handle_talk_event(p); + SetFocus(talk_edit_box); + } + break; + } + } + else{ switch (message) { case WM_KEYDOWN: if (wParam == VK_RETURN) @@ -78,6 +95,7 @@ long CALLBACK fresh_edit_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPa 9, 0 ); + break; if (wParam == VK_ESCAPE) SendMessage(store_edit_parent, WM_COMMAND, @@ -85,8 +103,8 @@ long CALLBACK fresh_edit_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPa 0); break; } + } - //return CallWindowProc((WNDPROC) old_edit_proc,hwnd,message,wParam,lParam); return CallWindowProc((WNDPROC) old_edit_proc,hwnd,message,wParam,lParam); } @@ -103,6 +121,127 @@ short cd_create_dialog_parent_num(short dlog_num,short parent) } +short cd_create_custom_pic_dialog(HWND parent, HBITMAP picture) +{ + + short i,j,free_slot = -1,free_item = -1; + + short cur_item = 1, but_items; + RECT pic_rect = {0,0,0,0}, c_rect; + + if (parent != NULL) { + if (IsWindowEnabled(parent) == 0) + return -1; + } + GetObject(picture, sizeof(bitmap_info), &bitmap_info); + + GetClientRect(mainPtr, &c_rect); + + if(bitmap_info.bmWidth > c_rect.right) + bitmap_info.bmWidth = c_rect.right; + + if(bitmap_info.bmHeight > c_rect.bottom) + bitmap_info.bmHeight = c_rect.bottom - 60; + + pic_rect.right = bitmap_info.bmWidth; + pic_rect.bottom = bitmap_info.bmHeight; + + store_dlog_num = 905; + + for (i = 0; i < ND; i++) { + if ((dlg_keys[i] >= 0) && (dlg_types[i] == 905)) //custom_pic_dialog is number 905 + 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] = 905; + 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, + bitmap_info.bmWidth + 2, + bitmap_info.bmHeight + 65, // additional space for the ok button + 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; + + 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] = 1; + item_number[free_item] = cur_item; + + item_flag[free_item] = available_dlog_buttons[1]; + item_active[free_item] = 1; + item_label[free_item] = 0; + item_label_loc[free_item] = -1; + item_key[free_item] = 31; + but_items = free_item; // remember this to set item rect later + cur_item++; + + item_rect[but_items].right = bitmap_info.bmWidth - 10; + item_rect[but_items].left = item_rect[but_items].right - 63; + item_rect[but_items].top = bitmap_info.bmHeight + 5; + item_rect[but_items].bottom = item_rect[but_items].top + 23; + + 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_number[free_item] = cur_item; + item_type[free_item] = 20; //draw loaded picture + item_active[free_item] = 1; + cur_item++; + + dlg_highest_item[free_slot] = cur_item - 1; + + 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_custom_dialog(HWND parent, char *str_block,short pic_num,short buttons[3]) { @@ -962,7 +1101,7 @@ void cd_key_label(short dlog_num, short item_num,short loc) void cd_draw_item(short dlog_num,short item_num) { short dlg_index,item_index,store_label; - HDC win_dc; + HDC win_dc, hdc; 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; @@ -973,7 +1112,7 @@ void cd_draw_item(short dlog_num,short item_num) return; win_dc = cd_get_dlog_dc(dlg_index); - old_font = (HFONT) SelectObject(win_dc,small_bold_font); + old_font = (HFONT) SelectObject(win_dc,small_bold_font); dlg_force_dc = win_dc; if (item_active[item_index] == 0) { @@ -1058,6 +1197,25 @@ void cd_draw_item(short dlog_num,short 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; + case 20: // display picture special case + + from_rect.right = bitmap_info.bmWidth; + from_rect.bottom = bitmap_info.bmHeight; + + GetObject(displayed_picture, sizeof(bitmap_info), &bitmap_info); //is picture greater ... + + hdc = CreateCompatibleDC(NULL); //let's draw the picture + SelectObject(hdc, displayed_picture); + if((from_rect.right != bitmap_info.bmWidth) || (from_rect.bottom != bitmap_info.bmHeight)){ // ... than the screen ? + StretchBlt(win_dc,0, 0, from_rect.right, from_rect.bottom, hdc, 0 ,0 , bitmap_info.bmWidth, bitmap_info.bmHeight, SRCCOPY); + bitmap_info.bmWidth = from_rect.right; //in case of redraw ... + bitmap_info.bmHeight = from_rect.bottom; //... put back the screen max values + } + else + BitBlt(win_dc,0, 0, from_rect.right, from_rect.bottom, hdc, 0 ,0 , SRCCOPY); + + DeleteDC(hdc); //clean after drawing + //careful with the graphic files, if streched the quality can drop significantly. } } @@ -1239,7 +1397,7 @@ void cd_press_button(short dlog_num, short item_num) if (cd_get_indices(dlog_num,item_num,&dlg_index,&item_index) < 0) return; - // no press action for redio buttons + // no press action for redo buttons if ((item_type[item_index] == 2) || (item_flag[item_index] == 143)) { play_sound(34); return; @@ -1449,7 +1607,7 @@ void draw_dialog_graphic(HWND hDlg, RECT rect, short which_g, Boolean do_frame,s 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 bw_from = {0,0,120,120}; RECT pc_info_from = {0,127,106,157}; RECT item_info_from = {174,0,312,112}; diff --git a/Blades of Exile/DLOGTOOL.H b/Blades of Exile/DLOGTOOL.H index de164947..083e15eb 100644 --- a/Blades of Exile/DLOGTOOL.H +++ b/Blades of Exile/DLOGTOOL.H @@ -42,6 +42,7 @@ 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); +short cd_create_custom_pic_dialog(HWND parent, HBITMAP picture); void cd_get_text_edit_str(short dlog_num, char *str); // NOTE!!! Expects a c string @@ -56,6 +57,8 @@ inline void csp(short dlog_num, short item_num, short pict_num) inline void cd_set_edit_focus() { if (edit_box) SetFocus(edit_box); } void ModalDialog(); +extern HWND dlgs[ND]; + RECT calc_rect(short i, short j); #endif diff --git a/Blades of Exile/FILEIO.CPP b/Blades of Exile/FILEIO.CPP index 3adc65f8..621f2710 100644 --- a/Blades of Exile/FILEIO.CPP +++ b/Blades of Exile/FILEIO.CPP @@ -23,7 +23,7 @@ #define DONE_BUTTON_ITEM 1 -extern BOOL fry_startup; +extern BOOL play_startup; typedef struct { char expl[96][96]; @@ -58,7 +58,7 @@ 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 +int i=strlen(file_path); // initialize the first while loop while(file_path[i] != '\\') { i--; // find the last '\' in the path to the executable @@ -1719,9 +1719,11 @@ void get_reg_data() 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); + play_startup = atoi(buffer); GetPrivateProfileString(section, "darker_graphics", "0", buffer, BUFFER_LEN, iniFile); party.stuff_done[307][0] = atoi(buffer); //1 is darker + GetPrivateProfileString(section, "talk_edit_box", "0", buffer, BUFFER_LEN, iniFile); + party.stuff_done[307][1] = 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); @@ -1730,6 +1732,12 @@ void get_reg_data() 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 + GetPrivateProfileString(section, "special_interrupt", "0", buffer, BUFFER_LEN, iniFile); + party.stuff_done[309][4] = atoi(buffer); + GetPrivateProfileString(section, "stairway_everywhere", "0", buffer, BUFFER_LEN, iniFile); + party.stuff_done[309][5] = atoi(buffer); + GetPrivateProfileString(section, "resting_checks_timers", "0", buffer, BUFFER_LEN, iniFile); + party.stuff_done[309][6] = atoi(buffer); } @@ -1744,14 +1752,18 @@ void build_data_file(short which) // 1 - compatibility ; 2 - preferences 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, "fancy_startup", (play_startup == TRUE) ? "1" : "0", iniFile); WritePrivateProfileString(section, "darker_graphics", (party.stuff_done[307][0] == 0) ? "0": "1", iniFile); + WritePrivateProfileString(section, "talk_edit_box", (party.stuff_done[307][1] == 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); + WritePrivateProfileString(section, "special_interrupt", (party.stuff_done[309][4] == 0)? "0" : "1", iniFile); + WritePrivateProfileString(section, "stairway_everywhere", (party.stuff_done[309][5] == 0)? "0" : "1", iniFile); + WritePrivateProfileString(section, "resting_checks_timers", (party.stuff_done[309][6] == 0)? "0" : "1", iniFile); } } @@ -1865,7 +1877,7 @@ void ListFiles(char *path, HWND listbox){ short len; HANDLE find_file_id; WIN32_FIND_DATA lpFindFileData; - char copy_str[256]; + char copy_str[256], test_str[256]; sprintf(copy_str,"scenarios/%s*.*",path); @@ -1873,20 +1885,22 @@ void ListFiles(char *path, HWND listbox){ FindClose(find_file_id); return; } - - do{ - len = strlen(lpFindFileData.cFileName); - if(((lpFindFileData.cFileName[len-1] == 's') ||( lpFindFileData.cFileName[len-1] == 'S')) - && ((lpFindFileData.cFileName[len-2] == 'x') || (lpFindFileData.cFileName[len-2] == 'X')) - && ((lpFindFileData.cFileName[len-3] == 'e') || (lpFindFileData.cFileName[len-3] == 'E'))){// is extension .exs ? - sprintf(copy_str,"%s%s",path,lpFindFileData.cFileName); - SendMessage(listbox,LB_ADDSTRING,0,(LPARAM) (LPCTSTR) copy_str); - } - else if((lpFindFileData.dwFileAttributes == FILE_ATTRIBUTE_DIRECTORY) && (strcmp(lpFindFileData.cFileName,".") != 0) && (strcmp(lpFindFileData.cFileName,"..") != 0)){ - sprintf(copy_str,"%s%s/",path,lpFindFileData.cFileName); - ListFiles(copy_str,listbox);//so list scenarios under the subdirectory - } - }while(FindNextFile(find_file_id,&lpFindFileData) != 0); + + do{ + if((strcmp(lpFindFileData.cFileName, "VALLEYDY.EXS") != 0) && (strcmp(lpFindFileData.cFileName, "STEALTH.EXS") != 0) && (strcmp(lpFindFileData.cFileName, "ZAKHAZI.EXS") != 0)){ + len = strlen(lpFindFileData.cFileName); + if(((lpFindFileData.cFileName[len-1] == 's') ||( lpFindFileData.cFileName[len-1] == 'S')) + && ((lpFindFileData.cFileName[len-2] == 'x') || (lpFindFileData.cFileName[len-2] == 'X')) + && ((lpFindFileData.cFileName[len-3] == 'e') || (lpFindFileData.cFileName[len-3] == 'E'))){// is extension .exs ? + sprintf(copy_str,"%s%s",path,lpFindFileData.cFileName); + SendMessage(listbox,LB_ADDSTRING,0,(LPARAM) (LPCTSTR) copy_str); + } + else if((lpFindFileData.dwFileAttributes == FILE_ATTRIBUTE_DIRECTORY) && (strcmp(lpFindFileData.cFileName,".") != 0) && (strcmp(lpFindFileData.cFileName,"..") != 0)){ + sprintf(copy_str,"%s%s/",path,lpFindFileData.cFileName); + ListFiles(copy_str,listbox);//so list scenarios under the subdirectory + } + } + }while(FindNextFile(find_file_id,&lpFindFileData) != 0); FindClose(find_file_id); @@ -1924,6 +1938,7 @@ void build_scen_headers() data_store2 = new piles_of_stuff_dumping_type2[count]; + if(scen_headers != NULL){ delete[] scen_headers; scen_headers = NULL; @@ -2174,7 +2189,7 @@ void port_scenario() flip_short(&scenario.flag_f); flip_short(&scenario.flag_g); flip_short(&scenario.flag_h); - flip_short(&scenario.flag_i); + flip_short(&scenario.adjust_diff); flip_short(&scenario.intro_mess_pic); flip_short(&scenario.intro_mess_len); flip_short(&scenario.which_town_start); diff --git a/Blades of Exile/GAMEDLOG.RC b/Blades of Exile/GAMEDLOG.RC index 5148486c..b9d1786e 100644 --- a/Blades of Exile/GAMEDLOG.RC +++ b/Blades of Exile/GAMEDLOG.RC @@ -145,7 +145,7 @@ STYLE WS_POPUP | WS_DLGFRAME STYLE WS_POPUP | WS_DLGFRAME { } - + 901 DIALOG 10, 10, 338, 113 STYLE WS_POPUP | WS_DLGFRAME { @@ -1160,15 +1160,9 @@ STYLE WS_POPUP | WS_DLGFRAME 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 2 | 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*/ LTEXT "1_63", 1, 435, 295, 61, 20 LTEXT "5_716", 2, 6, 6, 36, 36 - LTEXT "Classic Blades of Exile Beta 2 | 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 "Classic Blades of Exile version 1.0 | 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 "CONTRIBUTORS : Ormus, Ishad Nha, Celtic Minstrel, Niemand and all involved in the BoE community.", 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 @@ -1562,11 +1556,11 @@ STYLE WS_POPUP | WS_DLGFRAME LTEXT "*" 83, 396, 227, 100, 16 } -1099 DIALOG 10, 10, 470, 510 +1099 DIALOG 10, 10, 470, 530 STYLE WS_POPUP | WS_DLGFRAME { - LTEXT "1_63", 1, 354, 480, 58, 20 - LTEXT "0_5", 2, 281, 480, 62, 20 + LTEXT "1_63", 1, 354, 500, 58, 20 + LTEXT "0_5", 2, 281, 500, 62, 20 LTEXT "", 3, 64, 48, 277, 102 LTEXT "2_0", 4, 147, 88, 16, 18 LTEXT "2_0", 5, 72, 55, 16, 18 @@ -1623,6 +1617,8 @@ STYLE WS_POPUP | WS_DLGFRAME LTEXT "*Faster Boom Space Effects",57,72,440,340,16 LTEXT "2_0", 58, 53, 462,17,18 LTEXT "*Use Darker (Mac) Graphics",59,72,458,340,16 + LTEXT "2_0", 60, 53, 480,17,18 + LTEXT "*Ask About text box in talking mode",61,72,476,340,16 } 1100 DIALOG 10, 10, 450, 451 STYLE WS_POPUP | WS_DLGFRAME @@ -1638,14 +1634,12 @@ STYLE WS_POPUP | WS_DLGFRAME 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 "Display Grass and Moutains 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 + LTEXT "Specials Interrupt Waiting/Rest", 14, 70 ,142 ,182 ,17 + LTEXT "2_0", 15, 49, 146, 17, 18 + LTEXT "Stairway Nodes can be called anytime", 16, 70 ,162 ,182 ,17 + LTEXT "2_0", 17, 49, 166, 17, 18 + LTEXT "Special Timers are checked when resting outdoor/in inn", 18, 70 ,182 ,182 ,17 + LTEXT "2_0", 19, 49, 186, 17, 18 } diff --git a/Blades of Exile/GLOBAL.H b/Blades of Exile/GLOBAL.H index a5a7dbc3..44e8f820 100644 --- a/Blades of Exile/GLOBAL.H +++ b/Blades of Exile/GLOBAL.H @@ -161,7 +161,11 @@ struct town_record_type short timer_specs[8]; unsigned char strlens[180]; special_node_type specials[100]; - unsigned char specials1,specials2,res1,res2; + unsigned char defy_mapping,defy_scrying; + char hostile_spec_to_call,res2; +/* bool strong_barriers : 1; + bool defy_mapping : 1; + char reserved_bits : 6;*/ short difficulty; /* functions */ @@ -296,7 +300,8 @@ typedef struct { item_storage_shortcut_type storage_shortcuts[10]; short flag_d; unsigned char scen_str_len[300]; - short flag_i; +// short flag_i; + short adjust_diff; location last_out_edited; short last_town_edited; } scenario_data_type; @@ -460,4 +465,13 @@ void move_to_zero(T & value) else if (value < 0) ++value; }; +typedef struct { + + short queued_special; + long trigger_time; + unsigned short mode; + unsigned char type; // 0 - scen, 1 - out, 2 - town + location where; + }pending_special_type; + #endif diff --git a/Blades of Exile/GLOBVAR.CPP b/Blades of Exile/GLOBVAR.CPP index 5ee8fcf6..2287d90b 100644 --- a/Blades of Exile/GLOBVAR.CPP +++ b/Blades of Exile/GLOBVAR.CPP @@ -23,7 +23,7 @@ RECT medium_buttons[4] = 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]; +pending_special_type 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, @@ -387,7 +387,7 @@ char text_long_str[10][256]; char text_short_str[140][35]; char labels[NL][25]; Boolean label_taken[NL]; -HWND edit_box ; +HWND edit_box, talk_edit_box = NULL ; HWND store_edit_parent; // kludgy HDC dlg_force_dc ; // save HDCs when dealing with dlogs short store_free_slot,store_dlog_num; @@ -544,6 +544,8 @@ char szFileName [128] = "blades.sav"; char szTitleName [128] = "blades.sav"; OPENFILENAME ofn; SCROLLINFO lpsi; +MSG msg; +BITMAP bitmap_info; // Trying this to fix bug. Hope it works. tiny_tr_type tiny_t; ave_tr_type ave_t; @@ -579,6 +581,7 @@ HBITMAP 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; HBITMAP talking_portraits_gworld, frills_gworld, ter_anim_gworld, monsters_gworld[10], terrains_gworld[6]; +HBITMAP displayed_picture = NULL; // Startup graphics, will die when play starts HBITMAP startup_gworld; HRGN clip_region; @@ -896,7 +899,7 @@ short abil_chart[200] = {4,4,4,4,4,4,4,4,4,4, 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, + 13,3,3,5,0, 10,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, @@ -980,3 +983,5 @@ word_rect_type store_words[50]; //Timer Special happened ? BOOL timed_special_happened = FALSE; BOOL ghost_mode = FALSE; +char talk_edit_string[40] = ""; +unsigned char queue_position = 1; //timer queue position diff --git a/Blades of Exile/GLOBVAR.H b/Blades of Exile/GLOBVAR.H index 8771efba..58631d8e 100644 --- a/Blades of Exile/GLOBVAR.H +++ b/Blades of Exile/GLOBVAR.H @@ -15,7 +15,7 @@ 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 pending_special_type special_queue[20]; extern Boolean end_scenario ; extern short refer_priest[62]; extern short mage_need_select[62]; @@ -265,7 +265,7 @@ extern char text_short_str[140][35]; extern char labels[NL][25]; extern Boolean label_taken[NL]; -extern HWND edit_box; +extern HWND edit_box, talk_edit_box; extern HWND store_edit_parent; // kludgy extern HDC dlg_force_dc; // save HDCs when dealing with dlogs @@ -320,6 +320,8 @@ extern char szTitleName [128]; extern OPENFILENAME ofn; extern OFSTRUCT save_dir,save_dir2; extern SCROLLINFO lpsi; +extern MSG msg; +extern BITMAP bitmap_info; // Trying this to fix bug. Hope it works. extern tiny_tr_type tiny_t; @@ -358,6 +360,7 @@ extern HBITMAP terrain_screen_gworld,text_bar_gworld,orig_text_bar_gworld,button extern HBITMAP items_gworld,tiny_obj_gworld,fields_gworld; extern HBITMAP dlg_buttons_gworld,missiles_gworld,dlogpics_gworld,small_temp_gworld; extern HBITMAP talking_portraits_gworld, frills_gworld, ter_anim_gworld,monsters_gworld[10], terrains_gworld[6]; +extern HBITMAP displayed_picture; extern HBITMAP dialog_pattern_gworld,pattern_gworld,status_pattern_gworld; @@ -498,7 +501,7 @@ 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 talk_edit_string[40]; extern char c_line[60]; @@ -599,5 +602,6 @@ extern word_rect_type store_words[50]; //Timer Special happened ? extern BOOL timed_special_happened; extern BOOL ghost_mode; +extern unsigned char queue_position; #endif diff --git a/Blades of Exile/GRAPHICS.CPP b/Blades of Exile/GRAPHICS.CPP index 74044e05..df83846f 100644 --- a/Blades of Exile/GRAPHICS.CPP +++ b/Blades of Exile/GRAPHICS.CPP @@ -18,7 +18,7 @@ #include "globvar.h" -BOOL fry_startup = FALSE; +BOOL play_startup = FALSE; void adjust_window_mode() { @@ -86,14 +86,15 @@ void plop_fancy_startup() 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); + if(play_startup == TRUE) + play_sound(95); DeleteObject(pict_to_draw); cur_time = GetCurrentTime(); while (GetCurrentTime() - cur_time < 1500); -if(fry_startup == TRUE){ + if(play_startup == TRUE){ pict_to_draw = load_pict(3000, (HDC) 0); @@ -139,22 +140,15 @@ void init_startup() 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}; + RECT to_rect, rect; 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); + GetClientRect(mainPtr,&rect); + paint_pattern(NULL,1,rect,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); @@ -384,6 +378,10 @@ void reload_startup()//// ShowScrollBar(text_sbar,SB_CTL,FALSE); ShowScrollBar(item_sbar,SB_CTL,FALSE); } + if(talk_edit_box != NULL){ //exited while talking so delete the talk edit box + DestroyWindow(talk_edit_box); + talk_edit_box = NULL; + } init_startup(); startup_loaded = TRUE; @@ -1118,7 +1116,7 @@ void draw_terrain(short mode) draw_one_terrain_spot(q,r,short_spec_terrain,0); break; - case 79: case 80: case 81: + case 79: case 80: case 81: //roads (cave, grass, mountain) 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; @@ -1134,15 +1132,10 @@ void draw_terrain(short mode) draw_one_terrain_spot(q,r,short_spec_terrain,0); place_road(q,r,where_draw); break; - case 90: + case 90: //pits 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 <= 4)) || - ((short_spec_terrain >= 22) && (short_spec_terrain <= 49))) - current_ground = 2; draw_one_terrain_spot(q,r,short_spec_terrain,0); break; } @@ -1224,8 +1217,36 @@ 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; + + char ground_type[260]= + {0,0,2,2,2,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0, + 0,0,36,36,36,36,36,36,36,36, + 36,36,36,36,36,36,36,36,2,2, + 2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,// 50 + 2,2,2,2,2,2,2,2,2,2, + 2,0,0,0,0, 0,0 ,0,0,0, + 2,36,0,2,0,0,0,2,2,2, + 0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,// 100 + 2,2,2,2,2,2,2,2,2,2, + 2,2,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,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,0,0,0,0,0,0, + 0,0,0,0,0,0,0,1,1,1,// 200 + 1,0,2,1,1,1,0,1,1,1, + 1,1,0,0,0,0,1,0,1,1, + 1,1,0,0,2,2,2,2,2,2, + 2,2,2,2,2,2,0,2,2,2, + 2,2,2,2,2,1,1,1,1,1};// 250 - // FIrst quick check ... if a pit or barrier in outdoor combat, no trim + // 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) @@ -1261,32 +1282,81 @@ void place_trim(short q,short r,location where,unsigned char ter_type) // 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) + if (town_trim[where.x][where.y] & 1){ + current_ground = ground_type[t_d.terrain[where.x][where.y - 1]]; + draw_trim(q,r,1,0); + } + if (town_trim[where.x][where.y] & 2){ + current_ground = ground_type[t_d.terrain[where.x + 1][where.y - 1]]; draw_trim(q,r,2,5); - if (town_trim[where.x][where.y] & 4) + } + if (town_trim[where.x][where.y] & 4){ + current_ground = ground_type[t_d.terrain[where.x + 1][where.y]]; draw_trim(q,r,0,3); - if (town_trim[where.x][where.y] & 8) + } + if (town_trim[where.x][where.y] & 8){ + current_ground = ground_type[t_d.terrain[where.x + 1][where.y + 1]]; 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) + } + if (town_trim[where.x][where.y] & 16){ + current_ground = ground_type[t_d.terrain[where.x][where.y + 1]]; + draw_trim(q,r,1,1); + } + if (town_trim[where.x][where.y] & 32){ + current_ground = ground_type[t_d.terrain[where.x - 1][where.y + 1]]; draw_trim(q,r,2,7); - if (town_trim[where.x][where.y] & 64) + } + if (town_trim[where.x][where.y] & 64){ + current_ground = ground_type[t_d.terrain[where.x - 1][where.y]]; draw_trim(q,r,0,2); - if (town_trim[where.x][where.y] & 128) - draw_trim(q,r,2,4); + } + if (town_trim[where.x][where.y] & 128){ + current_ground = ground_type[t_d.terrain[where.x - 1][where.y - 1]]; + 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); + targ = where.toLocal(); + if (out_trim[where.x][where.y] & 1){ +// current_ground = ground_type[out[where.x][where.y - 1]]; + current_ground = ground_type[outdoors[party.i_w_c.x][party.i_w_c.y].terrain[targ.x][targ.y - 1]]; + draw_trim(q,r,1,0); + } + if (out_trim[where.x][where.y] & 2){ +// current_ground = ground_type[out[where.x - 1][where.y - 1]]; + current_ground = ground_type[outdoors[party.i_w_c.x][party.i_w_c.y].terrain[targ.x + 1][targ.y - 1]]; + draw_trim(q,r,2,5); + } + if (out_trim[where.x][where.y] & 4){ +// current_ground = ground_type[out[where.x - 1][where.y - 1]]; + current_ground = ground_type[outdoors[party.i_w_c.x][party.i_w_c.y].terrain[targ.x + 1][targ.y ]]; + draw_trim(q,r,0,3); + } + if (out_trim[where.x][where.y] & 8){ +// current_ground = ground_type[out[where.x - 1][where.y - 1]]; + current_ground = ground_type[outdoors[party.i_w_c.x][party.i_w_c.y].terrain[targ.x + 1][targ.y + 1]]; + draw_trim(q,r,2,6); + } + if (out_trim[where.x][where.y] & 16){ +// current_ground = ground_type[out[where.x - 1][where.y - 1]]; + current_ground = ground_type[outdoors[party.i_w_c.x][party.i_w_c.y].terrain[targ.x][targ.y + 1]]; + draw_trim(q,r,1,1); + } + if (out_trim[where.x][where.y] & 32){ +// current_ground = ground_type[out[where.x - 1][where.y - 1]]; + current_ground = ground_type[outdoors[party.i_w_c.x][party.i_w_c.y].terrain[targ.x - 1][targ.y + 1]]; + draw_trim(q,r,2,7); + } + if (out_trim[where.x][where.y] & 64){ +// current_ground = ground_type[out[where.x - 1][where.y ]]; + current_ground = ground_type[outdoors[party.i_w_c.x][party.i_w_c.y].terrain[targ.x - 1][targ.y ]]; + draw_trim(q,r,0,2); + } + if (out_trim[where.x][where.y] & 128){ +// current_ground = ground_type[out[where.x - 1][where.y - 1]]; + current_ground = ground_type[outdoors[party.i_w_c.x][party.i_w_c.y].terrain[targ.x - 1][targ.y - 1]]; + draw_trim(q,r,2,4); + } } @@ -1300,34 +1370,44 @@ void place_trim(short q,short r,location where,unsigned char ter_type) if ((is_wall(store) == TRUE) && (is_wall(store1) == TRUE) && (is_ground(store2) == TRUE) - && (is_ground(store3) == TRUE)) + && (is_ground(store3) == TRUE)){ + current_ground = ground_type[t_d.terrain[where.x + 1][where.y + 1]]; draw_trim(q,r,3,6); + } if ((is_wall(store) == TRUE) && (is_wall(store3) == TRUE) && (is_ground(store2) == TRUE) - && (is_ground(store1) == TRUE)) + && (is_ground(store1) == TRUE)){ + current_ground = ground_type[t_d.terrain[where.x + 1][where.y - 1]]; 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); + && (is_ground(store3) == TRUE)){ + current_ground = ground_type[t_d.terrain[where.x - 1][where.y + 1]]; + 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); + && (is_ground(store1) == TRUE)){ + current_ground = ground_type[t_d.terrain[where.x - 1][where.y - 1]]; + draw_trim(q,r,3,4); + } if ((is_ground(store) == TRUE) && (is_ground(store1) == TRUE) && (is_ground(store2) == TRUE) && (is_wall(store3) == TRUE)) { + current_ground = ground_type[t_d.terrain[where.x - 1][where.y - 1]]; draw_trim(q,r,3,4); + current_ground = ground_type[t_d.terrain[where.x + 1][where.y - 1]]; draw_trim(q,r,3,5); } @@ -1335,7 +1415,9 @@ void place_trim(short q,short r,location where,unsigned char ter_type) && (is_ground(store3) == TRUE) && (is_ground(store2) == TRUE) && (is_ground(store1) == TRUE)) { + current_ground = ground_type[t_d.terrain[where.x + 1][where.y - 1]]; draw_trim(q,r,3,5); + current_ground = ground_type[t_d.terrain[where.x + 1][where.y + 1]]; draw_trim(q,r,3,6); } @@ -1343,7 +1425,9 @@ void place_trim(short q,short r,location where,unsigned char ter_type) && (is_wall(store1) == TRUE) && (is_ground(store) == TRUE) && (is_ground(store3) == TRUE)) { + current_ground = ground_type[t_d.terrain[where.x + 1][where.y + 1]]; draw_trim(q,r,3,6); + current_ground = ground_type[t_d.terrain[where.x - 1][where.y + 1]]; draw_trim(q,r,3,7); } @@ -1351,7 +1435,9 @@ void place_trim(short q,short r,location where,unsigned char ter_type) && (is_ground(store3) == TRUE) && (is_ground(store) == TRUE) && (is_ground(store1) == TRUE)) { + current_ground = ground_type[t_d.terrain[where.x - 1][where.y - 1]]; draw_trim(q,r,3,4); + current_ground = ground_type[t_d.terrain[where.x - 1][where.y + 1]]; draw_trim(q,r,3,7); } } @@ -1364,7 +1450,7 @@ void draw_trim(short q,short r,short which_trim,short which_mode) RECT from_rect = {0,0,28,36},to_rect; - if ((frills_on == FALSE) || ((current_ground == 2) && (PSD[309][3] == 0))) + if ((frills_on == FALSE) || (((current_ground == 2) || (current_ground == 36)) && (PSD[309][3] == 0))) return; terrain_there[q][r] = -1; @@ -1376,6 +1462,8 @@ void draw_trim(short q,short r,short which_trim,short which_mode) if (current_ground == 2) // trim with grass instead of cave floor OffsetRect(&from_rect,0,36); + if(current_ground == 36) // trim with mountains instead of cave floor + OffsetRect(&from_rect,0,72); 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; diff --git a/Blades of Exile/GRAPHUTL.CPP b/Blades of Exile/GRAPHUTL.CPP index 8fda2d3f..b4ce4a88 100644 --- a/Blades of Exile/GRAPHUTL.CPP +++ b/Blades of Exile/GRAPHUTL.CPP @@ -9,6 +9,7 @@ #include "text.h" #include "string.h" #include "exlsound.h" +#include "infodlgs.h" #include "graphutl.h" #include "globvar.h" @@ -327,7 +328,7 @@ HBITMAP load_pict(short pict_num,HDC) 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 1500: case 1501: case 1502: case 1503: @@ -335,7 +336,7 @@ HBITMAP load_pict(short pict_num,HDC) case 1505: case 1506: case 1507: - got_bitmap = ReadBMP("images/BIGMAPS.BMP"); break; + got_bitmap = ReadBMP("images/BIGMAPS.BMP"); break;*/ // <= doesn't exists 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; @@ -356,3 +357,18 @@ HBITMAP ReadBMP(char * fileName) { return (HBITMAP) LoadImage(0, fileName, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE); } + +HBITMAP ReadScenFile(char* filename){ //like ReadBMP but in the current scenario folder only. + + short store_val; + char str[256]= "scenarios/"; + store_val= strlen(party.scen_name)-1; + while(party.scen_name[store_val] != '.'){ // get rid of the .exs part + store_val--; + } + strncat(str, party.scen_name, store_val + 1); // the scenario is in a subfolder so add that to the filepath + strcat(str,"exr/"); + strcat(str,filename); + + return (HBITMAP) LoadImage(0, str, IMAGE_BITMAP, 0 ,0 , LR_LOADFROMFILE); +} diff --git a/Blades of Exile/GRAPHUTL.H b/Blades of Exile/GRAPHUTL.H index a8f1e8ef..5c03039f 100644 --- a/Blades of Exile/GRAPHUTL.H +++ b/Blades of Exile/GRAPHUTL.H @@ -11,5 +11,6 @@ void paint_pattern(HBITMAP dest,short which_mode,RECT dest_rect,short which_patt /* GK */ extern HBITMAP ReadBMP(char * fileName); +extern HBITMAP ReadScenFile(char* filename); #endif diff --git a/Blades of Exile/ITEMS.CPP b/Blades of Exile/ITEMS.CPP index 3122b434..96b2676c 100644 --- a/Blades of Exile/ITEMS.CPP +++ b/Blades of Exile/ITEMS.CPP @@ -18,6 +18,7 @@ #include "string.h" #include "graphutl.h" #include "monster.h" +#include "specials.h" #include "globvar.h" @@ -66,6 +67,10 @@ void party_record_type::giveGold(short amount, bool print_result) if (amount < 0) return; gold += amount; + if(gold > 30000){ + gold = 30000; + add_string_to_buf("Excess gold dropped. "); + } if (print_result) put_pc_screen(); } @@ -74,6 +79,8 @@ bool party_record_type::takeGold(short amount, bool print_result) if (gold < amount) return false; gold -= amount; + if(gold < 0) + gold = 0; if (print_result) put_pc_screen(); @@ -108,6 +115,10 @@ void party_record_type::giveFood(short amount, bool print_result) if (amount < 0) return; food += amount; + if(food > 25000){ + food = 25000; + add_string_to_buf("Excess food dropped. "); + } if (print_result) put_pc_screen(); } @@ -163,10 +174,10 @@ 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) { +/* 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; @@ -228,7 +239,7 @@ short get_item(location place,short pc_num,Boolean check_container) 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(); + set_town_status(0); i = T_M; add_string_to_buf("Your crime was seen!"); } @@ -245,11 +256,12 @@ short get_item(location place,short pc_num,Boolean check_container) return taken; } -void make_town_hostile() +void set_town_status(unsigned char attitude) +//0 - hostile, 1 - friendly, 2 - dead { - short i,num; - Boolean fry_party = FALSE; + short i,num,s1,s2,s3; + if(attitude == 0){ if (which_combat_type == 0) return; give_help(53,0,0); @@ -270,16 +282,25 @@ void make_town_hostile() } } + // 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; - } + if((PSD[SDF_LEGACY_SCENARIO] == 1) && (c_town.town.hostile_spec_to_call == 0))//preserve legacy towns + c_town.town.hostile_spec_to_call = -1; + + if ((c_town.town.hostile_spec_to_call >= 0) && (c_town.town.hostile_spec_to_call < 100)) + run_special(1,2,c_town.town.hostile_spec_to_call,c_town.p_loc,&s1,&s2,&s3); + + } + else if (attitude == 1){ + for (i = 0; i < T_M; i++) + c_town.monst.dudes[i].attitude = 0; + } + else {// dead part non working for now + c_town.town.town_chop_time = party.age/3700; + c_town.town.town_chop_key = 0; + } } @@ -922,3 +943,4 @@ bool pc_array::checkClass(short item_class, short mode) } return false; } + diff --git a/Blades of Exile/ITEMS.H b/Blades of Exile/ITEMS.H index ffdf627b..869a8f32 100644 --- a/Blades of Exile/ITEMS.H +++ b/Blades of Exile/ITEMS.H @@ -14,7 +14,7 @@ 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 set_town_status(unsigned char attitude); 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); diff --git a/Blades of Exile/MONSTER.CPP b/Blades of Exile/MONSTER.CPP index 5373d324..aee6788d 100644 --- a/Blades of Exile/MONSTER.CPP +++ b/Blades of Exile/MONSTER.CPP @@ -56,6 +56,9 @@ short difficulty_adjust() short i, j = 0; short to_return = 1; + if(scenario.adjust_diff > 0) // don't automatically adjust difficulty flag activated + return 1; + for (i = 0; i < 6; i++) if (adven[i].isAlive()) j += adven[i].level; @@ -1312,7 +1315,11 @@ void current_town_type::activateMonsters(short code) 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) + if (monst.dudes[i].monst_start.spec_enc_code == code){ + if((sd_legit(monst.dudes[i].monst_start.spec1,monst.dudes[i].monst_start.spec2) == TRUE) + && (party.stuff_done[monst.dudes[i].monst_start.spec1][monst.dudes[i].monst_start.spec2] == 1)) + monst.dudes[i].monst_start.spec_enc_code = 0;//monster has a life flag and is already dead + else { monst.dudes[i].monst_start.spec_enc_code = 0; monst.dudes[i].active = 2; @@ -1326,6 +1333,7 @@ void current_town_type::activateMonsters(short code) 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) diff --git a/Blades of Exile/NEWGRAPH.CPP b/Blades of Exile/NEWGRAPH.CPP index f2f23784..77b86ec0 100644 --- a/Blades of Exile/NEWGRAPH.CPP +++ b/Blades of Exile/NEWGRAPH.CPP @@ -1033,7 +1033,7 @@ void place_talk_str(char *str_to_place,char *str_to_place2,short color,RECT c_re 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; @@ -1070,6 +1070,8 @@ void place_talk_str(char *str_to_place,char *str_to_place2,short color,RECT c_re if (color == 0) SetTextColor(hdc,colors[5]); else SetTextColor(hdc,colors[6]); + if((PSD[307][1] == 1) && (talk_end_forced)) + ShowWindow(talk_edit_box, SW_HIDE); for (i = 0; i < 9; i++) if ((talk_end_forced == FALSE) || (i == 6) || (i == 5)) { OffsetRect(&preset_words[i].word_rect,0,-2); @@ -1249,12 +1251,13 @@ void place_talk_str(char *str_to_place,char *str_to_place2,short color,RECT c_re 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 @@ -1263,6 +1266,8 @@ void place_talk_str(char *str_to_place,char *str_to_place2,short color,RECT c_re 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() diff --git a/Blades of Exile/PARTY.CPP b/Blades of Exile/PARTY.CPP index a448fe77..a49a4ac0 100644 --- a/Blades of Exile/PARTY.CPP +++ b/Blades of Exile/PARTY.CPP @@ -858,6 +858,8 @@ Boolean spend_xp(short pc_num, short mode, short parent) ModalDialog(); cd_kill_dialog(1010,0); + + return dialog_answer; } @@ -1096,7 +1098,7 @@ void do_mage_spell(short pc_num,short spell_num) 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) + else if ((c_town.town.defy_scrying == 1) || (c_town.town.defy_mapping == 1)) add_string_to_buf(" The spell fails. "); else { adven[pc_num].removeCharge(item); @@ -1706,34 +1708,32 @@ void cast_town_spell(location where) } } -void check_spell_on_space(location where, unsigned char spell) +void check_spell_on_space(location where, unsigned char spell) //code is basically done for a "Check spell" node, remains to do a check when targeting a space in all mode ... { short i,s1,s2,s3; - if(PSD[SDF_LEGACY_SCENARIO] == 1){ - 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."); - } - else{ + if(PSD[SDF_LEGACY_SCENARIO] == 1){ + if(spell == 108){ // legacy behavior, only checks Ritual of Sanctify + for (i = 0; i < 50; i++) + if (same_point(where,c_town.town.special_locs[i]) == TRUE) + { + 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."); + } + } + else{ 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) && (c_town.town.specials[c_town.town.spec_id[i]].ex1a == spell)) - run_special(16,2,c_town.town.spec_id[i],where,&s1,&s2,&s3); - return; - } - if(spell == 108) - add_string_to_buf(" Nothing happens."); + if (same_point(where,c_town.town.special_locs[i]) == TRUE) + { + if ((c_town.town.specials[c_town.town.spec_id[i]].type == 24) && (c_town.town.specials[c_town.town.spec_id[i]].ex1a == spell)) + run_special(16,2,c_town.town.spec_id[i],where,&s1,&s2,&s3); + return; + } + if(spell == 108) + add_string_to_buf(" Nothing happens."); } } @@ -1746,7 +1746,7 @@ void do_mindduel(short pc_num,creature_data_type *monst) if (adven[pc_num].hasAbilEquip(53) < 24) adjust += 20; if (monst->attitude % 2 != 1) - make_town_hostile(); + set_town_status(0); monst->attitude = 1; add_string_to_buf("Mindduel!"); diff --git a/Blades of Exile/PC.CPP b/Blades of Exile/PC.CPP index b28f5e79..9a1db89e 100644 --- a/Blades of Exile/PC.CPP +++ b/Blades of Exile/PC.CPP @@ -164,7 +164,7 @@ bool pc_record_type::runTrap(short trap_type, short trap_level, short diff) case TRAP_ALERT: add_string_to_buf(" An alarm goes off!!! "); - make_town_hostile(); + set_town_status(0); break; case TRAP_FLAMES: diff --git a/Blades of Exile/SPECIALS.CPP b/Blades of Exile/SPECIALS.CPP index 59b4f593..826d1b32 100644 --- a/Blades of Exile/SPECIALS.CPP +++ b/Blades of Exile/SPECIALS.CPP @@ -18,10 +18,12 @@ #include "specials.h" #include "newgraph.h" #include "dlgutils.h" +#include "actions.h" +#include "graphutl.h" +#include "dlogtool.h" #include "globvar.h" - void start_split(short a, short b, short noise) { party.stuff_done[304][0] = 1; @@ -718,6 +720,31 @@ effect_pat_type s = {{{0,0,0,0,0,0,0,0,0}, break; } break; + case 95: + switch(type){ + case 0: + if((is_town()) || ((is_combat()) && (which_combat_type == 1))) + run_special(8,2,str,location(),&i,&j,&r1);// Call town special + else + run_special(8,1,str,location(),&i,&j,&r1);// Call outdoor special + break; + case 1: + if((is_town()) || ((is_combat()) && (which_combat_type == 1))) + run_special(8,2,str,location(),&i,&j,&r1);// Call town special + else + run_special(8,0,str,location(),&i,&j,&r1);// Call scenario special + break; + case 2: + if((is_town()) || ((is_combat()) && (which_combat_type == 1))) + run_special(8,0,str,location(),&i,&j,&r1);// Call scenario special + else + run_special(8,1,str,location(),&i,&j,&r1);// Call outdoor special + break; + case 3: + run_special(8,0,str,location(),&i,&j,&r1);// Call scenario special + break; + } + break; // spell effects case 110: @@ -815,7 +842,7 @@ effect_pat_type s = {{{0,0,0,0,0,0,0,0,0}, } break; case 131: - if (c_town.town.specials2 % 10 == 1) { + if ((c_town.town.defy_scrying == 1) && (c_town.town.defy_mapping == 1)) { add_string_to_buf(" It doesn't work."); break; } @@ -1223,13 +1250,13 @@ Boolean damage_monst(short which_m, short who_hit, short how_much, short how_muc (processing_fields == FALSE) && (monsters_going == FALSE)) { add_string_to_buf("Damaged an innocent. "); victim->attitude = 1; - make_town_hostile(); + set_town_status(0); } 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(); + set_town_status(0); } return TRUE; @@ -1426,7 +1453,8 @@ void push_things() } } -BOOL special_increase_age() +BOOL special_increase_age(char mode) +//mode : 0 triggers, 1 delay { short i,s1,s2,s3; Boolean redraw = FALSE,stat_area = FALSE; @@ -1435,32 +1463,68 @@ BOOL special_increase_age() 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; - to_return = TRUE; + if(mode == 0){ + run_special(9,2,c_town.town.timer_specs[i],location(),&s1,&s2,&s3); + stat_area = TRUE; + if (s3 > 0) + redraw = TRUE; + to_return = TRUE; + } + else if (queue_position < 20){ + special_queue[queue_position].queued_special = c_town.town.timer_specs[i]; + special_queue[queue_position].trigger_time = party.age; + special_queue[queue_position].type = 2; + special_queue[queue_position].mode = 9; + special_queue[queue_position].where = location(); + queue_position++; + } } 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; - to_return = TRUE; + if(mode == 0){ + run_special(10,0,scenario.scenario_timer_specs[i],location(),&s1,&s2,&s3); + stat_area = TRUE; + if (s3 > 0) + redraw = TRUE; + to_return = TRUE; + } + else if (queue_position < 20){ + special_queue[queue_position].queued_special = scenario.scenario_timer_specs[i]; + special_queue[queue_position].trigger_time = party.age; + special_queue[queue_position].type = 0; + special_queue[queue_position].mode = 10; + special_queue[queue_position].where = location(); + queue_position++; + } } 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; - to_return = TRUE; - } + if(mode == 0){ + 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; + to_return = TRUE; + } + else if (queue_position < 20){ + if (party.global_or_town[i] == 0){ + special_queue[queue_position].type = 0; + special_queue[queue_position].mode = 11; + } + else{ + special_queue[queue_position].type = 2; + special_queue[queue_position].mode = 11; + } + special_queue[queue_position].queued_special = party.node_to_call[i]; + special_queue[queue_position].trigger_time = party.age; + special_queue[queue_position].where = location(); + queue_position++; + } + } else party.party_event_timers[i]--; } if (stat_area == TRUE) { @@ -1501,7 +1565,6 @@ void run_special(short which_mode,short which_type,short start_spec,location spe { short cur_spec,cur_spec_type,next_spec,next_spec_type; special_node_type cur_node; - 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; @@ -1528,7 +1591,7 @@ void run_special(short which_mode,short which_type,short start_spec,location spe special_in_progress = FALSE; return; } - if ((cur_node.type >= 0) && (cur_node.type <= 27)) { + if ((cur_node.type >= 0) && (cur_node.type <= 28)) { 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)) { @@ -1537,10 +1600,10 @@ void run_special(short which_mode,short which_type,short start_spec,location spe 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)) { + if ((cur_node.type >= 130) && (cur_node.type <= 156)) { 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)) { + if ((cur_node.type >= 170) && (cur_node.type <= 197)) { 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)) { @@ -1549,8 +1612,7 @@ void run_special(short which_mode,short which_type,short start_spec,location spe 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); } - -// if(((GetAsyncKeyState(VK_LCONTROL) & 32768) == 32768) && ((GetAsyncKeyState(0x43) & 32768) == 32768)) {//Ctrl-C escape sequence check + if(check_for_interrupt()){ give_error("The special encounter was interrupted. The scenario may be in an unexpected state; it is recommended that you reload from a saved game.","",0); // give_error("A special encounter can be at most 50 nodes long. The 50th node was just processed. The encounter will now end.","",0); @@ -1561,6 +1623,7 @@ void run_special(short which_mode,short which_type,short start_spec,location spe erase_out_specials(); else erase_specials(); special_in_progress = FALSE; + } special_node_type get_node(short cur_spec,short cur_spec_type) @@ -1675,7 +1738,10 @@ void general_spec(short which_mode,special_node_type cur_node,short cur_spec_typ } break; case 14: - play_sound(1000 + spec.ex1a); + if(spec.ex1a < 0) + play_sound(spec.ex1a); + else + play_sound(1000 + spec.ex1a); break; case 15: check_mess = TRUE; @@ -1740,7 +1806,14 @@ void general_spec(short which_mode,special_node_type cur_node,short cur_spec_typ break; case 25: check_mess = TRUE; - party.age += spec.ex1a; + if(party.stuff_done[309][6] == 1){ + for(i = 0; i < spec.ex1a ; i++){ + party.age++; + special_increase_age(1);//if timed special happens, put them on the timer queue + } + } + else + party.age += spec.ex1a; adven.heal(spec.ex1b); adven.restoreSP(spec.ex1b); break; @@ -1750,15 +1823,36 @@ void general_spec(short which_mode,special_node_type cur_node,short cur_spec_typ *a = (spec.ex1a == 0) ? 1 : 0; break; case 27: - char count=0;//temporary fix, maybe we'll do a special "you lose" dialog. - for(i=0;i<6;i++) + for(i=0;i<6;i++)//temporary fix, maybe we'll do a special "you lose" dialog. if(adven[i].isAlive() == FALSE) - count++; + store_val++; - if(count != 6) + if(store_val != 6) end_scenario = TRUE; break; - } + case 28: + check_mess = FALSE; + if(spec.ex1a >= 160 && spec.ex1a < 260) + strcpy(str1, scen_strs2[spec.ex1a - 160]); + else{ + give_error("Wrong scenario text number has been called (must be between 160 and 259).","",0); + break; + } + if ((displayed_picture = ReadScenFile(str1)) == NULL){ + give_error("Error opening the image file. Make sure the extension (.bmp) is specified in the scenario message text (the first search directory is the current scenario folder).","",0); + break; + } + + cd_create_custom_pic_dialog(mainPtr,displayed_picture); + + while (dialog_not_toast) + ModalDialog(); + + cd_kill_dialog(905,0); + DeleteObject(displayed_picture); + displayed_picture = NULL; + break; + } if (check_mess == TRUE) { handle_message(which_mode,cur_spec_type,cur_node.m1,cur_node.m2,a,b); } @@ -1953,12 +2047,10 @@ void affect_spec(short which_mode,special_node_type cur_node,short cur_spec_type else 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) @@ -2113,22 +2205,42 @@ void affect_spec(short which_mode,special_node_type cur_node,short cur_spec_type 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); + if(spec.ex1b == -1) + spec.ex1b = 1; + if ((spec.ex1b != 0) && (spec.ex1b != 1)){ + give_error("Error the Extra 1b field should be 0 (take spell) or 1 (give spell). (-1 is legacy compatibility)","",0); + break; + } + if((spec.ex1a < 0) || ((spec.ex1a > 31) && ( spec.ex1a < 100)) || (spec.ex1a > 129)){ + give_error("Mage spell is out of range (0 - 31) or (100-129). See docs.","",0); break; } + if(spec.ex1a >= 100) + r1 = spec.ex1a - 130; + else + r1 = spec.ex1a; for (i = 0; i < 6; i++) if ((pc < 0) || (pc == i)) - adven[i].mage_spells[spec.ex1a + 30] = TRUE; + adven[i].mage_spells[r1 + 30] = spec.ex1b; 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); + if(spec.ex1b == -1) + spec.ex1b = 1; + if ((spec.ex1b != 0) && (spec.ex1b != 1)){ + give_error("Error the Extra 1b field should be 0 (take spell) or 1 (give spell). (-1 is legacy compatibility)","",0); + break; + } + if((spec.ex1a < 0) || ((spec.ex1a > 31) && ( spec.ex1a < 100)) || (spec.ex1a > 129)){ + give_error("Priest spell is out of range (0 - 31) or (100-129). See docs.","",0); break; } + if(spec.ex1a >= 100) + r1 = spec.ex1a - 130; + else + r1 = spec.ex1a; for (i = 0; i < 6; i++) if ((pc < 0) || (pc == i)) - adven[i].priest_spells[spec.ex1a + 30] = TRUE; + adven[i].priest_spells[r1 + 30] = spec.ex1b; break; case 101: if (spec.ex1b == 0) @@ -2326,9 +2438,350 @@ void ifthen_spec(short which_mode,special_node_type cur_node,short cur_spec_type 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; + case 153: //has enough statistic ? + char to_check; + k=0; // number to compare to + j=0; // number of alive pc + + if((spec.ex2b == -1) || (spec.ex2a == -1)){ + if (adven.getMageLore() >= spec.ex1a) + *next_spec = spec.ex1b; + break; + } + + if((spec.ex2a < -1) || (spec.ex2a > 25)){ + give_error("The check statistic node tried to check an out-of-range statistic (shoud be between 0 - strengh to 18 - luck and 25. -1 is default compatibility to check mage lore.).","",0); + break; + } + + if(current_pc_picked_in_spec_enc >= 0)// is a pc selected ? + to_check = 10 + current_pc_picked_in_spec_enc; + else + to_check = spec.ex2b; + + switch(to_check){ + case 1: // highest + for(i = 0;i < 6; i++) + if(adven[i].main_status == MAIN_STATUS_ALIVE){ + switch (spec.ex2a){ + case 19: //current health + if(k < adven[i].cur_health) + k = adven[i].cur_health; + break; + case 20: //max health + if(k < adven[i].max_health) + k = adven[i].max_health; + break; + case 21: //current spell points + if(k < adven[i].cur_sp) + k = adven[i].cur_sp; + break; + case 22: //max spell points + if(k < adven[i].max_sp) + k = adven[i].max_sp; + break; + case 23 ://experience + if(k < adven[i].experience) + k = adven[i].experience; + break; + case 24 ://skill points + if(k < adven[i].skill_pts) + k = adven[i].skill_pts; + break; + case 25://level + if(k < adven[i].level) + k = adven[i].level; + break; + default : + if(k < adven[i].skills[spec.ex2a]) + k = adven[i].skills[spec.ex2a]; + break; + } + } + break; + case 2:// average + for(i = 0;i < 6;i++) + if(adven[i].main_status == MAIN_STATUS_ALIVE){ + switch (spec.ex2a){ + case 19: //current health + k += adven[i].cur_health; + break; + case 20: //max health + k += adven[i].max_health; + break; + case 21: //current spell points + k += adven[i].cur_sp; + break; + case 22: //max spell points + k += adven[i].max_sp; + break; + case 23 ://experience + k += adven[i].experience; + break; + case 24 ://skill points + k += adven[i].skill_pts; + break; + case 25://level + k += adven[i].level; + break; + default : + k += adven[i].skills[spec.ex2a]; + break; + } + j++; + } + k = k / j; + break; + case 3: // lowest + k = 32000; + for(i = 0;i < 6 ; i++) + if(adven[i].main_status == MAIN_STATUS_ALIVE) + switch (spec.ex2a){ + case 19: //current health + if(k > adven[i].cur_health) + k = adven[i].cur_health; + break; + case 20: //max health + if(k > adven[i].max_health) + k = adven[i].max_health; + break; + case 21: //current spell points + if(k > adven[i].cur_sp) + k = adven[i].cur_sp; + break; + case 22: //max spell points + if(k > adven[i].max_sp) + k = adven[i].max_sp; + break; + case 23 ://experience + if(k > adven[i].experience) + k = adven[i].experience; + break; + case 24 ://skill points + if(k > adven[i].skill_pts) + k = adven[i].skill_pts; + break; + case 25://level + if(k > adven[i].level) + k = adven[i].level; + break; + default : + if(k > adven[i].skills[spec.ex2a]) + k = adven[i].skills[spec.ex2a]; + break; + } + + break; + case 10: //pc 1 + if(adven[0].main_status == MAIN_STATUS_ALIVE) + switch (spec.ex2a){ + case 19: //current health + k = adven[0].cur_health; + break; + case 20: //max health + k = adven[0].max_health; + break; + case 21: //current spell points + k = adven[0].cur_sp; + break; + case 22: //max spell points + k = adven[0].max_sp; + break; + case 23 ://experience + k = adven[0].experience; + break; + case 24 ://skill points + k = adven[0].skill_pts; + break; + case 25://level + k = adven[0].level; + break; + default : + k = adven[0].skills[spec.ex2a]; + break; + } + break; + case 11: //pc 2 + if(adven[1].main_status == MAIN_STATUS_ALIVE) + switch (spec.ex2a){ + case 19: //current health + k = adven[1].cur_health; + break; + case 20: //max health + k = adven[1].max_health; + break; + case 21: //current spell points + k = adven[1].cur_sp; + break; + case 22: //max spell points + k = adven[1].max_sp; + break; + case 23 ://experience + k = adven[1].experience; + break; + case 24 ://skill points + k = adven[1].skill_pts; + break; + case 25://level + k = adven[1].level; + break; + default : + k = adven[1].skills[spec.ex2a]; + break; + } + break; + case 12: //pc 3 + if(adven[2].main_status == MAIN_STATUS_ALIVE) + switch (spec.ex2a){ + case 19: //current health + k = adven[2].cur_health; + break; + case 20: //max health + k = adven[2].max_health; + break; + case 21: //current spell points + k = adven[2].cur_sp; + break; + case 22: //max spell points + k = adven[2].max_sp; + break; + case 23 ://experience + k = adven[2].experience; + break; + case 24 ://skill points + k = adven[2].skill_pts; + break; + case 25://level + k = adven[2].level; + break; + default : + k = adven[2].skills[spec.ex2a]; + break; + } + break; + case 13: //pc 4 + if(adven[3].main_status == MAIN_STATUS_ALIVE) + switch (spec.ex2a){ + case 19: //current health + k = adven[3].cur_health; + break; + case 20: //max health + k = adven[3].max_health; + break; + case 21: //current spell points + k = adven[3].cur_sp; + break; + case 22: //max spell points + k = adven[3].max_sp; + break; + case 23 ://experience + k = adven[3].experience; + break; + case 24 ://skill points + k = adven[3].skill_pts; + break; + case 25://level + k = adven[3].level; + break; + default : + k = adven[3].skills[spec.ex2a]; + break; + } + break; + case 14: //pc 5 + if(adven[4].main_status == MAIN_STATUS_ALIVE) + switch (spec.ex2a){ + case 19: //current health + k = adven[4].cur_health; + break; + case 20: //max health + k = adven[4].max_health; + break; + case 21: //current spell points + k = adven[4].cur_sp; + break; + case 22: //max spell points + k = adven[4].max_sp; + break; + case 23 ://experience + k = adven[4].experience; + break; + case 24 ://skill points + k = adven[4].skill_pts; + break; + case 25://level + k = adven[4].level; + break; + default : + k = adven[4].skills[spec.ex2a]; + break; + } + break; + case 15: //pc 6 + if(adven[5].main_status == MAIN_STATUS_ALIVE) + switch (spec.ex2a){ + case 19: //current health + k = adven[5].cur_health; + break; + case 20: //max health + k = adven[5].max_health; + break; + case 21: //current spell points + k = adven[5].cur_sp; + break; + case 22: //max spell points + k = adven[5].max_sp; + break; + case 23 ://experience + k = adven[5].experience; + break; + case 24 ://skill points + k = adven[5].skill_pts; + break; + case 25://level + k = adven[5].level; + break; + default : + k = adven[5].skills[spec.ex2a]; + break; + } + break; + default : // cumulative + for(i = 0;i < 6;i++) + if(adven[i].main_status == MAIN_STATUS_ALIVE) + switch (spec.ex2a){ + case 19: //current health + k += adven[i].cur_health; + break; + case 20: //max health + k += adven[i].max_health; + break; + case 21: //current spell points + k += adven[i].cur_sp; + break; + case 22: //max spell points + k += adven[i].max_sp; + break; + case 23 ://experience + k += adven[i].experience; + break; + case 24 ://skill points + k += adven[i].skill_pts; + break; + case 25://level + k += adven[i].level; + break; + default : + k += adven[i].skills[spec.ex2a]; + break; + } + break; + } + char buf[256]; + sprintf(buf,"%d",k); + give_error(buf,"",0); + if (k >= spec.ex1a) + *next_spec = spec.ex1b; break; case 154: // text response check_mess = FALSE; @@ -2353,6 +2806,19 @@ void ifthen_spec(short which_mode,special_node_type cur_node,short cur_spec_type *next_spec = spec.ex1b; } break; + case 156: + k = 0; // number to compare to + + if((spec.ex1a < 0) || (spec.ex1a > 2)){ + give_error("Species out of range. (should be 0 - Human, 1 - Nephilim, 2 - Slith)","",0); + break; + } + for(i = 0; i < 6; i++) + if((adven[i].main_status == MAIN_STATUS_ALIVE) && (adven[i].race == spec.ex1a)) + k++; + if(((spec.ex2b == -1) && (k < spec.ex2a)) || ((spec.ex2b == 0) && (k == spec.ex2a)) || ((spec.ex2b == -1) && (k > spec.ex2a))) + *next_spec = spec.ex1b; + break; } if (check_mess == TRUE) { handle_message(which_mode,cur_spec_type,cur_node.m1,cur_node.m2,a,b); @@ -2379,7 +2845,13 @@ void townmode_spec(short which_mode,special_node_type cur_node,short cur_spec_ty return; switch (cur_node.type) { case 170: - make_town_hostile(); + if(spec.ex1a == -1)// legacy compatibility check + spec.ex1a = 0; + if((spec.ex1a < 0) || (spec.ex1a > 2)){ + give_error("The status to change town to was out of reach (should be 0 - Hostile, 1 - Friendly, 2- Dead).","",0); + break; + } + set_town_status(spec.ex1a); break; case 171: set_terrain(l,spec.ex2a); @@ -2422,6 +2894,7 @@ void townmode_spec(short which_mode,special_node_type cur_node,short cur_spec_ty check_mess = FALSE; } else { // 1 no + if (which_mode < 3) *a = 1; if ((which_mode == 7) || (spec.ex2a == 0)) teleport_party(spec.ex1a,spec.ex1b,1); @@ -2508,7 +2981,8 @@ void townmode_spec(short which_mode,special_node_type cur_node,short cur_spec_ty } else if (FCD(870,0) == 1) { *next_spec = -1; if (which_mode < 3) *a = 1;} else{ - *a = 1; + if (which_mode < 3) + *a = 1; if ((which_mode == 7) || (spec.ex2a == 0)) teleport_party(spec.ex1a,spec.ex1b,1); else teleport_party(spec.ex1a,spec.ex1b,0); @@ -2521,13 +2995,13 @@ void townmode_spec(short which_mode,special_node_type cur_node,short cur_spec_ty break; case 187: check_mess = FALSE; - if (is_combat()) { +/* if (is_combat()) { ASB("Can't change level in combat."); if (which_mode < 3) *a = 1; *next_spec = -1; - } - else if (which_mode != 1) { + }*/ + if (which_mode != 1 && PSD[309][5] == 0) { ASB("Can't change level now."); if (which_mode < 3) *a = 1; @@ -2536,8 +3010,27 @@ void townmode_spec(short which_mode,special_node_type cur_node,short cur_spec_ty 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;} + if (FCD(880 + spec.ex2b,0) == 1) { + *next_spec = -1; + if (which_mode < 3) *a = 1; + } else { + if(overall_mode == MODE_TALKING) + end_talk_mode(); + if (is_combat()){ + if (which_combat_type == 0){ //outdoor combat + end_combat(); + end_town_mode(0,c_town.p_loc); + menu_activate(1); + put_pc_screen(); + set_stat_window(current_pc); + } + else{ //town combat + party.direction = end_town_combat(); + set_stat_window(current_pc); + menu_activate(1); + } + } *a = 1; change_level(spec.ex2a,l.x,l.y); } @@ -2592,8 +3085,9 @@ void townmode_spec(short which_mode,special_node_type cur_node,short cur_spec_ty 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)) + if (which_mode < 3) + *a = 1; + if (spec.ex2a == 0) teleport_party(spec.ex1a,spec.ex1b,1); else teleport_party(spec.ex1a,spec.ex1b,0); } @@ -2603,14 +3097,7 @@ void townmode_spec(short which_mode,special_node_type cur_node,short cur_spec_ty 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) { + if (which_mode != 1 && PSD[309][5] == 0) { ASB("Can't change level now."); if (which_mode < 3) *a = 1; @@ -2627,11 +3114,35 @@ void townmode_spec(short which_mode,special_node_type cur_node,short cur_spec_ty if (spec.ex2b == 1) i = 2; else i = custom_choice_dialog((char *) strs,719,buttons) ; - *a = 1; - if (i == 1) { *next_spec = -1;} + + if (i == 1) { + *next_spec = -1; + if(which_mode < 3) + *a = 1; + } else { + if(overall_mode == MODE_TALKING) + end_talk_mode(); + if (is_combat()){ + i = 10; //was in combat ... + if (which_combat_type == 0){ //outdoor combat + end_combat(); + end_town_mode(0,c_town.p_loc); + menu_activate(1); + put_pc_screen(); + set_stat_window(current_pc); + } + else{ //town combat + party.direction = end_town_combat(); + set_stat_window(current_pc); + menu_activate(1); + } + } *a = 1; change_level(spec.ex2a,l.x,l.y); + if(i == 10){ // ... so back in combat + start_town_combat(party.direction); + } } } break; @@ -2691,6 +3202,25 @@ void townmode_spec(short which_mode,special_node_type cur_node,short cur_spec_ty i = 30; } break; + case 196: + if(spec.ex1a >= 0 && spec.ex1a < 4)//change town lightning + c_town.town.lighting = spec.ex1a; + if(spec.ex2b == 0)//give party light + party.light_level += spec.ex2a; + else if(spec.ex2b == 1)//take party light + party.light_level -= spec.ex2a; + break; + case 197: //attitude: 0 - Friendly, Docile, 1 - Hostile, Type A, 2 - Friendly, Will fight, 3 - Hostile, Type B + if((spec.ex1a < 0) || (spec.ex1a > 59)){ + give_error("The monster number in Extra 1a was out of bound (should be between 0 and 59).","",0); + break; + } + if((spec.ex1b < 0) || (spec.ex1b > 3)){ + give_error("The attitude Extra 1b was out of bound (0 - Friendly Docile, 1 - Hostile Type A, 2 - Friendly Will Fight, 3 -Hostile Type B).","",0); + break; + } + c_town.monst.dudes[spec.ex1a].attitude = spec.ex1b; + break; } if (check_mess == TRUE) { handle_message(which_mode,cur_spec_type,cur_node.m1,cur_node.m2,a,b); @@ -2797,7 +3327,6 @@ void rect_spec(short which_mode,special_node_type cur_node,short cur_spec_type, if(party.stuff_done[308][0] == 0) draw_map_rect(modeless_dialogs[5],l.x,l.y,l.x,l.y); break; - } } } @@ -2888,8 +3417,9 @@ void handle_message(short which_mode,short cur_type,short mess1,short mess2,shor short label1 = -1,label2 = -1,label1b = -1,label2b = -1; short mess_adj[3] = {160,10,20}; - if ((mess1 < 0) && (mess2 < 0)) - return; + 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); diff --git a/Blades of Exile/SPECIALS.H b/Blades of Exile/SPECIALS.H index 0767c3ac..d2303792 100644 --- a/Blades of Exile/SPECIALS.H +++ b/Blades of Exile/SPECIALS.H @@ -13,7 +13,7 @@ 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); -BOOL special_increase_age(); +BOOL special_increase_age(char mode); void out_move_party(char x,char y) ; void teleport_party(short x,short y,short mode); Boolean run_stone_circle(short which); diff --git a/Blades of Exile/TEXT.CPP b/Blades of Exile/TEXT.CPP index 3db14475..a1ce912d 100644 --- a/Blades of Exile/TEXT.CPP +++ b/Blades of Exile/TEXT.CPP @@ -1199,6 +1199,8 @@ short print_terrain(location space) void add_string_to_buf(char *string) { + if(strcmp(string,"") == 0) + return; // SetScrollPos(text_sbar,SB_CTL,58,TRUE); lpsi.nPos = 58; lpsi.fMask = SIF_POS; diff --git a/Blades of Exile/TOWN.CPP b/Blades of Exile/TOWN.CPP index a6e43258..c6bb7335 100644 --- a/Blades of Exile/TOWN.CPP +++ b/Blades of Exile/TOWN.CPP @@ -99,8 +99,8 @@ void start_town_mode(short which_town, short entry_dir) 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 (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)) @@ -300,8 +300,8 @@ void start_town_mode(short which_town, short entry_dir) 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; + special_queue[0].queued_special = c_town.town.spec_on_entry_if_dead; + else special_queue[0].queued_special = 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) && @@ -526,28 +526,28 @@ location end_town_mode(short switching_level,location destination) // returns n 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]; + special_queue[1].queued_special = 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]; + special_queue[1].queued_special = 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]; + special_queue[1].queued_special = 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]; + special_queue[1].queued_special = c_town.town.exit_specs[2]; } } @@ -573,6 +573,8 @@ location end_town_mode(short switching_level,location destination) // returns n if (combat_end == FALSE) clear_map(); + c_town.town_num = -1; //no longer in a town + return to_return; } @@ -710,6 +712,7 @@ void create_out_combat_terrain(short type,short num_walls) 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 surface swamp 11 surface woods 12 s. shrub 13 stalags +// 14 cave road, 15 grass road, 16 mountain road 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, @@ -730,13 +733,13 @@ short general_types[260] = {1,1,0,0,0,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,0,0,0,0,0,0, -0,0,1,0,2,0,0,1,1,1,// 200 +0,0,14,15,16,0,0,1,1,1,// 200 1,0,2,1,1,1,0,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 ter_base[17] = {2,0,36,50,71, 0,0,0,0,2, 2,2,2,0, 0,2,36}; //short ground_type[14] = {2,0,36,50,71, 0,0,0,0,2, 2,2,2,0}; location special_ter_locs[15] = @@ -750,7 +753,7 @@ unsigned char mntn_pillar[4][4] = {{37,29,27,36},{29,33,34,27},{31,32,35,25},{36 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}, +short terrain_odds[17][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}, @@ -763,7 +766,10 @@ short terrain_odds[14][10] = {{3,80,4,40,115,20,114,10,112,1}, {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 ... + {1,25,84,15,98,300,97,280,0,0}, + {1,50,93,25,94,5,98,10,95,1}, + {3,80,4,40,115,20,114,10,112,1}, + {37,20,0,0,0,0,0,0,0,0}}; // ter then odds then ter then odds ... ter_type = scenario.ter_types[type].picture; @@ -790,13 +796,21 @@ short terrain_odds[14][10] = {{3,80,4,40,115,20,114,10,112,1}, t_d.terrain[0][0] = ter_base[ter_type]; - if ((ter_type == 3) || (ter_type == 4) ) { + if (ter_type == 3) { 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 (ter_type == 11) { + + if(ter_type == 4){ + t_d.terrain[0][0] = 82; + for (i = 15; i < 26; i++) + for (j = 9; j < 35; j++) + t_d.terrain[i][j] = 82; + } + + if (ter_type == 14 || ter_type == 15 || ter_type == 16) { t_d.terrain[0][0] = 82; for (i = 19; i < 23; i++) for (j = 9; j < 35; j++) @@ -1261,8 +1275,7 @@ void draw_map (HWND the_dialog, short the_item) Boolean out_mode; // UINT c; -if(party.stuff_done[308][0] > 0 ){//map not available ; (temporary ?) assigned to SDF[308][0] - +if(c_town.town.defy_mapping == 1 ){//map not available 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}; @@ -1271,7 +1284,7 @@ if (modeless_exists[5] == TRUE){ SetBkMode(hdc2,TRANSPARENT); SelectObject(hdc2,bold_font); SetTextColor(hdc2,RGB(255,255,255)); - char_win_draw_string(hdc2,text_rect,"Map unavailable.",1,10); + char_win_draw_string(hdc2,text_rect,"This place defies mapping.",1,10); GetClientRect(GetDlgItem(the_dialog,1),&draw_rect); InvalidateRect(GetDlgItem(the_dialog,1),&draw_rect,FALSE); fry_dc(the_dialog,hdc2); @@ -1630,7 +1643,6 @@ BOOL CALLBACK map_dialog_proc(HWND hDlg, UINT message, WPARAM wParam, LPARAM) return FALSE; } - void display_map() { if ( modeless_exists[5] == TRUE) diff --git a/Scenario Editor/BLSCENED.CPP b/Scenario Editor/BLSCENED.CPP index eccc8bfb..b18901fb 100644 --- a/Scenario Editor/BLSCENED.CPP +++ b/Scenario Editor/BLSCENED.CPP @@ -167,8 +167,8 @@ int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR, int nCmd } mainPtr = CreateWindow (szAppName, - "Classic BoE Scenario Editor Beta 2", - WS_OVERLAPPEDWINDOW, + "Classic BoE Scenario Editor 1.0", + WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN, 0, 0, 536, diff --git a/Scenario Editor/BLSCENED.RC b/Scenario Editor/BLSCENED.RC index 1c3d0f0b..06ce800e 100644 --- a/Scenario Editor/BLSCENED.RC +++ b/Scenario Editor/BLSCENED.RC @@ -72,9 +72,9 @@ Exile MENU 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 " Edit Special Nodes", 213 + MENUITEM " Edit Town Text", 214 + MENUITEM " Advanced Town Details", 215 MENUITEM " Set Town Event Timers", 216 MENUITEM SEPARATOR MENUITEM " Clear All Monsters", 217 @@ -94,7 +94,7 @@ Exile MENU MENUITEM SEPARATOR MENUITEM "Advanced:", 310 MENUITEM " Edit Special Nodes\tCtrl+U", 311 - MENUITEM " Edit Outdoor Text\tCtrl+V", 312 + MENUITEM " Edit Outdoor Text", 312 MENUITEM " Delete All Placed Specials", 313 } @@ -208,11 +208,7 @@ ACCELERATORS_1 ACCELERATORS "^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 diff --git a/Scenario Editor/Changes_SE.txt b/Scenario Editor/Changes_SE.txt new file mode 100644 index 00000000..c74da9f5 --- /dev/null +++ b/Scenario Editor/Changes_SE.txt @@ -0,0 +1,134 @@ +Changes : + +- Changed the description of Affect Webs node spec1b so that it states that 0 was inflict and 1 cure. +- Changed the description of Town Special Encounter spec1a so that it states to choose between 1 and 10. +- Changed the Event preventing the Town from dying to accept (and states to choose) values between 1 and 10. +- Animated terrains now play animations. +- Custom terrains now displays (and animated terrains plays) +- Custom items and monsters now display. +- Boats and horses now displays on the view when editing towns. +- Changing the picture of a monster won't display random numbers in monster width and height anymore. +- Added Shops dumping (Ishad Nha's initial work) + +Beta 2 : + +- Dumping functions won't change current town/outdoor section anymore. +- Finished porting the file IO functions to 32 bits. +- Added a rudimentary custom intro picture behavior : if the intro picture is set to 100, the first icon on the custom sheet will be displayed in the scenario selection menu. Scenario intro pics must be drawn on the same scale as talk icons. +- Whenever the “Place Random Items” function is used, the editor will inform the user that it could not place all items because the town item # limit has been reached, regardless of how many items are actually in the town. That has been fixed (the message now displays only if the max number of items is indeed reached). +- Cleaned the ressource file (smaller executable). +- Added a Monster data dumping function (dumps all info about monsters : wandering/special enc/town monsters details ...) +- Added a Specials data dumping function (dumps all info about specials : number, types, variables, ...) +- Town Room/Outdoors Info rectangles are now initialized at ((-1,-1),(-1,-1)) freeing the 0 coordinate and fixing the "Rectangle X" description at (0,0) in the game. +- Cleanse Rectangle SDF1 info rewritten to match actual behavior (0 leave force/fire/webs/crate/barrel, 1 cleans all). +- Corrected the Do SFX Burst info text (1 - telep., 2 - elec.) +- When placing an item with a custom graphic in a town, the editor will display the graphic in the upper-left corner of the space it is placed on. Fixed. +- If you edit a monster’s abilities and click Cancel, the ability of that monster will be removed. Fixed. +- If you edit a item's ability, all previously unsaved modifications are erased. Fixed. +- Disappearences of right scroll bar fixed. + +Version 1.0 : + +- Added a switch to the Scenario Details to bypass the automatic difficulty adjust +- Added the ability to play sound asynchronously (use -sound_number instead of sound_number). +- If a custom monster pic was shown in the monster dialog and a non-custom monster was loaded via the arrows, the pic was always drawn from the custom sheet. Fixed. +- Cancelling while choosing an item ability won't reset the item ability to "No ability" anymore. +- Added a "Change Town Lightning" node. (StarEye a.k.a *i) +- Loading a town in the main menu won't get into editing mode automatically anymore. +- Added an option in the Town Advanced details to prevent the mapping (like in older Exiles). +- Added a "Display picture" node, that living up to its name, displays a picture. Bitmaps (BMP) are the only supported format but image can be of any size +(be warned that if the image is larger/wider than the screen, it will be streched to fit, meaning a (potentially substancial) loss of quality). +The name of the file is search in the scenario special strings (160 to 259) as specified in the node ex1a field. The format must be "[eventual path]filename.bmp". +The base search folder is "[folder_the_scenario_is_in]/scenario_name.exr/". +- Corrected the "Type Flag" description text (is between 0 and 255). +- Modified the "Has Enough Mage Lore?" node into a general statistic check node. (StarEye a.k.a *i) +Here is a description of fields : + +ex1a: how much of skill +ex1b: special to call if enough +ex2a: skill index (-1 defaults to mage lore to preserve compatibility) +0 - 18 corresponding skill, +19 - Current Health, +20 - Max Health, +21 - Current Spell Points, +22 - Max Spell Points, +23 - Experience, +24 - Skill points, +25 - Level. + +ex2b: 0, others - cumulative, 1 - highest, 2 - average, 3 - lowest, 10 + x - that PC. (-1 defaults to mage lore to preserve compatibility) +- Added a "Has enough species ?" node, which checks if the party has (at least) a specified number of character with a given race. (StarEye a.k.a *i) +- Modified the "Give ... spells" nodes to either take (spec.1b = 0) or give (spec.1b = 1) spells and have access to low level spells (spec.1a = 100 + spell_number, with 0 <= spell_number <= 29 ) (StarEye a.k.a *i) +- Added an option in Town Advanced Details to prevent Magic Mapping from being cast (already included in the Map Unavailable option). +- Added an option in Town Advanced Details that specifies a town special to call if the town becomes hostile (for compatibility reasons the special 0 can't be called in legacy scenarios). +- Added a "Change Creature Attitude" node in Town specs : spec.ex1a is the number of the monster in the current town and ex.1b is the attitude to set it to (0 - Friendly, Docile, 1 - Hostile, Type A, 2 - Friendly, Will fight, 3 - Hostile, Type B). +- Modified the "Make town hostile" node to "Set Town Attitude". Spec.ex1a is 0 for hostile, 1 for friendly. The dead part (2) is currently non functionnal. + +ToDo : + +- Make an option to disable the editor's automatic placement of terrains. This includes the conforming of cave wall, mountains, water, hills; placing hills around mountains; placing the second half of the 2-space rubbles. +-Inverted/Skewed Values — many things in the BOE editor have the wrong value to start off with. Crystal Wand and Prismatic Wand are inverted. Many monsters are this way as well — One of the Unicorns begins the game as reptile. (Thanks to ‘A Short Term Effect’ for pointing this one out.) +If you change these values in Bladbase.exs, they will remain changed in any new scenarios you create, saving you the trouble of fixing these in every new scenario you create. + +First, I was reading a section under the BOE FAQ, and it mentioned something +along the lines of a lock-picking sword. Which would presumably be a weapon +with the special ability "lockpick." They mentioned the trick of changing the +item's type from Tool (the item type of the lockpicks already included in the +default items list) to something else. But I'm afraid that this is the only +way that I seem to be able to create the standard type of lockpicks as a new +item. When I click on the "reagents" button, it tells me that an item of that +type (tool) cannot be given an ability of that sort because it can be +equipped. But only equipped lockpicks are usable by the player character, +right? What I have to do is to select an item type of "non-use item" for +example, set the ability to "lockpick" and then change the item type back to +"Tool" without opening the "item special abilities" menu, since the editor +seems to automatically clear any item ability that doesn't seem to belong for +a certain item type. + +3) If the kill/raise dead special is called during combat mode, and the +special brings a dead member back to life, strange things will happen. + +*4) To enhance a steel wave blade with the flaming weapon ability, it will +cost 10000 gold, but with the steel halberd (Which is worth a lot more) it +only costs 1500 gold! steel halberd => flaming : 28139, +1 : 13813 + steel great sword => flaming : 28093, +1 : 13409 + steel great mace => flaming : 28069, +1 : 13206 + +12) If you have two items with the same ability equiped, it seems that it +will give your character the lower ability strength of the two. + +13) When you creat a new scenario, it will ask you to name it. What ever +you type in for Scenario Name seems to not do anything. + +14) If you have the special node, Call Global Special, and you have already +set which global special to call as a number over 99, and press the +Creat/Edit button, instead of taking you to the number that you typed in, +it will creat a new special. + +15) Here's a strange bug that I don't quite know how to explain: Lets say +you are in town #x, and you step on a stairway special that is on the +coordinants a,b and the town that the special takes you to is less than x, +and the coordinants that it takes you to are something other than a,b and +there is a special in the new town on the coordinates a,b then the game +will call the special that is on coordinates a,b in the new town. (And no, +I did not set the advanced settings to call any special when that town is +entered) I know I worded that a little strange, if you need me explain it +better, please let me know. + +16) Here's a good way to cheat, use the mage spell Simalcrum and capture a +basilisk, then you can summon it and have it kill a boss enemy. I did this +in A Small Rebelion and killed Stalker without even having to get near him. + +20) On faster computers, it is hard to see the animation on animated terrains. + +21) If you use a custom graphic for an item, it doesn't seem to center it +properly. + +23) At high levels, casting the bless spell once will make your character +impossible to be hit by physical attacks. + +24) Using the refresh jobs/shops debug option while shoping in one of the +Magic Shops will produce strange results. Also there are no jobs, so +souldn't it be called just refresh shops instead of refresh jobs/shops? + + diff --git a/Scenario Editor/GAMEDLOG.RC b/Scenario Editor/GAMEDLOG.RC index 34cdf5a7..061c456d 100644 --- a/Scenario Editor/GAMEDLOG.RC +++ b/Scenario Editor/GAMEDLOG.RC @@ -68,10 +68,12 @@ LTEXT "*PG" 18, 107, 301, 23, 14 LTEXT "*R" 19, 107, 318, 23, 14 LTEXT "*NC-17" 20, 107, 335, 32, 15 + LTEXT "*Don't automatically adjust difficulty" 34, 50, 352, 50, 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 "2_0" 35, 260, 356, 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 @@ -749,7 +751,7 @@ STYLE WS_POPUP | WS_DLGFRAME 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 "*Type flag: (0-255)" 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 @@ -1191,7 +1193,7 @@ STYLE WS_POPUP | WS_DLGFRAME LTEXT "0_106" 33, 325, 315, 75, 16 } -834 DIALOG 10, 10, 548, 389 +834 DIALOG 10, 10, 548, 469 STYLE WS_POPUP | WS_DLGFRAME { // DEFPUSHBUTTON "" 1, 292, 238, 31, 10//, WS_GROUP | WS_TABSTOP @@ -1209,8 +1211,8 @@ STYLE WS_POPUP | WS_DLGFRAME 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 "1_63" 16, 452, 447, 61, 15 + LTEXT "0_5" 17, 386, 447, 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 @@ -1231,6 +1233,12 @@ STYLE WS_POPUP | WS_DLGFRAME 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 + LTEXT "Map unavailable ? (Map won't appear on this town.)" 38, 50, 379, 320, 27 + LTEXT "2_0" 39, 373, 384, 23, 14 + LTEXT "Can't cast Magic Map ? (Included in Map unavailable.)" 40, 50, 399, 320, 27 + LTEXT "2_0" 41, 373, 404, 23, 14 + LTEXT "Town special to call if town becomes hostile :" 42, 50, 419, 320, 27 + LTEXT "6_0" 43, 373, 422, 39, 16 } 835 DIALOG 10, 10, 531, 280 @@ -1960,7 +1968,7 @@ 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 2 | 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 "Classic Blades of Exile Scenario Editor version 1.0 | 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 diff --git a/Scenario Editor/GLOBAL.H b/Scenario Editor/GLOBAL.H index 8e02465a..fc0f7add 100644 --- a/Scenario Editor/GLOBAL.H +++ b/Scenario Editor/GLOBAL.H @@ -172,7 +172,8 @@ typedef struct { short timer_specs[8]; unsigned char strlens[180]; special_node_type specials[100]; - unsigned char specials1,specials2,res1,res2; + unsigned char defy_mapping, defy_scrying; + char hostile_spec_to_call, res2; short difficulty; } town_record_type; @@ -288,7 +289,8 @@ typedef struct { item_storage_shortcut_type storage_shortcuts[10]; short flag_d; unsigned char scen_str_len[300]; - short flag_i; +// short flag_i; + short adjust_diff; location last_out_edited; short last_town_edited; diff --git a/Scenario Editor/GRAPHICS.CPP b/Scenario Editor/GRAPHICS.CPP index 53693e5a..dfd9b4e7 100644 --- a/Scenario Editor/GRAPHICS.CPP +++ b/Scenario Editor/GRAPHICS.CPP @@ -284,14 +284,6 @@ void draw_main_screen() paint_pattern(NULL,1,draw_rect,3); draw_rb(); - - // redraw scroll bar here - lpsi.fMask = SIF_POS; - GetScrollInfo(right_sbar,SB_CTL,&lpsi);//ugly hack to redraw the bar + thumb - SetScrollInfo(right_sbar,SB_CTL,&lpsi,TRUE); - EnableScrollBar(right_sbar,SB_CTL,ESB_DISABLE_BOTH);//ugly hack to redraw the arrows - EnableScrollBar(right_sbar,SB_CTL,ESB_ENABLE_BOTH); -// SetScrollPos(right_sbar,SB_CTL,0,TRUE); } // draw terrain palette diff --git a/Scenario Editor/KEYDLGS.CPP b/Scenario Editor/KEYDLGS.CPP index 18cef90b..bfa8451a 100644 --- a/Scenario Editor/KEYDLGS.CPP +++ b/Scenario Editor/KEYDLGS.CPP @@ -102,7 +102,7 @@ char edit_spec_mess_mess[256] = { 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, + 2,1,1,1,1,1,1,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, @@ -152,7 +152,7 @@ char edit_jumpto_mess[256] = { 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 + 3,3,3,3,3,0,3,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, @@ -819,7 +819,7 @@ void edit_spec_enc_event_filter (short item_hit) 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:"); + i = choose_text_res(22,1,29,store_spec_node.type + 1,822,"Choose General Use Special:"); if (i >= 0) { store_spec_node.type = i - 1; } @@ -848,7 +848,7 @@ void edit_spec_enc_event_filter (short item_hit) 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:"); + i = choose_text_res(22,131,157,store_spec_node.type + 1,822,"Choose If-Then Special:"); if (i >= 0) { store_spec_node.type = i - 1; } diff --git a/Scenario Editor/SCENARIO.CPP b/Scenario Editor/SCENARIO.CPP index 84315fb1..1e39b016 100644 --- a/Scenario Editor/SCENARIO.CPP +++ b/Scenario Editor/SCENARIO.CPP @@ -1263,8 +1263,8 @@ void edit_monst_type_event_filter (short item_hit) store_which_monst--; if (store_which_monst < 1) store_which_monst = 255; store_monst = scenario.scen_monsters[store_which_monst]; + custom_pic = (store_monst.picture_num) / 1000; put_monst_info_in_dlog(); - custom_pic = (store_monst.picture_num) / 1000; break; case 22://next monster if (save_monst_info() == FALSE) break; @@ -1272,8 +1272,8 @@ void edit_monst_type_event_filter (short item_hit) store_which_monst++; if (store_which_monst > 255) store_which_monst = 1; store_monst = scenario.scen_monsters[store_which_monst]; + custom_pic = (store_monst.picture_num) / 1000; put_monst_info_in_dlog(); - custom_pic = (store_monst.picture_num) / 1000; break; case 24: // picture if (save_monst_info() == FALSE) break; @@ -1568,7 +1568,7 @@ Boolean save_item_info() 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; + if (cre(store_item.type_flag,0,255,"Type Flag must be from 0 to 255.","",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); @@ -1584,7 +1584,7 @@ Boolean save_item_info() 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)) { + if ((store_item.ability >= 70) && (store_item.ability < 170) && (store_item.ability != 95) && (store_item.charges == 0)) { give_error("An item with the special ability selected must have at least 1 charge.","",818); return FALSE; } @@ -1721,10 +1721,10 @@ Boolean save_item_abils() 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 ((store_item2.ability != 119) && (store_item2.ability != 120) && (store_item2.ability != 95)) { 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; +// 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; => useless, ability strength is an unsigned char 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; @@ -1753,7 +1753,6 @@ void edit_item_abil_event_filter (short item_hit) } 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: @@ -1766,7 +1765,6 @@ void edit_item_abil_event_filter (short item_hit) } 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: @@ -1775,9 +1773,8 @@ void edit_item_abil_event_filter (short item_hit) 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)"); + i = choose_text_res(23,71,96,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: @@ -1788,7 +1785,6 @@ void edit_item_abil_event_filter (short item_hit) } 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: @@ -1799,7 +1795,6 @@ void edit_item_abil_event_filter (short item_hit) } 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: @@ -1810,7 +1805,6 @@ void edit_item_abil_event_filter (short item_hit) } 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: @@ -2388,6 +2382,7 @@ Boolean save_scen_details() scenario.difficulty = cd_get_led_range(803,30,33); scenario.rating = cd_get_led_range(803,21,24); + scenario.adjust_diff = cd_get_led(803,35); scenario.ver[0] = CDGN(803,2); scenario.ver[1] = CDGN(803,3); scenario.ver[2] = CDGN(803,4); @@ -2412,6 +2407,7 @@ void put_scen_details_in_dlog() cd_set_led_range(803,30,33,scenario.difficulty); cd_set_led_range(803,21,24,scenario.rating); + cd_set_led(803,35,scenario.adjust_diff); CDSN(803,2,scenario.ver[0]); CDSN(803,3,scenario.ver[1]); CDSN(803,4,scenario.ver[2]); @@ -2430,6 +2426,9 @@ void edit_scen_details_event_filter (short item_hit) if (save_scen_details() == TRUE) dialog_not_toast = FALSE; break; + case 35: + cd_set_led(803,35,1 - cd_get_led(803,35)); + break; default: cd_hit_led_range(803,21,24,item_hit); cd_hit_led_range(803,30,33,item_hit); diff --git a/Scenario Editor/STRINGS.RC b/Scenario Editor/STRINGS.RC index 392b5038..0bd3b9f6 100644 --- a/Scenario Editor/STRINGS.RC +++ b/Scenario Editor/STRINGS.RC @@ -1,3 +1,10 @@ +/* For node x +name : 6600 + x + 1 +ex1a text : 9000 + x +1 +ex1b text : 9300 + x +1 +ex2a text : 9600 + x +1 +ex2b text : 9900 + x +1 +*/ STRINGTABLE { 6001, "No special ability" @@ -195,6 +202,7 @@ STRINGTABLE 6626, "Have a Rest" 6627, "Wandering will fight" 6628, "End Scenario" + 6629, "Display Picture" 6651, "Give Item" 6652, "Give Special Item" 6653, "One-Time Do Nothing" @@ -228,8 +236,8 @@ STRINGTABLE 6697, "Affect Sleep" 6698, "Affect Paralysis" 6699, "Affect Statistic" - 6700, "Give Mage Spell" - 6701, "Give Priest Spell" + 6700, "Affect Mage Spell" + 6701, "Affect Priest Spell" 6702, "Affect Gold" 6703, "Affect Food" 6704, "Affect Alchemy" @@ -259,10 +267,11 @@ STRINGTABLE 6751, "Special Thing Happened?" 6752, "Has Cave Lore?" 6753, "Has Woodsman?" - 6754, "Has Enough Mage Lore?" + 6754, "Has Enough Statistic?" 6755, "Text Response?" 6756, "Stuff Done Equal?" - 6771, "Town Hostile" + 6757, "Has enough of species?" + 6771, "Set Town Status" 6772, "Change Terrain" 6773, "Swap Terrain" 6774, "Transform Terrain" @@ -288,8 +297,8 @@ STRINGTABLE 6794, "Split Party" 6795, "Reunite Party" 6796, "Start Town Timer" - 6797, "Unused" - 6798, "Unused" + 6797, "Change Town Lightning" + 6798, "Change Creature Attitude" 6799, "Unused" 6800, "Unused" 6801, "Place Fire Wall" @@ -389,6 +398,7 @@ STRINGTABLE 6993, "Firewalk" 6994, "Flying" 6995, "Major Healing" + 6996, "Call Special" 7011, "Flame" 7012, "Fireball" 7013, "Firestorm" @@ -462,6 +472,7 @@ STRINGTABLE 9026, "Number of moves that pass" 9027, "0 - no attack, 1 - attack" 9028, "Unused" + 9029, "Scenario special message with filename" 9051, "Item to give" 9052, "Num. of spec. item to give (0 .. 49)" 9053, "Unused" @@ -495,8 +506,8 @@ STRINGTABLE 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)" + 9100, "Which Spell (0-31, 100-129, see docs)" + 9101, "Which Spell (0-31, 100-129, see docs)" 9102, "Amount (0 .. 25000)" 9103, "Amount (0 .. 25000)" 9104, "Which Recipe (0 .. 19)" @@ -526,10 +537,11 @@ STRINGTABLE 9151, "If this day has been reached ..." 9152, "Unused" 9153, "Unused" - 9154, "If the party has this much Mage Lore" + 9154, "If the party has this much of skill" 9155, "Number of a SCENARIO special message" 9156, "If flag has this value ..." - 9171, "Unused" + 9157, "Which Species? (0 - H.,1 - N., 2 - S.)" + 9171, "0 - Hostile, 1 - Friendly"//, 2 - Dead" 9172, "X coordinate of space" 9173, "X coordinate of space" 9174, "X coordinate of space" @@ -555,6 +567,8 @@ STRINGTABLE 9194, "X coordinate to place lone PC at" 9195, "0 - no sound, 1 - teleport sound" 9196, "Number of moves until event" + 9197, "Lightning (0-Fully Lit, 3-Totally Dark)" + 9198, "Number of the creature in current town" 9201, "Top of rectangle" 9202, "Top of rectangle" 9203, "Top of rectangle" @@ -607,6 +621,7 @@ STRINGTABLE 9326, "Health and spell pts. to give" 9327, "Unused" 9328, "Unused" + 9329, "Unused" 9351, "Amount of gold to give" 9352, "0 - give item, 1 - take away" 9353, "Unused" @@ -640,8 +655,8 @@ STRINGTABLE 9397, "0 - cure, 1 - inflict" 9398, "0 - cure, 1 - inflict" 9399, "0 - increase, 1 - decrease" - 9400, "Unused" - 9401, "Unused" + 9400, "0 - Take away, 1 - Give" + 9401, "0 - Take away, 1 - Give" 9402, "0 - increase, 1 - decrease" 9403, "0 - increase, 1 - decrease" 9404, "Unused" @@ -674,6 +689,7 @@ STRINGTABLE 9454, "Call this special ..." 9455, "If answer matches, call this special" 9456, "Call this special ..." + 9457, "Call this special ..." 9471, "Unused" 9472, "Y coordinate of space" 9473, "Y coordinate of space" @@ -700,6 +716,8 @@ STRINGTABLE 9494, "Y coordinate to place lone PC at" 9495, "Unused" 9496, "Call this special when time runs out" + 9497, "Unused" + 9498, "Attitude to change to (0 - 3, see docs)" 9501, "Left of rectangle" 9502, "Left of rectangle" 9503, "Left of rectangle" @@ -752,6 +770,7 @@ STRINGTABLE 9626, "Unused" 9627, "Unused" 9628, "Unused" + 9629, "Unused" 9651, "Amount of food to give" 9652, "Unused" 9653, "Unused" @@ -816,9 +835,10 @@ STRINGTABLE 9751, "Unused" 9752, "Unused" 9753, "Unused" - 9754, "Unused" + 9754, "Skill to check (0 - 25, see docs)" 9755, "Number of a SCENARIO special message" 9756, "Unused" + 9757, "Has this much of species" 9771, "Unused" 9772, "Terrain to change to" 9773, "Swap this terrain ..." @@ -845,6 +865,8 @@ STRINGTABLE 9794, "0 - no telep. noise, 1 - play a noise" 9795, "Unused" 9796, "Unused" + 9797, "Amount of Light to Change" + 9798, "Unused" 9801, "Bottom of rectangle" 9802, "Bottom of rectangle" 9803, "Bottom of rectangle" @@ -897,6 +919,7 @@ STRINGTABLE 9926, "Unused" 9927, "Unused" 9928, "Unused" + 9929, "Unused" 9951, "Special if item not given" 9952, "Unused" 9953, "Unused" @@ -962,9 +985,10 @@ STRINGTABLE 10051, "Call this special ..." 10052, "Unused" 10053, "Unused" - 10054, "Unused" + 10054, "Checking method (see docs)" 10055, "If answer matches, call this special" 10056, "Unused" + 10057, "Checking method (-1 <, 0 =, 1 >)" 10071, "Unused" 10072, "Unused" 10073, "With this terrain ..." @@ -991,6 +1015,8 @@ STRINGTABLE 10094, "Unused" 10095, "Unused" 10096, "Unused" + 10097, "0 - Give, 1 - Take Away" + 10098, "Unused" 10101, "Right of rectangle" 10102, "Right of rectangle" 10103, "Right of rectangle" diff --git a/Scenario Editor/TACTIONS.CPP b/Scenario Editor/TACTIONS.CPP index fee5d6a8..b1afe6aa 100644 --- a/Scenario Editor/TACTIONS.CPP +++ b/Scenario Editor/TACTIONS.CPP @@ -222,7 +222,7 @@ Boolean handle_action(POINT the_point, WPARAM wparam, LPARAM lparam ) if (x >= 0) { load_town(x); set_up_main_screen(); - start_town_edit(); +// start_town_edit(); mouse_button_held = FALSE; return FALSE; } diff --git a/Scenario Editor/TFILEIO.CPP b/Scenario Editor/TFILEIO.CPP index b7dd0714..fa3c9cbe 100644 --- a/Scenario Editor/TFILEIO.CPP +++ b/Scenario Editor/TFILEIO.CPP @@ -2201,7 +2201,7 @@ void port_scenario() flip_short(&scenario.flag_f); flip_short(&scenario.flag_g); flip_short(&scenario.flag_h); - flip_short(&scenario.flag_i); + flip_short(&scenario.adjust_diff); flip_short(&scenario.intro_mess_pic); flip_short(&scenario.intro_mess_len); flip_short(&scenario.which_town_start); diff --git a/Scenario Editor/townout.cpp b/Scenario Editor/townout.cpp index 7d214414..11ffb881 100644 --- a/Scenario Editor/townout.cpp +++ b/Scenario Editor/townout.cpp @@ -113,10 +113,11 @@ void init_town(short size) for (i = 0; i < 100; i++) { town.specials[i] = null_spec_node; } - town.specials1 = 0; - town.specials2 = 0; - town.res1 = 0; + town.defy_scrying = 0; + town.hostile_spec_to_call = -1; town.res2 = 0; +// town.strong_barriers = 0; + town.defy_mapping = 0; town.difficulty = 0; for (i = 0; i < 180; i++) { get_str(temp_str,36,i + 1); @@ -1176,11 +1177,16 @@ Boolean save_advanced_town() } town.spec_on_entry = CDGN(834,6); town.spec_on_entry_if_dead = CDGN(834,7); + town.hostile_spec_to_call = CDGN(834,43); 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; + if (cre(town.hostile_spec_to_call,-1,99,"The town specials to call 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); + town.defy_mapping = cd_get_led(834,39); + town.defy_scrying = cd_get_led(834,41); return TRUE; } @@ -1193,11 +1199,13 @@ void put_advanced_town_in_dlog() 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,43,town.hostile_spec_to_call); } 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]); - + cd_set_led(834,39,town.defy_mapping); + cd_set_led(834,41,town.defy_scrying); } void edit_advanced_town_event_filter (short item_hit) @@ -1216,6 +1224,12 @@ void edit_advanced_town_event_filter (short item_hit) case 37: cd_flip_led(834,37,item_hit); break; + case 39: + cd_flip_led(834,39,item_hit); + break; + case 41: + cd_flip_led(834,41,item_hit); + break; } }