mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Exp is now awarded to specific skill groups. It's automatically split between a general pool and weapon pools based on if you have the weapon in your loadout and if you've unlocked the weapon pools.
This commit is contained in:
parent
1dd47bc6d9
commit
63eb71ed5b
@ -936,7 +936,24 @@ impl Client {
|
||||
/// Send a chat message to the server.
|
||||
pub fn send_chat(&mut self, message: String) {
|
||||
match validate_chat_msg(&message) {
|
||||
Ok(()) => self.send_msg(ClientGeneral::ChatMsg(message)),
|
||||
/* Ok(()) => self.send_msg(ClientGeneral::ChatMsg(message)), */
|
||||
Ok(()) => {
|
||||
if message.starts_with('@') {
|
||||
if message == "@stats" {
|
||||
let stats = self
|
||||
.state
|
||||
.ecs()
|
||||
.read_storage::<comp::Stats>()
|
||||
.get(self.entity)
|
||||
.cloned()
|
||||
.unwrap();
|
||||
|
||||
tracing::info!("{:?}", stats.skill_set);
|
||||
}
|
||||
} else {
|
||||
self.send_msg(ClientGeneral::ChatMsg(message))
|
||||
}
|
||||
},
|
||||
Err(ChatMsgValidationError::TooLong) => tracing::warn!(
|
||||
"Attempted to send a message that's too long (Over {} bytes)",
|
||||
MAX_BYTES_CHAT_MSG
|
||||
|
@ -1,6 +1,6 @@
|
||||
use crate::{
|
||||
comp::{
|
||||
inventory::item::{armor::Protection, ItemKind},
|
||||
inventory::{item::{armor::Protection, tool::ToolKind, ItemKind}, slot::EquipSlot},
|
||||
BuffKind, HealthChange, HealthSource, Inventory,
|
||||
},
|
||||
uid::Uid,
|
||||
@ -195,3 +195,23 @@ impl Knockback {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_weapons(inv: &Inventory) -> (Option<ToolKind>, Option<ToolKind>) {
|
||||
(
|
||||
inv.equipped(EquipSlot::Mainhand).and_then(|i| {
|
||||
if let ItemKind::Tool(tool) = &i.kind() {
|
||||
Some(tool.kind)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}),
|
||||
inv.equipped(EquipSlot::Offhand).and_then(|i| {
|
||||
if let ItemKind::Tool(tool) = &i.kind() {
|
||||
Some(tool.kind)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}),
|
||||
|
||||
)
|
||||
}
|
@ -1,8 +1,8 @@
|
||||
use crate::{
|
||||
assets::{self, Asset},
|
||||
comp::{
|
||||
projectile::ProjectileConstructor, Body, CharacterState, EnergySource, Gravity,
|
||||
LightEmitter, StateUpdate,
|
||||
projectile::ProjectileConstructor,
|
||||
Body, CharacterState, EnergySource, Gravity, LightEmitter, StateUpdate,
|
||||
},
|
||||
states::{
|
||||
behavior::JoinData,
|
||||
|
@ -1,3 +1,4 @@
|
||||
use crate::comp::item::tool::ToolKind;
|
||||
use hashbrown::{HashMap, HashSet};
|
||||
use lazy_static::lazy_static;
|
||||
use serde::{Deserialize, Serialize};
|
||||
@ -10,23 +11,34 @@ lazy_static! {
|
||||
// is requested. TODO: Externalise this data in a RON file for ease of modification
|
||||
pub static ref SKILL_GROUP_DEFS: HashMap<SkillGroupType, HashSet<Skill>> = {
|
||||
let mut defs = HashMap::new();
|
||||
defs.insert(SkillGroupType::T1, [ Skill::TestT1Skill1,
|
||||
Skill::TestT1Skill2,
|
||||
Skill::TestT1Skill3,
|
||||
Skill::TestT1Skill4,
|
||||
Skill::TestT1Skill5]
|
||||
.iter().cloned().collect::<HashSet<Skill>>());
|
||||
|
||||
defs.insert(SkillGroupType::Swords, [ Skill::TestSwordSkill1,
|
||||
Skill::TestSwordSkill2,
|
||||
Skill::TestSwordSkill3]
|
||||
.iter().cloned().collect::<HashSet<Skill>>());
|
||||
|
||||
defs.insert(SkillGroupType::Axes, [ Skill::TestAxeSkill1,
|
||||
Skill::TestAxeSkill2,
|
||||
Skill::TestAxeSkill3]
|
||||
.iter().cloned().collect::<HashSet<Skill>>());
|
||||
|
||||
defs.insert(
|
||||
SkillGroupType::General, [
|
||||
Skill::General(GeneralSkill::HealthIncrease1),
|
||||
].iter().cloned().collect::<HashSet<Skill>>());
|
||||
defs.insert(
|
||||
SkillGroupType::Weapon(ToolKind::Sword), [
|
||||
Skill::Sword(SwordSkill::UnlockSpin),
|
||||
].iter().cloned().collect::<HashSet<Skill>>());
|
||||
defs.insert(
|
||||
SkillGroupType::Weapon(ToolKind::Axe), [
|
||||
Skill::Axe(AxeSkill::UnlockLeap),
|
||||
].iter().cloned().collect::<HashSet<Skill>>());
|
||||
defs.insert(
|
||||
SkillGroupType::Weapon(ToolKind::Hammer), [
|
||||
Skill::Hammer(HammerSkill::UnlockLeap),
|
||||
].iter().cloned().collect::<HashSet<Skill>>());
|
||||
defs.insert(
|
||||
SkillGroupType::Weapon(ToolKind::Bow), [
|
||||
Skill::Bow(BowSkill::UnlockRepeater),
|
||||
].iter().cloned().collect::<HashSet<Skill>>());
|
||||
defs.insert(
|
||||
SkillGroupType::Weapon(ToolKind::Staff), [
|
||||
Skill::Staff(StaffSkill::UnlockShockwave),
|
||||
].iter().cloned().collect::<HashSet<Skill>>());
|
||||
defs.insert(
|
||||
SkillGroupType::Weapon(ToolKind::Sceptre), [
|
||||
Skill::Sceptre(SceptreSkill::Unlock404),
|
||||
].iter().cloned().collect::<HashSet<Skill>>());
|
||||
defs
|
||||
};
|
||||
}
|
||||
@ -37,30 +49,66 @@ lazy_static! {
|
||||
/// handled by dedicated ECS systems.
|
||||
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub enum Skill {
|
||||
TestT1Skill1,
|
||||
TestT1Skill2,
|
||||
TestT1Skill3,
|
||||
TestT1Skill4,
|
||||
TestT1Skill5,
|
||||
TestSwordSkill1,
|
||||
TestSwordSkill2,
|
||||
TestSwordSkill3,
|
||||
TestAxeSkill1,
|
||||
TestAxeSkill2,
|
||||
TestAxeSkill3,
|
||||
General(GeneralSkill),
|
||||
Sword(SwordSkill),
|
||||
Axe(AxeSkill),
|
||||
Hammer(HammerSkill),
|
||||
Bow(BowSkill),
|
||||
Staff(StaffSkill),
|
||||
Sceptre(SceptreSkill),
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub enum SwordSkill {
|
||||
UnlockSpin,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub enum AxeSkill {
|
||||
UnlockLeap,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub enum HammerSkill {
|
||||
UnlockLeap,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub enum BowSkill {
|
||||
UnlockRepeater,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub enum StaffSkill {
|
||||
UnlockShockwave,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub enum SceptreSkill {
|
||||
Unlock404,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub enum GeneralSkill {
|
||||
HealthIncrease1,
|
||||
UnlockSwordTree,
|
||||
UnlockAxeTree,
|
||||
UnlockHammerTree,
|
||||
UnlockBowTree,
|
||||
UnlockStaffTree,
|
||||
UnlockSceptreTree,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub enum SkillGroupType {
|
||||
T1,
|
||||
Swords,
|
||||
Axes,
|
||||
General,
|
||||
Weapon(ToolKind),
|
||||
}
|
||||
|
||||
/// A group of skills that have been unlocked by a player. Each skill group has
|
||||
/// independent exp and skill points which are used to unlock skills in that
|
||||
/// skill group.
|
||||
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
|
||||
#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)]
|
||||
pub struct SkillGroup {
|
||||
pub skill_group_type: SkillGroupType,
|
||||
pub exp: u32,
|
||||
@ -93,20 +141,17 @@ impl Default for SkillSet {
|
||||
fn default() -> Self {
|
||||
// TODO: Default skill groups for new players?
|
||||
Self {
|
||||
skill_groups: Vec::new(),
|
||||
skill_groups: vec![
|
||||
SkillGroup::new(SkillGroupType::General),
|
||||
SkillGroup::new(SkillGroupType::Weapon(ToolKind::Sword)),
|
||||
SkillGroup::new(SkillGroupType::Weapon(ToolKind::Bow)),
|
||||
],
|
||||
skills: HashSet::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl SkillSet {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
skill_groups: Vec::new(),
|
||||
skills: HashSet::new(),
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Game design to determine how skill groups are unlocked
|
||||
/// Unlocks a skill group for a player. It starts with 0 exp and 0 skill
|
||||
/// points.
|
||||
@ -251,6 +296,27 @@ impl SkillSet {
|
||||
warn!("Tried to add skill points to a skill group that player does not have");
|
||||
}
|
||||
}
|
||||
|
||||
/// Checks if the skill set of an entity contains a particular skill group
|
||||
/// type
|
||||
pub fn contains_skill_group(&self, skill_group_type: SkillGroupType) -> bool {
|
||||
self.skill_groups
|
||||
.iter()
|
||||
.any(|x| x.skill_group_type == skill_group_type)
|
||||
}
|
||||
|
||||
/// Adds experience to the skill group within an entity's skill set
|
||||
pub fn add_experience(&mut self, skill_group_type: SkillGroupType, amount: u32) {
|
||||
if let Some(mut skill_group) = self
|
||||
.skill_groups
|
||||
.iter_mut()
|
||||
.find(|x| x.skill_group_type == skill_group_type)
|
||||
{
|
||||
skill_group.exp += amount;
|
||||
} else {
|
||||
warn!("Tried to add experience to a skill group that player does not have");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
@ -1,11 +1,12 @@
|
||||
use crate::{
|
||||
client::Client,
|
||||
comp::{biped_large, quadruped_low, quadruped_medium, quadruped_small, theropod, PhysicsState},
|
||||
comp::{biped_large, quadruped_low, quadruped_medium, quadruped_small, skills::SkillGroupType, theropod, PhysicsState},
|
||||
rtsim::RtSim,
|
||||
Server, SpawnPoint, StateExt,
|
||||
};
|
||||
use common::{
|
||||
assets::AssetExt,
|
||||
combat,
|
||||
comp::{
|
||||
self, aura, buff,
|
||||
chat::{KillSource, KillType},
|
||||
@ -29,6 +30,7 @@ use common_sys::state::BlockChange;
|
||||
use comp::item::Reagent;
|
||||
use rand::prelude::*;
|
||||
use specs::{join::Join, saveload::MarkerAllocator, Entity as EcsEntity, WorldExt};
|
||||
use std::collections::HashSet;
|
||||
use tracing::error;
|
||||
use vek::Vec3;
|
||||
|
||||
@ -223,16 +225,76 @@ pub fn handle_destroy(server: &mut Server, entity: EcsEntity, cause: HealthSourc
|
||||
let exp = exp_reward / (num_not_pets_in_range as f32 + ATTACKER_EXP_WEIGHT);
|
||||
exp_reward = exp * ATTACKER_EXP_WEIGHT;
|
||||
members_in_range.into_iter().for_each(|e| {
|
||||
let (main_tool_kind, second_tool_kind) =
|
||||
if let Some(inventory) = state.ecs().read_storage::<comp::Inventory>().get(e) {
|
||||
combat::get_weapons(inventory)
|
||||
} else {
|
||||
(None, None)
|
||||
};
|
||||
if let Some(mut stats) = stats.get_mut(e) {
|
||||
stats.exp.change_by(exp.ceil() as i64);
|
||||
// stats.exp.change_by(exp.ceil() as i64);
|
||||
let mut xp_pools = HashSet::<SkillGroupType>::new();
|
||||
xp_pools.insert(SkillGroupType::General);
|
||||
if let Some(w) = main_tool_kind {
|
||||
if stats
|
||||
.skill_set
|
||||
.contains_skill_group(SkillGroupType::Weapon(w))
|
||||
{
|
||||
xp_pools.insert(SkillGroupType::Weapon(w));
|
||||
}
|
||||
}
|
||||
if let Some(w) = second_tool_kind {
|
||||
if stats
|
||||
.skill_set
|
||||
.contains_skill_group(SkillGroupType::Weapon(w))
|
||||
{
|
||||
xp_pools.insert(SkillGroupType::Weapon(w));
|
||||
}
|
||||
}
|
||||
let num_pools = xp_pools.len() as f32;
|
||||
for pool in xp_pools.drain() {
|
||||
stats
|
||||
.skill_set
|
||||
.add_experience(pool, (exp / num_pools).ceil() as u32);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
let (main_tool_kind, second_tool_kind) =
|
||||
if let Some(inventory) = state.ecs().read_storage::<comp::Inventory>().get(attacker) {
|
||||
combat::get_weapons(inventory)
|
||||
} else {
|
||||
(None, None)
|
||||
};
|
||||
if let Some(mut attacker_stats) = stats.get_mut(attacker) {
|
||||
// TODO: Discuss whether we should give EXP by Player
|
||||
// Killing or not.
|
||||
attacker_stats.exp.change_by(exp_reward.ceil() as i64);
|
||||
// attacker_stats.exp.change_by(exp_reward.ceil() as i64);
|
||||
let mut xp_pools = HashSet::<SkillGroupType>::new();
|
||||
xp_pools.insert(SkillGroupType::General);
|
||||
if let Some(w) = main_tool_kind {
|
||||
if attacker_stats
|
||||
.skill_set
|
||||
.contains_skill_group(SkillGroupType::Weapon(w))
|
||||
{
|
||||
xp_pools.insert(SkillGroupType::Weapon(w));
|
||||
}
|
||||
}
|
||||
if let Some(w) = second_tool_kind {
|
||||
if attacker_stats
|
||||
.skill_set
|
||||
.contains_skill_group(SkillGroupType::Weapon(w))
|
||||
{
|
||||
xp_pools.insert(SkillGroupType::Weapon(w));
|
||||
}
|
||||
}
|
||||
let num_pools = xp_pools.len() as f32;
|
||||
for pool in xp_pools.drain() {
|
||||
attacker_stats
|
||||
.skill_set
|
||||
.add_experience(pool, (exp_reward / num_pools).ceil() as u32);
|
||||
}
|
||||
}
|
||||
})();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user