diff --git a/osx/boe.actions.cpp b/osx/boe.actions.cpp index 41247fff..6fe247cd 100644 --- a/osx/boe.actions.cpp +++ b/osx/boe.actions.cpp @@ -386,10 +386,8 @@ static void handle_rest(bool& need_redraw, bool& need_reprint) { put_pc_screen(); } if(i == 50) { - univ.party.age += 1200;//// + do_rest(1200, get_ran(5,1,10), 50); add_string_to_buf(" Rest successful. "); - heal_party(get_ran(5,1,10)); - restore_sp_party(50); put_pc_screen(); } need_reprint = true; @@ -908,10 +906,6 @@ bool handle_action(sf::Event event) { the_point = location(event.mouseButton.x, event.mouseButton.y); the_point.x -= ul.x; the_point.y -= ul.y; - if(!special_queue.empty()) - printf("Note: %ld queued specials have been flushed without running!", special_queue.size()); - while(!special_queue.empty()) // TODO: Does this cause problems by leaving some specials uncalled? - special_queue.pop(); end_scenario = false; // Now split off the extra stuff, like talking and shopping. @@ -2165,6 +2159,56 @@ void do_save(short mode) redraw_screen(REFRESH_TEXT); } +void do_rest(long length, int hp_restore, int mp_restore) { + unsigned long age_before = univ.party.age; + univ.party.age += length; + if(!PSD[SDF_TIMERS_DURING_REST]) { + heal_party(hp_restore); + restore_sp_party(mp_restore); + put_pc_screen(); + return; + } + // If some players diseased, allow it to progress a bit + handle_disease(); + handle_disease(); + handle_disease(); + // Clear party spell effects + PSD[SDF_PARTY_STEALTHY] = 0; + PSD[SDF_PARTY_DETECT_LIFE] = 0; + PSD[SDF_PARTY_FIREWALK] = 0; + PSD[SDF_PARTY_FLIGHT] = 0; // This one shouldn't be nonzero anyway, since you can't rest while flying. + for(int i = 0; i < 6; i++) + univ.party[i].status.clear(); + // Specials countdowns + if((length > 500 || age_before / 500 < univ.party.age / 500) && party_has_abil(52) && get_ran(1,0,5) == 3) { + // TODO: This seems to be the "radioactivity" handler, and the string appears to not exist. + cStrDlog display_enc_string("Missing String: Radioactivity", "", "", 8, PIC_DLOG); + display_enc_string.setSound(3); + display_enc_string.show(); + for(int i = 0; i < 6; i++) + disease_pc(i,5); + } + // Plants and magic shops + if(length > 4000 || age_before / 4000 < univ.party.age / 4000) + refresh_store_items(); + // Heal party + heal_party(hp_restore); + restore_sp_party(mp_restore); + // Recuperation and chronic disease disads + for(int i = 0; i < 6; i++) + if(univ.party[i].main_status == eMainStatus::ALIVE) { + if(univ.party[i].traits[9] > 0 && univ.party[i].cur_health < univ.party[i].max_health) { + heal_pc(i,hp_restore / 5); + } + if(univ.party[i].traits[13] > 0 && get_ran(1,0,110) == 1) { + disease_pc(i,6); + } + } + special_increase_age(length, true); + put_pc_screen(); + adjust_spell_menus(); +} + void increase_age()//// { short i,j,item,how_many_short = 0,r1,store_day; diff --git a/osx/boe.actions.h b/osx/boe.actions.h index 45ec62f2..33e60e96 100644 --- a/osx/boe.actions.h +++ b/osx/boe.actions.h @@ -9,6 +9,7 @@ void init_screen_locs(); bool prime_time(); bool handle_action(sf::Event event); +void handle_monster_actions(bool& need_redraw, bool& need_reprint); bool someone_awake(); void handle_menu_spell(short spell_picked,short spell_type) ; void initiate_outdoor_combat(short i); diff --git a/osx/boe.consts.h b/osx/boe.consts.h index 6ab4c6cf..3703cd98 100644 --- a/osx/boe.consts.h +++ b/osx/boe.consts.h @@ -59,6 +59,7 @@ #define SDF_EASY_MODE 306][7 #define SDF_LESS_WANDER_ENC 306][8 #define SDF_NO_TER_ANIM 306][9 +#define SDF_TIMERS_DURING_REST 307][0 /* [305] [6] is No targeting line (use if getting crashes) @@ -82,6 +83,7 @@ enum eGameMode { MODE_DROP_COMBAT = 15, MODE_TALKING = 20, MODE_SHOPPING = 21, + MODE_ROOM_DESCR = 30, // for future use MODE_LOOK_OUTDOORS = 35, // looking at something MODE_LOOK_TOWN = 36, MODE_LOOK_COMBAT = 37, diff --git a/osx/boe.dlgutil.cpp b/osx/boe.dlgutil.cpp index 8bd1f50a..0ba09e7a 100644 --- a/osx/boe.dlgutil.cpp +++ b/osx/boe.dlgutil.cpp @@ -732,9 +732,7 @@ void handle_talk_event(location p) talk_end_forced = true; univ.party.gold -= a; put_pc_screen(); - heal_party(30 * b); - restore_sp_party(25 * b); - univ.party.age += 700; + do_rest(700, 30 & b, 25 * b); univ.town.p_loc.x = c; univ.town.p_loc.y = d; center = univ.town.p_loc; diff --git a/osx/boe.party.cpp b/osx/boe.party.cpp index b11f959f..24cf4219 100644 --- a/osx/boe.party.cpp +++ b/osx/boe.party.cpp @@ -521,9 +521,11 @@ void put_party_in_scen(std::string scen_name) if(scenario.format.prog_make_ver[0] < 2){ PSD[SDF_RESURRECT_NO_BALM] = 1; PSD[SDF_NO_BOAT_SPECIALS] = 1; + PSD[SDF_TIMERS_DURING_REST] = 0; } else { PSD[SDF_RESURRECT_NO_BALM] = 0; PSD[SDF_NO_BOAT_SPECIALS] = 0; + PSD[SDF_TIMERS_DURING_REST] = 1; } } diff --git a/osx/boe.specials.cpp b/osx/boe.specials.cpp index 9e4114e5..90cae2d5 100644 --- a/osx/boe.specials.cpp +++ b/osx/boe.specials.cpp @@ -1855,49 +1855,67 @@ void push_things()//// } } -void special_increase_age() +void special_increase_age(long length, bool queue) { unsigned short i; short s1,s2,s3; bool redraw = false,stat_area = false; location null_loc; // TODO: Should we pass the party's location here? It doesn't quite make sense to me though... + unsigned long age_before = univ.party.age - length; + unsigned long current_age = univ.party.age; - if(is_town()) { + if(is_town() || (is_combat() && which_combat_type == 1)) { for(i = 0; i < 8; i++) - if((univ.town->timer_spec_times[i] > 0) && (univ.party.age % univ.town->timer_spec_times[i] == 0) - && ((is_town() == true) || ((is_combat() == true) && (which_combat_type == 1)))) { - run_special(eSpecCtx::TOWN_TIMER,2,univ.town->timer_specs[i],null_loc,&s1,&s2,&s3); + if(univ.town->timer_spec_times[i] > 0) { + short time = univ.town->timer_spec_times[i]; + for(unsigned long j = age_before; j <= current_age; j++) + if(j % time == 0) { + if(queue) { + univ.party.age = j; + queue_special(eSpecCtx::TOWN_TIMER, 2, univ.town->timer_specs[i], null_loc); + } else run_special(eSpecCtx::TOWN_TIMER,2,univ.town->timer_specs[i],null_loc,&s1,&s2,&s3); + } stat_area = true; if(s3 > 0) redraw = true; } } + univ.party.age = current_age; for (i = 0; i < 20; i++) - if ((scenario.scenario_timer_times[i] > 0) && (univ.party.age % scenario.scenario_timer_times[i] == 0)) { - run_special(eSpecCtx::SCEN_TIMER,0,scenario.scenario_timer_specs[i],null_loc,&s1,&s2,&s3); + if(scenario.scenario_timer_times[i] > 0) { + short time = scenario.scenario_timer_times[i]; + for(unsigned long j = age_before; j <= current_age; j++) + if(j % time == 0) { + if(queue) { + univ.party.age = j; + queue_special(eSpecCtx::SCEN_TIMER, 0, scenario.scenario_timer_specs[i], null_loc); + } else run_special(eSpecCtx::SCEN_TIMER,0,scenario.scenario_timer_specs[i],null_loc,&s1,&s2,&s3); + } stat_area = true; if (s3 > 0) redraw = true; } + univ.party.age = current_age; for (i = 0; i < univ.party.party_event_timers.size(); i++) { - if (univ.party.party_event_timers[i].time == 1) { - if (univ.party.party_event_timers[i].global_or_town == 0) - run_special(eSpecCtx::PARTY_TIMER,0,univ.party.party_event_timers[i].node_to_call,null_loc,&s1,&s2,&s3); - else run_special(eSpecCtx::PARTY_TIMER,2,univ.party.party_event_timers[i].node_to_call,null_loc,&s1,&s2,&s3); + if (univ.party.party_event_timers[i].time <= length) { + univ.party.age = age_before + univ.party.party_event_timers[i].time; + short which_type = univ.party.party_event_timers[i].global_or_town == 0 ? 0 : 2; + if(queue) + queue_special(eSpecCtx::PARTY_TIMER, which_type, univ.party.party_event_timers[i].node_to_call, null_loc); + else run_special(eSpecCtx::PARTY_TIMER,which_type,univ.party.party_event_timers[i].node_to_call,null_loc,&s1,&s2,&s3); univ.party.party_event_timers[i].time = 0; stat_area = true; if (s3 > 0) redraw = true; - } - else univ.party.party_event_timers[i].time--; + } else univ.party.party_event_timers[i].time -= length; } + univ.party.age = current_age; if (stat_area == true) { put_pc_screen(); put_item_screen(stat_window,0); } if (redraw == true) draw_terrain(0); - } void queue_special(eSpecCtx mode, short which_type, short spec, location spec_loc) { @@ -1907,7 +1925,7 @@ void queue_special(eSpecCtx mode, short which_type, short spec, location spec_lo queued_special.where = spec_loc; queued_special.type = which_type; queued_special.mode = mode; -// queued_special.trigger_time = univ.party.age; // Don't think this is needed after all. + queued_special.trigger_time = univ.party.age; special_queue.push(queued_special); } @@ -2193,9 +2211,7 @@ void general_spec(eSpecCtx which_mode,cSpecial cur_node,short cur_spec_type, break; case eSpecType::REST: check_mess = true; - univ.party.age += spec.ex1a; - heal_party(spec.ex1b); - restore_sp_party(spec.ex1b); + do_rest(spec.ex1a, spec.ex1b, spec.ex1b); break; case eSpecType::WANDERING_WILL_FIGHT: if(which_mode != eSpecCtx::OUTDOOR_ENC) diff --git a/osx/boe.specials.h b/osx/boe.specials.h index abf63905..f2b55f6b 100644 --- a/osx/boe.specials.h +++ b/osx/boe.specials.h @@ -10,14 +10,14 @@ bool adj_town_look(location where); void PSOE(short which_special,unsigned char *stuff_done_val,short where_put); bool damage_monst(short which_m, short who_hit, short how_much, short how_much_spec, eDamageType dam_type, short sound_type); void kill_monst(cCreature *which_m,short who_killed); -void special_increase_age(); +void special_increase_age(long length = 1, bool queue = false); +void do_rest(long length, int hp_restore, int mp_restore); void out_move_party(char x,char y) ; void teleport_party(short x,short y,short mode); bool run_stone_circle(short which); void fade_party(); void change_level(short town_num,short x,short y); void push_things(); -void special_increase_age(); void set_terrain(location l, ter_num_t terrain_type); void queue_special(eSpecCtx mode, short which_type, short spec, location spec_loc); void run_special(eSpecCtx which_mode,short which_type,short start_spec,location spec_loc,short *a,short *b,short *redraw);