From 65c6919b1d967dbbc86162bd096d4098ce93517a Mon Sep 17 00:00:00 2001 From: Celtic Minstrel Date: Mon, 15 Dec 2014 20:06:08 -0500 Subject: [PATCH] Organize talking strings rather than stuffing them all in one big array (Note: This seems to break recording talking/encounter strings.) --- osx/boe.dlgutil.cpp | 133 +++++++++++++++----------------- osx/boe.graphutil.cpp | 8 +- osx/boe.infodlg.cpp | 136 +++++++++------------------------ osx/boe.infodlg.h | 22 ++++-- osx/boe.specials.cpp | 28 ++----- osx/classes/party.cpp | 140 +++++++++++++--------------------- osx/classes/party.h | 19 ++--- osx/classes/talking.h | 9 ++- osx/scenedit/scen.actions.cpp | 2 +- osx/scenedit/scen.fileio.cpp | 19 +++-- osx/scenedit/scen.townout.cpp | 14 ++-- osx/tools/fileio.cpp | 85 ++++++++++++++++----- 12 files changed, 276 insertions(+), 339 deletions(-) diff --git a/osx/boe.dlgutil.cpp b/osx/boe.dlgutil.cpp index 8c332e38..0bc9ff38 100644 --- a/osx/boe.dlgutil.cpp +++ b/osx/boe.dlgutil.cpp @@ -71,6 +71,7 @@ short store_tip_page_on = 0; // Talking vars eGameMode store_pre_talk_mode; short store_personality,store_personality_graphic,shop_identify_cost; +std::string save_talk_str1, save_talk_str2; sf::RenderTexture talk_gworld; bool talk_end_forced; RECT talk_area_rect = {5,5,420,284}, word_place_rect = {44,7,372,257},talk_help_rect = {5,254,21,272}; @@ -544,7 +545,7 @@ void start_talk_mode(short m_num,short personality,m_num_t monst_type,short stor store_responses(); // Dredge up critter's name - title_string = std::string(univ.town.cur_talk().talk_strs[personality % 10]) + ":"; + title_string = std::string(univ.town.cur_talk().people[personality % 10].title) + ":"; store_pre_talk_mode = overall_mode; overall_mode = MODE_TALKING; @@ -553,7 +554,7 @@ void start_talk_mode(short m_num,short personality,m_num_t monst_type,short stor current_talk_node = TALK_LOOK; // Bring up and place first strings. - place_string1 = univ.town.cur_talk().talk_strs[personality % 10 + 10]; + place_string1 = univ.town.cur_talk().people[personality % 10].look; strnum1 = personality % 10 + 10; strnum2 = 0; @@ -584,7 +585,6 @@ void end_talk_mode() { void handle_talk_event(location p) { short i,get_pc,s1 = -1,s2 = -1,s3 = -1; char asked[4]; - std::string place_string1, place_string2; short a,b,c,d,ttype; @@ -611,9 +611,9 @@ void handle_talk_event(location p) { switch(which_talk_entry) { case TALK_DUNNO: SPECIAL_DUNNO: - place_string1 = univ.town.cur_talk().talk_strs[store_personality % 10 + 160]; - if(place_string1.length() < 2) place_string1 = "You get no response."; - place_talk_str(place_string1, "", 0, dummy_rect); + save_talk_str1 = univ.town.cur_talk().people[store_personality % 10].dunno; + if(save_talk_str1.length() < 2) save_talk_str1 = "You get no response."; + place_talk_str(save_talk_str1, "", 0, dummy_rect); update_last_talk(TALK_DUNNO); return; case TALK_BUSINESS: // This one only reachable via "go back". @@ -622,20 +622,20 @@ void handle_talk_event(location p) { return; case TALK_LOOK: SPECIAL_LOOK: - place_string1 = univ.town.cur_talk().talk_strs[store_personality % 10 + 10]; - place_talk_str(place_string1, "", 0, dummy_rect); + save_talk_str1 = univ.town.cur_talk().people[store_personality % 10].look; + place_talk_str(save_talk_str1, "", 0, dummy_rect); update_last_talk(TALK_LOOK); return; case TALK_NAME: SPECIAL_NAME: - place_string1 = univ.town.cur_talk().talk_strs[store_personality % 10 + 20]; - place_talk_str(place_string1, "", 0, dummy_rect); + save_talk_str1 = univ.town.cur_talk().people[store_personality % 10].name; + place_talk_str(save_talk_str1, "", 0, dummy_rect); update_last_talk(TALK_NAME); return; case TALK_JOB: SPECIAL_JOB: - place_string1 = univ.town.cur_talk().talk_strs[store_personality % 10 + 30]; - place_talk_str(place_string1, "", 0, dummy_rect); + save_talk_str1 = univ.town.cur_talk().people[store_personality % 10].job; + place_talk_str(save_talk_str1, "", 0, dummy_rect); update_last_talk(TALK_JOB); return; case TALK_BUY: @@ -657,20 +657,11 @@ void handle_talk_event(location p) { beep(); return; } - if(univ.party.has_talk_save(store_personality, univ.town.num, strnum1, strnum2)){ - ASB("This is already saved."); - print_buf(); - return; - } else { + if(univ.party.save_talk(univ.town->talking.people[store_personality].title, univ.town->town_name, save_talk_str1, save_talk_str2)) { give_help(57,0); play_sound(0); - bool success = univ.party.save_talk(store_personality,univ.town.num,strnum1,strnum2); - if(success){ - ASB("Noted in journal."); - } else { - ASB("No more room in talking journal."); - } - } + ASB("Noted in journal."); + } else ASB("This is already saved."); print_buf(); return; case TALK_DONE: @@ -680,8 +671,8 @@ void handle_talk_event(location p) { case TALK_BACK: // only if there's nothing to go back to return; // so, there's nothing to do here case TALK_ASK: // ask about - place_string1 = get_text_response("Ask about what?", 8); - strncpy(asked, place_string1.c_str(), 4); + save_talk_str1 = get_text_response("Ask about what?", 8); + strncpy(asked, save_talk_str1.c_str(), 4); if(strncmp(asked, "name", 4) == 0) goto SPECIAL_NAME; if(strncmp(asked, "look", 4) == 0) goto SPECIAL_LOOK; if(strncmp(asked, "job", 3) == 0) goto SPECIAL_JOB; @@ -701,8 +692,8 @@ void handle_talk_event(location p) { c = univ.town.cur_talk().talk_nodes[which_talk_entry].extras[2]; d = univ.town.cur_talk().talk_nodes[which_talk_entry].extras[3]; - place_string1 = univ.town.cur_talk().talk_strs[40 + which_talk_entry * 2]; - place_string2 = univ.town.cur_talk().talk_strs[40 + which_talk_entry * 2 + 1]; + save_talk_str1 = univ.town.cur_talk().talk_nodes[which_talk_entry].str1; + save_talk_str2 = univ.town.cur_talk().talk_nodes[which_talk_entry].str2; oldstrnum1 = strnum1; oldstrnum2 = strnum2; strnum1 = 40 + which_talk_entry * 2; strnum2 = 40 + which_talk_entry * 2 + 1; @@ -713,9 +704,9 @@ void handle_talk_event(location p) { case 1: if(PSD[a][b] > c) { strnum1 = strnum2; - place_string1 = place_string2; + save_talk_str1 = save_talk_str2; } - place_string2 = ""; + save_talk_str2 = ""; strnum2 = 0; break; case 2: @@ -724,7 +715,7 @@ void handle_talk_event(location p) { case 3: if(univ.party.gold < a) { strnum1 = strnum2; - place_string1 = place_string2; + save_talk_str1 = save_talk_str2; } else { talk_end_forced = true; @@ -736,36 +727,35 @@ void handle_talk_event(location p) { center = univ.town.p_loc; } strnum2 = 0; - place_string2 = ""; + save_talk_str2 = ""; break; case 4: if(day_reached((unsigned char) a,0)) { strnum1 = strnum2; - place_string1 = place_string2; + save_talk_str1 = save_talk_str2; } - place_string2 = ""; + save_talk_str2 = ""; strnum2 = 0; break; case 5: if(day_reached((unsigned char) a,(unsigned char) b)) { strnum1 = strnum2; - place_string1 = place_string2; + save_talk_str1 = save_talk_str2; } - place_string2 = ""; + save_talk_str2 = ""; strnum2 = 0; break; case 6: if(univ.town.num != a) { strnum1 = strnum2; - place_string1 = place_string2; + save_talk_str1 = save_talk_str2; } - place_string2 = ""; + save_talk_str2 = ""; strnum2 = 0; break; case 7: c = minmax(1,30,c); - start_shop_mode(2,b, - b + c - 1,a,place_string1.c_str()); + start_shop_mode(2,b,b + c - 1,a,save_talk_str1.c_str()); strnum1 = -1; return; case 8: @@ -773,19 +763,18 @@ void handle_talk_event(location p) { strnum1 = -1; spend_xp(get_pc,1, NULL); } - place_string1 = "You conclude your training."; + save_talk_str1 = "You conclude your training."; return; case 9: case 10: case 11: c = minmax(1,30,c); - start_shop_mode(ttype + 1,b, - b + c - 1,a,place_string1.c_str()); + start_shop_mode(ttype + 1,b,b + c - 1,a,save_talk_str1.c_str()); strnum1 = -1; return; case 12: //healer // TODO: extra1 and extra2 are actually never used! So remove them. start_shop_mode(3,univ.town.monst[store_m_num].extra1, - univ.town.monst[store_m_num].extra2,a,place_string1.c_str()); + univ.town.monst[store_m_num].extra2,a,save_talk_str1.c_str()); strnum1 = -1; return; break; @@ -817,24 +806,24 @@ void handle_talk_event(location p) { case 18: if(univ.party.gold < a) { strnum1 = strnum2; - place_string1 = place_string2; + save_talk_str1 = save_talk_str2; } else { univ.party.gold -= a; put_pc_screen(); } - place_string2 = ""; + save_talk_str2 = ""; strnum2 = 0; break; case 19: if((sd_legit(b,c)) && (PSD[b][c] == d)) { - place_string1 = "You've already learned that."; + save_talk_str1 = "You've already learned that."; strnum1 = -1; } else if(univ.party.gold < a) { strnum1 = strnum2; - place_string1 + place_string2; + save_talk_str1 + save_talk_str2; } else { univ.party.gold -= a; @@ -844,14 +833,14 @@ void handle_talk_event(location p) { else giveError("Invalid Stuff Done flag called in conversation."); } strnum2 = 0; - place_string2 = ""; + save_talk_str2 = ""; break; case 20: if(univ.party.gold < a) { strnum1 = strnum2; strnum2 = 0; - place_string1 = place_string2; - place_string2 = ""; + save_talk_str1 = save_talk_str2; + save_talk_str2 = ""; break; } else { @@ -860,15 +849,15 @@ void handle_talk_event(location p) { univ.party.gold -= a; put_pc_screen(); univ.party.boats[i].property = false; - place_string2 = ""; + save_talk_str2 = ""; strnum2 = 0; i = 1000; } if(i >= 1000) break; } - place_string1 = "There are no boats left."; - place_string2 = ""; + save_talk_str1 = "There are no boats left."; + save_talk_str2 = ""; strnum1 = -1; strnum2 = -1; break; @@ -876,8 +865,8 @@ void handle_talk_event(location p) { if(univ.party.gold < a) { strnum1 = strnum2; strnum2 = 0; - place_string1 = place_string2; - place_string2 = ""; + save_talk_str1 = save_talk_str2; + save_talk_str2 = ""; break; } else { @@ -886,25 +875,25 @@ void handle_talk_event(location p) { univ.party.gold -= a; put_pc_screen(); univ.party.horses[i].property = false; - place_string2 = ""; + save_talk_str2 = ""; strnum2 = 0; i = 1000; } if(i >= 1000) break; } - place_string1 = "There are no horses left."; - place_string2 = ""; + save_talk_str1 = "There are no horses left."; + save_talk_str2 = ""; strnum1 = -1; strnum2 = -1; break; case 22: if(univ.party.spec_items[a] > 0) { - place_string1 = "You already have it."; + save_talk_str1 = "You already have it."; strnum1 = -1; } else if(univ.party.gold < b) { - place_string1 = place_string2; + save_talk_str1 = save_talk_str2; strnum1 = strnum2; } else { @@ -913,11 +902,11 @@ void handle_talk_event(location p) { univ.party.spec_items[a] = 1; } strnum2 = 0; - place_string2 = ""; + save_talk_str2 = ""; break; case 23: start_shop_mode(5 + b,0, - 9,a,place_string1.c_str()); + 9,a,save_talk_str1.c_str()); strnum1 = -1; return; case 24: @@ -926,7 +915,7 @@ void handle_talk_event(location p) { } else if(univ.party.gold < a) { strnum1 = strnum2; - place_string1 = place_string2; + save_talk_str1 = save_talk_str2; } else { univ.party.gold -= a; @@ -934,7 +923,7 @@ void handle_talk_event(location p) { univ.party.can_find_town[b] = 1; } strnum2 = 0; - place_string2 = ""; + save_talk_str2 = ""; break; case 25: talk_end_forced = true; @@ -963,10 +952,10 @@ void handle_talk_event(location p) { if((s1 >= 0) || (s2 >= 0)) { strnum1 = -1; strnum2 = -1; - place_string1 = ""; - place_string2 = ""; + save_talk_str1 = ""; + save_talk_str2 = ""; } - get_strs(place_string1,place_string2,2,s1,s2); + get_strs(save_talk_str1,save_talk_str2,2,s1,s2); if(s1 >= 0) strnum1 = 2000 + s1; if(s2 >= 0) strnum2 = 2000 + s2; put_pc_screen(); @@ -978,10 +967,10 @@ void handle_talk_event(location p) { if((s1 >= 0) || (s2 >= 0)) { strnum1 = -1; strnum2 = -1; - place_string1 = ""; - place_string2 = ""; + save_talk_str1 = ""; + save_talk_str2 = ""; } - get_strs(place_string1,place_string2,0,s1,s2); + get_strs(save_talk_str1,save_talk_str2,0,s1,s2); if(s1 >= 0) strnum1 = 3000 + s1; if(s2 >= 0) strnum2 = 3000 + s2; put_pc_screen(); @@ -989,7 +978,7 @@ void handle_talk_event(location p) { break; } - place_talk_str(place_string1,place_string2,0,dummy_rect); + place_talk_str(save_talk_str1,save_talk_str2,0,dummy_rect); } void store_responses() { diff --git a/osx/boe.graphutil.cpp b/osx/boe.graphutil.cpp index 2ba2f8bc..af3cbd39 100644 --- a/osx/boe.graphutil.cpp +++ b/osx/boe.graphutil.cpp @@ -310,12 +310,12 @@ void play_see_monster_str(unsigned short m, location monst_loc) { spec = scenario.scen_monsters[m].see_spec; // First display strings, if any if(str1 || str2) { + short where1 = is_out() ? univ.party.i_w_c.x : univ.town.num; + short where2 = is_out() ? univ.party.i_w_c.y : univ.town.num; + std::string placename = is_out() ? univ.out.outdoors[where1][where2].out_name : univ.town->town_name; cStrDlog display_strings(str1 ? scenario.monst_strs[str1] : "", str2 ? scenario.monst_strs[str2] : "", "", pic, type, NULL); display_strings.setSound(snd); - display_strings.setRecordHandler(cStringRecorder() - .string1(NOTE_MONST, m, 0) - .string2(NOTE_MONST, m, 1) - ); + display_strings.setRecordHandler(cStringRecorder(NOTE_MONST).string1(str1).string2(str2).from(where1,where2).at(placename)); display_strings.show(); } // Then run the special, if any diff --git a/osx/boe.infodlg.cpp b/osx/boe.infodlg.cpp index 02d4d562..cbbca943 100644 --- a/osx/boe.infodlg.cpp +++ b/osx/boe.infodlg.cpp @@ -700,8 +700,6 @@ void give_pc_info(short pc_num) { static bool adventure_notes_event_filter(cDialog& me, std::string item_hit, eKeyMod) { unsigned short i; - std::string place_str; - char temp_str[256]; if(item_hit == "done") me.toast(true); else if(item_hit == "left") { @@ -722,23 +720,7 @@ static bool adventure_notes_event_filter(cDialog& me, std::string item_hit, eKey for(i = 0; i < 3; i++) { std::string n = boost::lexical_cast(i + 1); if(univ.party.special_notes.size() > i) { - switch(univ.party.special_notes[i].str_num / 1000) { - case 0: - // TODO: Should we subtract 160 here? - place_str = scenario.spec_strs[univ.party.special_notes[i].str_num % 1000]; - break; - case 1: - load_outdoor_str(loc(univ.party.special_notes[i].where % scenario.out_width, - univ.party.special_notes[i].where / scenario.out_width),univ.party.special_notes[i].str_num % 1000,temp_str); - place_str = temp_str; - break; - case 2: - load_town_str(univ.party.special_notes[i].where,univ.party.special_notes[i].str_num,temp_str); - place_str = temp_str; - break; - } - - me["str" + n].setText(place_str); + me["str" + n].setText(univ.party.special_notes[i].the_str); me["del" + n].show(); } else me["del" + n].hide(); @@ -747,24 +729,7 @@ static bool adventure_notes_event_filter(cDialog& me, std::string item_hit, eKey for(i = store_page_on * 3; i < (store_page_on * 3) + 3; i++) { std::string n = boost::lexical_cast(i + 1); if(univ.party.special_notes.size() > i) { - switch(univ.party.special_notes[i].str_num / 1000) { - case 0: - // TODO: Should we subtract 160 here? - place_str = scenario.spec_strs[univ.party.special_notes[i].str_num % 1000]; - break; - case 1: - load_outdoor_str(loc(univ.party.special_notes[i].where % scenario.out_width, - univ.party.special_notes[i].where / scenario.out_width), univ.party.special_notes[i].str_num % 1000,temp_str); - place_str = temp_str; - break; - case 2: - load_town_str(univ.party.special_notes[i].where,univ.party.special_notes[i].str_num % 1000,temp_str); - place_str = temp_str; - break; - } - - - me["str" + n].setText(place_str); + me["str" + n].setText(univ.party.special_notes[i].the_str); me["del" + n].show(); } else { @@ -778,8 +743,6 @@ static bool adventure_notes_event_filter(cDialog& me, std::string item_hit, eKey void adventure_notes() { unsigned short i; - std::string place_str; - char temp_str[256]; store_num_i = 0; //for(i = 0; i < 140; i++) @@ -800,23 +763,7 @@ void adventure_notes() { for(i = 0; i < 3; i++) { std::string n = boost::lexical_cast(i + 1); if(univ.party.special_notes.size() > i) { - switch(univ.party.special_notes[i].str_num / 1000) { - case 0: - // TODO: Should we subtract 160 here? - place_str = scenario.spec_strs[univ.party.special_notes[i].str_num % 1000]; - break; - case 1: - load_outdoor_str(loc(univ.party.special_notes[i].where % scenario.out_width, - univ.party.special_notes[i].where / scenario.out_width), univ.party.special_notes[i].str_num % 1000, temp_str); - place_str = temp_str; - break; - case 2: - load_town_str(univ.party.special_notes[i].where,univ.party.special_notes[i].str_num % 1000,temp_str); - place_str = temp_str; - break; - } - - encNotes["str" + n].setText(place_str); + encNotes["str" + n].setText(univ.party.special_notes[i].the_str); encNotes["del" + n].show(); } else encNotes["del" + n].hide(); @@ -830,42 +777,11 @@ void adventure_notes() { } static void put_talk(cDialog& me) { - short personality; - char place_str[256]; - - if((personality = univ.party.talk_save[store_page_on].personality) >= 0) { - load_town_talk(personality / 10); - - // TODO: Use cached strings instead of loading them - load_town_str(univ.party.talk_save[store_page_on].town_num,0,(char *) place_str); - me["loc"].setText(place_str); - - me["who"].setText(univ.town.cur_talk().talk_strs[personality % 10]); - - // TODO: Should we alter the scenario strings by 160 or not? - if(univ.party.talk_save[store_page_on].str_num1 >= 1000) { - if(univ.party.talk_save[store_page_on].str_num1 >= 3000) - me["str1"].setText(scenario.spec_strs[univ.party.talk_save[store_page_on].str_num1 - 3000]); - else { - load_town_str(univ.party.talk_save[store_page_on].town_num, - univ.party.talk_save[store_page_on].str_num1 - 2000 ,(char *) place_str); - me["str1"].setText(place_str); - } - } - else if(univ.party.talk_save[store_page_on].str_num1 > 0) - me["str1"].setText(univ.town.cur_talk().talk_strs[univ.party.talk_save[store_page_on].str_num1]); - - if(univ.party.talk_save[store_page_on].str_num2 >= 1000) { - if(univ.party.talk_save[store_page_on].str_num2 >= 3000) - me["str2"].setText(scenario.spec_strs[univ.party.talk_save[store_page_on].str_num2 - 3000 + 160]); - else { - load_town_str(univ.party.talk_save[store_page_on].town_num, - univ.party.talk_save[store_page_on].str_num2 - 2000/* + 20*/,(char *) place_str); - me["str2"].setText(place_str); - } - } - else if(univ.party.talk_save[store_page_on].str_num2 > 0) - me["str2"].setText(univ.town.cur_talk().talk_strs[univ.party.talk_save[store_page_on].str_num2]); + if(univ.party.talk_save[store_page_on].filled) { + me["loc"].setText(univ.party.talk_save[store_page_on].in_town); + me["who"].setText(univ.party.talk_save[store_page_on].who_said); + me["str1"].setText(univ.party.talk_save[store_page_on].the_str1); + me["str2"].setText(univ.party.talk_save[store_page_on].the_str2); } } @@ -880,8 +796,8 @@ static bool talk_notes_event_filter(cDialog& me, std::string item_hit, eKeyMod) store_page_on = 0; else store_page_on++; } else if(item_hit == "del") { - // TODO: Actually remove it rather than setting it to -1 - univ.party.talk_save[store_page_on].personality = -1; + // TODO: Actually remove it rather than filled to false + univ.party.talk_save[store_page_on].filled = false; } put_talk(me); return true; @@ -893,7 +809,7 @@ void talk_notes() { store_num_i = 0; for(i = 0; i < 120; i++) - if(univ.party.talk_save[i].personality != -1) + if(univ.party.talk_save[i].filled) store_num_i = i + 1; store_page_on = 0; if(store_num_i == 0) { @@ -933,7 +849,7 @@ static bool journal_event_filter(cDialog& me, std::string item_hit, eKeyMod) { for(i = 0; i < 3; i++) { std::string n = boost::lexical_cast(i + 1); if((long)univ.party.journal.size() > i + (store_page_on * 3)) { - me["str" + n].setText(scenario.journal_strs[univ.party.journal[i].str_num]); + me["str" + n].setText(univ.party.journal[i].the_str); sprintf((char *)place_str,"Day: %d",univ.party.journal[i].day); me["day" + n].setText(place_str); } @@ -963,9 +879,8 @@ void journal() { for(i = 0; i < 3; i++) { if(univ.party.journal.size() > i) { - // TODO: Use the cached strings instead of looking them up std::string n = boost::lexical_cast(i + 1); - journal["str" + n].setText(scenario.journal_strs[univ.party.journal[i].str_num]); + journal["str" + n].setText(univ.party.journal[i].the_str); sprintf((char *)place_str,"Day: %d",univ.party.journal[i].day); journal["day" + n].setText(place_str); } @@ -978,7 +893,7 @@ void journal() { journal.run(); } void add_to_journal(short event) { - if(univ.party.add_to_journal(event, calc_day())) + if(univ.party.add_to_journal(scenario.journal_strs[event], calc_day())) ASB("Something was added to your journal."); } @@ -1027,8 +942,27 @@ void put_spec_item_info (short which_i) { // Callback for recording encounter strings void cStringRecorder::operator()(cDialog& me) { play_sound(0); - if(univ.party.record(str1type, label1, label1b)) + std::string str1, str2; + switch(type) { + case NOTE_SCEN: + str1 = scenario.spec_strs[label1]; + str2 = scenario.spec_strs[label2]; + break; + case NOTE_TOWN: + str1 = univ.town->spec_strs[label1]; + str2 = univ.town->spec_strs[label2]; + break; + case NOTE_OUT: + str1 = univ.out.outdoors[label1b][label2b].spec_strs[label1]; + str2 = univ.out.outdoors[label1b][label2b].spec_strs[label2]; + break; + case NOTE_MONST: + str1 = scenario.monst_strs[label1]; + str2 = scenario.monst_strs[label2]; + break; + } + if(univ.party.record(type, str1, location)) give_help(58,0,&me); - univ.party.record(str2type, label2, label2b); + univ.party.record(type, str2, location); } diff --git a/osx/boe.infodlg.h b/osx/boe.infodlg.h index 78677054..087c5c42 100644 --- a/osx/boe.infodlg.h +++ b/osx/boe.infodlg.h @@ -36,20 +36,26 @@ void display_alchemy(bool allowEdit); // Callback for recording encounter strings class cStringRecorder { private: - eEncNoteType str1type, str2type; + eEncNoteType type; unsigned short label1, label2, label1b, label2b; + std::string location; public: - cStringRecorder() {} - cStringRecorder& string1(eEncNoteType type, unsigned short which, unsigned short where) { - str1type = type; + cStringRecorder(eEncNoteType type) : type(type) {} + cStringRecorder& string1(unsigned short which) { label1 = which; - label1b = where; return *this; } - cStringRecorder& string2(eEncNoteType type, unsigned short which, unsigned short where) { - str2type = type; + cStringRecorder& string2(unsigned short which) { label2 = which; - label2b = where; + return *this; + } + cStringRecorder& from(unsigned short where1, unsigned short where2) { + label1b = where1; + label2b = where2; + return *this; + } + cStringRecorder& at(std::string where) { + location = where; return *this; } void operator()(cDialog&); diff --git a/osx/boe.specials.cpp b/osx/boe.specials.cpp index 9cfac34f..b68e95dd 100644 --- a/osx/boe.specials.cpp +++ b/osx/boe.specials.cpp @@ -3952,34 +3952,22 @@ void handle_message(eSpecCtx which_mode,short cur_type,short mess1,short mess2,s break; } std::string str1, str2; - short label1 = -1,label2 = -1,label1b = -1,label2b = -1; - short mess_adj[3] = {160,10,0}; + short where1 = -1,where2 = -1; if((mess1 < 0) && (mess2 < 0)) return; if(which_mode == eSpecCtx::TALK) { - *a = mess1 + ((mess1 >= 0) ? mess_adj[cur_type] : 0); - *b = mess2 + ((mess2 >= 0) ? mess_adj[cur_type] : 0); + *a = mess1; + *b = mess2; return; } - get_strs(str1,str2, cur_type, mess1 + ((mess1 >= 0) ? mess_adj[cur_type] : 0), - mess2 + ((mess2 >= 0) ? mess_adj[cur_type] : 0)) ; - if(mess1 >= 0) { - label1 = mess1 + mess_adj[cur_type]; - label1b = (is_out()) ? (univ.party.outdoor_corner.x + univ.party.i_w_c.x) + - scenario.out_width * (univ.party.outdoor_corner.y + univ.party.i_w_c.y) : univ.town.num; - } - if(mess2 >= 0) { - label2 = mess2 + mess_adj[cur_type]; - label2b = (is_out()) ? (univ.party.outdoor_corner.x + univ.party.i_w_c.x) + - scenario.out_width * (univ.party.outdoor_corner.y + univ.party.i_w_c.y) : univ.town.num; - } + get_strs(str1, str2, cur_type, mess1, mess2); + where1 = is_out() ? univ.party.i_w_c.x : univ.town.num; + where2 = is_out() ? univ.party.i_w_c.y : univ.town.num; + std::string placename = is_out() ? univ.out.outdoors[where1][where2].out_name : univ.town->town_name; cStrDlog display_strings(str1.c_str(), str2.c_str(),"",scenario.intro_pic,PIC_SCEN,0); display_strings.setSound(57); - display_strings.setRecordHandler(cStringRecorder() - .string1(note_type, label1, label1b) - .string2(note_type, label2, label2b) - ); + display_strings.setRecordHandler(cStringRecorder(note_type).string1(mess1).string2(mess2).from(where1,where2).at(placename)); display_strings.show(); } diff --git a/osx/classes/party.cpp b/osx/classes/party.cpp index 0b55a277..7d76757e 100644 --- a/osx/classes/party.cpp +++ b/osx/classes/party.cpp @@ -66,7 +66,6 @@ cParty& cParty::operator = (legacy::party_record_type& old){ journal.reserve(50); for(i = 0; i < 50; i++){ cJournal j; - j.str_num = old.journal_str[i]; j.day = old.journal_day[i]; journal.push_back(j); // journal[i].str_num = old.journal_str[i]; @@ -76,8 +75,9 @@ cParty& cParty::operator = (legacy::party_record_type& old){ special_notes.reserve(140); for(i = 0; i < 140; i++){ cEncNote n; - n.str_num = old.special_notes_str[i][0]; - n.where = old.special_notes_str[i][1]; + // TODO: Fix up this conversion by looking up the required strings. +// n.str_num = old.special_notes_str[i][0]; +// n.where = old.special_notes_str[i][1]; special_notes.push_back(n); // special_notes[i].str_num = old.special_notes_str[i][0]; // special_notes[i].where = old.special_notes_str[i][1]; @@ -85,7 +85,8 @@ cParty& cParty::operator = (legacy::party_record_type& old){ talk_save.reserve(120); for(i = 0; i < 120; i++){ cConvers t; - t = old.talk_save[i]; + // TODO: Fix up this conversion by looking up the required strings. +// t = old.talk_save[i]; talk_save.push_back(t); // talk_save[i] = old.talk_save[i]; help_received[i] = old.help_received[i]; @@ -121,10 +122,11 @@ void cParty::append(legacy::setup_save_type& old){ } cParty::cConvers& cParty::cConvers::operator = (legacy::talk_save_type old){ - personality = old.personality; - town_num = old.town_num; - str_num1 = old.str1; - str_num2 = old.str2; + // TODO: Fix up this conversion by looking up the required strings. +// personality = old.personality; +// town_num = old.town_num; +// str_num1 = old.str1; +// str_num2 = old.str2; return *this; } @@ -149,53 +151,46 @@ void cParty::add_pc(cPlayer new_pc){ } } -bool cParty::has_talk_save(short who, short where, short str1, short str2){ - cConvers match = {who, where, str1, str2}; - if(std::find(talk_save.begin(), talk_save.end(), match) != talk_save.end()) +bool cParty::save_talk(const std::string& who, const std::string& where, const std::string& str1, const std::string& str2){ + if(talk_save.size() == talk_save.max_size()) return false; // This is extremely unlikely + cConvers talk; + talk.who_said = who; + talk.in_town = where; + talk.the_str1 = str1; + talk.the_str2 = str2; + talk.in_scen = scen_name; + if(std::find(talk_save.begin(), talk_save.end(), talk) == talk_save.end()) { + talk_save.push_back(talk); return true; + } return false; } -bool cParty::save_talk(short who, unsigned char where, short str1, short str2){ - if(talk_save.size() == talk_save.max_size()) return false; // This is extremely unlikely - cConvers talk; - talk.personality = who; - talk.town_num = where; - talk.str_num1 = str1; - talk.str_num2 = str2; - talk.in_scen = scen_name; - // TODO: locate the strings and store them in the record. - if(std::find(talk_save.begin(), talk_save.end(), talk) == talk_save.end()) { - talk_save.push_back(talk); - } - return true; -} - -bool cParty::add_to_journal(short event, short day){ +bool cParty::add_to_journal(const std::string& event, short day){ if(journal.size() == journal.max_size()) return false; // Practically impossible cJournal entry; - entry.str_num = event; entry.day = day; + entry.the_str = event; entry.in_scen = scen_name; - // TODO: locate the strings and store them in the record. if(std::find(journal.begin(), journal.end(), entry) == journal.end()) { journal.push_back(entry); + return true; } - return true; + return false; } -bool cParty::record(eEncNoteType type, short what, short where){ +bool cParty::record(eEncNoteType type, const std::string& what, const std::string& where){ if(special_notes.size() == special_notes.max_size()) return false; // Never happen cEncNote note; note.type = type; - note.str_num = what; + note.the_str = what; note.where = where; note.in_scen = scen_name; - // TODO: locate the strings and store them in the record. if(std::find(special_notes.begin(), special_notes.end(), note) == special_notes.end()) { special_notes.push_back(note); + return true; } - return true; + return false; } bool cParty::start_timer(short time, short node, short type){ @@ -273,36 +268,7 @@ void cParty::writeTo(std::ostream& file){ if(graphicUsed[i]) file << "GRAPHIC " << i << '\n'; for(auto iter = campaign_flags.begin(); iter != campaign_flags.end(); iter++){ - std::string campaign_id = iter->first; - if(campaign_id.find_first_of(' ') != std::string::npos || campaign_id[0] == '"' || campaign_id[0] == '\'') { - // The string contains spaces or starts with a quote, so quote it. - // We may have to escape quotes or backslashes. - int apos = 0, quot = 0, bslash = 0; - std::for_each(campaign_id.begin(), campaign_id.end(), [&apos,",&bslash](char c) { - if(c == '\'') apos++; - if(c == '"') quot++; - if(c == '\\') bslash++; - }); - char quote_c; - // Surround it in whichever quote character appears fewer times. - if(quot < apos) quote_c = '"'; - else quote_c = '\''; - // Let's create this string to initially have the required size. - std::string temp; - size_t quoted_len = campaign_id.length() + std::min(quot,apos) + bslash + 2; - temp.reserve(quoted_len); - temp += quote_c; - for(size_t i = 0; i < campaign_id.length(); i++) { - if(campaign_id[i] == quote_c) { - temp += '\\'; - temp += quote_c; - } else if(campaign_id[i] == '\\') - temp += "\\\\"; - else temp += campaign_id[i]; - } - temp += quote_c; - campaign_id.swap(temp); - } + std::string campaign_id = maybe_quote_string(iter->first); // Okay, we have the campaign ID in a state such that reading it back in will restore the original ID. // Now output any flags that are set for this campaign. for(unsigned int i = 0; i < 25; i++) @@ -379,27 +345,24 @@ void cParty::writeTo(std::ostream& file){ if(journal.size() > 0) { file << '\f'; for(cJournal& entry : journal) { - file << "JOURNAL " << entry.str_num << ' ' << entry.day << ' ' << maybe_quote_string(entry.in_scen) << '\n'; - // TODO: Save the actual string, if the player has asked us to + file << "JOURNAL " << entry.day << ' ' << maybe_quote_string(entry.in_scen) << '\n' << entry.the_str << '\n'; file << '\f'; } } if(special_notes.size() > 0) { file << '\f'; for(cEncNote& note : special_notes) { - file << "ENCNOTE " << note.type << ' ' << note.str_num << ' ' << note.where << '\n'; - // TODO: Save the actual strings, if the player has asked us to + file << "ENCNOTE " << note.type << ' ' << maybe_quote_string(note.where) << '\n' << note.the_str << '\n'; file << '\f'; } } if(talk_save.size() > 0) { file << '\f'; for(cConvers& note : talk_save) { - file << "TALKNOTE " << note.str_num1 << ' ' << note.str_num2 << '\n'; - file << "WHO " << note.personality << '\n'; - file << "WHERE " << note.town_num << ' ' << note.in_scen << '\n'; - file << "-\n"; - // TODO: Save the actual strings and names, if the player has asked us to + file << "TALKNOTE"; + file << "WHO " << maybe_quote_string(note.who_said) << '\n'; + file << "WHERE " << maybe_quote_string(note.in_town) << ' ' << maybe_quote_string(note.in_scen) << '\n'; + file << "-\n" << note.the_str1 << '\n' << note.the_str2 << '\n'; file << '\f'; } } @@ -585,31 +548,30 @@ void cParty::readFrom(std::istream& file){ summons.push_back(monst); } else if(cur == "JOURNAL") { cJournal entry; - bin >> entry.str_num >> entry.day; + bin >> entry.day; entry.in_scen = read_maybe_quoted_string(bin); + bin >> std::skipws; getline(bin, entry.the_str); } else if(cur == "ENCNOTE") { cEncNote note; - bin >> note.type >> note.str_num >> note.where; - getline(bin, note.the_str1); - getline(bin, note.the_str2); + bin >> note.type; + note.where = read_maybe_quoted_string(bin); + bin >> std::skipws; + getline(bin, note.the_str); } else if(cur == "TALKNOTE") { cConvers note; - bin >> note.str_num1 >> note.str_num2; while(bin) { getline(bin, cur); std::istringstream sin(cur); sin >> cur; if(cur == "WHO") - sin >> note.personality; + note.who_said = read_maybe_quoted_string(bin); else if(cur == "WHERE") { - sin >> note.town_num; + note.in_town = read_maybe_quoted_string(bin); note.in_scen = read_maybe_quoted_string(sin); - } else if(cur == "NAMES") { - note.in_town = read_maybe_quoted_string(sin); - note.who_said = read_maybe_quoted_string(sin); } else if(cur == "-") break; } + bin >> std::skipws; getline(bin, note.the_str1); getline(bin, note.the_str2); } @@ -731,16 +693,16 @@ short cParty::pc_present(){ } bool operator==(const cParty::cConvers& one, const cParty::cConvers& two) { - if(one.personality != two.personality) return false; - if(one.town_num != two.town_num) return false; - if(one.str_num1 != two.str_num1) return false; - if(one.str_num2 != two.str_num2) return false; + if(one.who_said != two.who_said) return false; + if(one.in_town != two.in_town) return false; + if(one.the_str1 != two.the_str1) return false; + if(one.the_str2 != two.the_str2) return false; if(one.in_scen != two.in_scen) return false; return true; } bool operator==(const cParty::cJournal& one, const cParty::cJournal& two) { - if(one.str_num != two.str_num) return false; + if(one.the_str != two.the_str) return false; // TODO: Should I compare the day as well? if(one.in_scen != two.in_scen) return false; return true; @@ -748,7 +710,7 @@ bool operator==(const cParty::cJournal& one, const cParty::cJournal& two) { bool operator==(const cParty::cEncNote& one, const cParty::cEncNote& two) { if(one.type != two.type) return false; - if(one.str_num != two.str_num) return false; + if(one.the_str != two.the_str) return false; if(one.where != two.where) return false; if(one.in_scen != two.in_scen) return false; return true; diff --git a/osx/classes/party.h b/osx/classes/party.h index ff425cf1..f348c6f8 100644 --- a/osx/classes/party.h +++ b/osx/classes/party.h @@ -38,24 +38,20 @@ class cParty { public: class cConvers { // conversation; formerly talk_save_type public: - short personality; - short town_num; - short str_num1, str_num2; - std::string who_said, in_town, the_str1, the_str2, in_scen; // the actual strings; not always saved, like maps + bool filled = false; + std::string who_said, in_town, the_str1, the_str2, in_scen; cConvers& operator = (legacy::talk_save_type old); }; class cJournal { public: - unsigned short str_num; unsigned short day; - std::string the_str, in_scen; // the actual strings; not always saved, like maps + std::string the_str, in_scen; }; class cEncNote { public: eEncNoteType type; - unsigned short str_num, where; - std::string the_str1, the_str2, in_scen; // the actual strings; not always saved, like maps + std::string the_str, where, in_scen; }; class cTimer { public: @@ -132,10 +128,9 @@ public: void add_pc(legacy::pc_record_type old); void add_pc(cPlayer new_pc); void void_pcs(); - bool has_talk_save(short who, short where, short str1, short str2); - bool save_talk(short who, unsigned char where, short str1, short str2); - bool add_to_journal(short event, short day); - bool record(eEncNoteType type, short what, short where); + bool save_talk(const std::string& who, const std::string& where, const std::string& str1, const std::string& str2); + bool add_to_journal(const std::string& event, short day); + bool record(eEncNoteType type, const std::string& what, const std::string& where); bool start_timer(short time, short node, short type); cPlayer& operator[](unsigned short n); void writeTo(std::ostream& file); diff --git a/osx/classes/talking.h b/osx/classes/talking.h index 8251d5a7..123710d3 100644 --- a/osx/classes/talking.h +++ b/osx/classes/talking.h @@ -16,6 +16,12 @@ namespace legacy { struct talking_node_type; }; +class cPersonality { +public: + std::string title; + std::string look, name, job, dunno; +}; + class cSpeech { // formerly talking_record_type public: class cNode { // formerly talking_node_type @@ -23,9 +29,10 @@ public: short personality,type; char link1[4],link2[4]; short extras[4]; + std::string str1, str2; }; unsigned char strlens[200]; - char talk_strs[170][256]; + cPersonality people[10]; cNode talk_nodes[60]; cSpeech& operator = (legacy::talking_record_type& old); diff --git a/osx/scenedit/scen.actions.cpp b/osx/scenedit/scen.actions.cpp index e56d7da4..510f08ad 100644 --- a/osx/scenedit/scen.actions.cpp +++ b/osx/scenedit/scen.actions.cpp @@ -3349,7 +3349,7 @@ void start_dialogue_editing(short restoring) { } for(i = 0; i < 10; i++) { sprintf((char *) str,"Personality %d - %s",i + cur_town * 10, - (char *) town->talking.talk_strs[i]); + town->talking.people[i].title.c_str()); set_rb(i,13000 + i,(char *) str,0); } for(i = 0; i < 60; i++) { diff --git a/osx/scenedit/scen.fileio.cpp b/osx/scenedit/scen.fileio.cpp index eb1933b1..c2887365 100644 --- a/osx/scenedit/scen.fileio.cpp +++ b/osx/scenedit/scen.fileio.cpp @@ -1105,15 +1105,18 @@ void scen_text_dump(){ fout << " Sign " << i << ": " << town->sign_strs[i] << endl; fout << endl << " Town Dialogue:" << endl; for(i = 0; i < 10; i++) { - fout << " Personality " << i << " (" << town->talking.talk_strs[i] << "): " << endl; - fout << " look: " << town->talking.talk_strs[i + 10] << endl; - fout << " name: " << town->talking.talk_strs[i + 20] << endl; - fout << " job: " << town->talking.talk_strs[i + 30] << endl; - fout << " confused: " << town->talking.talk_strs[i + 160] << endl; + fout << " Personality " << j + i << " (" << town->talking.people[i].title << "): " << endl; + fout << " look: " << town->talking.people[i].look << endl; + fout << " name: " << town->talking.people[i].name << endl; + fout << " job: " << town->talking.people[i].job << endl; + fout << " confused: " << town->talking.people[i].dunno << endl; + } + for(i = 0; i < 60; i++) { + if(town->talking.talk_nodes[i].str1.length() > 0) + fout << " Node " << i << "a: " << town->talking.talk_nodes[i].str1 << endl; + if(town->talking.talk_nodes[i].str2.length() > 0) + fout << " Node " << i << "b: " << town->talking.talk_nodes[i].str2 << endl; } - for(i = 40; i < 160; i++) - if(strlen((char *) (town->talking.talk_strs[i])) > 0) - fout << " Node " << i << ": " << town->talking.talk_strs[i] << endl; fout << endl; } fout.close(); diff --git a/osx/scenedit/scen.townout.cpp b/osx/scenedit/scen.townout.cpp index 03c84f0d..8cf30076 100644 --- a/osx/scenedit/scen.townout.cpp +++ b/osx/scenedit/scen.townout.cpp @@ -74,11 +74,13 @@ void init_town(short size) { for(i = 0; i < 200; i++) town->talking.strlens[i] = 0; - for(i = 0; i < 170; i++) - if(i < 10) - strcpy(town->talking.talk_strs[i],"Unused"); - else strcpy(town->talking.talk_strs[i],""); - + for(i = 0; i < 10; i++) { + town->talking.people[i].title = "Unused"; + town->talking.people[i].look = ""; + town->talking.people[i].name = ""; + town->talking.people[i].job = ""; + town->talking.people[i].dunno = ""; + } for(i = 0; i < 60; i++) { town->talking.talk_nodes[i].personality = -1; town->talking.talk_nodes[i].type = 0; @@ -86,6 +88,8 @@ void init_town(short size) { town->talking.talk_nodes[i].extras[1] = 0; town->talking.talk_nodes[i].extras[2] = 0; town->talking.talk_nodes[i].extras[3] = -1; + town->talking.talk_nodes[i].str1 = ""; + town->talking.talk_nodes[i].str2 = ""; for(j = 0; j < 4; j++) { town->talking.talk_nodes[i].link1[j] = 'x'; town->talking.talk_nodes[i].link2[j] = 'x'; diff --git a/osx/tools/fileio.cpp b/osx/tools/fileio.cpp index 73c18ad0..4cdf2169 100644 --- a/osx/tools/fileio.cpp +++ b/osx/tools/fileio.cpp @@ -284,8 +284,23 @@ static bool load_town_v1(short which_town, cTown*& the_town) { for(i = 0; i < 170; i++) { len = (long) (the_town->talking.strlens[i]); - n = fread(&(the_town->talking.talk_strs[i]), len, 1, file_id); - the_town->talking.talk_strs[i][len] = 0; + n = fread(temp_str, len, 1, file_id); + temp_str[len] = 0; + if(i >= 0 && i < 10) + the_town->talking.people[i].title = temp_str; + else if(i >= 10 && i < 20) + the_town->talking.people[i-10].look = temp_str; + else if(i >= 20 && i < 30) + the_town->talking.people[i-20].name = temp_str; + else if(i >= 30 && i < 40) + the_town->talking.people[i-30].job = temp_str; + else if(i >= 160) + the_town->talking.people[i-160].dunno = temp_str; + else { + if(i % 2 == 0) + the_town->talking.talk_nodes[(i-40)/2].str1 = temp_str; + else the_town->talking.talk_nodes[(i-40)/2].str2 = temp_str; + } } n = fclose(file_id); @@ -317,6 +332,7 @@ bool load_town(short which_town, cTown*& the_town) { static bool load_town_talk_v1(short which_town) { if(univ.town.prep_talk(which_town)) return true; + char temp_str[256]; short i,n; long len,len_to_jump = 0; @@ -384,8 +400,22 @@ static bool load_town_talk_v1(short which_town) { for(i = 0; i < 170; i++) { len = (long) (the_talk.strlens[i]); - n = fread(&(the_talk.talk_strs[i]), len, 1, file_id); - the_talk.talk_strs[i][len] = 0; + n = fread(temp_str, len, 1, file_id); + temp_str[len] = 0; + if(i >= 0 && i < 10) + the_talk.people[i].title = temp_str; + else if(i >= 10 && i < 20) + the_talk.people[i-10].look = temp_str; + else if(i >= 20 && i < 30) + the_talk.people[i-20].name = temp_str; + else if(i >= 30 && i < 40) + the_talk.people[i-30].job = temp_str; + else if(i >= 160) + the_talk.people[i-160].dunno = temp_str; + else { + if(i % 2 == 0) the_talk.talk_nodes[(i-40)/2].str1 = temp_str; + else the_talk.talk_nodes[(i-40)/2].str2 = temp_str; + } } n = fclose(file_id); @@ -1003,6 +1033,8 @@ bool load_party_v1(fs::path file_to_load, bool town_restore, bool in_scen, bool fin.close(); + // TODO: Need to convert after loading the scenario in order to look up saved strings. + // However, for that to work, the entire scenario (all towns and sections) would need to be in memory. univ.party = store_party; univ.party.append(store_setup); univ.party.void_pcs(); @@ -1033,6 +1065,7 @@ bool load_party_v1(fs::path file_to_load, bool town_restore, bool in_scen, bool } // Compatibility flags + // TODO: Pretty sure I did this elsewhere, so probably don't need it here if(in_scen && scenario.format.prog_make_ver[0] < 2){ univ.party.stuff_done[305][8] = 1; } else { @@ -1228,6 +1261,7 @@ bool save_party(fs::path dest_file) { std::string read_maybe_quoted_string(std::istream& from) { std::string result; + from >> std::skipws; if(from.peek() == '"' || from.peek() == '\'') { char delim = from.get(); getline(from, result, delim); @@ -1243,20 +1277,35 @@ std::string read_maybe_quoted_string(std::istream& from) { } std::string maybe_quote_string(std::string which) { - if(which.find(' ') == std::string::npos && which.find('\t') == std::string::npos) - return which; - if(which.find('\'') == std::string::npos) - return '\'' + which + '\''; - if(which.find('"') == std::string::npos) - return '"' + which + '"'; - std::ostringstream fmt; - std::string part; - fmt << '"'; - for(char c : which) { - if(c == '"') fmt << R"(\")"; - else fmt.put(c); + if(which.find_first_of(' ') != std::string::npos || which[0] == '"' || which[0] == '\'') { + // The string contains spaces or starts with a quote, so quote it. + // We may have to escape quotes or backslashes. + int apos = 0, quot = 0, bslash = 0; + std::for_each(which.begin(), which.end(), [&apos,",&bslash](char c) { + if(c == '\'') apos++; + if(c == '"') quot++; + if(c == '\\') bslash++; + }); + char quote_c; + // Surround it in whichever quote character appears fewer times. + if(quot < apos) quote_c = '"'; + else quote_c = '\''; + // Let's create this string to initially have the required size. + std::string temp; + size_t quoted_len = which.length() + std::min(quot,apos) + bslash + 2; + temp.reserve(quoted_len); + temp += quote_c; + for(size_t i = 0; i < which.length(); i++) { + if(which[i] == quote_c) { + temp += '\\'; + temp += quote_c; + } else if(which[i] == '\\') + temp += R"(\\)"; + else temp += which[i]; + } + temp += quote_c; + which.swap(temp); } - fmt << '"'; - return fmt.str(); + return which; }