Merge branch 'sam/purge-body-from-stats' into 'master'

Removed body from stats component as there is already a body component.

Closes #931

See merge request veloren/veloren!1714
This commit is contained in:
Samuel Keiffer 2021-01-22 23:08:07 +00:00
commit d58a72e91b
13 changed files with 128 additions and 122 deletions

View File

@ -9,7 +9,7 @@ use crate::{
slot::EquipSlot,
},
skills::{SkillGroupKind, SkillSet},
BuffKind, Health, HealthChange, HealthSource, Inventory, Stats,
Body, BuffKind, Health, HealthChange, HealthSource, Inventory, Stats,
},
uid::Uid,
util::Dir,
@ -245,7 +245,7 @@ fn offensive_rating(inv: &Inventory, skillset: &SkillSet) -> f32 {
active_damage.max(second_damage)
}
pub fn combat_rating(inventory: &Inventory, health: &Health, stats: &Stats) -> f32 {
pub fn combat_rating(inventory: &Inventory, health: &Health, stats: &Stats, body: Body) -> f32 {
let defensive_weighting = 1.0;
let offensive_weighting = 1.0;
let defensive_rating = health.maximum() as f32
@ -256,5 +256,5 @@ pub fn combat_rating(inventory: &Inventory, health: &Health, stats: &Stats) -> f
let combined_rating = (offensive_rating * offensive_weighting
+ defensive_rating * defensive_weighting)
/ (offensive_weighting + defensive_weighting);
combined_rating * stats.body_type.combat_multiplier()
combined_rating * body.combat_multiplier()
}

View File

@ -1,7 +1,4 @@
use crate::{
comp,
comp::{skills::SkillSet, Body},
};
use crate::comp::skills::SkillSet;
use serde::{Deserialize, Serialize};
use specs::{Component, DerefFlaggedStorage};
use specs_idvs::IdvStorage;
@ -27,15 +24,13 @@ impl Error for StatChangeError {}
pub struct Stats {
pub name: String,
pub skill_set: SkillSet,
pub body_type: Body,
}
impl Stats {
pub fn new(name: String, body: Body) -> Self {
pub fn new(name: String) -> Self {
Self {
name,
skill_set: SkillSet::default(),
body_type: body,
}
}
@ -45,7 +40,6 @@ impl Stats {
Self {
name: "".to_owned(),
skill_set: SkillSet::default(),
body_type: comp::Body::Humanoid(comp::body::humanoid::Body::random()),
}
}
}

View File

@ -1,7 +1,7 @@
use common::{
comp::{
skills::{GeneralSkill, Skill},
CharacterState, Energy, EnergyChange, EnergySource, Health, Pos, Stats,
Body, CharacterState, Energy, EnergyChange, EnergySource, Health, Pos, Stats,
},
event::{EventBus, ServerEvent},
metrics::SysMetrics,
@ -31,6 +31,7 @@ impl<'a> System<'a> for Sys {
ReadStorage<'a, Uid>,
ReadStorage<'a, Pos>,
Write<'a, Vec<Outcome>>,
ReadStorage<'a, Body>,
);
fn run(
@ -47,6 +48,7 @@ impl<'a> System<'a> for Sys {
uids,
positions,
mut outcomes,
bodies,
): Self::SystemData,
) {
let start_time = std::time::Instant::now();
@ -111,10 +113,11 @@ impl<'a> System<'a> for Sys {
}
// Apply effects from leveling skills
for (mut stats, mut health, mut energy) in (
for (mut stats, mut health, mut energy, body) in (
&mut stats.restrict_mut(),
&mut healths.restrict_mut(),
&mut energies.restrict_mut(),
&bodies,
)
.join()
{
@ -126,7 +129,7 @@ impl<'a> System<'a> for Sys {
.skill_level(Skill::General(GeneralSkill::HealthIncrease))
.unwrap_or(None)
.unwrap_or(0);
health.update_max_hp(Some(stat.body_type), health_level);
health.update_max_hp(Some(*body), health_level);
let mut stat = stats.get_mut_unchecked();
stat.skill_set.modify_health = false;
}
@ -138,7 +141,7 @@ impl<'a> System<'a> for Sys {
.skill_level(Skill::General(GeneralSkill::EnergyIncrease))
.unwrap_or(None)
.unwrap_or(0);
energy.update_max_energy(Some(stat.body_type), energy_level);
energy.update_max_energy(Some(*body), energy_level);
let mut stat = stats.get_mut_unchecked();
stat.skill_set.modify_energy = false;
}

View File

@ -10,7 +10,7 @@ pub fn create_character(
body: Body,
character_loader: &ReadExpect<'_, CharacterLoader>,
) {
let stats = Stats::new(character_alias.to_string(), body);
let stats = Stats::new(character_alias.to_string());
let loadout = LoadoutBuilder::new()
.defaults()

View File

@ -820,10 +820,10 @@ fn handle_spawn(
.state
.create_npc(
pos,
comp::Stats::new(
get_npc_name(id, npc::BodyType::from_body(body)),
body,
),
comp::Stats::new(get_npc_name(
id,
npc::BodyType::from_body(body),
)),
comp::Health::new(body, 1),
inventory,
body,
@ -929,7 +929,7 @@ fn handle_spawn_training_dummy(
let body = comp::Body::Object(comp::object::Body::TrainingDummy);
let stats = comp::Stats::new("Training Dummy".to_string(), body);
let stats = comp::Stats::new("Training Dummy".to_string());
let health = comp::Health::new(body, 0);

View File

@ -164,6 +164,7 @@ pub fn handle_destroy(server: &mut Server, entity: EcsEntity, cause: HealthSourc
let healths = state.ecs().read_storage::<Health>();
let inventories = state.ecs().read_storage::<Inventory>();
let players = state.ecs().read_storage::<Player>();
let bodies = state.ecs().read_storage::<Body>();
let by = if let HealthSource::Damage { by: Some(by), .. } = cause {
by
} else {
@ -174,16 +175,21 @@ pub fn handle_destroy(server: &mut Server, entity: EcsEntity, cause: HealthSourc
} else {
return;
};
let (entity_stats, entity_health, entity_inventory) =
if let (Some(entity_stats), Some(entity_health), Some(entity_inventory)) = (
stats.get(entity),
healths.get(entity),
inventories.get(entity),
) {
(entity_stats, entity_health, entity_inventory)
} else {
return;
};
let (entity_stats, entity_health, entity_inventory, entity_body) = if let (
Some(entity_stats),
Some(entity_health),
Some(entity_inventory),
Some(entity_body),
) = (
stats.get(entity),
healths.get(entity),
inventories.get(entity),
bodies.get(entity),
) {
(entity_stats, entity_health, entity_inventory, entity_body)
} else {
return;
};
let groups = state.ecs().read_storage::<Group>();
let attacker_group = groups.get(attacker);
@ -201,7 +207,8 @@ pub fn handle_destroy(server: &mut Server, entity: EcsEntity, cause: HealthSourc
// TODO: Scale xp from skillset rather than health, when NPCs have their own
// skillsets
let mut exp_reward =
combat::combat_rating(entity_inventory, entity_health, entity_stats) * 2.5;
combat::combat_rating(entity_inventory, entity_health, entity_stats, *entity_body)
* 2.5;
// Distribute EXP to group
let positions = state.ecs().read_storage::<Pos>();

View File

@ -562,10 +562,7 @@ pub fn handle_inventory(server: &mut Server, entity: EcsEntity, manip: comp::Inv
});
},
item::Throwable::TrainingDummy => {
new_entity = new_entity.with(comp::Stats::new(
"Training Dummy".to_string(),
comp::object::Body::TrainingDummy.into(),
));
new_entity = new_entity.with(comp::Stats::new("Training Dummy".to_string()));
},
};

View File

@ -97,7 +97,7 @@ impl<'a> System<'a> for Sys {
let body = entity.get_body();
server_emitter.emit(ServerEvent::CreateNpc {
pos: comp::Pos(spawn_pos),
stats: comp::Stats::new(entity.get_name(), body),
stats: comp::Stats::new(entity.get_name()),
health: comp::Health::new(body, 10),
loadout: match body {
comp::Body::Humanoid(_) => entity.get_loadout(),

View File

@ -290,8 +290,8 @@ impl StateExt for State {
.unwrap_or(None)
.unwrap_or(0),
);
self.write_component(entity, comp::Health::new(stats.body_type, health_level));
self.write_component(entity, comp::Energy::new(stats.body_type, energy_level));
self.write_component(entity, comp::Health::new(body, health_level));
self.write_component(entity, comp::Energy::new(body, energy_level));
self.write_component(entity, stats);
self.write_component(entity, inventory);
self.write_component(

View File

@ -124,7 +124,7 @@ impl<'a> System<'a> for Sys {
let name = entity.name.unwrap_or_else(|| "Unnamed".to_string());
let alignment = entity.alignment;
let main_tool = entity.main_tool;
let mut stats = comp::Stats::new(name, body);
let mut stats = comp::Stats::new(name);
let mut scale = entity.scale;
@ -135,13 +135,10 @@ impl<'a> System<'a> for Sys {
let npc_names = NPC_NAMES.read();
body = comp::Body::Humanoid(body_new);
stats = comp::Stats::new(
format!(
"Gentle Giant {}",
get_npc_name(&npc_names.humanoid, body_new.species)
),
body,
);
stats = comp::Stats::new(format!(
"Gentle Giant {}",
get_npc_name(&npc_names.humanoid, body_new.species)
));
}
scale = 2.0 + rand::random::<f32>();
}
@ -154,7 +151,7 @@ impl<'a> System<'a> for Sys {
let loadout =
LoadoutBuilder::build_loadout(body, main_tool, loadout_config).build();
let health = comp::Health::new(stats.body_type, entity.level.unwrap_or(0));
let health = comp::Health::new(body, entity.level.unwrap_or(0));
let can_speak = match body {
comp::Body::Humanoid(_) => alignment == comp::Alignment::Npc,

View File

@ -18,7 +18,7 @@ use crate::{
use client::Client;
use common::{
combat::{combat_rating, Damage},
comp::{item::Quality, Energy, Health, Stats},
comp::{item::Quality, Body, Energy, Health, Stats},
};
use conrod_core::{
color,
@ -100,6 +100,7 @@ pub struct Bag<'a> {
health: &'a Health,
energy: &'a Energy,
show: &'a Show,
body: &'a Body,
}
impl<'a> Bag<'a> {
@ -118,6 +119,7 @@ impl<'a> Bag<'a> {
health: &'a Health,
energy: &'a Energy,
show: &'a Show,
body: &'a Body,
) -> Self {
Self {
client,
@ -134,6 +136,7 @@ impl<'a> Bag<'a> {
energy,
health,
show,
body,
}
}
}
@ -428,7 +431,8 @@ impl<'a> Widget for Bag<'a> {
.resize(STATS.len(), &mut ui.widget_id_generator())
});
// Stats
let combat_rating = combat_rating(inventory, self.health, self.stats).min(999.9);
let combat_rating =
combat_rating(inventory, self.health, self.stats, *self.body).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

@ -340,6 +340,7 @@ impl<'a> Widget for Group<'a> {
let buffs = client_state.ecs().read_storage::<common::comp::Buffs>();
let inventory = client_state.ecs().read_storage::<common::comp::Inventory>();
let uid_allocator = client_state.ecs().read_resource::<UidAllocator>();
let bodies = client_state.ecs().read_storage::<common::comp::Body>();
// Keep track of the total number of widget ids we are using for buffs
let mut total_buff_count = 0;
@ -352,80 +353,80 @@ impl<'a> Widget for Group<'a> {
let buffs = entity.and_then(|entity| buffs.get(entity));
let inventory = entity.and_then(|entity| inventory.get(entity));
let is_leader = uid == leader;
let body = entity.and_then(|entity| bodies.get(entity));
if let Some(stats) = stats {
let combat_rating =
combat::combat_rating(inventory.unwrap(), &health.unwrap(), stats); // We can unwrap here because we check for stats first
if let (Some(stats), Some(inventory), Some(health), Some(body)) =
(stats, inventory, health, body)
{
let combat_rating = combat::combat_rating(inventory, health, stats, *body);
let char_name = stats.name.to_string();
if let Some(health) = health {
let health_perc = health.current() as f64 / health.maximum() as f64;
// change panel positions when debug info is shown
let x = if debug_on { i / 8 } else { i / 12 };
let y = if debug_on { i % 8 } else { i % 12 };
let back = Image::new(self.imgs.member_bg).top_left_with_margins_on(
ui.window,
50.0 + offset + y as f64 * 77.0,
10.0 + x as f64 * 180.0,
);
let hp_ani = (self.pulse * 4.0/* speed factor */).cos() * 0.5 + 0.8; //Animation timer
let crit_hp_color: Color = Color::Rgba(0.79, 0.19, 0.17, hp_ani);
let health_col = match (health_perc * 100.0) as u8 {
0..=20 => crit_hp_color,
21..=40 => LOW_HP_COLOR,
_ => HP_COLOR,
};
// Don't show panel for the player!
// Panel BG
back.w_h(152.0, 36.0)
.color(if is_leader {
Some(ERROR_COLOR)
} else {
Some(TEXT_COLOR)
})
.set(state.ids.member_panels_bg[i], ui);
// Health
Image::new(self.imgs.bar_content)
.w_h(148.0 * health_perc, 22.0)
.color(Some(health_col))
.top_left_with_margins_on(state.ids.member_panels_bg[i], 2.0, 2.0)
.set(state.ids.member_health[i], ui);
if health.is_dead {
// Death Text
Text::new(&self.localized_strings.get("hud.group.dead"))
.mid_top_with_margin_on(state.ids.member_panels_bg[i], 1.0)
.font_size(20)
.font_id(self.fonts.cyri.conrod_id)
.color(KILL_COLOR)
.set(state.ids.dead_txt[i], ui);
let health_perc = health.current() as f64 / health.maximum() as f64;
// change panel positions when debug info is shown
let x = if debug_on { i / 8 } else { i / 12 };
let y = if debug_on { i % 8 } else { i % 12 };
let back = Image::new(self.imgs.member_bg).top_left_with_margins_on(
ui.window,
50.0 + offset + y as f64 * 77.0,
10.0 + x as f64 * 180.0,
);
let hp_ani = (self.pulse * 4.0/* speed factor */).cos() * 0.5 + 0.8; //Animation timer
let crit_hp_color: Color = Color::Rgba(0.79, 0.19, 0.17, hp_ani);
let health_col = match (health_perc * 100.0) as u8 {
0..=20 => crit_hp_color,
21..=40 => LOW_HP_COLOR,
_ => HP_COLOR,
};
// Don't show panel for the player!
// Panel BG
back.w_h(152.0, 36.0)
.color(if is_leader {
Some(ERROR_COLOR)
} else {
// Health Text
let txt = format!(
"{}/{}",
health.current() / 10_u32,
health.maximum() / 10_u32,
);
// Change font size depending on health amount
let font_size = match health.maximum() {
0..=999 => 14,
1000..=9999 => 13,
10000..=99999 => 12,
_ => 11,
};
// Change text offset depending on health amount
let txt_offset = match health.maximum() {
0..=999 => 4.0,
1000..=9999 => 4.5,
10000..=99999 => 5.0,
_ => 5.5,
};
Text::new(&txt)
.mid_top_with_margin_on(state.ids.member_panels_bg[i], txt_offset)
.font_size(font_size)
.font_id(self.fonts.cyri.conrod_id)
.color(Color::Rgba(1.0, 1.0, 1.0, 0.5))
.set(state.ids.health_txt[i], ui);
Some(TEXT_COLOR)
})
.set(state.ids.member_panels_bg[i], ui);
// Health
Image::new(self.imgs.bar_content)
.w_h(148.0 * health_perc, 22.0)
.color(Some(health_col))
.top_left_with_margins_on(state.ids.member_panels_bg[i], 2.0, 2.0)
.set(state.ids.member_health[i], ui);
if health.is_dead {
// Death Text
Text::new(&self.localized_strings.get("hud.group.dead"))
.mid_top_with_margin_on(state.ids.member_panels_bg[i], 1.0)
.font_size(20)
.font_id(self.fonts.cyri.conrod_id)
.color(KILL_COLOR)
.set(state.ids.dead_txt[i], ui);
} else {
// Health Text
let txt = format!(
"{}/{}",
health.current() / 10_u32,
health.maximum() / 10_u32,
);
// Change font size depending on health amount
let font_size = match health.maximum() {
0..=999 => 14,
1000..=9999 => 13,
10000..=99999 => 12,
_ => 11,
};
}
// Change text offset depending on health amount
let txt_offset = match health.maximum() {
0..=999 => 4.0,
1000..=9999 => 4.5,
10000..=99999 => 5.0,
_ => 5.5,
};
Text::new(&txt)
.mid_top_with_margin_on(state.ids.member_panels_bg[i], txt_offset)
.font_size(font_size)
.font_id(self.fonts.cyri.conrod_id)
.color(Color::Rgba(1.0, 1.0, 1.0, 0.5))
.set(state.ids.health_txt[i], ui);
};
// Panel Frame
Image::new(self.imgs.member_frame)

View File

@ -1341,7 +1341,7 @@ impl Hud {
health,
buffs,
energy,
combat_rating: combat::combat_rating(inventory, health, stats),
combat_rating: combat::combat_rating(inventory, health, stats, *body),
});
let bubble = if dist_sqr < SPEECH_BUBBLE_RANGE.powi(2) {
speech_bubbles.get(uid)
@ -2011,6 +2011,7 @@ impl Hud {
let character_states = ecs.read_storage::<comp::CharacterState>();
let controllers = ecs.read_storage::<comp::Controller>();
let ability_map = ecs.fetch::<comp::item::tool::AbilityMap>();
let bodies = ecs.read_storage::<comp::Body>();
if let (
Some(health),
@ -2047,10 +2048,11 @@ impl Hud {
}
// Bag contents
if self.show.bag {
if let (Some(player_stats), Some(health), Some(energy)) = (
if let (Some(player_stats), Some(health), Some(energy), Some(body)) = (
stats.get(client.entity()),
healths.get(entity),
energies.get(entity),
bodies.get(entity),
) {
match Bag::new(
client,
@ -2066,6 +2068,7 @@ impl Hud {
&health,
&energy,
&self.show,
&body,
)
.set(self.ids.bag, ui_widgets)
{