mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
/skill_preset command
This commit is contained in:
parent
ad3a63fc80
commit
1c22a2b3fd
@ -56,6 +56,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
- There's now a checkbox in the graphics tab to opt-in to receiving lossily-compressed terrain colors.
|
||||
- /buff command which allows you to cast a buff on player
|
||||
- Warn the user with an animated red text in the second phase of a trade in which a party is offering nothing.
|
||||
- /skill_preset command which allows you to apply skill presets
|
||||
|
||||
### Changed
|
||||
|
||||
|
129
assets/server/manifests/presets.ron
Normal file
129
assets/server/manifests/presets.ron
Normal file
@ -0,0 +1,129 @@
|
||||
// NOTE: Order matters here
|
||||
// (you need to unlock skillgroup to be able to unlock skills in it
|
||||
({
|
||||
"max": [
|
||||
// General skills
|
||||
(General(HealthIncrease), 10),
|
||||
(General(EnergyIncrease), 5),
|
||||
(Roll(Cost), 2),
|
||||
(Roll(Strength), 2),
|
||||
(Roll(Duration), 2),
|
||||
(Climb(Cost), 2),
|
||||
(Climb(Speed), 2),
|
||||
(Swim(Speed), 2),
|
||||
|
||||
// Sword
|
||||
(UnlockGroup(Weapon(Sword)), 1),
|
||||
|
||||
(Sword(InterruptingAttacks), 1),
|
||||
|
||||
(Sword(TsCombo), 1),
|
||||
(Sword(TsDamage), 3),
|
||||
(Sword(TsRegen), 2),
|
||||
(Sword(TsSpeed), 3),
|
||||
|
||||
(Sword(DCost), 2),
|
||||
(Sword(DDrain), 2),
|
||||
(Sword(DDamage), 2),
|
||||
(Sword(DScaling), 3),
|
||||
(Sword(DSpeed), 1),
|
||||
(Sword(DInfinite), 1),
|
||||
|
||||
(Sword(UnlockSpin), 1),
|
||||
(Sword(SDamage), 2),
|
||||
(Sword(SSpeed), 2),
|
||||
(Sword(SCost), 2),
|
||||
(Sword(SSpins), 2),
|
||||
// Axe
|
||||
(UnlockGroup(Weapon(Axe)), 1),
|
||||
|
||||
(Axe(DsCombo), 1),
|
||||
(Axe(DsDamage), 3),
|
||||
(Axe(DsRegen), 2),
|
||||
(Axe(DsSpeed), 3),
|
||||
|
||||
(Axe(SInfinite), 1),
|
||||
(Axe(SHelicopter), 1),
|
||||
(Axe(SDamage), 3),
|
||||
(Axe(SSpeed), 2),
|
||||
(Axe(SCost), 2),
|
||||
|
||||
(Axe(UnlockLeap), 1),
|
||||
(Axe(LDamage), 2),
|
||||
(Axe(LKnockback), 2),
|
||||
(Axe(LCost), 2),
|
||||
(Axe(LDistance), 2),
|
||||
// Hammer
|
||||
(UnlockGroup(Weapon(Hammer)), 1),
|
||||
|
||||
(Hammer(SsKnockback), 2),
|
||||
(Hammer(SsDamage), 3),
|
||||
(Hammer(SsRegen), 2),
|
||||
(Hammer(SsSpeed), 3),
|
||||
|
||||
(Hammer(CDamage), 3),
|
||||
(Hammer(CKnockback), 3),
|
||||
(Hammer(CDrain), 2),
|
||||
(Hammer(CSpeed), 2),
|
||||
|
||||
(Hammer(UnlockLeap), 1),
|
||||
(Hammer(LDamage), 2),
|
||||
(Hammer(LCost), 2),
|
||||
(Hammer(LDistance), 2),
|
||||
(Hammer(LKnockback), 2),
|
||||
(Hammer(LRange), 2),
|
||||
// Bow
|
||||
(UnlockGroup(Weapon(Bow)), 1),
|
||||
|
||||
(Bow(ProjSpeed), 2),
|
||||
(Bow(BDamage), 3),
|
||||
(Bow(BRegen), 2),
|
||||
|
||||
(Bow(CDamage), 3),
|
||||
(Bow(CKnockback), 2),
|
||||
(Bow(CProjSpeed), 2),
|
||||
(Bow(CDrain), 2),
|
||||
(Bow(CSpeed), 2),
|
||||
(Bow(CMove), 2),
|
||||
|
||||
(Bow(UnlockRepeater), 1),
|
||||
(Bow(RGlide), 1),
|
||||
(Bow(RDamage), 2),
|
||||
(Bow(RArrows), 2),
|
||||
(Bow(RCost), 2),
|
||||
// Staff
|
||||
(UnlockGroup(Weapon(Staff)), 1),
|
||||
|
||||
(Staff(BDamage), 3),
|
||||
(Staff(BRegen), 2),
|
||||
(Staff(BRadius), 3),
|
||||
|
||||
(Staff(FRange), 2),
|
||||
(Staff(FDamage), 3),
|
||||
(Staff(FDrain), 2),
|
||||
(Staff(FVelocity), 2),
|
||||
|
||||
(Staff(UnlockShockwave), 1),
|
||||
(Staff(SDamage), 2),
|
||||
(Staff(SKnockback), 2),
|
||||
(Staff(SRange), 2),
|
||||
(Staff(SCost), 2),
|
||||
// Sceptre
|
||||
(UnlockGroup(Weapon(Sceptre)), 1),
|
||||
|
||||
(Sceptre(LDamage), 3),
|
||||
(Sceptre(LRange), 2),
|
||||
(Sceptre(LLifesteal), 3),
|
||||
(Sceptre(LRegen), 2),
|
||||
|
||||
(Sceptre(HHeal), 3),
|
||||
(Sceptre(HCost), 2),
|
||||
(Sceptre(HRange), 2),
|
||||
|
||||
(Sceptre(UnlockAura), 1),
|
||||
(Sceptre(AStrength), 2),
|
||||
(Sceptre(ADuration), 2),
|
||||
(Sceptre(ARange), 2),
|
||||
(Sceptre(ACost), 2),
|
||||
],
|
||||
})
|
@ -1,6 +1,6 @@
|
||||
use crate::{
|
||||
assets,
|
||||
comp::{self, buff::BuffKind},
|
||||
comp::{self, buff::BuffKind, Skill},
|
||||
npc, terrain,
|
||||
};
|
||||
use assets::AssetExt;
|
||||
@ -92,6 +92,7 @@ pub enum ChatCommand {
|
||||
SetMotd,
|
||||
Site,
|
||||
SkillPoint,
|
||||
SkillPreset,
|
||||
Spawn,
|
||||
Sudo,
|
||||
Tell,
|
||||
@ -100,8 +101,8 @@ pub enum ChatCommand {
|
||||
Unban,
|
||||
Version,
|
||||
Waypoint,
|
||||
Wiring,
|
||||
Whitelist,
|
||||
Wiring,
|
||||
World,
|
||||
}
|
||||
|
||||
@ -157,6 +158,7 @@ pub static CHAT_COMMANDS: &[ChatCommand] = &[
|
||||
ChatCommand::SetMotd,
|
||||
ChatCommand::Site,
|
||||
ChatCommand::SkillPoint,
|
||||
ChatCommand::SkillPreset,
|
||||
ChatCommand::Spawn,
|
||||
ChatCommand::Sudo,
|
||||
ChatCommand::Tell,
|
||||
@ -165,8 +167,8 @@ pub static CHAT_COMMANDS: &[ChatCommand] = &[
|
||||
ChatCommand::Unban,
|
||||
ChatCommand::Version,
|
||||
ChatCommand::Waypoint,
|
||||
ChatCommand::Wiring,
|
||||
ChatCommand::Whitelist,
|
||||
ChatCommand::Wiring,
|
||||
ChatCommand::World,
|
||||
];
|
||||
|
||||
@ -178,6 +180,14 @@ impl assets::Asset for KitManifest {
|
||||
const EXTENSION: &'static str = "ron";
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
|
||||
pub struct SkillPresetManifest(pub HashMap<String, Vec<(Skill, u8)>>);
|
||||
impl assets::Asset for SkillPresetManifest {
|
||||
type Loader = assets::RonLoader;
|
||||
|
||||
const EXTENSION: &'static str = "ron";
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
pub static ref CHAT_SHORTCUTS: HashMap<char, ChatCommand> = [
|
||||
('f', ChatCommand::Faction),
|
||||
@ -290,6 +300,22 @@ lazy_static! {
|
||||
Vec::new()
|
||||
}
|
||||
};
|
||||
|
||||
static ref PRESETS: HashMap<String, Vec<(Skill, u8)>> = {
|
||||
if let Ok(presets) = SkillPresetManifest::load("server.manifests.presets") {
|
||||
presets.read().0.clone()
|
||||
} else {
|
||||
warn!("Error while loading presets");
|
||||
HashMap::new()
|
||||
}
|
||||
};
|
||||
|
||||
static ref PRESET_LIST: Vec<String> = {
|
||||
let mut preset_list: Vec<String> = PRESETS.keys().cloned().collect();
|
||||
preset_list.push("clear".to_owned());
|
||||
|
||||
preset_list
|
||||
};
|
||||
}
|
||||
|
||||
impl ChatCommand {
|
||||
@ -543,6 +569,11 @@ impl ChatCommand {
|
||||
"Give yourself skill points for a particular skill tree",
|
||||
Admin,
|
||||
),
|
||||
ChatCommand::SkillPreset => cmd(
|
||||
vec![Enum("preset_name", PRESET_LIST.to_vec(), Required)],
|
||||
"Gives your character desired skills.",
|
||||
Admin,
|
||||
),
|
||||
ChatCommand::Spawn => cmd(
|
||||
vec![
|
||||
Enum("alignment", ALIGNMENTS.clone(), Required),
|
||||
@ -649,6 +680,7 @@ impl ChatCommand {
|
||||
ChatCommand::SetMotd => "set_motd",
|
||||
ChatCommand::Site => "site",
|
||||
ChatCommand::SkillPoint => "skill_point",
|
||||
ChatCommand::SkillPreset => "skill_preset",
|
||||
ChatCommand::Spawn => "spawn",
|
||||
ChatCommand::Sudo => "sudo",
|
||||
ChatCommand::Tell => "tell",
|
||||
@ -754,7 +786,7 @@ pub enum ArgumentSpec {
|
||||
/// * suggested tab-completion
|
||||
/// * whether it's optional
|
||||
Float(&'static str, f32, Requirement),
|
||||
/// The argument is a float. The associated values are
|
||||
/// The argument is an integer. The associated values are
|
||||
/// * label
|
||||
/// * suggested tab-completion
|
||||
/// * whether it's optional
|
||||
|
@ -143,6 +143,7 @@ fn get_handler(cmd: &ChatCommand) -> CommandHandler {
|
||||
ChatCommand::SetMotd => handle_set_motd,
|
||||
ChatCommand::Site => handle_site,
|
||||
ChatCommand::SkillPoint => handle_skill_point,
|
||||
ChatCommand::SkillPreset => handle_skill_preset,
|
||||
ChatCommand::Spawn => handle_spawn,
|
||||
ChatCommand::Sudo => handle_sudo,
|
||||
ChatCommand::Tell => handle_tell,
|
||||
@ -2714,3 +2715,61 @@ fn cast_buff(kind: &str, data: BuffData, server: &mut Server, target: EcsEntity)
|
||||
}
|
||||
|
||||
fn parse_buffkind(buff: &str) -> Option<BuffKind> { BUFF_PARSER.get(buff).copied() }
|
||||
|
||||
fn handle_skill_preset(
|
||||
server: &mut Server,
|
||||
_client: EcsEntity,
|
||||
target: EcsEntity,
|
||||
args: String,
|
||||
action: &ChatCommand,
|
||||
) -> CmdResult<()> {
|
||||
if let Some(preset) = scan_fmt_some!(&args, &action.arg_fmt(), String) {
|
||||
if let Some(mut skill_set) = server
|
||||
.state
|
||||
.ecs_mut()
|
||||
.write_storage::<comp::SkillSet>()
|
||||
.get_mut(target)
|
||||
{
|
||||
match preset.as_str() {
|
||||
"clear" => {
|
||||
clear_skillset(&mut skill_set);
|
||||
Ok(())
|
||||
},
|
||||
preset => set_skills(&mut skill_set, preset),
|
||||
}
|
||||
} else {
|
||||
Err("Player has no stats!".into())
|
||||
}
|
||||
} else {
|
||||
Err(action.help_string())
|
||||
}
|
||||
}
|
||||
|
||||
fn clear_skillset(skill_set: &mut comp::SkillSet) { *skill_set = comp::SkillSet::default(); }
|
||||
|
||||
fn set_skills(skill_set: &mut comp::SkillSet, preset: &str) -> CmdResult<()> {
|
||||
let presets =
|
||||
if let Ok(presets) = common::cmd::SkillPresetManifest::load("server.manifests.presets") {
|
||||
presets.read().0.clone()
|
||||
} else {
|
||||
return Err("Error while loading presets".to_owned());
|
||||
};
|
||||
if let Some(preset) = presets.get(preset) {
|
||||
for (skill, level) in preset {
|
||||
let group = if let Some(group) = skill.skill_group_kind() {
|
||||
group
|
||||
} else {
|
||||
warn!("Skill in preset doesn't exist in any group");
|
||||
return Err("Preset is broken".to_owned());
|
||||
};
|
||||
for _ in 0..*level {
|
||||
let cost = skill_set.skill_cost(*skill);
|
||||
skill_set.add_skill_points(group, cost);
|
||||
skill_set.unlock_skill(*skill);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
} else {
|
||||
Err("Such preset doesn't exist".to_owned())
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user