Remove sceptre, add swords

This commit is contained in:
Monty Marz 2021-07-29 22:38:35 +00:00
parent c98fd2f27a
commit 14eb0f9aa2
17 changed files with 215 additions and 81 deletions

View File

@ -23,6 +23,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Quotes and escape codes can be used in command arguments - Quotes and escape codes can be used in command arguments
- Toggle chat with a shortcut (default is F5) - Toggle chat with a shortcut (default is F5)
- Pets are now saved on logout 🐕 🦎 🐼 - Pets are now saved on logout 🐕 🦎 🐼
- Dualwielded, one-handed swords as starting weapons (Will be replaced by daggers in the future!)
- Healing sceptre crafting recipe
### Changed ### Changed
@ -41,10 +43,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Trades now consider if items can stack in full inventories. - Trades now consider if items can stack in full inventories.
- The types of animals that can be tamed as pets are now limited to certain species, pending further balancing of pets - The types of animals that can be tamed as pets are now limited to certain species, pending further balancing of pets
### Removed ### Removed
- Enemies no longer spawn in dungeon boss room - Enemies no longer spawn in dungeon boss room
- Melee critical hit no longer applies after reduction by armour - Melee critical hit no longer applies after reduction by armour
- Enemies no more spawn in dungeon boss room
- Melee critical hit no more applies after reduction by armour
- Removed Healing Sceptre as a starting weapon as it is considered an advanced weapon
### Fixed ### Fixed

View File

@ -0,0 +1,21 @@
ItemDef(
name: "Damaged Gladius",
description: "This blade has seen better days.",
kind: Tool((
kind: Sword,
hands: One,
stats: Direct((
equip_time_secs: 0.3,
power: 0.5,
effect_power: 1.0,
speed: 1.0,
crit_chance: 0.16,
range: 1.0,
energy_efficiency: 1.0,
buff_strength: 1.0,
)),
)),
quality: Low,
tags: [],
ability_spec: None,
)

View File

@ -506,6 +506,15 @@
craft_sprite: Some(CraftingBench), craft_sprite: Some(CraftingBench),
is_recycling: false, is_recycling: false,
), ),
"Healing Sceptre": (
output: ("common.items.weapons.sceptre.starter_sceptre", 1),
inputs: [
(Item("common.items.crafting_ing.twigs"), 10),
(Item("common.items.crafting_ing.stones"), 0),
],
craft_sprite: None,
is_recycling: false,
),
"Soothing Loop": ( "Soothing Loop": (
output: ("common.items.weapons.sceptre.loops0", 1), output: ("common.items.weapons.sceptre.loops0", 1),
inputs: [ inputs: [
@ -514,7 +523,7 @@
(Item("common.items.mineral.gem.ruby"), 4), (Item("common.items.mineral.gem.ruby"), 4),
(Item("common.items.tool.craftsman_hammer"), 0), (Item("common.items.tool.craftsman_hammer"), 0),
], ],
craft_sprite: None, craft_sprite: Some(CraftingBench),
is_recycling: false, is_recycling: false,
), ),
"Hunting Bow": ( "Hunting Bow": (

Binary file not shown.

Binary file not shown.

BIN
assets/voxygen/element/weapons/swords.png (Stored with Git LFS) Normal file

Binary file not shown.

View File

@ -61,12 +61,14 @@ Is the client up to date?"#,
"common.species.danari": "Danari", "common.species.danari": "Danari",
"common.weapons.axe": "Axe", "common.weapons.axe": "Axe",
"common.weapons.greatsword": "Greatsword",
"common.weapons.shortswords": "Shortswords",
"common.weapons.sword": "Sword", "common.weapons.sword": "Sword",
"common.weapons.staff": "Staff", "common.weapons.staff": "Firestaff",
"common.weapons.bow": "Bow", "common.weapons.bow": "Bow",
"common.weapons.hammer": "Hammer", "common.weapons.hammer": "Hammer",
"common.weapons.general": "General Combat", "common.weapons.general": "General Combat",
"common.weapons.sceptre": "Sceptre", "common.weapons.sceptre": "Healing Sceptre",
"common.weapons.shield": "Shield", "common.weapons.shield": "Shield",
"common.weapons.spear": "Spear", "common.weapons.spear": "Spear",
"common.weapons.hammer_simple": "Simple Hammer", "common.weapons.hammer_simple": "Simple Hammer",

View File

@ -437,6 +437,10 @@
"voxel.weapon.sword_1h.cobalt-3", "voxel.weapon.sword_1h.cobalt-3",
(1.0, -1.0, 0.0), (-135.0, 90.0, 0.0), 1.2, (1.0, -1.0, 0.0), (-135.0, 90.0, 0.0), 1.2,
), ),
Tool("common.items.weapons.sword_1h.starter"): VoxTrans(
"voxel.weapon.sword_1h.starter",
(-1.0, 1.0, 0.0), (-135.0, 90.0, 0.0), 1.2,
),
Tool("common.items.weapons.sword_1h.iron-0"): VoxTrans( Tool("common.items.weapons.sword_1h.iron-0"): VoxTrans(
"voxel.weapon.sword_1h.iron-0", "voxel.weapon.sword_1h.iron-0",
(1.0, -1.0, 0.0), (-135.0, 90.0, 0.0), 1.2, (1.0, -1.0, 0.0), (-135.0, 90.0, 0.0), 1.2,

View File

@ -224,6 +224,10 @@
vox_spec: ("weapon.sword_1h.iron-4", (-2.0, -4.5, -3.0)), vox_spec: ("weapon.sword_1h.iron-4", (-2.0, -4.5, -3.0)),
color: None color: None
), ),
"common.items.weapons.sword_1h.starter": (
vox_spec: ("weapon.sword_1h.starter", (-2.0, -4.5, -3.0)),
color: None
),
"common.items.weapons.sword_1h.obsidian-0": ( "common.items.weapons.sword_1h.obsidian-0": (
vox_spec: ("weapon.sword_1h.obsidian-0", (-2.0, -4.5, -3.0)), vox_spec: ("weapon.sword_1h.obsidian-0", (-2.0, -4.5, -3.0)),
color: None color: None

BIN
assets/voxygen/voxel/weapon/sword_1h/starter.vox (Stored with Git LFS) Normal file

Binary file not shown.

View File

@ -174,6 +174,7 @@ impl BotClient {
client.create_character( client.create_character(
cred.username.clone(), cred.username.clone(),
Some("common.items.weapons.sword.starter".to_string()), Some("common.items.weapons.sword.starter".to_string()),
None,
body.into(), body.into(),
); );
client.load_character_list(); client.load_character_list();

View File

@ -826,9 +826,20 @@ impl Client {
} }
/// New character creation /// New character creation
pub fn create_character(&mut self, alias: String, tool: Option<String>, body: comp::Body) { pub fn create_character(
&mut self,
alias: String,
mainhand: Option<String>,
offhand: Option<String>,
body: comp::Body,
) {
self.character_list.loading = true; self.character_list.loading = true;
self.send_msg(ClientGeneral::CreateCharacter { alias, tool, body }); self.send_msg(ClientGeneral::CreateCharacter {
alias,
mainhand,
offhand,
body,
});
} }
/// Character deletion /// Character deletion

View File

@ -51,7 +51,8 @@ pub enum ClientGeneral {
RequestCharacterList, RequestCharacterList,
CreateCharacter { CreateCharacter {
alias: String, alias: String,
tool: Option<String>, mainhand: Option<String>,
offhand: Option<String>,
body: comp::Body, body: comp::Body,
}, },
DeleteCharacter(CharacterId), DeleteCharacter(CharacterId),

View File

@ -4,45 +4,54 @@ use common::comp::{
}; };
use specs::{Entity, WriteExpect}; use specs::{Entity, WriteExpect};
const VALID_STARTER_ITEMS: [&str; 6] = [ const VALID_STARTER_ITEMS: &[[Option<&str>; 2]] = &[
"common.items.weapons.hammer.starter_hammer", [None, None], // Not used with an unmodified client but should still be allowed (zesterer)
"common.items.weapons.bow.starter", [Some("common.items.weapons.hammer.starter_hammer"), None],
"common.items.weapons.axe.starter_axe", [Some("common.items.weapons.bow.starter"), None],
"common.items.weapons.staff.starter_staff", [Some("common.items.weapons.axe.starter_axe"), None],
"common.items.weapons.sword.starter", [Some("common.items.weapons.staff.starter_staff"), None],
"common.items.weapons.sceptre.starter_sceptre", [Some("common.items.weapons.sword.starter"), None],
[
Some("common.items.weapons.sword_1h.starter"),
Some("common.items.weapons.sword_1h.starter"),
],
]; ];
#[derive(Debug)]
pub enum CreationError {
InvalidWeapon,
InvalidBody,
}
pub fn create_character( pub fn create_character(
entity: Entity, entity: Entity,
player_uuid: String, player_uuid: String,
character_alias: String, character_alias: String,
character_tool: Option<String>, character_mainhand: Option<String>,
character_offhand: Option<String>,
body: Body, body: Body,
character_updater: &mut WriteExpect<'_, CharacterUpdater>, character_updater: &mut WriteExpect<'_, CharacterUpdater>,
) { ) -> Result<(), CreationError> {
// quick fix whitelist validation for now; eventually replace the // quick fix whitelist validation for now; eventually replace the
// `Option<String>` with an index into a server-provided list of starter // `Option<String>` with an index into a server-provided list of starter
// items, and replace `comp::body::Body` with `comp::body::humanoid::Body` // items, and replace `comp::body::Body` with `comp::body::humanoid::Body`
// throughout the messages involved // throughout the messages involved
let tool_id = match character_tool {
Some(tool_id) if VALID_STARTER_ITEMS.contains(&&*tool_id) => tool_id,
_ => return,
};
if !matches!(body, Body::Humanoid(_)) { if !matches!(body, Body::Humanoid(_)) {
return; return Err(CreationError::InvalidBody);
} }
if !VALID_STARTER_ITEMS.contains(&[character_mainhand.as_deref(), character_offhand.as_deref()])
let stats = Stats::new(character_alias.to_string()); {
let skill_set = SkillSet::default(); return Err(CreationError::InvalidWeapon);
};
// The client sends None if a weapon hand is empty
let loadout = LoadoutBuilder::empty() let loadout = LoadoutBuilder::empty()
.defaults() .defaults()
.active_mainhand(Some(Item::new_from_asset_expect(&tool_id))) .active_mainhand(character_mainhand.map(|x| Item::new_from_asset_expect(&x)))
.active_offhand(character_offhand.map(|x| Item::new_from_asset_expect(&x)))
.build(); .build();
let mut inventory = Inventory::new_with_loadout(loadout); let mut inventory = Inventory::new_with_loadout(loadout);
let stats = Stats::new(character_alias.to_string());
let skill_set = SkillSet::default();
// Default items for new characters // Default items for new characters
inventory inventory
.push(Item::new_from_asset_expect( .push(Item::new_from_asset_expect(
@ -61,4 +70,21 @@ pub fn create_character(
character_alias, character_alias,
(body, stats, skill_set, inventory, waypoint, Vec::new()), (body, stats, skill_set, inventory, waypoint, Vec::new()),
); );
Ok(())
}
// Error handling
impl core::fmt::Display for CreationError {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
CreationError::InvalidWeapon => write!(
f,
"Invalid weapon.\nServer and client might be partially incompatible."
),
CreationError::InvalidBody => write!(
f,
"Invalid Body.\nServer and client might be partially incompatible"
),
}
}
} }

View File

@ -115,19 +115,34 @@ impl Sys {
character_loader.load_character_list(entity, player.uuid().to_string()) character_loader.load_character_list(entity, player.uuid().to_string())
} }
}, },
ClientGeneral::CreateCharacter { alias, tool, body } => { ClientGeneral::CreateCharacter {
alias,
mainhand,
offhand,
body,
} => {
if let Err(error) = alias_validator.validate(&alias) { if let Err(error) = alias_validator.validate(&alias) {
debug!(?error, ?alias, "denied alias as it contained a banned word"); debug!(?error, ?alias, "denied alias as it contained a banned word");
client.send(ServerGeneral::CharacterActionError(error.to_string()))?; client.send(ServerGeneral::CharacterActionError(error.to_string()))?;
} else if let Some(player) = players.get(entity) { } else if let Some(player) = players.get(entity) {
character_creator::create_character( if let Err(error) = character_creator::create_character(
entity, entity,
player.uuid().to_string(), player.uuid().to_string(),
alias, alias,
tool, mainhand.clone(),
offhand.clone(),
body, body,
character_updater, character_updater,
) {
debug!(
?error,
?mainhand,
?offhand,
?body,
"Denied creating character because of invalid input."
); );
client.send(ServerGeneral::CharacterActionError(error.to_string()))?;
}
} }
}, },
ClientGeneral::DeleteCharacter(character_id) => { ClientGeneral::DeleteCharacter(character_id) => {

View File

@ -109,10 +109,15 @@ impl PlayState for CharSelectionState {
ui::Event::Logout => { ui::Event::Logout => {
return PlayStateResult::Pop; return PlayStateResult::Pop;
}, },
ui::Event::AddCharacter { alias, tool, body } => { ui::Event::AddCharacter {
alias,
mainhand,
offhand,
body,
} => {
self.client self.client
.borrow_mut() .borrow_mut()
.create_character(alias, Some(tool), body); .create_character(alias, mainhand, offhand, body);
}, },
ui::Event::DeleteCharacter(character_id) => { ui::Event::DeleteCharacter(character_id) => {
self.client.borrow_mut().delete_character(character_id); self.client.borrow_mut().delete_character(character_id);

View File

@ -52,7 +52,8 @@ const STARTER_BOW: &str = "common.items.weapons.bow.starter";
const STARTER_AXE: &str = "common.items.weapons.axe.starter_axe"; const STARTER_AXE: &str = "common.items.weapons.axe.starter_axe";
const STARTER_STAFF: &str = "common.items.weapons.staff.starter_staff"; const STARTER_STAFF: &str = "common.items.weapons.staff.starter_staff";
const STARTER_SWORD: &str = "common.items.weapons.sword.starter"; const STARTER_SWORD: &str = "common.items.weapons.sword.starter";
const STARTER_SCEPTRE: &str = "common.items.weapons.sceptre.starter_sceptre"; const STARTER_SWORDS: &str = "common.items.weapons.sword_1h.starter";
// TODO: what does this comment mean? // TODO: what does this comment mean?
// // Use in future MR to make this a starter weapon // // Use in future MR to make this a starter weapon
@ -67,9 +68,9 @@ image_ids_ice! {
slider_range: "voxygen.element.ui.generic.slider.track", slider_range: "voxygen.element.ui.generic.slider.track",
slider_indicator: "voxygen.element.ui.generic.slider.indicator", slider_indicator: "voxygen.element.ui.generic.slider.indicator",
selection: "voxygen.element.ui.generic.frames.selection", char_selection: "voxygen.element.ui.generic.frames.selection",
selection_hover: "voxygen.element.ui.generic.frames.selection_hover", char_selection_hover: "voxygen.element.ui.generic.frames.selection_hover",
selection_press: "voxygen.element.ui.generic.frames.selection_press", char_selection_press: "voxygen.element.ui.generic.frames.selection_press",
delete_button: "voxygen.element.ui.char_select.icons.bin", delete_button: "voxygen.element.ui.char_select.icons.bin",
delete_button_hover: "voxygen.element.ui.char_select.icons.bin_hover", delete_button_hover: "voxygen.element.ui.char_select.icons.bin_hover",
@ -78,7 +79,7 @@ image_ids_ice! {
name_input: "voxygen.element.ui.generic.textbox", name_input: "voxygen.element.ui.generic.textbox",
// Tool Icons // Tool Icons
sceptre: "voxygen.element.weapons.sceptre", swords: "voxygen.element.weapons.swords",
sword: "voxygen.element.weapons.sword", sword: "voxygen.element.weapons.sword",
axe: "voxygen.element.weapons.axe", axe: "voxygen.element.weapons.axe",
hammer: "voxygen.element.weapons.hammer", hammer: "voxygen.element.weapons.hammer",
@ -124,7 +125,8 @@ pub enum Event {
Play(CharacterId), Play(CharacterId),
AddCharacter { AddCharacter {
alias: String, alias: String,
tool: String, mainhand: Option<String>,
offhand: Option<String>,
body: comp::Body, body: comp::Body,
}, },
DeleteCharacter(CharacterId), DeleteCharacter(CharacterId),
@ -148,7 +150,8 @@ enum Mode {
name: String, name: String,
body: humanoid::Body, body: humanoid::Body,
inventory: Box<comp::inventory::Inventory>, inventory: Box<comp::inventory::Inventory>,
tool: &'static str, mainhand: Option<&'static str>,
offhand: Option<&'static str>,
body_type_buttons: [button::State; 2], body_type_buttons: [button::State; 2],
species_buttons: [button::State; 6], species_buttons: [button::State; 6],
@ -178,11 +181,15 @@ impl Mode {
} }
pub fn create(name: String) -> Self { pub fn create(name: String) -> Self {
let tool = STARTER_SWORD; // TODO: Load these from the server (presumably from a .ron) to allow for easier
// modification of custom starting weapons
let mainhand = Some(STARTER_SWORD);
let offhand = None;
let loadout = LoadoutBuilder::empty() let loadout = LoadoutBuilder::empty()
.defaults() .defaults()
.active_mainhand(Some(Item::new_from_asset_expect(tool))) .active_mainhand(mainhand.map(Item::new_from_asset_expect))
.active_offhand(offhand.map(Item::new_from_asset_expect))
.build(); .build();
let inventory = Box::new(Inventory::new_with_loadout(loadout)); let inventory = Box::new(Inventory::new_with_loadout(loadout));
@ -191,7 +198,8 @@ impl Mode {
name, name,
body: humanoid::Body::random(), body: humanoid::Body::random(),
inventory, inventory,
tool, mainhand,
offhand,
body_type_buttons: Default::default(), body_type_buttons: Default::default(),
species_buttons: Default::default(), species_buttons: Default::default(),
tool_buttons: Default::default(), tool_buttons: Default::default(),
@ -244,7 +252,7 @@ enum Message {
Name(String), Name(String),
BodyType(humanoid::BodyType), BodyType(humanoid::BodyType),
Species(humanoid::Species), Species(humanoid::Species),
Tool(&'static str), Tool((Option<&'static str>, Option<&'static str>)),
RandomizeCharacter, RandomizeCharacter,
RandomizeName, RandomizeName,
CancelDeletion, CancelDeletion,
@ -468,12 +476,12 @@ impl Controls {
.padding(10) .padding(10)
.style( .style(
style::button::Style::new(if Some(i) == selected { style::button::Style::new(if Some(i) == selected {
imgs.selection_hover imgs.char_selection_hover
} else { } else {
imgs.selection imgs.char_selection
}) })
.hover_image(imgs.selection_hover) .hover_image(imgs.char_selection_hover)
.press_image(imgs.selection_press) .press_image(imgs.char_selection_press)
.image_color(Rgba::new( .image_color(Rgba::new(
select_col.0, select_col.0,
select_col.1, select_col.1,
@ -485,7 +493,7 @@ impl Controls {
.height(Length::Fill) .height(Length::Fill)
.on_press(Message::Select(character_id)), .on_press(Message::Select(character_id)),
) )
.ratio_of_image(imgs.selection), .ratio_of_image(imgs.char_selection),
) )
.padding(0) .padding(0)
.align_x(Align::End) .align_x(Align::End)
@ -514,9 +522,9 @@ impl Controls {
.center_y(), .center_y(),
) )
.style( .style(
style::button::Style::new(imgs.selection) style::button::Style::new(imgs.char_selection)
.hover_image(imgs.selection_hover) .hover_image(imgs.char_selection_hover)
.press_image(imgs.selection_press) .press_image(imgs.char_selection_press)
.image_color(Rgba::new(color.0, color.1, color.2, 255)) .image_color(Rgba::new(color.0, color.1, color.2, 255))
.text_color(iced::Color::from_rgb8(color.0, color.1, color.2)) .text_color(iced::Color::from_rgb8(color.0, color.1, color.2))
.disabled_text_color(iced::Color::from_rgb8( .disabled_text_color(iced::Color::from_rgb8(
@ -531,7 +539,7 @@ impl Controls {
button button
} }
}) })
.ratio_of_image(imgs.selection) .ratio_of_image(imgs.char_selection)
.into(), .into(),
); );
characters characters
@ -710,7 +718,8 @@ impl Controls {
name, name,
body, body,
inventory: _, inventory: _,
tool, mainhand,
offhand: _,
ref mut scroll, ref mut scroll,
ref mut body_type_buttons, ref mut body_type_buttons,
ref mut species_buttons, ref mut species_buttons,
@ -863,30 +872,30 @@ impl Controls {
]) ])
.spacing(1); .spacing(1);
let [ref mut sword_button, ref mut sceptre_button, ref mut axe_button, ref mut hammer_button, ref mut bow_button, ref mut staff_button] = let [ref mut sword_button, ref mut swords_button, ref mut axe_button, ref mut hammer_button, ref mut bow_button, ref mut staff_button] =
tool_buttons; tool_buttons;
let tool = Column::with_children(vec![ let tool = Column::with_children(vec![
Row::with_children(vec![ Row::with_children(vec![
icon_button_tooltip( icon_button_tooltip(
sword_button, sword_button,
*tool == STARTER_SWORD, *mainhand == Some(STARTER_SWORD),
Message::Tool(STARTER_SWORD), Message::Tool((Some(STARTER_SWORD), None)),
imgs.sword, imgs.sword,
"common.weapons.sword", "common.weapons.greatsword",
) )
.into(), .into(),
icon_button_tooltip( icon_button_tooltip(
hammer_button, hammer_button,
*tool == STARTER_HAMMER, *mainhand == Some(STARTER_HAMMER),
Message::Tool(STARTER_HAMMER), Message::Tool((Some(STARTER_HAMMER), None)),
imgs.hammer, imgs.hammer,
"common.weapons.hammer", "common.weapons.hammer",
) )
.into(), .into(),
icon_button_tooltip( icon_button_tooltip(
axe_button, axe_button,
*tool == STARTER_AXE, *mainhand == Some(STARTER_AXE),
Message::Tool(STARTER_AXE), Message::Tool((Some(STARTER_AXE), None)),
imgs.axe, imgs.axe,
"common.weapons.axe", "common.weapons.axe",
) )
@ -896,25 +905,26 @@ impl Controls {
.into(), .into(),
Row::with_children(vec![ Row::with_children(vec![
icon_button_tooltip( icon_button_tooltip(
sceptre_button, swords_button,
*tool == STARTER_SCEPTRE, *mainhand == Some(STARTER_SWORDS),
Message::Tool(STARTER_SCEPTRE), Message::Tool((Some(STARTER_SWORDS), Some(STARTER_SWORDS))),
imgs.sceptre, imgs.swords,
"common.weapons.sceptre", "common.weapons.greatsword
",
) )
.into(), .into(),
icon_button_tooltip( icon_button_tooltip(
bow_button, bow_button,
*tool == STARTER_BOW, *mainhand == Some(STARTER_BOW),
Message::Tool(STARTER_BOW), Message::Tool((Some(STARTER_BOW), None)),
imgs.bow, imgs.bow,
"common.weapons.bow", "common.weapons.bow",
) )
.into(), .into(),
icon_button_tooltip( icon_button_tooltip(
staff_button, staff_button,
*tool == STARTER_STAFF, *mainhand == Some(STARTER_STAFF),
Message::Tool(STARTER_STAFF), Message::Tool((Some(STARTER_STAFF), None)),
imgs.staff, imgs.staff,
"common.weapons.staff", "common.weapons.staff",
) )
@ -1076,8 +1086,8 @@ impl Controls {
let column_content = vec![ let column_content = vec![
body_type.into(), body_type.into(),
species.into(),
tool.into(), tool.into(),
species.into(),
slider_options.into(), slider_options.into(),
rand_character.into(), rand_character.into(),
]; ];
@ -1300,12 +1310,17 @@ impl Controls {
}, },
Message::CreateCharacter => { Message::CreateCharacter => {
if let Mode::Create { if let Mode::Create {
name, body, tool, .. name,
body,
mainhand,
offhand,
..
} = &self.mode } = &self.mode
{ {
events.push(Event::AddCharacter { events.push(Event::AddCharacter {
alias: name.clone(), alias: name.clone(),
tool: String::from(*tool), mainhand: mainhand.map(String::from),
offhand: offhand.map(String::from),
body: comp::Body::Humanoid(*body), body: comp::Body::Humanoid(*body),
}); });
self.mode = Mode::select(Some(InfoContent::CreatingCharacter)); self.mode = Mode::select(Some(InfoContent::CreatingCharacter));
@ -1330,13 +1345,21 @@ impl Controls {
}, },
Message::Tool(value) => { Message::Tool(value) => {
if let Mode::Create { if let Mode::Create {
tool, inventory, .. mainhand,
offhand,
inventory,
..
} = &mut self.mode } = &mut self.mode
{ {
*tool = value; *mainhand = value.0;
*offhand = value.1;
inventory.replace_loadout_item( inventory.replace_loadout_item(
EquipSlot::ActiveMainhand, EquipSlot::ActiveMainhand,
Some(Item::new_from_asset_expect(*tool)), mainhand.map(|specifier| Item::new_from_asset_expect(specifier)),
);
inventory.replace_loadout_item(
EquipSlot::ActiveOffhand,
offhand.map(|specifier| Item::new_from_asset_expect(specifier)),
); );
} }
}, },