Added SkillSetConfig to specify skill sets for npcs.

This commit is contained in:
Sam 2021-01-07 14:47:29 -05:00
parent 968b66260e
commit 6ce422748c
8 changed files with 114 additions and 41 deletions

View File

@ -332,7 +332,7 @@ impl SkillSet {
/// assert_eq!(skillset.skills.len(), 1);
/// ```
pub fn unlock_skill(&mut self, skill: Skill) {
if let Some(skill_group_type) = SkillSet::get_skill_group_type_for_skill(&skill) {
if let Some(skill_group_type) = skill.get_skill_group_type() {
let next_level = if self.skills.contains_key(&skill) {
self.skills.get(&skill).copied().flatten().map(|l| l + 1)
} else {
@ -395,7 +395,7 @@ impl SkillSet {
/// ```
pub fn refund_skill(&mut self, skill: Skill) {
if self.skills.contains_key(&skill) {
if let Some(skill_group_type) = SkillSet::get_skill_group_type_for_skill(&skill) {
if let Some(skill_group_type) = skill.get_skill_group_type() {
if let Some(mut skill_group) = self
.skill_groups
.iter_mut()
@ -423,18 +423,6 @@ impl SkillSet {
}
}
/// Returns the skill group type for a skill from the static skill group
/// definitions.
fn get_skill_group_type_for_skill(skill: &Skill) -> Option<SkillGroupType> {
SKILL_GROUP_DEFS.iter().find_map(|(key, val)| {
if val.contains(&skill) {
Some(*key)
} else {
None
}
})
}
/// Adds skill points to a skill group as long as the player has that skill
/// group type.
///
@ -538,7 +526,7 @@ impl SkillSet {
/// Checks if player has sufficient skill points to purchase a skill
pub fn sufficient_skill_points(&self, skill: Skill) -> bool {
if let Some(skill_group_type) = SkillSet::get_skill_group_type_for_skill(&skill) {
if let Some(skill_group_type) = skill.get_skill_group_type() {
if let Some(skill_group) = self
.skill_groups
.iter()
@ -589,6 +577,18 @@ impl Skill {
/// Returns the maximum level a skill can reach, returns None if the skill
/// doesn't level
pub fn get_max_level(self) -> Option<u16> { SKILL_MAX_LEVEL.get(&self).copied().flatten() }
/// Returns the skill group type for a skill from the static skill group
/// definitions.
pub fn get_skill_group_type(self) -> Option<SkillGroupType> {
SKILL_GROUP_DEFS.iter().find_map(|(key, val)| {
if val.contains(&self) {
Some(*key)
} else {
None
}
})
}
}
#[cfg(test)]

View File

@ -1,6 +1,7 @@
use crate::{
comp::{self, humanoid, inventory::loadout_builder::LoadoutConfig, Alignment, Body, Item},
npc::{self, NPC_NAMES},
skillset_builder::SkillSetConfig,
};
use vek::*;
@ -23,7 +24,8 @@ pub struct EntityInfo {
// TODO: Properly give NPCs skills
pub level: Option<u16>,
pub loot_drop: Option<Item>,
pub config: Option<LoadoutConfig>,
pub loadout_config: Option<LoadoutConfig>,
pub skillset_config: Option<SkillSetConfig>,
pub pet: Option<Box<EntityInfo>>,
}
@ -42,7 +44,8 @@ impl EntityInfo {
scale: 1.0,
level: None,
loot_drop: None,
config: None,
loadout_config: None,
skillset_config: None,
pet: None,
}
}
@ -109,8 +112,13 @@ impl EntityInfo {
self
}
pub fn with_config(mut self, config: LoadoutConfig) -> Self {
self.config = Some(config);
pub fn with_loadout_config(mut self, config: LoadoutConfig) -> Self {
self.loadout_config = Some(config);
self
}
pub fn with_skillset_config(mut self, config: SkillSetConfig) -> Self {
self.skillset_config = Some(config);
self
}

View File

@ -43,6 +43,7 @@ pub mod recipe;
pub mod region;
pub mod resources;
pub mod rtsim;
pub mod skillset_builder;
pub mod spiral;
pub mod states;
pub mod store;
@ -57,3 +58,4 @@ pub mod volumes;
pub use combat::{Damage, DamageSource, GroupTarget, Knockback};
pub use comp::inventory::loadout_builder::LoadoutBuilder;
pub use explosion::{Explosion, RadiusEffect};
pub use skillset_builder::SkillSetBuilder;

View File

@ -0,0 +1,59 @@
use crate::comp::{
item::tool::ToolKind,
skills::{Skill, SkillGroupType, SkillSet, SwordSkill},
};
use tracing::warn;
#[derive(Copy, Clone)]
pub enum SkillSetConfig {
Guard,
Villager,
Outcast,
Highwayman,
Bandit,
CultistNovice,
CultistAcolyte,
Warlord,
Warlock,
}
pub struct SkillSetBuilder(SkillSet);
impl Default for SkillSetBuilder {
fn default() -> Self { Self(SkillSet::default()) }
}
impl SkillSetBuilder {
pub fn build_skillset(config: SkillSetConfig) -> Self {
let mut skillset = Self::default();
use SkillSetConfig::*;
match config {
Guard => {
skillset.with_skill_group(SkillGroupType::Weapon(ToolKind::Sword));
skillset.with_skill(Skill::Sword(SwordSkill::SUnlockSpin));
},
_ => {},
}
skillset
}
pub fn with_skill(&mut self, skill: Skill) {
if let Some(skill_group) = skill.get_skill_group_type() {
self.0
.add_skill_points(skill_group, self.0.skill_point_cost(skill));
self.0.unlock_skill(skill);
if !self.0.skills.contains_key(&skill) {
warn!(
"Failed to add skill. Verify that it has the appropriate skill group \
available."
);
}
}
}
pub fn with_skill_group(&mut self, skill_group: SkillGroupType) {
self.0.unlock_skill_group(skill_group);
}
pub fn build(self) -> SkillSet { self.0 }
}

View File

@ -9,7 +9,7 @@ use common::{
npc::NPC_NAMES,
span,
terrain::TerrainGrid,
LoadoutBuilder,
LoadoutBuilder, SkillSetBuilder,
};
use common_net::msg::ServerGeneral;
use common_sys::state::TerrainChanges;
@ -148,9 +148,13 @@ impl<'a> System<'a> for Sys {
scale = 2.0 + rand::random::<f32>();
}
let config = entity.config;
let loadout_config = entity.loadout_config;
let skillset_config = entity.skillset_config;
let loadout = LoadoutBuilder::build_loadout(body, main_tool, config).build();
let loadout = LoadoutBuilder::build_loadout(body, main_tool, loadout_config).build();
if let Some(config) = skillset_config {
stats.skill_set = SkillSetBuilder::build_skillset(config).build();
}
let health = comp::Health::new(stats.body_type, entity.level.unwrap_or(0));
@ -184,7 +188,7 @@ impl<'a> System<'a> for Sys {
can_speak,
&body,
matches!(
config,
loadout_config,
Some(comp::inventory::loadout_builder::LoadoutConfig::Guard)
),
))

View File

@ -853,7 +853,7 @@ impl Hud {
let scales = ecs.read_storage::<comp::Scale>();
let bodies = ecs.read_storage::<comp::Body>();
let items = ecs.read_storage::<comp::Item>();
let loadouts = ecs.read_storage::<comp::Loadout>();
let inventories = ecs.read_storage::<comp::Inventory>();
let entities = ecs.entities();
let me = client.entity();
//self.input = client.read_storage::<comp::ControllerInputs>();
@ -1276,7 +1276,7 @@ impl Hud {
&bodies,
&hp_floater_lists,
&uids,
&loadouts,
&inventories,
)
.join()
.filter(|t| {
@ -1297,7 +1297,7 @@ impl Hud {
body,
hpfl,
uid,
loadout,
inventory,
)| {
// Use interpolated position if available
let pos = interpolated.map_or(pos.0, |i| i.pos);
@ -1330,7 +1330,7 @@ impl Hud {
health,
buffs,
energy,
combat_rating: combat::combat_rating(loadout, health, &stats.body_type),
combat_rating: combat::combat_rating(inventory, health, &stats.body_type),
});
let bubble = if dist_sqr < SPEECH_BUBBLE_RANGE.powi(2) {
speech_bubbles.get(uid)

View File

@ -599,7 +599,7 @@ impl Floor {
//.do_if(is_giant, |e| e.into_giant())
.with_body(comp::Body::Humanoid(comp::humanoid::Body::random()))
.with_alignment(comp::Alignment::Enemy)
.with_config(loadout_builder::LoadoutConfig::CultistAcolyte)
.with_loadout_config(loadout_builder::LoadoutConfig::CultistAcolyte)
.with_loot_drop(comp::Item::new_from_asset_expect(chosen))
.with_level(dynamic_rng.gen_range(
(room.difficulty as f32).powf(1.25) + 3.0,
@ -608,7 +608,7 @@ impl Floor {
let entity = match room.difficulty {
0 => entity
.with_name("Outcast")
.with_config(loadout_builder::LoadoutConfig::Outcast)
.with_loadout_config(loadout_builder::LoadoutConfig::Outcast)
.with_loot_drop(comp::Item::new_from_asset_expect(chosen))
.with_main_tool(comp::Item::new_from_asset_expect(
match dynamic_rng.gen_range(0, 6) {
@ -622,7 +622,7 @@ impl Floor {
)),
1 => entity
.with_name("Highwayman")
.with_config(loadout_builder::LoadoutConfig::Highwayman)
.with_loadout_config(loadout_builder::LoadoutConfig::Highwayman)
.with_loot_drop(comp::Item::new_from_asset_expect(chosen))
.with_main_tool(comp::Item::new_from_asset_expect(
match dynamic_rng.gen_range(0, 6) {
@ -636,7 +636,7 @@ impl Floor {
)),
2 => entity
.with_name("Bandit")
.with_config(loadout_builder::LoadoutConfig::Bandit)
.with_loadout_config(loadout_builder::LoadoutConfig::Bandit)
.with_loot_drop(comp::Item::new_from_asset_expect(chosen))
.with_main_tool(comp::Item::new_from_asset_expect(
match dynamic_rng.gen_range(0, 6) {
@ -650,7 +650,7 @@ impl Floor {
)),
3 => entity
.with_name("Cultist Novice")
.with_config(loadout_builder::LoadoutConfig::CultistNovice)
.with_loadout_config(loadout_builder::LoadoutConfig::CultistNovice)
.with_loot_drop(comp::Item::new_from_asset_expect(chosen))
.with_main_tool(comp::Item::new_from_asset_expect(
match dynamic_rng.gen_range(0, 6) {
@ -664,7 +664,7 @@ impl Floor {
)),
4 => entity
.with_name("Cultist Acolyte")
.with_config(loadout_builder::LoadoutConfig::CultistAcolyte)
.with_loadout_config(loadout_builder::LoadoutConfig::CultistAcolyte)
.with_loot_drop(comp::Item::new_from_asset_expect(chosen))
.with_main_tool(comp::Item::new_from_asset_expect(
match dynamic_rng.gen_range(0, 6) {
@ -679,14 +679,14 @@ impl Floor {
5 => match dynamic_rng.gen_range(0, 6) {
0 => entity
.with_name("Cultist Warlock")
.with_config(loadout_builder::LoadoutConfig::Warlock)
.with_loadout_config(loadout_builder::LoadoutConfig::Warlock)
.with_loot_drop(comp::Item::new_from_asset_expect(chosen))
.with_main_tool(comp::Item::new_from_asset_expect(
"common.items.npc_weapons.staff.cultist_staff",
)),
_ => entity
.with_name("Cultist Warlord")
.with_config(loadout_builder::LoadoutConfig::Warlord)
.with_loadout_config(loadout_builder::LoadoutConfig::Warlord)
.with_loot_drop(comp::Item::new_from_asset_expect(chosen))
.with_main_tool(comp::Item::new_from_asset_expect(
match dynamic_rng.gen_range(0, 5) {
@ -755,7 +755,7 @@ impl Floor {
))
.with_name("Outcast Leader".to_string())
.with_loot_drop(comp::Item::new_from_asset_expect(chosen))
.with_config(loadout_builder::LoadoutConfig::Outcast)
.with_loadout_config(loadout_builder::LoadoutConfig::Outcast)
.with_scale(2.0)
.with_main_tool(comp::Item::new_from_asset_expect(
match dynamic_rng.gen_range(0, 6) {
@ -801,7 +801,7 @@ impl Floor {
))
.with_name("Bandit Captain".to_string())
.with_loot_drop(comp::Item::new_from_asset_expect(chosen))
.with_config(loadout_builder::LoadoutConfig::Bandit)
.with_loadout_config(loadout_builder::LoadoutConfig::Bandit)
.with_scale(2.0)
.with_main_tool(comp::Item::new_from_asset_expect(
match dynamic_rng.gen_range(0, 6) {
@ -822,7 +822,7 @@ impl Floor {
))
.with_name("Cultist Acolyte".to_string())
.with_loot_drop(comp::Item::new_from_asset_expect(chosen))
.with_config(loadout_builder::LoadoutConfig::CultistAcolyte)
.with_loadout_config(loadout_builder::LoadoutConfig::CultistAcolyte)
.with_scale(2.0)
.with_main_tool(comp::Item::new_from_asset_expect(
match dynamic_rng.gen_range(0, 6) {
@ -973,7 +973,7 @@ impl Floor {
))
.with_name("Animal Trainer".to_string())
.with_loot_drop(comp::Item::new_from_asset_expect(chosen))
.with_config(loadout_builder::LoadoutConfig::CultistAcolyte)
.with_loadout_config(loadout_builder::LoadoutConfig::CultistAcolyte)
.with_scale(2.0)
.with_main_tool(comp::Item::new_from_asset_expect(
match dynamic_rng.gen_range(0, 6) {

View File

@ -934,7 +934,7 @@ impl Settlement {
))
.with_name("Guard")
.with_level(dynamic_rng.gen_range(10, 15))
.with_config(loadout_builder::LoadoutConfig::Guard),
.with_loadout_config(loadout_builder::LoadoutConfig::Guard),
_ => entity
.with_main_tool(Item::new_from_asset_expect(
match dynamic_rng.gen_range(0, 7) {
@ -948,7 +948,7 @@ impl Settlement {
//_ => "common.items.npc_weapons.bow.starter_bow", TODO: Re-Add this when we have a better way of distributing npc_weapons here
},
))
.with_config(loadout_builder::LoadoutConfig::Villager),
.with_loadout_config(loadout_builder::LoadoutConfig::Villager),
}
});