change liminal implementation, from a night and day malus to a twilight bonus

This commit is contained in:
fsd 2018-03-16 09:44:49 +01:00
parent bba1dc264b
commit 40483874ea
5 changed files with 66 additions and 11 deletions

View file

@ -317,7 +317,7 @@ battle_context_unit_stats::battle_context_unit_stats(const unit_type* u_type,
int base_damage = weapon->modified_damage(backstab_pos);
int damage_multiplier = 100;
damage_multiplier
+= generic_combat_modifier(lawful_bonus, u_type->alignment(), u_type->musthave_status("fearless"));
+= generic_combat_modifier(lawful_bonus, u_type->alignment(), u_type->musthave_status("fearless"), 0);
damage_multiplier *= opp_type->resistance_against(weapon->type(), !attacking);
damage = round_damage(base_damage, damage_multiplier, 10000);
@ -1608,10 +1608,10 @@ int combat_modifier(const unit_map& units,
{
const tod_manager& tod_m = *resources::tod_manager;
int lawful_bonus = tod_m.get_illuminated_time_of_day(units, map, loc).lawful_bonus;
return generic_combat_modifier(lawful_bonus, alignment, is_fearless);
return generic_combat_modifier(lawful_bonus, alignment, is_fearless, tod_m.get_max_liminal_bonus());
}
int generic_combat_modifier(int lawful_bonus, unit_type::ALIGNMENT alignment, bool is_fearless)
int generic_combat_modifier(int lawful_bonus, unit_type::ALIGNMENT alignment, bool is_fearless, int max_liminal_bonus)
{
int bonus;
@ -1626,7 +1626,7 @@ int generic_combat_modifier(int lawful_bonus, unit_type::ALIGNMENT alignment, bo
bonus = -lawful_bonus;
break;
case unit_type::ALIGNMENT::LIMINAL:
bonus = -std::abs(lawful_bonus);
bonus = std::max(0, max_liminal_bonus-std::abs(lawful_bonus));
break;
default:
bonus = 0;

View file

@ -282,7 +282,7 @@ int combat_modifier(const unit_map& units,
* Returns the amount that a unit's damage should be multiplied by
* due to a given lawful_bonus.
*/
int generic_combat_modifier(int lawful_bonus, unit_type::ALIGNMENT alignment, bool is_fearless);
int generic_combat_modifier(int lawful_bonus, unit_type::ALIGNMENT alignment, bool is_fearless, int max_liminal_bonus);
/**
* Function to check if an attack will satisfy the requirements for backstab.
* Input:

View file

@ -1106,7 +1106,7 @@ static config time_of_day_at(reports::context & rc, const map_location& mouseove
}
int b = tod.lawful_bonus;
int l = generic_combat_modifier(b, unit_type::ALIGNMENT::LIMINAL, false, rc.tod().get_max_liminal_bonus());
std::string lawful_color("white");
std::string chaotic_color("white");
std::string liminal_color("white");
@ -1114,7 +1114,9 @@ static config time_of_day_at(reports::context & rc, const map_location& mouseove
if (b != 0) {
lawful_color = (b > 0) ? "green" : "red";
chaotic_color = (b < 0) ? "green" : "red";
liminal_color = "red";
}
if (l != 0) {
liminal_color = (l > 0) ? "green" : "red";
}
tooltip << tod.name << '\n'
<< _("Lawful units: ") << "<span foreground=\"" << lawful_color << "\">"
@ -1123,7 +1125,7 @@ static config time_of_day_at(reports::context & rc, const map_location& mouseove
<< _("Chaotic units: ") << "<span foreground=\"" << chaotic_color << "\">"
<< utils::signed_percent(-b) << "</span>\n"
<< _("Liminal units: ") << "<span foreground=\"" << liminal_color << "\">"
<< utils::signed_percent(-(std::abs(b))) << "</span>\n";
<< utils::signed_percent(l) << "</span>\n";
std::string tod_image = tod.image;
if(tod.bonus_modified > 0) {
@ -1158,6 +1160,7 @@ static config unit_box_at(reports::context & rc, const map_location& mouseover_h
}
int bonus = local_tod.lawful_bonus;
int l = generic_combat_modifier(bonus, unit_type::ALIGNMENT::LIMINAL, false, rc.tod().get_max_liminal_bonus());
std::string lawful_color("white");
std::string chaotic_color("white");
@ -1166,7 +1169,9 @@ static config unit_box_at(reports::context & rc, const map_location& mouseover_h
if (bonus != 0) {
lawful_color = (bonus > 0) ? "green" : "red";
chaotic_color = (bonus < 0) ? "green" : "red";
liminal_color = "red";
}
if (l != 0) {
liminal_color = (l > 0) ? "green" : "red";
}
tooltip << local_tod.name << '\n'
<< _("Lawful units: ") << "<span foreground=\"" << lawful_color << "\">"
@ -1175,7 +1180,7 @@ static config unit_box_at(reports::context & rc, const map_location& mouseover_h
<< _("Chaotic units: ") << "<span foreground=\"" << chaotic_color << "\">"
<< utils::signed_percent(-bonus) << "</span>\n"
<< _("Liminal units: ") << "<span foreground=\"" << liminal_color << "\">"
<< utils::signed_percent(-(std::abs(bonus))) << "</span>\n";
<< utils::signed_percent(l) << "</span>\n";
std::string local_tod_image = "themes/classic/" + local_tod.image;
std::string global_tod_image = "themes/classic/" + global_tod.image;

View file

@ -29,6 +29,7 @@
#include <algorithm>
#include <iterator>
#include "utils/functional.hpp"
#include "actions/attack.hpp"
static lg::log_domain log_engine("engine");
#define LOG_NG LOG_STREAM(info, log_engine)
@ -37,10 +38,12 @@ tod_manager::tod_manager(const config& scenario_cfg):
currentTime_(0),
times_(),
areas_(),
liminal_bonus_(25),
turn_(scenario_cfg["turn_at"].to_int(1)),
num_turns_(scenario_cfg["turns"].to_int(-1)),
has_turn_event_fired_(!scenario_cfg["it_is_a_new_turn"].to_bool(true)),
has_tod_bonus_changed_ (false)
has_tod_bonus_changed_ (false),
has_cfg_liminal_bonus_ (false)
{
// ? : operator doesn't work in this case.
if (scenario_cfg["current_time"].to_int(-17403) == -17403)
@ -49,6 +52,13 @@ tod_manager::tod_manager(const config& scenario_cfg):
random_tod_ = false;
time_of_day::parse_times(scenario_cfg,times_);
int maybe_liminal_bonus = scenario_cfg["liminal_bonus"].to_int(-1);
if (maybe_liminal_bonus < 0)
liminal_bonus_ = calculate_best_liminal_bonus(times_);
else {
liminal_bonus_ = maybe_liminal_bonus;
has_cfg_liminal_bonus_ = true;
}
//We need to call parse_times before calculate_current_time because otherwise the first parameter will always be 0.
currentTime_ = calculate_current_time(times_.size(), turn_, scenario_cfg["current_time"].to_int(0), true);
@ -63,12 +73,14 @@ tod_manager& tod_manager::operator=(const tod_manager& manager)
currentTime_ = manager.currentTime_;
times_ = manager.times_;
areas_ = manager.areas_;
liminal_bonus_ = manager.liminal_bonus_;
turn_ = manager.turn_;
num_turns_ = manager.num_turns_;
has_turn_event_fired_ = manager.has_turn_event_fired_;
has_tod_bonus_changed_= manager.has_tod_bonus_changed_;
has_cfg_liminal_bonus_ = manager.has_cfg_liminal_bonus_;
random_tod_ = manager.random_tod_;
@ -124,6 +136,8 @@ config tod_manager::to_config() const
cfg["current_time"] = currentTime_;
cfg["random_start_time"] = random_tod_;
cfg["it_is_a_new_turn"] = !has_turn_event_fired_;
if (has_cfg_liminal_bonus_)
cfg["liminal_bonus"] = liminal_bonus_;
for(const time_of_day& tod : times_) {
// Don't write the stub default ToD if it happens to be present.
@ -536,3 +550,29 @@ bool tod_manager::is_time_left() const
{
return num_turns_ == -1 || turn_ <= num_turns_;
}
int tod_manager::calculate_best_liminal_bonus(const std::vector<time_of_day>& schedule) const
{
int fearless_chaotic = 0;
int fearless_lawful = 0;
std::set<int> bonuses;
for (const auto& tod : schedule) {
fearless_chaotic += generic_combat_modifier(tod.lawful_bonus, unit_type::ALIGNMENT::CHAOTIC, true, 0);
fearless_lawful += generic_combat_modifier(tod.lawful_bonus, unit_type::ALIGNMENT::LAWFUL, true, 0);
bonuses.insert(std::abs(tod.lawful_bonus));
}
int target = std::max(fearless_chaotic, fearless_lawful);
int delta = target;
int result = 0;
for (int bonus : bonuses) {
int liminal_effect = 0;
for (const auto& tod : schedule) {
liminal_effect += generic_combat_modifier(tod.lawful_bonus, unit_type::ALIGNMENT::LIMINAL, false, bonus);
}
if (std::abs(target - liminal_effect) < delta) {
result = bonus;
delta = std::abs(target - liminal_effect);
}
}
return result;
}

View file

@ -178,6 +178,8 @@ class tod_manager
{ has_turn_event_fired_ = true; }
bool has_tod_bonus_changed() const
{ return has_tod_bonus_changed_; }
int get_max_liminal_bonus() const
{ return liminal_bonus_; }
private:
/**
@ -198,6 +200,10 @@ class tod_manager
const int for_turn_number,
const int current_time,
const bool only_to_allowed_range = false) const;
/**
* Computes the maximum absolute value of lawful_bonus in the schedule.
*/
int calculate_best_liminal_bonus(const std::vector<time_of_day>& schedule) const;
/**
* For a change of the current turn number, sets the current times of the main time
@ -230,6 +236,9 @@ class tod_manager
std::vector<time_of_day> times_;
std::vector<area_time_of_day> areas_;
//max liminal bonus
int liminal_bonus_;
// current turn
int turn_;
//turn limit
@ -237,6 +246,7 @@ class tod_manager
//Whether the "turn X" and the "new turn" events were already fired this turn.
bool has_turn_event_fired_;
bool has_tod_bonus_changed_;
bool has_cfg_liminal_bonus_;
//
config::attribute_value random_tod_;
};