Merge branch 'ygor/combat-rating-all-stats' into 'master'

Use all armor stats to calculate combat rating

Closes #1285

See merge request veloren/veloren!2770
This commit is contained in:
Samuel Keiffer 2021-08-20 21:16:05 +00:00
commit 4d62b9b937
5 changed files with 86 additions and 43 deletions

View File

@ -13,7 +13,7 @@ use crate::{
poise::PoiseChange,
skills::SkillGroupKind,
Body, CharacterState, Combo, Energy, EnergyChange, EnergySource, Health, HealthChange,
HealthSource, Inventory, Ori, Player, SkillSet, Stats,
HealthSource, Inventory, Ori, Player, Poise, SkillSet, Stats,
},
event::ServerEvent,
outcome::Outcome,
@ -852,30 +852,52 @@ fn get_weapon_rating(inventory: &Inventory, msm: &MaterialStatManifest) -> f32 {
pub fn combat_rating(
inventory: &Inventory,
health: &Health,
energy: &Energy,
skill_set: &SkillSet,
body: Body,
msm: &MaterialStatManifest,
) -> f32 {
const WEAPON_WEIGHT: f32 = 1.0;
const HEALTH_WEIGHT: f32 = 1.0;
const HEALTH_WEIGHT: f32 = 0.5;
const ENERGY_WEIGHT: f32 = 0.5;
const SKILLS_WEIGHT: f32 = 1.0;
const POISE_WEIGHT: f32 = 0.5;
const CRIT_WEIGHT: f32 = 0.6;
// Assumes a "standard" max health of 100
let health_rating = health.base_max() as f32
/ 100.0
/ (1.0 - Damage::compute_damage_reduction(Some(inventory), None, None)).max(0.00001);
let energy_rating = energy.maximum() as f32
* (1.0 + compute_max_energy_mod(energy, Some(inventory)))
* compute_energy_reward_mod(Some(inventory))
/ 200.0;
let poise_rating = 10.0 / (1.0 - Poise::compute_poise_damage_reduction(inventory)).max(0.00001);
let crit_rating = 10.0 * compute_crit_mult(Some(inventory));
// Assumes a standard person has earned 20 skill points in the general skill
// tree and 10 skill points for the weapon skill tree
let skills_rating = (skill_set.earned_sp(SkillGroupKind::General) as f32 / 20.0
+ weapon_skills(inventory, skill_set) / 10.0)
/ 2.0;
let weapon_rating = get_weapon_rating(inventory, msm);
//Multiply weapon rating by 10 to keep it in the same scale as the others
let weapon_rating = 10.0 * get_weapon_rating(inventory, msm);
let combined_rating = (health_rating * HEALTH_WEIGHT
+ energy_rating * ENERGY_WEIGHT
+ poise_rating * POISE_WEIGHT
+ crit_rating * CRIT_WEIGHT
+ skills_rating * SKILLS_WEIGHT
+ weapon_rating * WEAPON_WEIGHT)
/ (HEALTH_WEIGHT + SKILLS_WEIGHT + WEAPON_WEIGHT);
/ (HEALTH_WEIGHT
+ ENERGY_WEIGHT
+ POISE_WEIGHT
+ CRIT_WEIGHT
+ SKILLS_WEIGHT
+ WEAPON_WEIGHT);
// Body multiplier meant to account for an enemy being harder than equipment and
// skills would account for. It should only not be 1.0 for non-humanoids

View File

@ -211,6 +211,7 @@ pub fn handle_destroy(server: &mut Server, entity: EcsEntity, cause: HealthSourc
(|| {
let mut skill_set = state.ecs().write_storage::<SkillSet>();
let healths = state.ecs().read_storage::<Health>();
let energies = state.ecs().read_storage::<Energy>();
let inventories = state.ecs().read_storage::<Inventory>();
let players = state.ecs().read_storage::<Player>();
let bodies = state.ecs().read_storage::<Body>();
@ -224,26 +225,30 @@ pub fn handle_destroy(server: &mut Server, entity: EcsEntity, cause: HealthSourc
} else {
return;
};
let (entity_skill_set, entity_health, entity_inventory, entity_body) = if let (
Some(entity_skill_set),
Some(entity_health),
Some(entity_inventory),
Some(entity_body),
) = (
skill_set.get(entity),
healths.get(entity),
inventories.get(entity),
bodies.get(entity),
) {
(
entity_skill_set,
entity_health,
entity_inventory,
entity_body,
)
} else {
return;
};
let (entity_skill_set, entity_health, entity_energy, entity_inventory, entity_body) =
if let (
Some(entity_skill_set),
Some(entity_health),
Some(entity_energy),
Some(entity_inventory),
Some(entity_body),
) = (
skill_set.get(entity),
healths.get(entity),
energies.get(entity),
inventories.get(entity),
bodies.get(entity),
) {
(
entity_skill_set,
entity_health,
entity_energy,
entity_inventory,
entity_body,
)
} else {
return;
};
let groups = state.ecs().read_storage::<Group>();
let attacker_group = groups.get(attacker);
@ -264,6 +269,7 @@ pub fn handle_destroy(server: &mut Server, entity: EcsEntity, cause: HealthSourc
let mut exp_reward = combat::combat_rating(
entity_inventory,
entity_health,
entity_energy,
entity_skill_set,
*entity_body,
&msm,

View File

@ -865,9 +865,15 @@ impl<'a> Widget for Bag<'a> {
.resize(STATS.len(), &mut ui.widget_id_generator())
});
// Stats
let combat_rating =
combat_rating(inventory, self.health, self.skill_set, *self.body, self.msm)
.min(999.9);
let combat_rating = combat_rating(
inventory,
self.health,
self.energy,
self.skill_set,
*self.body,
self.msm,
)
.min(999.9);
let indicator_col = cr_color(combat_rating);
for i in STATS.iter().copied().enumerate() {
let btn = Button::image(match i.1 {

View File

@ -370,11 +370,18 @@ impl<'a> Widget for Group<'a> {
let is_leader = uid == leader;
let body = entity.and_then(|entity| bodies.get(entity));
if let (Some(stats), Some(skill_set), Some(inventory), Some(health), Some(body)) =
(stats, skill_set, inventory, health, body)
if let (
Some(stats),
Some(skill_set),
Some(inventory),
Some(health),
Some(energy),
Some(body),
) = (stats, skill_set, inventory, health, energy, body)
{
let combat_rating =
combat::combat_rating(inventory, health, skill_set, *body, self.msm);
let combat_rating = combat::combat_rating(
inventory, health, energy, skill_set, *body, self.msm,
);
let char_name = stats.name.to_string();
let health_perc =
health.current() as f64 / health.base_max().max(health.maximum()) as f64;
@ -483,15 +490,13 @@ impl<'a> Widget for Group<'a> {
.color(if is_leader { ERROR_COLOR } else { GROUP_COLOR })
.w(300.0) // limit name length display
.set(state.ids.member_panels_txt[i], ui);
if let Some(energy) = energy {
let stam_perc = energy.current() as f64 / energy.maximum() as f64;
// Energy
Image::new(self.imgs.bar_content)
.w_h(100.0 * stam_perc, 8.0)
.color(Some(STAMINA_COLOR))
.top_left_with_margins_on(state.ids.member_panels_bg[i], 26.0, 2.0)
.set(state.ids.member_energy[i], ui);
}
let stam_perc = energy.current() as f64 / energy.maximum() as f64;
// Energy
Image::new(self.imgs.bar_content)
.w_h(100.0 * stam_perc, 8.0)
.color(Some(STAMINA_COLOR))
.top_left_with_margins_on(state.ids.member_panels_bg[i], 26.0, 2.0)
.set(state.ids.member_energy[i], ui);
if let Some(buffs) = buffs {
// Limit displayed buffs to 11
let buff_count = buffs.kinds.len().min(11);

View File

@ -1761,9 +1761,13 @@ impl Hud {
health,
buffs,
energy,
combat_rating: health.map_or(0.0, |health| {
combat::combat_rating(inventory, health, skill_set, *body, &msm)
}),
combat_rating: if let (Some(health), Some(energy)) = (health, energy) {
combat::combat_rating(
inventory, health, energy, skill_set, *body, &msm,
)
} else {
0.0
},
});
let bubble = if dist_sqr < SPEECH_BUBBLE_RANGE.powi(2) {
speech_bubbles.get(uid)