#define LINES_IN_TEXT_WIN 11 #define TEXT_BUF_LEN 70 #include #include //#include "item.h" #include "boe.global.h" #include "classes.h" #include "boe.text.h" #include "boe.locutils.h" #include "mathutil.h" #include "graphtool.h" //#include "soundtool.h" #include "scrollbar.h" #include "restypes.hpp" const char *m_mage_sp[] = { "Spark","Minor Haste","Strength","Flame Cloud","Flame", "Minor Poison","Slow","Dumbfound","Stinking Cloud","Summon Beast", "Conflagration","Fireball","Weak Summoning","Web","Poison", "Ice Bolt","Slow Group","Major Haste","Firestorm","Summoning", "Shockstorm","Major Poison","Kill","Daemon","Major Blessing", "Major Summoning","Shockwave"}; const char *m_priest_sp[] = { "Minor Bless","Light Heal","Wrack","Stumble","Bless", "Curse","Wound","Summon Spirit","Disease","Heal", "Holy Scourge","Smite","Curse All","Sticks to Snakes","Martyr's Shield", "Bless All","Major Heal","Flamestrike","Summon Host","Heal All", "Unholy Ravaging","Summon Guardian","Pestilence","Revive All","Avatar", "Divine Thud"}; typedef struct { char line[50]; } buf_line; buf_line text_buffer[TEXT_BUF_LEN]; short buf_pointer = 30, lines_to_print= 0, num_added_since_stop = 0; //char store_string[60],store_string2[60]; short start_print_point= 0; short mark_where_printing_long; bool printing_long = false; char c_str[256] = ""; bool save_mess_given = false; RECT status_panel_clip_rect = {11, 299, 175, 495},item_panel_clip_rect = {11,297,175,463}; // TODO: The duplication of RECT here shouldn't be necessary... RECT item_buttons_from[7] = { RECT{11,0,24,14},RECT{11,14,24,28},RECT{11,28,24,42},RECT{11,42,24,56}, RECT{24,0,36,30},RECT{24,30,36,60},RECT{36,0,48,30}}; eGameMode store_mode; extern short had_text_freeze,stat_screen_mode; // graphics globals extern RECT status_panel_rect,status_panel_title_rect; extern RECT text_panel_rect; extern short which_combat_type,stat_window; extern eGameMode overall_mode; extern sf::RenderWindow mainPtr; extern RECT more_info_button; extern short which_item_page[6]; //extern CursHandle sword_curs; extern std::shared_ptr text_sbar,item_sbar; extern location store_anim_ul; extern tessel_ref_t bg[]; extern short dest_personalities[40]; extern location source_locs[6]; extern location dest_locs[40] ; //extern piles_of_stuff_dumping_type *data_store; extern cScenario scenario; extern sf::Texture tiny_obj_gworld,invenbtn_gworld,status_gworld; extern cCustomGraphics spec_scen_g; extern sf::Texture pc_gworld; extern sf::RenderTexture pc_stats_gworld, item_stats_gworld, text_area_gworld; extern short terrain_there[9][9]; // game globals //extern party_record_type party; //extern current_town_type univ.town; //extern cOutdoors outdoors[2][2]; //extern town_item_list univ.town; //extern unsigned char out[96][96]; //extern big_tr_type t_d; extern location ul; extern bool play_sounds,suppress_stat_screen; 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 bool item_area_button_active[8][6]; extern bool pc_area_button_active[6][5]; extern RECT item_screen_button_rects[9]; extern short spec_item_array[60]; extern short abil_chart[200]; // combat globals extern short item_bottom_button_active[9]; extern cUniverse univ; extern location pc_pos[6]; extern ter_num_t combat_terrain[64][64]; extern short current_pc; extern short shop_identify_cost; extern short store_selling_values[8]; extern short combat_posing_monster, current_working_monster; // 0-5 PC 100 + x - monster x extern bool supressing_some_spaces; extern location ok_space[4]; extern sf::Texture bg_gworld; short text_pc_has_abil_equip(short pc_num,short abil) { short i = 0; while((univ.party[pc_num].items[i].variety == eItemType::NO_ITEM || univ.party[pc_num].items[i].ability != abil || (univ.party[pc_num].equip[i] == false)) && (i < 24)) i++; return i; } // Draws the pc area in upper right //void win_draw_string(WindowPtr dest_window,RECT dest_rect,char *str,short mode,short line_height) void put_pc_screen() { char to_draw[256]; short i = 0,j; RECT erase_rect = {17,2,98,269},to_draw_rect,from_rect; // TODO: The duplication of RECT here shouldn't be necessary... RECT small_erase_rects[3] = {RECT{101,34,114,76},RECT{101,106,114,147},RECT{101,174,114,201}}; RECT bottom_bar_rect = {99,0,116,271}; RECT info_from = {0,1,12,13}; pc_stats_gworld.setActive(); // First clean up gworld with pretty patterns tileImage(pc_stats_gworld, erase_rect,bg[6]); for (i = 0; i < 3; i++) tileImage(pc_stats_gworld, small_erase_rects[i],bg[7]); TextStyle style; style.font = FONT_BOLD; style.pointSize = 12; style.colour = sf::Color::White; style.lineHeight = 10; // Put food, gold, day sprintf((char *) to_draw, "%d", (short) univ.party.gold); win_draw_string( pc_stats_gworld,small_erase_rects[1],to_draw,eTextMode::WRAP,style); sprintf((char *) to_draw, "%d", (short) univ.party.food); win_draw_string( pc_stats_gworld,small_erase_rects[0],to_draw,eTextMode::WRAP,style); i = calc_day(); sprintf((char *) to_draw, "%d", i); win_draw_string( pc_stats_gworld,small_erase_rects[2],to_draw,eTextMode::WRAP,style); style.colour = sf::Color::Black; for (i = 0; i < 6; i++) { if(univ.party[i].main_status != eMainStatus::ABSENT) { for (j = 0; j < 5; j++) pc_area_button_active[i][j] = 1; if (i == current_pc) { style.italic = true; style.colour = sf::Color::Blue; } sprintf((char *) to_draw, "%d. %-20s ", i + 1, (char *) univ.party[i].name.c_str()); win_draw_string(pc_stats_gworld,pc_buttons[i][0],to_draw,eTextMode::WRAP,style); style.italic = false; style.colour = sf::Color::Black; to_draw_rect = pc_buttons[i][1]; to_draw_rect.right += 20; switch (univ.party[i].main_status) { case eMainStatus::ALIVE: if (univ.party[i].cur_health == univ.party[i].max_health) style.colour = sf::Color::Green; else style.colour = sf::Color::Red; sprintf((char *) to_draw, "%-3d ",univ.party[i].cur_health); win_draw_string( pc_stats_gworld,pc_buttons[i][1],to_draw,eTextMode::WRAP,style); if (univ.party[i].cur_sp == univ.party[i].max_sp) style.colour = sf::Color::Blue; else style.colour = sf::Color::Magenta; sprintf((char *) to_draw, "%-3d ",univ.party[i].cur_sp); win_draw_string( pc_stats_gworld,pc_buttons[i][2],to_draw,eTextMode::WRAP,style); draw_pc_effects(i); break; case eMainStatus::DEAD: sprintf((char *) to_draw, "Dead"); break; case eMainStatus::DUST: sprintf((char *) to_draw, "Dust"); break; case eMainStatus::STONE: sprintf((char *) to_draw, "Stone"); break; case eMainStatus::FLED: sprintf((char *) to_draw, "Fled"); break; case eMainStatus::SURFACE: sprintf((char *) to_draw, "Surface"); break; case eMainStatus::WON: sprintf((char *) to_draw, "Won"); break; default: sprintf((char *) to_draw, "Absent"); break; } if(univ.party[i].main_status != eMainStatus::ALIVE) win_draw_string( pc_stats_gworld,to_draw_rect,to_draw,eTextMode::WRAP,style); style.colour = sf::Color::Black; // Now put trade and info buttons //rect_draw_some_item(mixed_gworld,info_from,pc_stats_gworld,pc_buttons[i][3],1,0); //rect_draw_some_item(mixed_gworld,switch_from,pc_stats_gworld,pc_buttons[i][4],1,0); // do faster! to_draw_rect = pc_buttons[i][3]; to_draw_rect.right = pc_buttons[i][4].right + 1; from_rect = info_from; from_rect.right = from_rect.left + to_draw_rect.right - to_draw_rect.left; rect_draw_some_item(invenbtn_gworld,from_rect,pc_stats_gworld,to_draw_rect,sf::BlendAlpha); } else { for (j = 0; j < 5; j++) pc_area_button_active[i][j] = 0; } } pc_stats_gworld.display(); // Sometimes this gets called when character is slain. when that happens, if items for // that PC are up, switch item page. if(current_pc < 6 && univ.party[current_pc].main_status != eMainStatus::ALIVE && stat_window == current_pc) { set_stat_window(current_pc); } } // Draws item area in middle right // Screen_num is what page is visible in the item menu. // 0 - 5 pc inventory 6 - special item 7 - missions // Stat_screen_mode ... 0 - normal, adventuring, all buttons vis // 1 - in shop, item info only // 2 - in shop, identifying, shop_identify_cost is cost // 3 - in shop, selling weapons // 4 - in shop, selling armor // 5 - in shop, selling all // 6 - in shop, augmenting weapon,shop_identify_cost is type void put_item_screen(short screen_num,short suppress_buttons) // if suppress_buttons > 0, save time by not redrawing buttons { std::ostringstream sout; short i_num,item_offset; short i = 0,j,pc; RECT erase_rect = {17,2,122,255},dest_rect; RECT upper_frame_rect = {3,3,15,268}; item_stats_gworld.setActive(); // First clean up gworld with pretty patterns tileImage(item_stats_gworld, erase_rect,bg[6]); if (suppress_buttons == 0) for (i = 0; i < 6; i++) tileImage(item_stats_gworld, item_screen_button_rects[i],bg[7]); tileImage(item_stats_gworld, upper_frame_rect,bg[7]); // Draw buttons at bottom if (suppress_buttons == 0) { for (i = 0; i < 6; i++) tileImage(item_stats_gworld, item_screen_button_rects[i],bg[7]); } item_offset = item_sbar->getPosition(); for (i = 0; i < 8; i++) for (j = 0; j < 6; j++) item_area_button_active[i][j] = false; TextStyle style; style.lineHeight = 10; switch (screen_num) { case 6: // On special items page style.font = FONT_BOLD; style.colour = sf::Color::White; win_draw_string(item_stats_gworld,upper_frame_rect,"Special items:",eTextMode::WRAP,style); style.colour = sf::Color::Black; for (i = 0; i < 8; i++) { i_num = i + item_offset; if (spec_item_array[i_num] >= 0) { // 2nd condition above is quite kludgy, in case it gets here with array all 0's win_draw_string(item_stats_gworld,item_buttons[i][0],scenario.scen_strs(60 + spec_item_array[i_num] * 2),eTextMode::WRAP,style); place_item_button(3,i,4,0); if ((scenario.special_items[spec_item_array[i_num]].flags % 10 == 1) && (!(is_combat()))) place_item_button(0,i,3,0); } } break; case 7: // On jobs page //// break; default: // on an items page pc = screen_num; style.colour = sf::Color::White; style.font = FONT_PLAIN; sout.str("");; sout << univ.party[pc].name << " inventory:", win_draw_string(item_stats_gworld,upper_frame_rect,sout.str(),eTextMode::WRAP,style); style.colour = sf::Color::Black; style.font = FONT_BOLD; for (i = 0; i < 8; i++) { i_num = i + item_offset; sout.str(""); sout << i_num + 1 << '.'; win_draw_string(item_stats_gworld,item_buttons[i][0],sout.str(),eTextMode::WRAP,style); dest_rect = item_buttons[i][0]; dest_rect.left += 36; if(univ.party[pc].items[i_num].variety == eItemType::NO_ITEM) { } else { style.font = FONT_PLAIN; if (univ.party[pc].equip[i_num] == true) { style.italic = true; if(univ.party[pc].items[i_num].variety == eItemType::ONE_HANDED || univ.party[pc].items[i_num].variety == eItemType::TWO_HANDED) style.colour = sf::Color::Magenta; else if(isArmourType(univ.party[pc].items[i_num].variety)) style.colour = sf::Color::Green; else style.colour = sf::Color::Blue; } else style.colour = sf::Color::Black; //// sout.str(""); if (!univ.party[pc].items[i_num].ident) sout << univ.party[pc].items[i_num].name << " "; else { /// Don't place # of charges when Sell button up and space tight sout << univ.party[pc].items[i_num].full_name << ' '; // TODO: Why are bashing weapons excluded from this? if(univ.party[pc].items[i_num].charges > 0 && univ.party[pc].items[i_num].type != eWeapType::BASHING && (stat_screen_mode <= 1)) sout << '(' << int(univ.party[pc].items[i_num].charges) << ')'; } dest_rect.left -= 2; win_draw_string(item_stats_gworld,dest_rect,sout.str(),eTextMode::WRAP,style); style.italic = false; style.colour = sf::Color::Black; // this is kludgy, awkwark, and has redundant code. Done this way to // make go faster, and I got lazy. if ((stat_screen_mode == 0) && ((is_town()) || (is_out()) || ((is_combat()) && (pc == current_pc)))) { // place give and drop and use place_item_button(0,i,0,univ.party[pc].items[i_num].graphic_num); // item_graphic if (abil_chart[univ.party[pc].items[i_num].ability] != 4) // place use if can place_item_button(10,i,1,0); else place_item_button(11,i,1,0); } else { place_item_button(0,i,0,univ.party[pc].items[i_num].graphic_num); // item_graphic place_item_button(3,i,4,0); // info button if ((stat_screen_mode == 0) && ((is_town()) || (is_out()) || ((is_combat()) && (pc == current_pc)))) { // place give and drop and use place_item_button(1,i,2,0); place_item_button(2,i,3,0); if (abil_chart[univ.party[pc].items[i_num].ability] != 4) // place use if can place_item_button(0,i,1,0); } } if (stat_screen_mode > 1) { place_buy_button(i,pc,i_num); } } // end of if item is there } // end of for (i = 0; i < 8; i++) break; } place_item_bottom_buttons(); item_stats_gworld.display(); } void place_buy_button(short position,short pc_num,short item_num) { RECT dest_rect,source_rect; // TODO: The duplication of RECT here shouldn't be necessary... RECT button_sources[3] = {RECT{24,0,36,30},RECT{36,0,48,30},RECT{48,0,60,30}}; short val_to_place; char store_str[60]; short aug_cost[10] = {4,7,10,8, 15,15,10, 0,0,0}; if(univ.party[pc_num].items[item_num].variety == eItemType::NO_ITEM) return; dest_rect = item_buttons[position][5]; val_to_place = (univ.party[pc_num].items[item_num].charges > 0) ? univ.party[pc_num].items[item_num].charges * univ.party[pc_num].items[item_num].value : univ.party[pc_num].items[item_num].value; val_to_place = val_to_place / 2; switch (stat_screen_mode) { case 2: if (!univ.party[pc_num].items[item_num].ident) { item_area_button_active[position][5] = true; source_rect = button_sources[0]; val_to_place = shop_identify_cost; } break; case 3: // sell weapons if (isWeaponType(univ.party[pc_num].items[item_num].variety) && (!univ.party[pc_num].equip[item_num]) && (univ.party[pc_num].items[item_num].ident) && (val_to_place > 0) && (!univ.party[pc_num].items[item_num].unsellable)) { item_area_button_active[position][5] = true; source_rect = button_sources[1]; } break; case 4: // sell armor if(isArmourType(univ.party[pc_num].items[item_num].variety) && (!univ.party[pc_num].equip[item_num]) && (univ.party[pc_num].items[item_num].ident) && (val_to_place > 0) && (!univ.party[pc_num].items[item_num].unsellable)) { item_area_button_active[position][5] = true; source_rect = button_sources[1]; } break; case 5: // sell any if ((val_to_place > 0) && (univ.party[pc_num].items[item_num].ident) && (!univ.party[pc_num].equip[item_num]) && (!univ.party[pc_num].items[item_num].unsellable)) { item_area_button_active[position][5] = true; source_rect = button_sources[1]; } break; case 6: // augment weapons if ((univ.party[pc_num].items[item_num].variety == eItemType::ONE_HANDED || univ.party[pc_num].items[item_num].variety == eItemType::TWO_HANDED) && (univ.party[pc_num].items[item_num].ident) && (univ.party[pc_num].items[item_num].ability == 0) && (!univ.party[pc_num].items[item_num].magic)) { item_area_button_active[position][5] = true; source_rect = button_sources[2]; val_to_place = max(aug_cost[shop_identify_cost] * 100,univ.party[pc_num].items[item_num].value * (5 + aug_cost[shop_identify_cost])); } break; } if (item_area_button_active[position][5]) { store_selling_values[position] = val_to_place; dest_rect = item_buttons[position][5]; dest_rect.right = dest_rect.left + 30; rect_draw_some_item(invenbtn_gworld, source_rect, item_stats_gworld, dest_rect, sf::BlendAlpha); sprintf((char *) store_str," %d",val_to_place); TextStyle style; if (val_to_place >= 10000) style.font = FONT_PLAIN; style.lineHeight = 10; win_draw_string(item_stats_gworld,item_buttons[position][5],store_str,eTextMode::LEFT_TOP,style); } } //extern bool item_area_button_active[8][6]; // name, use, give, drop, info, sell/id // shortcuts - if which_button_to_put is 10, all 4 buttons now // if which_button_to_put is 11, just right 2 void place_item_button(short which_button_to_put,short which_slot,short which_button_position,short extra_val) { RECT from_rect = {0,0,18,18},to_rect; if (which_button_position == 0) { // this means put little item graphic, extra val is which_graphic item_area_button_active[which_slot][which_button_position] = true; from_rect.offset((extra_val % 10) * 18,(extra_val / 10) * 18); to_rect = item_buttons[which_slot][0]; to_rect.right = to_rect.left + (to_rect.bottom - to_rect.top); to_rect.inset(-1,-1); to_rect.offset(20,1); from_rect.inset(2,2); if (extra_val >= 1000) { sf::Texture* src_gw; graf_pos_ref(src_gw, from_rect) = spec_scen_g.find_graphic(extra_val - 1000); rect_draw_some_item(*src_gw, from_rect, item_stats_gworld, to_rect,sf::BlendAlpha); } else rect_draw_some_item(tiny_obj_gworld, from_rect, item_stats_gworld, to_rect, sf::BlendAlpha); return; } if (which_button_to_put < 4) { // this means put a regular item button item_area_button_active[which_slot][which_button_position] = true; rect_draw_some_item(invenbtn_gworld, item_buttons_from[which_button_to_put], item_stats_gworld, item_buttons[which_slot][which_button_position], sf::BlendAlpha); } if (which_button_to_put == 10) { // this means put all 4 item_area_button_active[which_slot][1] = true; item_area_button_active[which_slot][2] = true; item_area_button_active[which_slot][3] = true; item_area_button_active[which_slot][4] = true; from_rect = item_buttons_from[0]; from_rect.right = item_buttons_from[3].right; to_rect = item_buttons[which_slot][1]; to_rect.right = to_rect.left + from_rect.right - from_rect.left; rect_draw_some_item(invenbtn_gworld, from_rect, item_stats_gworld, to_rect, sf::BlendAlpha); } if (which_button_to_put == 11) { // this means put right 3 item_area_button_active[which_slot][2] = true; item_area_button_active[which_slot][3] = true; item_area_button_active[which_slot][4] = true; from_rect = item_buttons_from[1]; from_rect.right = item_buttons_from[3].right; to_rect = item_buttons[which_slot][2]; to_rect.right = to_rect.left + from_rect.right - from_rect.left; rect_draw_some_item(invenbtn_gworld, from_rect, item_stats_gworld, to_rect, sf::BlendAlpha); } } //RECT get_custom_rect (short which_rect) //// //{ // RECT store_rect = {0,0,36,28}; // // OffsetRect(&store_rect,28 * (which_rect % 10),36 * (which_rect / 10)); // return store_rect; //} void place_item_bottom_buttons() { RECT pc_from_rect = {0,0,36,28},but_from_rect = {30,60,46,78},to_rect; RECT spec_from_rect = {0,60,15,95}, job_from_rect = {15,60,30,95}, help_from_rect = {46,60,59,76}; // TODO: What about when the buttons are pressed? short i; for (i = 0; i < 6; i++) { if(univ.party[i].main_status == eMainStatus::ALIVE) { item_bottom_button_active[i] = true; to_rect = item_screen_button_rects[i]; rect_draw_some_item(invenbtn_gworld, but_from_rect, item_stats_gworld, to_rect, sf::BlendAlpha); pc_from_rect = calc_rect(2 * (univ.party[i].which_graphic / 8), univ.party[i].which_graphic % 8); to_rect.inset(2,2); rect_draw_some_item(pc_gworld, pc_from_rect, item_stats_gworld, to_rect, sf::BlendAlpha); } else item_bottom_button_active[i] = false; } to_rect = item_screen_button_rects[6]; rect_draw_some_item(invenbtn_gworld, spec_from_rect, item_stats_gworld, to_rect, sf::BlendAlpha); to_rect = item_screen_button_rects[7]; rect_draw_some_item(invenbtn_gworld, job_from_rect, item_stats_gworld, to_rect, sf::BlendAlpha); to_rect = item_screen_button_rects[8]; rect_draw_some_item(invenbtn_gworld, help_from_rect, item_stats_gworld, to_rect, sf::BlendAlpha); } void set_stat_window(short new_stat) { short i,array_pos = 0; stat_window = new_stat; if(stat_window < 6 && univ.party[stat_window].main_status != eMainStatus::ALIVE) stat_window = first_active_pc(); item_sbar->setPageSize(8); switch (stat_window) { case 6: for (i = 0; i < 60; i++) spec_item_array[i] = -1; for (i = 0; i < 50; i++) //// if (univ.party.spec_items[i] > 0) { spec_item_array[array_pos] = i; array_pos++; } array_pos = max(0,array_pos - 8); item_sbar->setMaximum(array_pos); break; case 7: item_sbar->setMaximum(2); item_sbar->setPageSize(2); break; default: item_sbar->setMaximum(16); break; } item_sbar->setPosition(0); put_item_screen(stat_window,0); } short first_active_pc() { short i = 0; for (i = 0; i < 6; i++) if(univ.party[i].main_status == eMainStatus::ALIVE) return i; return 6; } void refresh_stat_areas(short mode) { short i; sf::BlendMode x; // TODO: The duplication of RECT here shouldn't be necessary... RECT dest_rect,parts_of_area_to_draw[3] = {RECT{0,0,17,271},RECT{16,0,123,256},RECT{123,0,144,271}}; //x = mode * 10; dest_rect = RECT(pc_stats_gworld); RECT oldRect = dest_rect; dest_rect.offset(PC_WIN_UL_X,PC_WIN_UL_Y); if(mode == 1) x = sf::BlendAdd; else x = sf::BlendNone; rect_draw_some_item (pc_stats_gworld.getTexture(), oldRect, dest_rect,ul, x); for (i = 0; i < 3; i++) { dest_rect = parts_of_area_to_draw[i]; dest_rect.offset(ITEM_WIN_UL_X,ITEM_WIN_UL_Y); rect_draw_some_item(item_stats_gworld.getTexture(), parts_of_area_to_draw[i], dest_rect,ul, x); } dest_rect = RECT(text_area_gworld); oldRect = dest_rect; dest_rect.offset(TEXT_WIN_UL_X,TEXT_WIN_UL_Y); rect_draw_some_item(text_area_gworld.getTexture(),oldRect, dest_rect,ul, x); } //// // get job info gone short total_encumberance(short pc_num) { short store = 0,i,what_val; for (i = 0; i < 24; i++) if (univ.party[pc_num].equip[i] == true) { what_val = univ.party[pc_num].items[i].awkward; store += what_val; } return store; } RECT get_stat_effect_rect(eStatus which_effect) { int code = (int) which_effect; RECT base = {0,0,12,12}; base.offset(12 * (code % 3), 12 * (code / 3)); return base; } void draw_pc_effects(short pc) { // TODO: Calculate these rects from scratch instead of hard-coding them. (use above function) // TODO: The duplication of RECT here shouldn't be necessary... RECT source_rects[18] = { RECT{00,0,12,12},RECT{00,12,12,24},RECT{00,24,12,36}, RECT{12,0,24,12},RECT{12,12,24,24},RECT{12,24,24,36}, RECT{24,0,36,12},RECT{24,12,36,24},RECT{24,24,36,36}, RECT{36,0,47,12},RECT{36,12,47,24},RECT{36,24,47,36}, RECT{47,0,60,12},RECT{47,12,60,24},RECT{47,24,60,36}, RECT{60,0,72,12},RECT{60,12,72,24},RECT{60,24,72,36} }; RECT dest_rect = {18,15,30,27},dlog_dest_rect = {66,354,78,366}; short right_limit = 250; short name_width; TextStyle style; name_width = string_length(univ.party[pc].name, style); right_limit = pc_buttons[0][1].left - 5; //dest_rect.left = pc_buttons[i][1].left - 16; dest_rect.left = name_width + 33; dest_rect.right = dest_rect.left + 12; dest_rect.top += pc * 13; dest_rect.bottom += pc * 13; if(exceptSplit(univ.party[pc].main_status) != eMainStatus::ALIVE) return; // TODO: This used to draw the status icons in the spell dialog, but it no longer does. Fix that. if ((univ.party[pc].status[eStatus::POISONED_WEAPON] > 0) && (dest_rect.right < right_limit)) { rect_draw_some_item(status_gworld,source_rects[4],pc_stats_gworld,dest_rect,sf::BlendAlpha); dest_rect.left += 13; dest_rect.right += 13; } if (univ.party[pc].status[eStatus::BLESS_CURSE] > 0) { rect_draw_some_item(status_gworld,source_rects[2],pc_stats_gworld,dest_rect,sf::BlendAlpha); dest_rect.left += 13; dest_rect.right += 13; } else if (univ.party[pc].status[eStatus::BLESS_CURSE] < 0) { rect_draw_some_item(status_gworld,source_rects[3],pc_stats_gworld,dest_rect,sf::BlendAlpha); dest_rect.left += 13; dest_rect.right += 13; } if (univ.party[pc].status[eStatus::POISON] > 0) { rect_draw_some_item(status_gworld,source_rects[(univ.party[pc].status[eStatus::POISON] > 4) ? 1 : 0],pc_stats_gworld,dest_rect,sf::BlendAlpha); dest_rect.left += 13; dest_rect.right += 13; } if (univ.party[pc].status[eStatus::INVULNERABLE] > 0) { rect_draw_some_item(status_gworld,source_rects[5],pc_stats_gworld,dest_rect,sf::BlendAlpha); dest_rect.left += 13; dest_rect.right += 13; } if (univ.party[pc].status[eStatus::HASTE_SLOW] > 0) { rect_draw_some_item(status_gworld,source_rects[6],pc_stats_gworld,dest_rect,sf::BlendAlpha); dest_rect.left += 13; dest_rect.right += 13; } else if (univ.party[pc].status[eStatus::HASTE_SLOW] < 0) { rect_draw_some_item(status_gworld,source_rects[8],pc_stats_gworld,dest_rect,sf::BlendAlpha); dest_rect.left += 13; dest_rect.right += 13; }else{ rect_draw_some_item(status_gworld,source_rects[7],pc_stats_gworld,dest_rect,sf::BlendAlpha); dest_rect.left += 13; dest_rect.right += 13; } if ((univ.party[pc].status[eStatus::MAGIC_RESISTANCE] > 0) && (dest_rect.right < right_limit)) { rect_draw_some_item(status_gworld,source_rects[9],pc_stats_gworld,dest_rect,sf::BlendAlpha); dest_rect.left += 13; dest_rect.right += 13; } if ((univ.party[pc].status[eStatus::WEBS] > 0) && (dest_rect.right < right_limit)) { rect_draw_some_item(status_gworld,source_rects[10],pc_stats_gworld,dest_rect,sf::BlendAlpha); dest_rect.left += 13; dest_rect.right += 13; } if ((univ.party[pc].status[eStatus::DISEASE] > 0) && (dest_rect.right < right_limit)){ rect_draw_some_item(status_gworld,source_rects[11],pc_stats_gworld,dest_rect,sf::BlendAlpha); dest_rect.left += 13; dest_rect.right += 13; } if ((univ.party[pc].status[eStatus::INVISIBLE] > 0) && (dest_rect.right < right_limit)){ rect_draw_some_item(status_gworld,source_rects[12],pc_stats_gworld,dest_rect,sf::BlendAlpha); dest_rect.left += 13; dest_rect.right += 13; } if ((univ.party[pc].status[eStatus::DUMB] > 0) && (dest_rect.right < right_limit)){ rect_draw_some_item(status_gworld,source_rects[13],pc_stats_gworld,dest_rect,sf::BlendAlpha); dest_rect.left += 13; dest_rect.right += 13; } if ((univ.party[pc].status[eStatus::MARTYRS_SHIELD] > 0) && (dest_rect.right < right_limit)){ rect_draw_some_item(status_gworld,source_rects[14],pc_stats_gworld,dest_rect,sf::BlendAlpha); dest_rect.left += 13; dest_rect.right += 13; } if ((univ.party[pc].status[eStatus::ASLEEP] > 0) && (dest_rect.right < right_limit)){ rect_draw_some_item(status_gworld,source_rects[15],pc_stats_gworld,dest_rect,sf::BlendAlpha); dest_rect.left += 13; dest_rect.right += 13; } if ((univ.party[pc].status[eStatus::PARALYZED] > 0) && (dest_rect.right < right_limit)){ rect_draw_some_item(status_gworld,source_rects[16],pc_stats_gworld,dest_rect,sf::BlendAlpha); dest_rect.left += 13; dest_rect.right += 13; } if ((univ.party[pc].status[eStatus::ACID] > 0) && (dest_rect.right < right_limit)){ rect_draw_some_item(status_gworld,source_rects[17],pc_stats_gworld,dest_rect,sf::BlendAlpha); dest_rect.left += 13; dest_rect.right += 13; } } void print_party_stats() { char store_string[256]; add_string_to_buf("PARTY STATS:"); sprintf((char *) store_string, " Number of kills: %lld ", univ.party.total_m_killed); add_string_to_buf(store_string); if ((is_town()) || ((is_combat()) && (which_combat_type == 1))) { sprintf((char *) store_string, " Kills in this town: %d ", univ.party.m_killed[univ.town.num]); add_string_to_buf(store_string); } sprintf((char *) store_string, " Total experience: %lld ", univ.party.total_xp_gained); add_string_to_buf(store_string); sprintf((char *) store_string, " Total damage done: %lld ", univ.party.total_dam_done); add_string_to_buf(store_string); sprintf((char *) store_string, " Total damage taken: %lld ", univ.party.total_dam_taken); add_string_to_buf(store_string); print_buf(); } short do_look(location space) { short i,j,num_items = 0; bool gold_here = false, food_here = false, is_lit = true; location from_where; std::string msg; from_where = get_cur_loc(); is_lit = is_out() || pt_in_light(from_where,space); if (((overall_mode == MODE_LOOK_OUTDOORS) && (space == univ.party.p_loc)) || ((overall_mode == MODE_LOOK_TOWN) && (space == univ.town.p_loc))) add_string_to_buf(" Your party"); if (overall_mode == MODE_LOOK_COMBAT) for (i = 0; i < 6; i++) if(space == pc_pos[i] && univ.party[i].main_status == eMainStatus::ALIVE && (is_lit == true) && (can_see_light(pc_pos[current_pc],space,sight_obscurity) < 5)) { msg = " " + univ.party[i].name; add_string_to_buf(msg); } if ((overall_mode == MODE_LOOK_TOWN) || (overall_mode == MODE_LOOK_COMBAT)) { for (i = 0; i < univ.town->max_monst(); i++) if ((univ.town.monst[i].active != 0) && (is_lit == true) && (monst_on_space(space,i) == true) && ((overall_mode == MODE_LOOK_TOWN) || (can_see_light(pc_pos[current_pc],space,sight_obscurity) < 5)) && (univ.town.monst[i].picture_num != 0)) { msg = get_m_name(univ.town.monst[i].number); if (univ.town.monst[i].health < univ.town.monst[i].m_health) { if (univ.town.monst[i].attitude % 2 == 1) msg = " Wounded " + msg + " (H)"; else msg = " Wounded " + msg + " (F)"; } else { if (univ.town.monst[i].attitude % 2 == 1) msg = " " + msg + " (H)"; else msg = " " + msg + " (F)"; } add_string_to_buf((char *) msg.c_str()); } } if (overall_mode == MODE_LOOK_OUTDOORS) { for (i = 0; i < 10; i++) { if ((univ.party.out_c[i].exists) && (space == univ.party.out_c[i].m_loc)) { for (j = 0; j < 7; j++) if (univ.party.out_c[i].what_monst.monst[j] != 0) { msg = get_m_name(univ.party.out_c[i].what_monst.monst[j]); msg = " " + msg; add_string_to_buf((char *) msg.c_str()); j = 7; } } } if (out_boat_there(space) < 30) add_string_to_buf(" Boat "); if (out_horse_there(space) < 30) add_string_to_buf(" Horse "); } if ((overall_mode == MODE_LOOK_TOWN) || (overall_mode == MODE_LOOK_COMBAT)) { if (town_boat_there(space) < 30) add_string_to_buf(" Boat "); if (town_horse_there(space) < 30) add_string_to_buf(" Horse "); if (univ.town.is_web(space.x,space.y)) add_string_to_buf(" Web "); if (univ.town.is_crate(space.x,space.y)) add_string_to_buf(" Crate "); if (univ.town.is_barrel(space.x,space.y)) add_string_to_buf(" Barrel "); if(univ.town.is_block(space.x,space.y)) add_string_to_buf(" Stone Block "); if (univ.town.is_fire_barr(space.x,space.y)) add_string_to_buf(" Magic Barrier "); if (univ.town.is_force_barr(space.x,space.y)) add_string_to_buf(" Magic Barrier "); if (univ.town.is_quickfire(space.x,space.y)) add_string_to_buf(" Quickfire "); if (univ.town.is_fire_wall(space.x,space.y)) add_string_to_buf(" Wall of Fire "); if (univ.town.is_force_wall(space.x,space.y)) add_string_to_buf(" Wall of Force "); if (univ.town.is_antimagic(space.x,space.y)) add_string_to_buf(" Antimagic Field "); if (univ.town.is_scloud(space.x,space.y)) add_string_to_buf(" Stinking Cloud "); if (univ.town.is_ice_wall(space.x,space.y)) add_string_to_buf(" Ice Wall "); if (univ.town.is_blade_wall(space.x,space.y)) add_string_to_buf(" Blade Wall "); if (univ.town.is_force_cage(space.x,space.y)) add_string_to_buf(" Force Cage "); if (univ.town.is_sm_blood(space.x,space.y)) add_string_to_buf(" Blood stain "); if (univ.town.is_med_blood(space.x,space.y)) add_string_to_buf(" Blood stain "); if (univ.town.is_lg_blood(space.x,space.y)) add_string_to_buf(" Blood stain "); if (univ.town.is_sm_slime(space.x,space.y)) add_string_to_buf(" Smears of slime "); if (univ.town.is_lg_slime(space.x,space.y)) add_string_to_buf(" Smears of slime "); if (univ.town.is_ash(space.x,space.y)) add_string_to_buf(" Ashes "); if (univ.town.is_bones(space.x,space.y)) add_string_to_buf(" Bones "); if (univ.town.is_rubble(space.x,space.y)) add_string_to_buf(" Rubble "); for (i = 0; i < NUM_TOWN_ITEMS; i++) { if(univ.town.items[i].variety != eItemType::NO_ITEM && space == univ.town.items[i].item_loc && (is_lit == true)) { if(univ.town.items[i].variety == eItemType::GOLD) gold_here = true; else if(univ.town.items[i].variety == eItemType::FOOD) food_here = true; else num_items++; } } if (gold_here == true) add_string_to_buf(" Gold"); if (food_here == true) add_string_to_buf(" Food"); if (num_items > 8) add_string_to_buf(" Many items"); else for (i = 0; i < NUM_TOWN_ITEMS; i++) { if(univ.town.items[i].variety != eItemType::NO_ITEM && univ.town.items[i].variety != eItemType::GOLD && univ.town.items[i].variety != eItemType::FOOD && (space == univ.town.items[i].item_loc) && (!univ.town.items[i].contained)) { if (univ.town.items[i].ident) msg = " " + univ.town.items[i].full_name; else msg = " " + univ.town.items[i].name; add_string_to_buf((char *) msg.c_str()); } } } if (is_lit == false) { add_string_to_buf(" Dark "); return 0; } return print_terrain(space); } short town_boat_there(location where) { short i; // Num boats stores highest # of boat in town for (i = 0; i < 30; i++) if ((univ.party.boats[i].exists) && (univ.party.boats[i].which_town == univ.town.num) && (where == univ.party.boats[i].loc)) return i; return 30; } short out_boat_there(location where) { short i; for (i = 0; i < 30; i++) if ((univ.party.boats[i].exists) && (where == univ.party.boats[i].loc) && (univ.party.boats[i].which_town == 200)) return i; return 30; } short town_horse_there(location where) { short i; // Num boats stores highest # of boat in town for (i = 0; i < 30; i++) if ((univ.party.horses[i].exists) && (univ.party.horses[i].which_town == univ.town.num) && (where == univ.party.horses[i].loc)) return i; return 30; } short out_horse_there(location where) { short i; for (i = 0; i < 30; i++) if ((univ.party.horses[i].exists) && (where == univ.party.horses[i].loc) && (univ.party.horses[i].which_town == 200)) return i; return 30; } void notify_out_combat_began(cOutdoors::cWandering encounter,short *nums) { short i; std::string msg; add_string_to_buf((char *) "COMBAT! "); for (i = 0; i < 6; i++) if (encounter.monst[i] != 0) { switch (encounter.monst[i]) { //// default: msg = get_m_name(encounter.monst[i]); std::ostringstream sout; sout << " " << nums[i] << " x " << msg << " "; msg = sout.str(); break; } add_string_to_buf((char *) msg.c_str()); } if (encounter.monst[6] != 0) { msg = " " + get_m_name(encounter.monst[6]) + " "; add_string_to_buf((char *) msg.c_str()); } } std::string get_m_name(m_num_t num) { //// //strcpy((char *) str,(char *) scenario.scen_monsters[num].m_name); return scenario.scen_monsters[num].m_name; } std::string get_ter_name(ter_num_t num) { std::string store_name = "Pit"; //// if ((num == 90) && ((is_out()) || (is_town()) || ((is_combat()) && (which_combat_type == 1)))); //sprintf((char *) store_name,"Pit"); else { store_name = scenario.ter_types[num].name; } return store_name; } void print_monst_name(m_num_t m_type) { std::string msg = get_m_name(m_type) + ':'; add_string_to_buf((char *) msg.c_str()); } void print_monst_attacks(m_num_t m_type,short target) //short target; // < 100 - pc >= 100 monst { //char store_string3[60]; std::string msg = get_m_name(m_type); msg += " attacks "; if (target < 100) msg += univ.party[target].name; else msg += get_m_name(univ.town.monst[target - 100].number); add_string_to_buf((char *) msg.c_str()); } //// void damaged_message(short damage,short type) { std::ostringstream sout; sout << " " << get_str("monster-abilities",130 + type); sout << " for " << damage; add_string_to_buf(sout.str().c_str()); } // This prepares the monster's string for the text bar std::string print_monster_going(m_num_t m_num,short ap) { std::ostringstream sout(get_m_name(m_num)); sout << " (ap: " << ap << ')'; return sout.str(); } void monst_spell_note(m_num_t number,short which_mess) { std::string msg = get_m_name(number); switch (which_mess) { case 1: msg = " " + msg + " scared. "; break; case 2: msg = " " + msg + " slowed. "; break; case 3: msg = " " + msg + " weakened. "; break; case 4: msg = " " + msg + " poisoned. "; break; case 5: msg = " " + msg + " cursed. "; break; case 6: msg = " " + msg + " ravaged. "; break; case 7: msg = " " + msg + " undamaged. "; break; case 8: msg = " " + msg + " is stoned. "; break; case 9: msg = " Gazes at " + msg + '.'; break; case 10: msg = " " + msg + " resists. "; break; case 11: msg = " Drains " + msg + '.'; break; case 12: msg = " Shoots at " + msg + '.'; break; case 13: msg = " Throws spear at " + msg + '.'; break; case 14: msg = " Throws rock at " + msg + '.'; break; case 15: msg = " Throws razordisk at " + msg + '.'; break; case 16: msg = " Hits " + msg + '.'; break; case 17: msg = " " + msg + " disappears. "; break; case 18: msg = " Misses " + msg + '.'; break; case 19: msg = " " + msg + " is webbed. "; break; case 20: msg = " " + msg + " chokes. "; break; case 21: msg = " " + msg + " summoned. "; break; case 22: msg = " " + msg + " is dumbfounded. "; break; case 23: msg = " " + msg + " is charmed. "; break; case 24: msg = " " + msg + " is recorded. "; break; case 25: msg = " " + msg + " is diseased. "; break; case 26: msg = " " + msg + " is an avatar!"; break; case 27: msg = " " + msg + " splits!"; break; case 28: msg = " " + msg + " falls asleep. "; break; case 29: msg = " " + msg + " wakes up. "; break; case 30: msg = " " + msg + " paralyzed. "; break; case 31: msg = " " + msg + " covered with acid. "; break; case 32: msg = " Fires spines at " + msg + '.'; break; case 33: msg = " " + msg + " summons aid. "; break; case 34: msg = " " + msg + " is cured."; break; case 35: msg = " " + msg + " is hasted."; break; case 36: msg = " " + msg + " is blessed."; break; case 37: msg = " " + msg + " cleans webs."; break; case 38: msg = " " + msg + " feels better."; break; case 39: msg = " " + msg + " mind cleared."; break; case 40: msg = " " + msg + " feels alert."; break; case 41: msg = " " + msg + " is healed."; break; case 42: msg = " " + msg + " drained of health."; break; case 43: msg = " " + msg + " magic recharged."; break; case 44: msg = " " + msg + " drained of magic."; break; case 45: msg = " " + msg + " returns to life!"; break; case 46: msg = " " + msg + " dies."; break; case 47: msg = " " + msg + " rallies its courage."; break; case 48: msg = " " + msg + " cleans off acid."; break; } if (which_mess > 0) add_string_to_buf((char *) msg.c_str()); } void monst_cast_spell_note(m_num_t number,short spell,short type) //short type; // 0 - mage 1- priest { std::string msg = get_m_name(number); msg += " casts:"; add_string_to_buf((char *) msg.c_str()); msg = (type == 1) ? m_priest_sp[spell - 1] : m_mage_sp[spell - 1]; msg = " " + msg; add_string_to_buf((char *) msg.c_str()); } void monst_breathe_note(m_num_t number) { std::string msg = get_m_name(number); msg += " breathes."; add_string_to_buf((char *) msg.c_str()); } void monst_damaged_mes(short which_m,short how_much,short how_much_spec) { std::string msg = get_m_name(univ.town.monst[which_m].number); msg = " " + msg + " takes "; std::ostringstream sout(msg); sout << how_much; if (how_much_spec > 0) sout << '+' << how_much_spec; msg = sout.str(); add_string_to_buf((char *) msg.c_str()); } void monst_killed_mes(short which_m) { std::string msg = get_m_name(univ.town.monst[which_m].number); msg = " " + msg + " dies."; add_string_to_buf((char *) msg.c_str()); } void print_nums(short a,short b,short c) { std::ostringstream sout; sout << "debug: " << a << ' ' << b << ' ' << c; add_string_to_buf((char *) sout.str().c_str()); } short print_terrain(location space) { ter_num_t which_terrain; if (overall_mode == MODE_LOOK_OUTDOORS) { which_terrain = univ.out[space.x][space.y]; } if (overall_mode == MODE_LOOK_TOWN) { which_terrain = univ.town->terrain(space.x,space.y); } if (overall_mode == MODE_LOOK_COMBAT) { which_terrain = combat_terrain[space.x][space.y]; } std::string msg = get_ter_name(which_terrain); msg = " " + msg; add_string_to_buf(msg); return (short) which_terrain; } void add_string_to_buf(std::string str, unsigned short indent) { if(overall_mode == MODE_STARTUP) return; if(str == "") return; if(indent && str.find_last_not_of(' ') > 48) { if(indent > 20) indent = 20; size_t split = str.find_last_of(' ', 49); add_string_to_buf(str.substr(0,split)); str = str.substr(split); while(str.find_last_not_of(' ') > 48 - indent) { std::string wrap(indent, ' '); split = str.find_last_of(' ', 49 - indent); wrap += str.substr(0,split); str = str.substr(split); add_string_to_buf(wrap); } return; } // Now check if this is a duplicate message int prev_pointer = buf_pointer - 1; if(prev_pointer < 0) prev_pointer = TEXT_BUF_LEN - 1; size_t last = 0, new_last = str.find_last_not_of(' '); while(last < str.length() && str[last] == text_buffer[prev_pointer].line[last]) last++; while(text_buffer[prev_pointer].line[--last] == ' '); bool is_dup; if(last == new_last) { size_t i, num_pos = 0; enum {begin, f_space, f_lparen, f_x, f_num, f_rparen} state = begin; for(i = last; i < 50 && text_buffer[prev_pointer].line[i]; i++) { if(state == f_x) num_pos = i; if(isdigit(text_buffer[prev_pointer].line[i]) && (state == f_x || state == f_num)) state = f_num; else switch(text_buffer[prev_pointer].line[i]) { case ' ': if(state == begin || state == f_space) state = f_space; break; case '(': if(state == begin || state == f_space) state = f_lparen; break; case 'x': if(state == f_lparen) state = f_x; break; case ')': if(state == f_num) state = f_rparen; break; } if(state == f_rparen) break; } if(state == begin || state == f_space || state == f_rparen) { is_dup = true; last++; } if(is_dup) { int lastCount = 0; if(num_pos > 0) sscanf(text_buffer[prev_pointer].line + num_pos, "%d", &lastCount); sprintf(text_buffer[prev_pointer].line + last, " (x%d)", lastCount + 1); return; } } text_sbar->setPosition(58); // TODO: This seems oddly specific if (buf_pointer == mark_where_printing_long) { printing_long = true; print_buf(); through_sending(); } sprintf((char *)text_buffer[buf_pointer].line, "%-49.49s", str.c_str()); // c2pstr((char *)text_buffer[buf_pointer].line); if (buf_pointer == (TEXT_BUF_LEN - 1)) buf_pointer = 0; else buf_pointer++; } void init_buf() { short i; for (i = 0; i < TEXT_BUF_LEN; i++) sprintf((char *) text_buffer[buf_pointer].line, " "); } void print_buf () { short num_lines_printed = 0,ctrl_val; short line_to_print; short start_print_point; bool end_loop = false; RECT store_text_rect,dest_rect,erase_rect = {2,2,136,255}; text_area_gworld.setActive(); // First clean up gworld with pretty patterns tileImage(text_area_gworld, erase_rect,bg[6]); ctrl_val = 58 - text_sbar->getPosition(); start_print_point = buf_pointer - LINES_IN_TEXT_WIN - ctrl_val; if (start_print_point< 0) start_print_point= TEXT_BUF_LEN + start_print_point; line_to_print= start_print_point; location moveTo; while ((line_to_print!= buf_pointer) && (num_lines_printed < LINES_IN_TEXT_WIN)) { moveTo = location(4, 1 + 12 * num_lines_printed); sf::Text text(text_buffer[line_to_print].line, *ResMgr::get("plain"), 12); text.setColor(sf::Color::Black); text.setPosition(moveTo); text_area_gworld.draw(text); num_lines_printed++; line_to_print++; if (line_to_print== TEXT_BUF_LEN) { line_to_print= 0; } if ((num_lines_printed == LINES_IN_TEXT_WIN - 1) && (printing_long == true)) { end_loop = false; line_to_print= buf_pointer; } } text_area_gworld.display(); } void restart_printing() { lines_to_print = 0; //clear_text_panel(); } void restore_mode() { overall_mode = store_mode; } void through_sending() { mark_where_printing_long = buf_pointer + LINES_IN_TEXT_WIN - 1; if (mark_where_printing_long > TEXT_BUF_LEN - 1) mark_where_printing_long -= TEXT_BUF_LEN; printing_long = false; } /* Draw a bitmap in the world window. hor in 0 .. 8, vert in 0 .. 8, object is ptr. to bitmap to be drawn, and masking is for Copybits. */ void Draw_Some_Item (sf::Texture& src_gworld, RECT src_rect, sf::RenderTarget& targ_gworld,location target, char masked, short main_win) { RECT destrec = {0,0,36,28}; if ((target.x < 0) || (target.y < 0) || (target.x > 8) || (target.y > 8)) return; if ((supressing_some_spaces == true) && (target != ok_space[0]) && (target != ok_space[1]) && (target != ok_space[2]) && (target != ok_space[3])) return; terrain_there[target.x][target.y] = -1; destrec = coord_to_rect(target.x,target.y); if (main_win == 1) destrec.offset(ul.x + 5,ul.y + 5); if (main_win == 0) { if(masked == 1) rect_draw_some_item(src_gworld, src_rect, targ_gworld, destrec, sf::BlendAlpha); else rect_draw_some_item(src_gworld, src_rect, targ_gworld, destrec, sf::BlendNone); } else { if(masked == 1) rect_draw_some_item(src_gworld, src_rect, targ_gworld, destrec, sf::BlendAlpha); else rect_draw_some_item(src_gworld, src_rect, targ_gworld, destrec, sf::BlendNone); } } // TODO: This seems to duplicate logic found in graphtool to get a rect from a picture index RECT coord_to_rect(short i,short j) { RECT to_return; to_return.left = 13 + BITMAP_WIDTH * i; to_return.right = to_return.left + BITMAP_WIDTH; to_return.top = 13 + BITMAP_HEIGHT * j; to_return.bottom = to_return.top + BITMAP_HEIGHT; return to_return; } void make_cursor_sword() { set_cursor(sword_curs); } short calc_day() { return (short) ((univ.party.age) / 3700) + 1; } bool day_reached(unsigned char which_day, unsigned char which_event) // which_day is day event should happen // which_event is the univ.party.key_times value to cross reference with. // if the key_time is reached before which_day, event won't happen // if it's 0, event always happens { // Windows version unconditionally added 20 days for no reason at all. // Instead, let's add 10 days, but only if easy mode enabled. if(PSD[SDF_EASY_MODE]) which_day += 10; if (which_event > 10) return false; if ((which_event > 0) && (univ.party.key_times[which_event] < which_day)) return false; if (calc_day() >= which_day) return true; else return false; }