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

This commit is contained in:
Sam 2021-01-22 16:12:16 -05:00
parent 4b4504a3a3
commit 4014b28d19
13 changed files with 128 additions and 122 deletions

View File

@ -9,7 +9,7 @@ use crate::{
slot::EquipSlot, slot::EquipSlot,
}, },
skills::{SkillGroupKind, SkillSet}, skills::{SkillGroupKind, SkillSet},
BuffKind, Health, HealthChange, HealthSource, Inventory, Stats, Body, BuffKind, Health, HealthChange, HealthSource, Inventory, Stats,
}, },
uid::Uid, uid::Uid,
util::Dir, util::Dir,
@ -245,7 +245,7 @@ fn offensive_rating(inv: &Inventory, skillset: &SkillSet) -> f32 {
active_damage.max(second_damage) 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 defensive_weighting = 1.0;
let offensive_weighting = 1.0; let offensive_weighting = 1.0;
let defensive_rating = health.maximum() as f32 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 let combined_rating = (offensive_rating * offensive_weighting
+ defensive_rating * defensive_weighting) + defensive_rating * defensive_weighting)
/ (offensive_weighting + 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::{ use crate::comp::skills::SkillSet;
comp,
comp::{skills::SkillSet, Body},
};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use specs::{Component, DerefFlaggedStorage}; use specs::{Component, DerefFlaggedStorage};
use specs_idvs::IdvStorage; use specs_idvs::IdvStorage;
@ -27,15 +24,13 @@ impl Error for StatChangeError {}
pub struct Stats { pub struct Stats {
pub name: String, pub name: String,
pub skill_set: SkillSet, pub skill_set: SkillSet,
pub body_type: Body,
} }
impl Stats { impl Stats {
pub fn new(name: String, body: Body) -> Self { pub fn new(name: String) -> Self {
Self { Self {
name, name,
skill_set: SkillSet::default(), skill_set: SkillSet::default(),
body_type: body,
} }
} }
@ -45,7 +40,6 @@ impl Stats {
Self { Self {
name: "".to_owned(), name: "".to_owned(),
skill_set: SkillSet::default(), skill_set: SkillSet::default(),
body_type: comp::Body::Humanoid(comp::body::humanoid::Body::random()),
} }
} }
} }

View File

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

View File

@ -10,7 +10,7 @@ pub fn create_character(
body: Body, body: Body,
character_loader: &ReadExpect<'_, CharacterLoader>, 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() let loadout = LoadoutBuilder::new()
.defaults() .defaults()

View File

@ -820,10 +820,10 @@ fn handle_spawn(
.state .state
.create_npc( .create_npc(
pos, pos,
comp::Stats::new( comp::Stats::new(get_npc_name(
get_npc_name(id, npc::BodyType::from_body(body)), id,
body, npc::BodyType::from_body(body),
), )),
comp::Health::new(body, 1), comp::Health::new(body, 1),
inventory, inventory,
body, body,
@ -929,7 +929,7 @@ fn handle_spawn_training_dummy(
let body = comp::Body::Object(comp::object::Body::TrainingDummy); 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); 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 healths = state.ecs().read_storage::<Health>();
let inventories = state.ecs().read_storage::<Inventory>(); let inventories = state.ecs().read_storage::<Inventory>();
let players = state.ecs().read_storage::<Player>(); let players = state.ecs().read_storage::<Player>();
let bodies = state.ecs().read_storage::<Body>();
let by = if let HealthSource::Damage { by: Some(by), .. } = cause { let by = if let HealthSource::Damage { by: Some(by), .. } = cause {
by by
} else { } else {
@ -174,16 +175,21 @@ pub fn handle_destroy(server: &mut Server, entity: EcsEntity, cause: HealthSourc
} else { } else {
return; return;
}; };
let (entity_stats, entity_health, entity_inventory) = let (entity_stats, entity_health, entity_inventory, entity_body) = if let (
if let (Some(entity_stats), Some(entity_health), Some(entity_inventory)) = ( Some(entity_stats),
stats.get(entity), Some(entity_health),
healths.get(entity), Some(entity_inventory),
inventories.get(entity), Some(entity_body),
) { ) = (
(entity_stats, entity_health, entity_inventory) stats.get(entity),
} else { healths.get(entity),
return; inventories.get(entity),
}; bodies.get(entity),
) {
(entity_stats, entity_health, entity_inventory, entity_body)
} else {
return;
};
let groups = state.ecs().read_storage::<Group>(); let groups = state.ecs().read_storage::<Group>();
let attacker_group = groups.get(attacker); 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 // TODO: Scale xp from skillset rather than health, when NPCs have their own
// skillsets // skillsets
let mut exp_reward = 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 // Distribute EXP to group
let positions = state.ecs().read_storage::<Pos>(); 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 => { item::Throwable::TrainingDummy => {
new_entity = new_entity.with(comp::Stats::new( new_entity = new_entity.with(comp::Stats::new("Training Dummy".to_string()));
"Training Dummy".to_string(),
comp::object::Body::TrainingDummy.into(),
));
}, },
}; };

View File

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

View File

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

View File

@ -18,7 +18,7 @@ use crate::{
use client::Client; use client::Client;
use common::{ use common::{
combat::{combat_rating, Damage}, combat::{combat_rating, Damage},
comp::{item::Quality, Energy, Health, Stats}, comp::{item::Quality, Body, Energy, Health, Stats},
}; };
use conrod_core::{ use conrod_core::{
color, color,
@ -100,6 +100,7 @@ pub struct Bag<'a> {
health: &'a Health, health: &'a Health,
energy: &'a Energy, energy: &'a Energy,
show: &'a Show, show: &'a Show,
body: &'a Body,
} }
impl<'a> Bag<'a> { impl<'a> Bag<'a> {
@ -118,6 +119,7 @@ impl<'a> Bag<'a> {
health: &'a Health, health: &'a Health,
energy: &'a Energy, energy: &'a Energy,
show: &'a Show, show: &'a Show,
body: &'a Body,
) -> Self { ) -> Self {
Self { Self {
client, client,
@ -134,6 +136,7 @@ impl<'a> Bag<'a> {
energy, energy,
health, health,
show, show,
body,
} }
} }
} }
@ -428,7 +431,8 @@ impl<'a> Widget for Bag<'a> {
.resize(STATS.len(), &mut ui.widget_id_generator()) .resize(STATS.len(), &mut ui.widget_id_generator())
}); });
// Stats // 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); let indicator_col = cr_color(combat_rating);
for i in STATS.iter().copied().enumerate() { for i in STATS.iter().copied().enumerate() {
let btn = Button::image(match i.1 { 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 buffs = client_state.ecs().read_storage::<common::comp::Buffs>();
let inventory = client_state.ecs().read_storage::<common::comp::Inventory>(); let inventory = client_state.ecs().read_storage::<common::comp::Inventory>();
let uid_allocator = client_state.ecs().read_resource::<UidAllocator>(); 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 // Keep track of the total number of widget ids we are using for buffs
let mut total_buff_count = 0; 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 buffs = entity.and_then(|entity| buffs.get(entity));
let inventory = entity.and_then(|entity| inventory.get(entity)); let inventory = entity.and_then(|entity| inventory.get(entity));
let is_leader = uid == leader; let is_leader = uid == leader;
let body = entity.and_then(|entity| bodies.get(entity));
if let Some(stats) = stats { if let (Some(stats), Some(inventory), Some(health), Some(body)) =
let combat_rating = (stats, inventory, health, body)
combat::combat_rating(inventory.unwrap(), &health.unwrap(), stats); // We can unwrap here because we check for stats first {
let combat_rating = combat::combat_rating(inventory, health, stats, *body);
let char_name = stats.name.to_string(); let char_name = stats.name.to_string();
if let Some(health) = health { let health_perc = health.current() as f64 / health.maximum() as f64;
let health_perc = health.current() as f64 / health.maximum() as f64; // change panel positions when debug info is shown
// change panel positions when debug info is shown let x = if debug_on { i / 8 } else { i / 12 };
let x = if debug_on { i / 8 } else { i / 12 }; let y = 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(
let back = Image::new(self.imgs.member_bg).top_left_with_margins_on( ui.window,
ui.window, 50.0 + offset + y as f64 * 77.0,
50.0 + offset + y as f64 * 77.0, 10.0 + x as f64 * 180.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 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 crit_hp_color: Color = Color::Rgba(0.79, 0.19, 0.17, hp_ani); let health_col = match (health_perc * 100.0) as u8 {
let health_col = match (health_perc * 100.0) as u8 { 0..=20 => crit_hp_color,
0..=20 => crit_hp_color, 21..=40 => LOW_HP_COLOR,
21..=40 => LOW_HP_COLOR, _ => HP_COLOR,
_ => HP_COLOR, };
}; // Don't show panel for the player!
// Don't show panel for the player! // Panel BG
// Panel BG back.w_h(152.0, 36.0)
back.w_h(152.0, 36.0) .color(if is_leader {
.color(if is_leader { Some(ERROR_COLOR)
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);
} else { } else {
// Health Text Some(TEXT_COLOR)
let txt = format!( })
"{}/{}", .set(state.ids.member_panels_bg[i], ui);
health.current() / 10_u32, // Health
health.maximum() / 10_u32, Image::new(self.imgs.bar_content)
); .w_h(148.0 * health_perc, 22.0)
// Change font size depending on health amount .color(Some(health_col))
let font_size = match health.maximum() { .top_left_with_margins_on(state.ids.member_panels_bg[i], 2.0, 2.0)
0..=999 => 14, .set(state.ids.member_health[i], ui);
1000..=9999 => 13, if health.is_dead {
10000..=99999 => 12, // Death Text
_ => 11, Text::new(&self.localized_strings.get("hud.group.dead"))
}; .mid_top_with_margin_on(state.ids.member_panels_bg[i], 1.0)
// Change text offset depending on health amount .font_size(20)
let txt_offset = match health.maximum() { .font_id(self.fonts.cyri.conrod_id)
0..=999 => 4.0, .color(KILL_COLOR)
1000..=9999 => 4.5, .set(state.ids.dead_txt[i], ui);
10000..=99999 => 5.0, } else {
_ => 5.5, // Health Text
}; let txt = format!(
Text::new(&txt) "{}/{}",
.mid_top_with_margin_on(state.ids.member_panels_bg[i], txt_offset) health.current() / 10_u32,
.font_size(font_size) health.maximum() / 10_u32,
.font_id(self.fonts.cyri.conrod_id) );
.color(Color::Rgba(1.0, 1.0, 1.0, 0.5)) // Change font size depending on health amount
.set(state.ids.health_txt[i], ui); 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 // Panel Frame
Image::new(self.imgs.member_frame) Image::new(self.imgs.member_frame)

View File

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