diff --git a/src/game/boe.combat.cpp b/src/game/boe.combat.cpp index e619ca579..562035a82 100644 --- a/src/game/boe.combat.cpp +++ b/src/game/boe.combat.cpp @@ -45,6 +45,7 @@ extern short fast_bang; extern short store_current_pc; extern short combat_posing_monster , current_working_monster ; // 0-5 PC 100 + x - monster x extern short missile_firer,current_monst_tactic; +extern cOutdoors::cWandering store_wandering_special; eSpell spell_being_cast; bool spell_freebie; short missile_inv_slot, ammo_inv_slot; @@ -4660,7 +4661,14 @@ bool hit_end_c_button() { bool end_ok = true; if(which_combat_type == 0) { - end_ok = out_monst_all_dead(); + auto out_monst_remaining = out_monst_alive(); + if(!out_monst_remaining.empty()){ + // Print remaining monsters. + add_string_to_buf("Enemies are still alive!"); + print_encounter_monsters(store_wandering_special, nullptr, out_monst_remaining); + + end_ok = false; + } } for(cPlayer& pc : univ.party) { if(pc.status[eStatus::FORCECAGE] > 0) { @@ -4674,14 +4682,23 @@ bool hit_end_c_button() { return end_ok; } -bool out_monst_all_dead() { - for(short i = 0; i < univ.town.monst.size(); i++) - if(univ.town.monst[i].is_alive() && !univ.town.monst[i].is_friendly()) { +std::map out_monst_alive() { + std::map monst_alive; + for(short i = 0; i < univ.town.monst.size(); i++){ + cCreature& m = univ.town.monst[i]; + if(m.is_alive() && !m.is_friendly()) { + if(monst_alive.find(m.m_name) != monst_alive.end()){ + // Would += work in this context? + monst_alive[m.m_name] = monst_alive[m.m_name] + 1; + }else{ + monst_alive[m.m_name] = 1; + } + //print_nums(5555,i,univ.town.monst[i].number); //print_nums(5555,univ.town.monst[i].m_loc.x,univ.town.monst[i].m_loc.y); - return false; } - return true; + } + return monst_alive; } void end_combat() { diff --git a/src/game/boe.combat.hpp b/src/game/boe.combat.hpp index baf78e6cc..56eb23309 100644 --- a/src/game/boe.combat.hpp +++ b/src/game/boe.combat.hpp @@ -2,6 +2,7 @@ #ifndef BOE_GAME_COMBAT_H #define BOE_GAME_COMBAT_H +#include #include "location.hpp" #include "scenario/monster.hpp" #include "scenario/outdoors.hpp" @@ -49,7 +50,7 @@ void do_poison(); void handle_disease(); void handle_acid(); bool hit_end_c_button(); -bool out_monst_all_dead(); +std::map out_monst_alive(); void end_combat(); bool combat_cast_mage_spell(); bool combat_cast_priest_spell(); diff --git a/src/game/boe.text.cpp b/src/game/boe.text.cpp index 645052fa4..617ccc02e 100644 --- a/src/game/boe.text.cpp +++ b/src/game/boe.text.cpp @@ -838,25 +838,54 @@ cVehicle* out_horse_there(location where) { return &univ.party.horses[i]; return nullptr; } -void notify_out_combat_began(cOutdoors::cWandering encounter,short *nums) { - std::string msg; - - add_string_to_buf("COMBAT!"); - - for(short i = 0; i < 6; i++) + +void print_monster_count(std::string m_name, short num){ + if(num > 0){ + std::ostringstream sout; + sout << " "; + if(num > 1){ + sout << num << " x "; + } + sout << m_name; + add_string_to_buf(sout.str()); + } +} + +void print_encounter_monsters(cOutdoors::cWandering encounter, short* nums, std::map alive) { + std::string m_name; + bool remaining_specified = !alive.empty(); + // Still follow the predefined ordering when giving an updated total, and leave summons to the end. + for(short i = 0; i < 7; i++) if(encounter.monst[i] != 0) { - msg = get_m_name(encounter.monst[i]); - std::ostringstream sout; - sout << " " << nums[i] << " x " << msg; - msg = sout.str(); - add_string_to_buf(msg); + m_name = get_m_name(encounter.monst[i]); + short num = 0; + // Combat is just starting, so print the predefined amount + if(!remaining_specified){ + num = nums[i]; + } + // Combat has started, so need to check how many are still alive + else{ + auto iter = alive.find(m_name); + if(iter != alive.end()){ + num = iter->second; + alive.erase(iter); + } + } + print_monster_count(m_name, num); + } + // Monsters still in the alive map must have been summoned + if(!alive.empty()){ + for (auto iter = alive.begin(); iter != alive.end(); ++iter){ + print_monster_count(iter->first, iter->second); } - if(encounter.monst[6] != 0) { - msg = " " + get_m_name(encounter.monst[6]); - add_string_to_buf(msg); } } +void notify_out_combat_began(cOutdoors::cWandering encounter,short *nums) { + add_string_to_buf("COMBAT!"); + print_encounter_monsters(encounter, nums); +} + std::string get_m_name(mon_num_t num) { if(num >= 10000) return univ.party.summons[num - 10000].m_name; return univ.scenario.scen_monsters[num].m_name; diff --git a/src/game/boe.text.hpp b/src/game/boe.text.hpp index 2f6a5545e..03d52354f 100644 --- a/src/game/boe.text.hpp +++ b/src/game/boe.text.hpp @@ -19,6 +19,8 @@ cVehicle* town_boat_there(location where); cVehicle* out_boat_there(location where); cVehicle* town_horse_there(location where); cVehicle* out_horse_there(location where); +// Specify the alive map when combat is in progress so casualties and summons are reflected +void print_encounter_monsters(cOutdoors::cWandering encounter, short* nums, std::map alive = {}); void notify_out_combat_began(cOutdoors::cWandering encounter,short *nums) ; std::string get_m_name(mon_num_t num); std::string get_ter_name(ter_num_t num);