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.
|
- 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
|
- /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.
|
- 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
|
### 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::{
|
use crate::{
|
||||||
assets,
|
assets,
|
||||||
comp::{self, buff::BuffKind},
|
comp::{self, buff::BuffKind, Skill},
|
||||||
npc, terrain,
|
npc, terrain,
|
||||||
};
|
};
|
||||||
use assets::AssetExt;
|
use assets::AssetExt;
|
||||||
@ -92,6 +92,7 @@ pub enum ChatCommand {
|
|||||||
SetMotd,
|
SetMotd,
|
||||||
Site,
|
Site,
|
||||||
SkillPoint,
|
SkillPoint,
|
||||||
|
SkillPreset,
|
||||||
Spawn,
|
Spawn,
|
||||||
Sudo,
|
Sudo,
|
||||||
Tell,
|
Tell,
|
||||||
@ -100,8 +101,8 @@ pub enum ChatCommand {
|
|||||||
Unban,
|
Unban,
|
||||||
Version,
|
Version,
|
||||||
Waypoint,
|
Waypoint,
|
||||||
Wiring,
|
|
||||||
Whitelist,
|
Whitelist,
|
||||||
|
Wiring,
|
||||||
World,
|
World,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -157,6 +158,7 @@ pub static CHAT_COMMANDS: &[ChatCommand] = &[
|
|||||||
ChatCommand::SetMotd,
|
ChatCommand::SetMotd,
|
||||||
ChatCommand::Site,
|
ChatCommand::Site,
|
||||||
ChatCommand::SkillPoint,
|
ChatCommand::SkillPoint,
|
||||||
|
ChatCommand::SkillPreset,
|
||||||
ChatCommand::Spawn,
|
ChatCommand::Spawn,
|
||||||
ChatCommand::Sudo,
|
ChatCommand::Sudo,
|
||||||
ChatCommand::Tell,
|
ChatCommand::Tell,
|
||||||
@ -165,8 +167,8 @@ pub static CHAT_COMMANDS: &[ChatCommand] = &[
|
|||||||
ChatCommand::Unban,
|
ChatCommand::Unban,
|
||||||
ChatCommand::Version,
|
ChatCommand::Version,
|
||||||
ChatCommand::Waypoint,
|
ChatCommand::Waypoint,
|
||||||
ChatCommand::Wiring,
|
|
||||||
ChatCommand::Whitelist,
|
ChatCommand::Whitelist,
|
||||||
|
ChatCommand::Wiring,
|
||||||
ChatCommand::World,
|
ChatCommand::World,
|
||||||
];
|
];
|
||||||
|
|
||||||
@ -178,6 +180,14 @@ impl assets::Asset for KitManifest {
|
|||||||
const EXTENSION: &'static str = "ron";
|
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! {
|
lazy_static! {
|
||||||
pub static ref CHAT_SHORTCUTS: HashMap<char, ChatCommand> = [
|
pub static ref CHAT_SHORTCUTS: HashMap<char, ChatCommand> = [
|
||||||
('f', ChatCommand::Faction),
|
('f', ChatCommand::Faction),
|
||||||
@ -290,6 +300,22 @@ lazy_static! {
|
|||||||
Vec::new()
|
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 {
|
impl ChatCommand {
|
||||||
@ -543,6 +569,11 @@ impl ChatCommand {
|
|||||||
"Give yourself skill points for a particular skill tree",
|
"Give yourself skill points for a particular skill tree",
|
||||||
Admin,
|
Admin,
|
||||||
),
|
),
|
||||||
|
ChatCommand::SkillPreset => cmd(
|
||||||
|
vec![Enum("preset_name", PRESET_LIST.to_vec(), Required)],
|
||||||
|
"Gives your character desired skills.",
|
||||||
|
Admin,
|
||||||
|
),
|
||||||
ChatCommand::Spawn => cmd(
|
ChatCommand::Spawn => cmd(
|
||||||
vec![
|
vec![
|
||||||
Enum("alignment", ALIGNMENTS.clone(), Required),
|
Enum("alignment", ALIGNMENTS.clone(), Required),
|
||||||
@ -649,6 +680,7 @@ impl ChatCommand {
|
|||||||
ChatCommand::SetMotd => "set_motd",
|
ChatCommand::SetMotd => "set_motd",
|
||||||
ChatCommand::Site => "site",
|
ChatCommand::Site => "site",
|
||||||
ChatCommand::SkillPoint => "skill_point",
|
ChatCommand::SkillPoint => "skill_point",
|
||||||
|
ChatCommand::SkillPreset => "skill_preset",
|
||||||
ChatCommand::Spawn => "spawn",
|
ChatCommand::Spawn => "spawn",
|
||||||
ChatCommand::Sudo => "sudo",
|
ChatCommand::Sudo => "sudo",
|
||||||
ChatCommand::Tell => "tell",
|
ChatCommand::Tell => "tell",
|
||||||
@ -754,7 +786,7 @@ pub enum ArgumentSpec {
|
|||||||
/// * suggested tab-completion
|
/// * suggested tab-completion
|
||||||
/// * whether it's optional
|
/// * whether it's optional
|
||||||
Float(&'static str, f32, Requirement),
|
Float(&'static str, f32, Requirement),
|
||||||
/// The argument is a float. The associated values are
|
/// The argument is an integer. The associated values are
|
||||||
/// * label
|
/// * label
|
||||||
/// * suggested tab-completion
|
/// * suggested tab-completion
|
||||||
/// * whether it's optional
|
/// * whether it's optional
|
||||||
|
@ -143,6 +143,7 @@ fn get_handler(cmd: &ChatCommand) -> CommandHandler {
|
|||||||
ChatCommand::SetMotd => handle_set_motd,
|
ChatCommand::SetMotd => handle_set_motd,
|
||||||
ChatCommand::Site => handle_site,
|
ChatCommand::Site => handle_site,
|
||||||
ChatCommand::SkillPoint => handle_skill_point,
|
ChatCommand::SkillPoint => handle_skill_point,
|
||||||
|
ChatCommand::SkillPreset => handle_skill_preset,
|
||||||
ChatCommand::Spawn => handle_spawn,
|
ChatCommand::Spawn => handle_spawn,
|
||||||
ChatCommand::Sudo => handle_sudo,
|
ChatCommand::Sudo => handle_sudo,
|
||||||
ChatCommand::Tell => handle_tell,
|
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 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