From 4d8862b46ca33d207d4a3b75a880b69bbcb88ea7 Mon Sep 17 00:00:00 2001 From: josteph Date: Sun, 21 Oct 2018 18:38:19 +0000 Subject: [PATCH 1/8] New helper function --- src/reports.cpp | 38 ++++++++++++++++---------------------- 1 file changed, 16 insertions(+), 22 deletions(-) diff --git a/src/reports.cpp b/src/reports.cpp index a9c0826b4ed6..c1df91757c4c 100644 --- a/src/reports.cpp +++ b/src/reports.cpp @@ -87,6 +87,20 @@ static std::string flush(std::ostringstream &s) return r; } +static const time_of_day get_visible_time_of_day_at(reports::context & rc, const map_location & hex) +{ + const team &viewing_team = rc.teams()[rc.screen().viewing_team()]; + if (viewing_team.shrouded(hex)) { + // Don't show time on shrouded tiles. + return rc.tod().get_time_of_day(); + } else if (viewing_team.fogged(hex)) { + // Don't show illuminated time on fogged tiles. + return rc.tod().get_time_of_day(hex); + } else { + return rc.tod().get_illuminated_time_of_day(rc.units(), rc.map(), hex); + } +} + typedef std::map static_report_generators; static static_report_generators static_generators; @@ -1098,17 +1112,7 @@ REPORT_GENERATOR(tod_stats, rc) static config time_of_day_at(reports::context & rc, const map_location& mouseover_hex) { std::ostringstream tooltip; - time_of_day tod; - const team &viewing_team = rc.teams()[rc.screen().viewing_team()]; - if (viewing_team.shrouded(mouseover_hex)) { - // Don't show time on shrouded tiles. - tod = rc.tod().get_time_of_day(); - } else if (viewing_team.fogged(mouseover_hex)) { - // Don't show illuminated time on fogged tiles. - tod = rc.tod().get_time_of_day(mouseover_hex); - } else { - tod = rc.tod().get_illuminated_time_of_day(rc.units(), rc.map(), mouseover_hex); - } + time_of_day tod = get_visible_time_of_day_at(rc, mouseover_hex); int b = tod.lawful_bonus; @@ -1149,18 +1153,8 @@ REPORT_GENERATOR(time_of_day, rc) static config unit_box_at(reports::context & rc, const map_location& mouseover_hex) { std::ostringstream tooltip; - time_of_day local_tod; time_of_day global_tod = rc.tod().get_time_of_day(); - const team &viewing_team = rc.teams()[rc.screen().viewing_team()]; - if (viewing_team.shrouded(mouseover_hex)) { - // Don't show time on shrouded tiles. - local_tod = global_tod; - } else if (viewing_team.fogged(mouseover_hex)) { - // Don't show illuminated time on fogged tiles. - local_tod = rc.tod().get_time_of_day(mouseover_hex); - } else { - local_tod = rc.tod().get_illuminated_time_of_day(rc.units(), rc.map(),mouseover_hex); - } + time_of_day local_tod = get_visible_time_of_day_at(rc, mouseover_hex); int bonus = local_tod.lawful_bonus; From 81b3c3f226f7704eb8e0d8a6929298f20bbe389e Mon Sep 17 00:00:00 2001 From: josteph Date: Sun, 21 Oct 2018 18:38:51 +0000 Subject: [PATCH 2/8] Add a new overload to combat_modifier --- src/actions/attack.cpp | 10 +++++++++- src/actions/attack.hpp | 9 +++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/actions/attack.cpp b/src/actions/attack.cpp index f4181993c004..a4c20aa55009 100644 --- a/src/actions/attack.cpp +++ b/src/actions/attack.cpp @@ -1735,7 +1735,15 @@ int combat_modifier(const unit_map& units, bool is_fearless) { const tod_manager& tod_m = *resources::tod_manager; - int lawful_bonus = tod_m.get_illuminated_time_of_day(units, map, loc).lawful_bonus; + const time_of_day& effective_tod = tod_m.get_illuminated_time_of_day(units, map, loc); + return combat_modifier(effective_tod, alignment, is_fearless); +} + +int combat_modifier(const time_of_day& effective_tod, + unit_type::ALIGNMENT alignment, + bool is_fearless) +{ + const int lawful_bonus = effective_tod.lawful_bonus; return generic_combat_modifier(lawful_bonus, alignment, is_fearless); } diff --git a/src/actions/attack.hpp b/src/actions/attack.hpp index 1dcc31ae81e1..83cd835b653d 100644 --- a/src/actions/attack.hpp +++ b/src/actions/attack.hpp @@ -29,6 +29,7 @@ struct map_location; class team; +struct time_of_day; class unit; class unit_map; class gamemap; @@ -294,6 +295,14 @@ int combat_modifier(const unit_map& units, unit_type::ALIGNMENT alignment, bool is_fearless); +/** + * Returns the amount that a unit's damage should be multiplied by + * due to the current time of day. + */ +int combat_modifier(const time_of_day& effective_tod, + unit_type::ALIGNMENT alignment, + bool is_fearless); + /** * Returns the amount that a unit's damage should be multiplied by * due to a given lawful_bonus. From 00f5b8822af03b31c5c4a1fa2a5cb06076217aac Mon Sep 17 00:00:00 2001 From: josteph Date: Sun, 21 Oct 2018 18:47:06 +0000 Subject: [PATCH 3/8] Expose attack_indicator_src_ --- src/game_display.hpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/game_display.hpp b/src/game_display.hpp index 136834c9db54..a2e29a55ed67 100644 --- a/src/game_display.hpp +++ b/src/game_display.hpp @@ -149,6 +149,8 @@ class game_display : public display /** Set the attack direction indicator. */ void set_attack_indicator(const map_location& src, const map_location& dst); void clear_attack_indicator(); + // TODO: compare reports::context::mhb()->current_unit_attacks_from() + const map_location& get_attack_indicator_src() { return attack_indicator_src_; } /** Function to get attack direction suffix. */ std::string attack_indicator_direction() const { From 27c9086be77ac95c74d4243c968d7d4b54280909 Mon Sep 17 00:00:00 2001 From: josteph Date: Sun, 21 Oct 2018 19:12:34 +0000 Subject: [PATCH 4/8] Show the alignment the selected unit will have at the mouseover hex, not at its current location, to match the time_of_day and tod_stats reports --- src/reports.cpp | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/reports.cpp b/src/reports.cpp index c1df91757c4c..6a3a898e1b75 100644 --- a/src/reports.cpp +++ b/src/reports.cpp @@ -341,14 +341,14 @@ REPORT_GENERATOR(selected_unit_status, rc) return unit_status(rc, u); } -static config unit_alignment(reports::context & rc, const unit* u) +static config unit_alignment(reports::context & rc, const unit* u, const map_location& hex) { if (!u) return config(); std::ostringstream str, tooltip; const std::string align = unit_type::alignment_description(u->alignment(), u->gender()); const std::string align_id = u->alignment().to_string(); - int cm = combat_modifier(rc.units(), rc.map(), rc.screen().displayed_unit_hex(), u->alignment(), - u->is_fearless()); + const time_of_day effective_tod = get_visible_time_of_day_at(rc, hex); + int cm = combat_modifier(effective_tod, u->alignment(), u->is_fearless()); color_t color = font::weapon_color; if (cm != 0) @@ -365,12 +365,18 @@ static config unit_alignment(reports::context & rc, const unit* u) REPORT_GENERATOR(unit_alignment, rc) { const unit *u = get_visible_unit(rc); - return unit_alignment(rc, u); + const map_location& mouseover_hex = rc.screen().mouseover_hex(); + const map_location& displayed_unit_hex = rc.screen().displayed_unit_hex(); + const map_location& hex = mouseover_hex.valid() ? mouseover_hex : displayed_unit_hex; + return unit_alignment(rc, u, hex); } REPORT_GENERATOR(selected_unit_alignment, rc) { const unit *u = get_selected_unit(rc); - return unit_alignment(rc, u); + const map_location& attack_indicator_src = game_display::get_singleton()->get_attack_indicator_src(); + const map_location& hex_to_show_alignment_at = + attack_indicator_src.valid() ? attack_indicator_src : u->get_location(); + return unit_alignment(rc, u, hex_to_show_alignment_at); } From a03740923f1d8207cb7aeba856590383ca5e783d Mon Sep 17 00:00:00 2001 From: josteph Date: Sun, 21 Oct 2018 19:14:01 +0000 Subject: [PATCH 5/8] Have unit_weapons use the alignment at the mouseover hex, for consistency with the alignment and tod reports --- src/reports.cpp | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/src/reports.cpp b/src/reports.cpp index 6a3a898e1b75..d495249890ff 100644 --- a/src/reports.cpp +++ b/src/reports.cpp @@ -686,7 +686,7 @@ static int attack_info(reports::context & rc, const attack_type &at, config &res int specials_damage = at.modified_damage(false); int damage_multiplier = 100; const_attack_ptr weapon = at.shared_from_this(); - int tod_bonus = combat_modifier(rc.units(), rc.map(), displayed_unit_hex, u.alignment(), u.is_fearless()); + int tod_bonus = combat_modifier(get_visible_time_of_day_at(rc, displayed_unit_hex), u.alignment(), u.is_fearless()); damage_multiplier += tod_bonus; int leader_bonus = under_leadership(rc.units(), displayed_unit_hex, weapon).first; if (leader_bonus != 0) @@ -999,12 +999,14 @@ static config unit_weapons(reports::context & rc, const unit *attacker, const ma return res; } -static config unit_weapons(reports::context & rc, const unit *u) +/* + * Display the attacks of the displayed unit against the unit passed as argument. + * 'hex' is the location the attacker will be at during combat. + */ +static config unit_weapons(reports::context & rc, const unit *u, const map_location &hex) { config res = config(); if ((u != nullptr) && (!u->attacks().empty())) { - map_location displayed_unit_hex = rc.screen().displayed_unit_hex(); - const std::string attack_headline = _n("Attack", "Attacks", u->attacks().size()); add_text(res, span_color(font::weapon_details_color) @@ -1012,7 +1014,7 @@ static config unit_weapons(reports::context & rc, const unit *u) for (const attack_type &at : u->attacks()) { - attack_info(rc, at, res, *u, displayed_unit_hex); + attack_info(rc, at, res, *u, hex); } } return res; @@ -1020,9 +1022,12 @@ static config unit_weapons(reports::context & rc, const unit *u) REPORT_GENERATOR(unit_weapons, rc) { const unit *u = get_visible_unit(rc); + const map_location& mouseover_hex = rc.screen().mouseover_hex(); + const map_location& displayed_unit_hex = rc.screen().displayed_unit_hex(); + const map_location& hex = mouseover_hex.valid() ? mouseover_hex : displayed_unit_hex; if (!u) return config(); - return unit_weapons(rc, u); + return unit_weapons(rc, u, hex); } REPORT_GENERATOR(highlighted_unit_weapons, rc) { @@ -1030,7 +1035,7 @@ REPORT_GENERATOR(highlighted_unit_weapons, rc) const unit *sec_u = get_visible_unit(rc); if (!u) return config(); - if (!sec_u || u == sec_u) return unit_weapons(rc, sec_u); + if (!sec_u || u == sec_u) return unit_weapons(rc, sec_u, rc.screen().mouseover_hex()); map_location highlighted_hex = rc.screen().displayed_unit_hex(); map_location attack_loc; @@ -1038,7 +1043,7 @@ REPORT_GENERATOR(highlighted_unit_weapons, rc) attack_loc = rc.mhb()->current_unit_attacks_from(highlighted_hex); if (!attack_loc.valid()) - return unit_weapons(rc, sec_u); + return unit_weapons(rc, sec_u, rc.screen().mouseover_hex()); return unit_weapons(rc, u, attack_loc, sec_u, false); } @@ -1048,7 +1053,7 @@ REPORT_GENERATOR(selected_unit_weapons, rc) const unit *sec_u = get_visible_unit(rc); if (!u) return config(); - if (!sec_u || u == sec_u) return unit_weapons(rc, u); + if (!sec_u || u == sec_u) return unit_weapons(rc, u, u->get_location()); map_location highlighted_hex = rc.screen().displayed_unit_hex(); map_location attack_loc; @@ -1056,7 +1061,7 @@ REPORT_GENERATOR(selected_unit_weapons, rc) attack_loc = rc.mhb()->current_unit_attacks_from(highlighted_hex); if (!attack_loc.valid()) - return unit_weapons(rc, u); + return unit_weapons(rc, u, u->get_location()); return unit_weapons(rc, u, attack_loc, sec_u, true); } From 55e3fa36605824e64be4a09e4e4f1bac38bc909f Mon Sep 17 00:00:00 2001 From: josteph Date: Sun, 21 Oct 2018 20:37:32 +0000 Subject: [PATCH 6/8] Simplify under_leadership(). It now takes a unit pointer directly instead of searching for it by location, even though callers already had the unit pointer. This also improves the sidebar weapons report. Now, if the mouseover hex is adjacent both to an allied leader and to an enemy, the sidebar will reflect the leadership bonus. --- src/actions/attack.cpp | 14 ++++++-------- src/actions/attack.hpp | 5 ++--- src/gui/dialogs/attack_predictions.cpp | 2 +- src/reports.cpp | 2 +- 4 files changed, 10 insertions(+), 13 deletions(-) diff --git a/src/actions/attack.cpp b/src/actions/attack.cpp index a4c20aa55009..be602617e87d 100644 --- a/src/actions/attack.cpp +++ b/src/actions/attack.cpp @@ -197,7 +197,7 @@ battle_context_unit_stats::battle_context_unit_stats(const unit& u, resources::gameboard->units(), resources::gameboard->map(), u_loc, u.alignment(), u.is_fearless()); // Leadership bonus. - int leader_bonus = under_leadership(units, u_loc, weapon, opp_weapon).first; + int leader_bonus = under_leadership(u, u_loc, weapon, opp_weapon); if(leader_bonus != 0) { damage_multiplier += leader_bonus; } @@ -1564,15 +1564,13 @@ void attack_unit_and_advance(const map_location& attacker, } } -std::pair under_leadership(const unit_map& units, const map_location& loc, const_attack_ptr weapon, const_attack_ptr opp_weapon) +int under_leadership(const unit &u, const map_location& loc, const_attack_ptr weapon, const_attack_ptr opp_weapon) { - const unit_map::const_iterator un = units.find(loc); - if(un == units.end()) { - return {0, map_location::null_location()}; - } + unit_ptr new_unit = u.clone(); + new_unit->set_location(loc); - unit_ability_list abil = un->get_abilities("leadership", weapon, opp_weapon); - return abil.highest("value"); + unit_ability_list abil = new_unit->get_abilities("leadership", weapon, opp_weapon); + return abil.highest("value").first; } //begin of weapon emulates function. diff --git a/src/actions/attack.hpp b/src/actions/attack.hpp index 83cd835b653d..cfd67df82e8b 100644 --- a/src/actions/attack.hpp +++ b/src/actions/attack.hpp @@ -276,10 +276,9 @@ void attack_unit_and_advance(const map_location& attacker, * Tests if the unit at loc is currently affected by leadership. * (i.e. has a higher-level unit with the 'leadership' ability next to it). * - * Returns a pair of bonus percentage and the leader's location if the unit is affected, - * or 0 and map_location::null_location() otherwise. + * Returns the bonus percentage (possibly 0 if there's no leader adjacent). */ -std::pair under_leadership(const unit_map& units, const map_location& loc, const_attack_ptr weapon, const_attack_ptr opp_weapon = nullptr); +int under_leadership(const unit &u, const map_location& loc, const_attack_ptr weapon, const_attack_ptr opp_weapon = nullptr); bool leadership_affects_self(const std::string& ability,const unit_map& units, const map_location& loc, const_attack_ptr weapon=nullptr,const_attack_ptr opp_weapon=nullptr); bool leadership_affects_opponent(const std::string& ability,const unit_map& units, const map_location& loc, const_attack_ptr weapon=nullptr,const_attack_ptr opp_weapon=nullptr); std::pair ability_leadership(const std::string& ability, const unit_map& units, const map_location& loc, const map_location& opp_loc, bool attacker=true, int abil_value=0, bool backstab_pos=false, const_attack_ptr weapon=nullptr, const_attack_ptr opp_weapon=nullptr); diff --git a/src/gui/dialogs/attack_predictions.cpp b/src/gui/dialogs/attack_predictions.cpp index bd3dc31af25e..26136ddff393 100644 --- a/src/gui/dialogs/attack_predictions.cpp +++ b/src/gui/dialogs/attack_predictions.cpp @@ -222,7 +222,7 @@ void attack_predictions::set_data(window& window, const combatant_data& attacker } // Leadership bonus. - const int leadership_bonus = under_leadership(resources::gameboard->units(), attacker.unit_.get_location(), weapon, opp_weapon).first; + const int leadership_bonus = under_leadership(attacker.unit_, attacker.unit_.get_location(), weapon, opp_weapon); if(leadership_bonus != 0) { set_label_helper("leadership_modifier", utils::signed_percent(leadership_bonus)); diff --git a/src/reports.cpp b/src/reports.cpp index d495249890ff..95e019161ca1 100644 --- a/src/reports.cpp +++ b/src/reports.cpp @@ -688,7 +688,7 @@ static int attack_info(reports::context & rc, const attack_type &at, config &res const_attack_ptr weapon = at.shared_from_this(); int tod_bonus = combat_modifier(get_visible_time_of_day_at(rc, displayed_unit_hex), u.alignment(), u.is_fearless()); damage_multiplier += tod_bonus; - int leader_bonus = under_leadership(rc.units(), displayed_unit_hex, weapon).first; + int leader_bonus = under_leadership(u, displayed_unit_hex, weapon); if (leader_bonus != 0) damage_multiplier += leader_bonus; From 839c9f37c7ef4aec77c015d19246f9cbf271ca7f Mon Sep 17 00:00:00 2001 From: josteph Date: Sun, 21 Oct 2018 20:49:50 +0000 Subject: [PATCH 7/8] Rename formal parameter --- src/reports.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/reports.cpp b/src/reports.cpp index 95e019161ca1..004877f2f2d6 100644 --- a/src/reports.cpp +++ b/src/reports.cpp @@ -675,20 +675,20 @@ static inline const color_t attack_info_percent_color(int resistance) return font::YELLOW_COLOR; } -static int attack_info(reports::context & rc, const attack_type &at, config &res, const unit &u, const map_location &displayed_unit_hex) +static int attack_info(reports::context & rc, const attack_type &at, config &res, const unit &u, const map_location &hex) { std::ostringstream str, tooltip; int damage = 0; { - auto ctx = at.specials_context(unit_const_ptr(&u), displayed_unit_hex, u.side() == rc.screen().playing_side()); + auto ctx = at.specials_context(unit_const_ptr(&u), hex, u.side() == rc.screen().playing_side()); int base_damage = at.damage(); int specials_damage = at.modified_damage(false); int damage_multiplier = 100; const_attack_ptr weapon = at.shared_from_this(); - int tod_bonus = combat_modifier(get_visible_time_of_day_at(rc, displayed_unit_hex), u.alignment(), u.is_fearless()); + int tod_bonus = combat_modifier(get_visible_time_of_day_at(rc, hex), u.alignment(), u.is_fearless()); damage_multiplier += tod_bonus; - int leader_bonus = under_leadership(u, displayed_unit_hex, weapon); + int leader_bonus = under_leadership(u, hex, weapon); if (leader_bonus != 0) damage_multiplier += leader_bonus; From d59dd8fb5ca600c58d6fc99647d8ae463af12b4a Mon Sep 17 00:00:00 2001 From: josteph Date: Tue, 23 Oct 2018 22:20:07 +0000 Subject: [PATCH 8/8] Simplify under_leadership() further. Avoid an expensive clone(). --- src/actions/attack.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/actions/attack.cpp b/src/actions/attack.cpp index be602617e87d..9ccb55f0aaca 100644 --- a/src/actions/attack.cpp +++ b/src/actions/attack.cpp @@ -1566,10 +1566,7 @@ void attack_unit_and_advance(const map_location& attacker, int under_leadership(const unit &u, const map_location& loc, const_attack_ptr weapon, const_attack_ptr opp_weapon) { - unit_ptr new_unit = u.clone(); - new_unit->set_location(loc); - - unit_ability_list abil = new_unit->get_abilities("leadership", weapon, opp_weapon); + unit_ability_list abil = u.get_abilities("leadership", loc, weapon, opp_weapon); return abil.highest("value").first; }