diff --git a/common/src/combat.rs b/common/src/combat.rs index 56f8b12dfa..82adadd44f 100644 --- a/common/src/combat.rs +++ b/common/src/combat.rs @@ -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 diff --git a/server/src/events/entity_manipulation.rs b/server/src/events/entity_manipulation.rs index 5c90d6f24e..fdf144277b 100644 --- a/server/src/events/entity_manipulation.rs +++ b/server/src/events/entity_manipulation.rs @@ -209,6 +209,7 @@ pub fn handle_destroy(server: &mut Server, entity: EcsEntity, cause: HealthSourc (|| { let mut skill_set = state.ecs().write_storage::(); let healths = state.ecs().read_storage::(); + let energies = state.ecs().read_storage::(); let inventories = state.ecs().read_storage::(); let players = state.ecs().read_storage::(); let bodies = state.ecs().read_storage::(); @@ -222,26 +223,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::(); let attacker_group = groups.get(attacker); @@ -262,6 +267,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, diff --git a/voxygen/src/hud/bag.rs b/voxygen/src/hud/bag.rs index dcab283ce1..34eacf20c4 100644 --- a/voxygen/src/hud/bag.rs +++ b/voxygen/src/hud/bag.rs @@ -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 { diff --git a/voxygen/src/hud/group.rs b/voxygen/src/hud/group.rs index 506501fe2b..2b8653ce18 100644 --- a/voxygen/src/hud/group.rs +++ b/voxygen/src/hud/group.rs @@ -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); diff --git a/voxygen/src/hud/mod.rs b/voxygen/src/hud/mod.rs index e246975721..ba65c48d9c 100644 --- a/voxygen/src/hud/mod.rs +++ b/voxygen/src/hud/mod.rs @@ -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)