feat: store items as RON files

When a new item is created, a ron file will be used as a template
This commit is contained in:
timokoesters
2019-10-22 20:18:40 +02:00
parent edd56e2fc0
commit 20248a4818
41 changed files with 364 additions and 415 deletions

1
Cargo.lock generated
View File

@ -3609,6 +3609,7 @@ dependencies = [
"parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
"rayon 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "rayon 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"ron 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",

View File

@ -0,0 +1,11 @@
Item(
name: "An apple",
description: "Looks refreshing",
kind: Consumable(
kind: Apple,
effect: Health((
amount: 10,
cause: Item,
)),
),
)

View File

@ -0,0 +1,5 @@
Item(
name: "Boost rod",
description: "Your legs feel full of energy while holding this",
kind: Debug(Boost),
)

View File

@ -0,0 +1,5 @@
Item(
name: "Possession rod",
description: "Your body seems loose while holding this",
kind: Debug(Possess),
)

View File

@ -0,0 +1,5 @@
Item(
name: "A blue flower",
description: "Look beautiful",
kind: Ingredient(Flower),
)

View File

@ -0,0 +1,5 @@
Item(
name: "A pink flower",
description: "Look beautiful",
kind: Ingredient(Flower),
)

View File

@ -0,0 +1,5 @@
Item(
name: "A red flower",
description: "Look beautiful",
kind: Ingredient(Flower),
)

View File

@ -0,0 +1,5 @@
Item(
name: "A sunflower",
description: "Look beautiful",
kind: Ingredient(Flower),
)

View File

@ -0,0 +1,5 @@
Item(
name: "A white flower",
description: "Look beautiful",
kind: Ingredient(Flower),
)

View File

@ -0,0 +1,5 @@
Item(
name: "A yellow flower",
description: "Look beautiful",
kind: Ingredient(Flower),
)

View File

@ -0,0 +1,5 @@
Item(
name: "Long grass",
description: "Just some grass",
kind: Ingredient(Grass),
)

View File

@ -0,0 +1,5 @@
Item(
name: "Medium grass",
description: "Just some grass",
kind: Ingredient(Grass),
)

View File

@ -0,0 +1,5 @@
Item(
name: "Short grass",
description: "Just some grass",
kind: Ingredient(Grass),
)

View File

@ -0,0 +1,11 @@
Item(
name: "A mushroom",
description: "It's dirty, but looks edible",
kind: Consumable(
kind: Mushroom,
effect: Health((
amount: 10,
cause: Item,
)),
),
)

View File

@ -0,0 +1,8 @@
Item(
name: "Velorite",
description: "It's smooth and looks edible",
kind: Consumable(
kind: Velorite,
effect: Xp(50),
),
)

View File

@ -0,0 +1,8 @@
Item(
name: "Velorite Fragment",
description: "It's dirty, but looks edible",
kind: Consumable(
kind: VeloriteFrag,
effect: Xp(20),
),
)

View File

@ -0,0 +1,8 @@
Item(
name: "Your first axe",
description: "A dusty axe that looks surprisingly weak",
kind: Tool(
kind: Axe,
power: 10,
),
)

View File

@ -0,0 +1,8 @@
Item(
name: "Your first bow",
description: "A dusty bow that looks surprisingly weak",
kind: Tool(
kind: Bow,
power: 10,
),
)

View File

@ -0,0 +1,8 @@
Item(
name: "Your first dagger",
description: "A dusty dagger that looks surprisingly weak",
kind: Tool(
kind: Dagger,
power: 10,
),
)

View File

@ -0,0 +1,8 @@
Item(
name: "Your first hammer",
description: "A dusty hammer that looks surprisingly weak",
kind: Tool(
kind: Hammer,
power: 10,
),
)

View File

@ -0,0 +1,8 @@
Item(
name: "Your first staff",
description: "A dusty staff that looks surprisingly weak",
kind: Tool(
kind: Staff,
power: 10,
),
)

View File

@ -0,0 +1,8 @@
Item(
name: "Your first sword",
description: "A dusty sword that looks surprisingly weak",
kind: Tool(
kind: Sword,
power: 10,
),
)

View File

@ -169,12 +169,7 @@ impl Client {
} }
/// Request a state transition to `ClientState::Character`. /// Request a state transition to `ClientState::Character`.
pub fn request_character( pub fn request_character(&mut self, name: String, body: comp::Body, main: Option<String>) {
&mut self,
name: String,
body: comp::Body,
main: Option<comp::item::Tool>,
) {
self.postbox self.postbox
.send_message(ClientMsg::Character { name, body, main }); .send_message(ClientMsg::Character { name, body, main });
self.client_state = ClientState::Pending; self.client_state = ClientState::Pending;

View File

@ -17,6 +17,7 @@ mio-extras = "2.0.5"
serde = "1.0.98" serde = "1.0.98"
serde_derive = "1.0.98" serde_derive = "1.0.98"
serde_json = "1.0.40" serde_json = "1.0.40"
ron = "0.5.1"
bincode = "1.1.4" bincode = "1.1.4"
log = "0.4.8" log = "0.4.8"
rand = "0.7.0" rand = "0.7.0"

View File

@ -84,6 +84,12 @@ pub fn load<A: Asset + 'static>(specifier: &str) -> Result<Arc<A>, Error> {
load_map(specifier, |x| x) load_map(specifier, |x| x)
} }
/// Function used to load assets from the filesystem or the cache and return a clone.
pub fn load_cloned<A: Asset + Clone + 'static>(specifier: &str) -> Option<A> {
let asset: Option<Arc<A>> = load(specifier).ok();
asset.map(|asset| (*asset).clone())
}
/// Function used to load essential assets from the filesystem or the cache. It will panic if the asset is not found. /// Function used to load essential assets from the filesystem or the cache. It will panic if the asset is not found.
/// Example usage: /// Example usage:
/// ```no_run /// ```no_run
@ -96,6 +102,12 @@ pub fn load_expect<A: Asset + 'static>(specifier: &str) -> Arc<A> {
load(specifier).unwrap_or_else(|_| panic!("Failed loading essential asset: {}", specifier)) load(specifier).unwrap_or_else(|_| panic!("Failed loading essential asset: {}", specifier))
} }
/// Function used to load essential assets from the filesystem or the cache and return a clone. It will panic if the asset is not found.
pub fn load_expect_cloned<A: Asset + Clone + 'static>(specifier: &str) -> A {
let asset: Arc<A> = load_expect(specifier);
(*asset).clone()
}
/// Load an asset while registering it to be watched and reloaded when it changes /// Load an asset while registering it to be watched and reloaded when it changes
pub fn load_watched<A: Asset + 'static>( pub fn load_watched<A: Asset + 'static>(
specifier: &str, specifier: &str,

View File

@ -1,11 +1,12 @@
use crate::{ use crate::{
comp, assets::{self, Asset},
effect::Effect, effect::Effect,
terrain::{Block, BlockKind}, terrain::{Block, BlockKind},
}; };
use rand::prelude::*;
use specs::{Component, FlaggedStorage}; use specs::{Component, FlaggedStorage};
use specs_idvs::IDVStorage; use specs_idvs::IDVStorage;
use std::fs::File;
use std::io::BufReader;
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum Tool { pub enum Tool {
@ -18,52 +19,6 @@ pub enum Tool {
Staff, Staff,
} }
impl Tool {
pub fn name(&self) -> &'static str {
match self {
Tool::Dagger => "Dagger",
Tool::Shield => "Shield",
Tool::Sword => "Sword",
Tool::Axe => "Axe",
Tool::Hammer => "Hammer",
Tool::Bow => "Bow",
Tool::Staff => "Staff",
}
}
pub fn description(&self) -> &'static str {
match self {
Tool::Dagger => {
"A basic kitchen knife.\n\
NOT YET AVAILABLE."
}
Tool::Shield => {
"This shield belonged to many adventurers.\n\
Now it's yours.\n\
NOT YET AVAILABLE."
}
Tool::Sword => "When closing one eye it's nearly like it wasn't rusty at all!",
Tool::Axe => {
"It has a name written on it.\n\
Sounds dwarvish."
}
Tool::Hammer => "Use with caution around nails.",
Tool::Bow => "An old but sturdy hunting bow.",
Tool::Staff => "The wood smells like magic.",
}
}
}
pub const ALL_TOOLS: [Tool; 7] = [
Tool::Dagger,
Tool::Shield,
Tool::Sword,
Tool::Axe,
Tool::Hammer,
Tool::Bow,
Tool::Staff,
];
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum Armor { pub enum Armor {
// TODO: Don't make armor be a body part. Wearing enemy's head is funny but also a creepy thing to do. // TODO: Don't make armor be a body part. Wearing enemy's head is funny but also a creepy thing to do.
@ -80,28 +35,6 @@ pub enum Armor {
Necklace, Necklace,
} }
impl Armor {
pub fn name(&self) -> &'static str {
match self {
Armor::Helmet => "Helmet",
Armor::Shoulders => "Shoulder Pads",
Armor::Chestplate => "Chestplate",
Armor::Belt => "Belt",
Armor::Gloves => "Gloves",
Armor::Pants => "Pants",
Armor::Boots => "Boots",
Armor::Back => "Back",
Armor::Tabard => "Tabard",
Armor::Gem => "Gem",
Armor::Necklace => "Necklace",
}
}
pub fn description(&self) -> &'static str {
self.name()
}
}
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum Consumable { pub enum Consumable {
Apple, Apple,
@ -111,50 +44,12 @@ pub enum Consumable {
VeloriteFrag, VeloriteFrag,
} }
impl Consumable {
pub fn name(&self) -> &'static str {
match self {
Consumable::Apple => "Apple",
Consumable::Potion => "Potion",
Consumable::Mushroom => "Mushroom",
Consumable::Velorite => "Velorite",
Consumable::VeloriteFrag => "Glowing Fragment",
}
}
pub fn description(&self) -> &'static str {
match self {
Consumable::Apple => "A tasty Apple.",
Consumable::Potion => "This Potion contains the essence of Life.",
Consumable::Mushroom => "A common Mushroom.",
Consumable::Velorite => "Has a subtle turqoise glow.",
Consumable::VeloriteFrag => "Seems to be the fragment of a bigger piece...",
}
}
}
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum Ingredient { pub enum Ingredient {
Flower, Flower,
Grass, Grass,
} }
impl Ingredient {
pub fn name(&self) -> &'static str {
match self {
Ingredient::Flower => "Flower",
Ingredient::Grass => "Grass",
}
}
pub fn description(&self) -> &'static str {
match self {
Ingredient::Flower => "It smells great.",
Ingredient::Grass => "Greener than an orc's snout.",
}
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum Debug { pub enum Debug {
Boost, Boost,
@ -162,167 +57,75 @@ pub enum Debug {
} }
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum Item { pub enum ItemKind {
Tool { Tool { kind: Tool, power: u32 },
kind: Tool, Armor { kind: Armor, power: u32 },
power: u32, Consumable { kind: Consumable, effect: Effect },
stamina: i32, Ingredient(Ingredient),
strength: i32,
dexterity: i32,
intelligence: i32,
},
Armor {
kind: Armor,
stamina: i32,
strength: i32,
dexterity: i32,
intelligence: i32,
},
Consumable {
kind: Consumable,
effect: Effect,
},
Ingredient {
kind: Ingredient,
},
Debug(Debug), Debug(Debug),
} }
impl Item { #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub fn name(&self) -> &'static str { pub struct Item {
match self { name: String,
Item::Tool { kind, .. } => kind.name(), description: String,
Item::Armor { kind, .. } => kind.name(), pub kind: ItemKind,
Item::Consumable { kind, .. } => kind.name(), }
Item::Ingredient { kind, .. } => kind.name(),
Item::Debug(_) => "Debugging item",
}
}
pub fn title(&self) -> String { impl Asset for Item {
format!("{} ({})", self.name(), self.category()) const ENDINGS: &'static [&'static str] = &["ron"];
} fn parse(buf_reader: BufReader<File>) -> Result<Self, assets::Error> {
Ok(ron::de::from_reader(buf_reader).unwrap())
pub fn info(&self) -> String {
match self {
Item::Tool { power, .. } => format!("{:+} attack", power),
Item::Armor { .. } => String::new(),
Item::Consumable { effect, .. } => format!("{}", effect.info()),
Item::Ingredient { .. } => String::new(),
Item::Debug(_) => format!("+99999 insanity"),
}
}
pub fn category(&self) -> &'static str {
match self {
Item::Tool { .. } => "Tool",
Item::Armor { .. } => "Armor",
Item::Consumable { .. } => "Consumable",
Item::Ingredient { .. } => "Ingredient",
Item::Debug(_) => "Debug",
}
}
pub fn description(&self) -> String {
match self {
Item::Tool { kind, .. } => format!("{}", kind.description()),
Item::Armor { kind, .. } => format!("{}", kind.description()),
Item::Consumable { kind, .. } => format!("{}", kind.description()),
Item::Ingredient { kind, .. } => format!("{}", kind.description()),
Item::Debug(_) => format!("Debugging item"),
}
}
pub fn try_reclaim_from_block(block: Block) -> Option<Self> {
match block.kind() {
BlockKind::Apple => Some(Self::apple()),
BlockKind::Mushroom => Some(Self::mushroom()),
BlockKind::Velorite => Some(Self::velorite()),
BlockKind::BlueFlower => Some(Self::flower()),
BlockKind::PinkFlower => Some(Self::flower()),
BlockKind::PurpleFlower => Some(Self::flower()),
BlockKind::RedFlower => Some(Self::flower()),
BlockKind::WhiteFlower => Some(Self::flower()),
BlockKind::YellowFlower => Some(Self::flower()),
BlockKind::Sunflower => Some(Self::flower()),
BlockKind::LongGrass => Some(Self::grass()),
BlockKind::MediumGrass => Some(Self::grass()),
BlockKind::ShortGrass => Some(Self::grass()),
BlockKind::Chest => Some(match rand::random::<usize>() % 4 {
0 => Self::apple(),
1 => Self::velorite(),
2 => Item::Tool {
kind: *(&ALL_TOOLS).choose(&mut rand::thread_rng()).unwrap(),
power: 8 + rand::random::<u32>() % (rand::random::<u32>() % 29 + 1),
stamina: 0,
strength: 0,
dexterity: 0,
intelligence: 0,
},
3 => Self::veloritefrag(),
_ => unreachable!(),
}),
_ => None,
}
}
// General item constructors
pub fn apple() -> Self {
Item::Consumable {
kind: Consumable::Apple,
effect: Effect::Health(comp::HealthChange {
amount: 50,
cause: comp::HealthSource::Item,
}),
}
}
pub fn mushroom() -> Self {
Item::Consumable {
kind: Consumable::Mushroom,
effect: Effect::Health(comp::HealthChange {
amount: 10,
cause: comp::HealthSource::Item,
}),
}
}
pub fn velorite() -> Self {
Item::Consumable {
kind: Consumable::Velorite,
effect: Effect::Xp(50),
}
}
pub fn veloritefrag() -> Self {
Item::Consumable {
kind: Consumable::VeloriteFrag,
effect: Effect::Xp(20),
}
}
pub fn flower() -> Self {
Item::Ingredient {
kind: Ingredient::Flower,
}
}
pub fn grass() -> Self {
Item::Ingredient {
kind: Ingredient::Grass,
}
} }
} }
impl Default for Item { impl Item {
fn default() -> Self { pub fn name(&self) -> &str {
Item::Tool { &self.name
kind: Tool::Hammer, }
power: 0, pub fn description(&self) -> &str {
stamina: 0, &self.description
strength: 0, }
dexterity: 0, pub fn try_reclaim_from_block(block: Block) -> Option<Self> {
intelligence: 0, match block.kind() {
BlockKind::Apple => Some(assets::load_expect_cloned("common.items.apple")),
BlockKind::Mushroom => Some(assets::load_expect_cloned("common.items.mushroom")),
BlockKind::Velorite => Some(assets::load_expect_cloned("common.items.velorite")),
BlockKind::BlueFlower => Some(assets::load_expect_cloned("common.items.flowers.blue")),
BlockKind::PinkFlower => Some(assets::load_expect_cloned("common.items.flowers.pink")),
BlockKind::PurpleFlower => {
Some(assets::load_expect_cloned("common.items.flowers.purple"))
}
BlockKind::RedFlower => Some(assets::load_expect_cloned("common.items.flowers.red")),
BlockKind::WhiteFlower => {
Some(assets::load_expect_cloned("common.items.flowers.white"))
}
BlockKind::YellowFlower => {
Some(assets::load_expect_cloned("common.items.flowers.yellow"))
}
BlockKind::Sunflower => Some(assets::load_expect_cloned("common.items.flowers.sun")),
BlockKind::LongGrass => Some(assets::load_expect_cloned("common.items.grasses.long")),
BlockKind::MediumGrass => {
Some(assets::load_expect_cloned("common.items.grasses.medium"))
}
BlockKind::ShortGrass => Some(assets::load_expect_cloned("common.items.grasses.short")),
BlockKind::Chest => Some(match rand::random::<usize>() % 4 {
0 => assets::load_expect_cloned("common.items.apple"),
1 => assets::load_expect_cloned("common.items.velorite"),
// TODO: Implement random asset loading
//2 => Item::Tool {
// kind: *(&ALL_TOOLS).choose(&mut rand::thread_rng()),
// power: 8 + rand::random::<u32>() % (rand::random::<u32>() % 29 + 1),
// stamina: 0,
// strength: 0,
// dexterity: 0,
// intelligence: 0,
//},
2 => assets::load_expect_cloned("common.items.apple"),
3 => assets::load_expect_cloned("common.items.veloritefrag"),
_ => unreachable!(),
}),
_ => None,
} }
} }
} }

View File

@ -1,8 +1,9 @@
pub mod item; pub mod item;
// Reexports // Reexports
pub use item::{Debug, Item, Tool}; pub use item::{Debug, Item, ItemKind, Tool};
use crate::assets;
use specs::{Component, HashMapStorage, NullStorage}; use specs::{Component, HashMapStorage, NullStorage};
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
@ -72,8 +73,8 @@ impl Default for Inventory {
slots: vec![None; 25], slots: vec![None; 25],
}; };
inventory.push(Item::Debug(Debug::Boost)); inventory.push(assets::load_expect_cloned("common.items.debug.boost"));
inventory.push(Item::Debug(Debug::Possess)); inventory.push(assets::load_expect_cloned("common.items.debug.possess"));
inventory inventory
} }
} }

View File

@ -22,7 +22,7 @@ pub use controller::{
ControlEvent, Controller, ControllerInputs, InventoryManip, MountState, Mounting, ControlEvent, Controller, ControllerInputs, InventoryManip, MountState, Mounting,
}; };
pub use inputs::CanBuild; pub use inputs::CanBuild;
pub use inventory::{item, Inventory, InventoryUpdate, Item}; pub use inventory::{item, Inventory, InventoryUpdate, Item, ItemKind};
pub use last::Last; pub use last::Last;
pub use location::Waypoint; pub use location::Waypoint;
pub use phys::{ForceUpdate, Gravity, Mass, Ori, PhysicsState, Pos, Scale, Sticky, Vel}; pub use phys::{ForceUpdate, Gravity, Mass, Ori, PhysicsState, Pos, Scale, Sticky, Vel};

View File

@ -51,7 +51,7 @@ pub enum ServerEvent {
entity: EcsEntity, entity: EcsEntity,
name: String, name: String,
body: comp::Body, body: comp::Body,
main: Option<comp::Item>, main: Option<String>,
}, },
CreateNpc { CreateNpc {
pos: comp::Pos, pos: comp::Pos,

View File

@ -12,7 +12,7 @@ pub enum ClientMsg {
Character { Character {
name: String, name: String,
body: comp::Body, body: comp::Body,
main: Option<comp::item::Tool>, main: Option<String>, // Specifier for the weapon
}, },
ControllerInputs(comp::ControllerInputs), ControllerInputs(comp::ControllerInputs),
ControlEvent(comp::ControlEvent), ControlEvent(comp::ControlEvent),

View File

@ -1,7 +1,7 @@
use crate::{ use crate::{
comp::{ comp::{
item::Item, ActionState::*, CharacterState, Controller, HealthChange, HealthSource, Ori, ActionState::*, CharacterState, Controller, HealthChange, HealthSource, ItemKind, Ori, Pos,
Pos, Stats, Stats,
}, },
event::{EventBus, LocalEvent, ServerEvent}, event::{EventBus, LocalEvent, ServerEvent},
state::{DeltaTime, Uid}, state::{DeltaTime, Uid},
@ -110,12 +110,13 @@ impl<'a> System<'a> for Sys {
&& ori2.angle_between(pos_b2 - pos2) < (1.0 / pos2.distance(pos_b2)).atan() && ori2.angle_between(pos_b2 - pos2) < (1.0 / pos2.distance(pos_b2)).atan()
{ {
// Weapon gives base damage // Weapon gives base damage
let mut dmg = let mut dmg = if let Some(ItemKind::Tool { power, .. }) =
if let Some(Item::Tool { power, .. }) = stat.equipment.main { stat.equipment.main.as_ref().map(|i| &i.kind)
power as i32 {
} else { *power as i32
1 } else {
}; 1
};
// Block // Block
if character_b.action.is_block() if character_b.action.is_block()

View File

@ -5,7 +5,8 @@ use super::{
use crate::{ use crate::{
comp::{ comp::{
self, item, projectile, ActionState::*, Body, CharacterState, ControlEvent, Controller, self, item, projectile, ActionState::*, Body, CharacterState, ControlEvent, Controller,
HealthChange, HealthSource, Item, MovementState::*, PhysicsState, Projectile, Stats, Vel, HealthChange, HealthSource, ItemKind, MovementState::*, PhysicsState, Projectile, Stats,
Vel,
}, },
event::{EventBus, LocalEvent, ServerEvent}, event::{EventBus, LocalEvent, ServerEvent},
}; };
@ -131,8 +132,8 @@ impl<'a> System<'a> for Sys {
}; };
} }
match stats.equipment.main { match stats.equipment.main.as_ref().map(|i| &i.kind) {
Some(Item::Tool { Some(ItemKind::Tool {
kind: item::Tool::Bow, kind: item::Tool::Bow,
power, power,
.. ..
@ -158,7 +159,7 @@ impl<'a> System<'a> for Sys {
hit_wall: vec![projectile::Effect::Stick], hit_wall: vec![projectile::Effect::Stick],
hit_entity: vec![ hit_entity: vec![
projectile::Effect::Damage(HealthChange { projectile::Effect::Damage(HealthChange {
amount: -(power as i32), amount: -(*power as i32),
cause: HealthSource::Attack { by: *uid }, cause: HealthSource::Attack { by: *uid },
}), }),
projectile::Effect::Vanish, projectile::Effect::Vanish,
@ -170,7 +171,7 @@ impl<'a> System<'a> for Sys {
} }
} }
} }
Some(Item::Tool { Some(ItemKind::Tool {
kind: item::Tool::Staff, kind: item::Tool::Staff,
power, power,
.. ..
@ -220,7 +221,7 @@ impl<'a> System<'a> for Sys {
hit_wall: vec![projectile::Effect::Vanish], hit_wall: vec![projectile::Effect::Vanish],
hit_entity: vec![ hit_entity: vec![
projectile::Effect::Damage(HealthChange { projectile::Effect::Damage(HealthChange {
amount: -(power as i32), amount: -(*power as i32),
cause: HealthSource::Attack { by: *uid }, cause: HealthSource::Attack { by: *uid },
}), }),
projectile::Effect::Vanish, projectile::Effect::Vanish,
@ -232,7 +233,7 @@ impl<'a> System<'a> for Sys {
} }
} }
} }
Some(Item::Tool { .. }) => { Some(ItemKind::Tool { .. }) => {
// Melee Attack // Melee Attack
if inputs.primary if inputs.primary
&& (character.movement == Stand && (character.movement == Stand
@ -263,7 +264,7 @@ impl<'a> System<'a> for Sys {
}; };
} }
} }
Some(Item::Debug(item::Debug::Boost)) => { Some(ItemKind::Debug(item::Debug::Boost)) => {
if inputs.primary { if inputs.primary {
local_emitter.emit(LocalEvent::Boost { local_emitter.emit(LocalEvent::Boost {
entity, entity,
@ -278,7 +279,7 @@ impl<'a> System<'a> for Sys {
}); });
} }
} }
Some(Item::Debug(item::Debug::Possess)) => { Some(ItemKind::Debug(item::Debug::Possess)) => {
if inputs.primary if inputs.primary
&& (character.movement == Stand && (character.movement == Stand
|| character.movement == Run || character.movement == Run

View File

@ -21,7 +21,7 @@ use crate::{
cmd::CHAT_COMMANDS, cmd::CHAT_COMMANDS,
}; };
use common::{ use common::{
comp, assets, comp,
effect::Effect, effect::Effect,
event::{EventBus, ServerEvent}, event::{EventBus, ServerEvent},
msg::{ClientMsg, ClientState, ServerError, ServerInfo, ServerMsg}, msg::{ClientMsg, ClientState, ServerError, ServerInfo, ServerMsg},
@ -201,9 +201,12 @@ impl Server {
entity: EcsEntity, entity: EcsEntity,
name: String, name: String,
body: comp::Body, body: comp::Body,
main: Option<comp::Item>, main: Option<String>,
server_settings: &ServerSettings, server_settings: &ServerSettings,
) { ) {
// Give no item when an invalid specifier is given
let main = main.and_then(|specifier| assets::load_cloned(&specifier));
let spawn_point = state.ecs().read_resource::<SpawnPoint>().0; let spawn_point = state.ecs().read_resource::<SpawnPoint>().0;
state.write_component(entity, body); state.write_component(entity, body);
@ -428,40 +431,44 @@ impl Server {
} }
comp::InventoryManip::Use(slot) => { comp::InventoryManip::Use(slot) => {
let item = state let item_opt = state
.ecs() .ecs()
.write_storage::<comp::Inventory>() .write_storage::<comp::Inventory>()
.get_mut(entity) .get_mut(entity)
.and_then(|inv| inv.remove(slot)); .and_then(|inv| inv.remove(slot));
match item { match item_opt {
Some(comp::Item::Tool { .. }) | Some(comp::Item::Debug(_)) => { Some(item) => match item.kind {
if let Some(stats) = comp::ItemKind::Tool { .. } => {
state.ecs().write_storage::<comp::Stats>().get_mut(entity) if let Some(stats) = state
{ .ecs()
// Insert old item into inventory .write_storage::<comp::Stats>()
if let Some(old_item) = stats.equipment.main.take() { .get_mut(entity)
state {
.ecs() // Insert old item into inventory
.write_storage::<comp::Inventory>() if let Some(old_item) = stats.equipment.main.take() {
.get_mut(entity) state
.map(|inv| inv.insert(slot, old_item)); .ecs()
} .write_storage::<comp::Inventory>()
.get_mut(entity)
.map(|inv| inv.insert(slot, old_item));
}
stats.equipment.main = item; stats.equipment.main = Some(item);
}
} }
} comp::ItemKind::Consumable { effect, .. } => {
Some(comp::Item::Consumable { effect, .. }) => { state.apply_effect(entity, effect);
state.apply_effect(entity, effect); }
} _ => {
Some(item) => { // Re-insert it if unused
// Re-insert it if unused let _ = state
let _ = state .ecs()
.ecs() .write_storage::<comp::Inventory>()
.write_storage::<comp::Inventory>() .get_mut(entity)
.get_mut(entity) .map(|inv| inv.insert(slot, item));
.map(|inv| inv.insert(slot, item)); }
} },
_ => {} _ => {}
} }
@ -610,14 +617,15 @@ impl Server {
{ {
let mut inventories = ecs.write_storage::<comp::Inventory>(); let mut inventories = ecs.write_storage::<comp::Inventory>();
if let Some(inventory) = inventories.get_mut(possesse) { if let Some(inventory) = inventories.get_mut(possesse) {
inventory inventory.push(assets::load_expect_cloned(
.push(comp::Item::Debug(comp::item::Debug::Possess)); "common.items.debug.possess",
));
} else { } else {
let _ = inventories.insert( let _ = inventories.insert(
possesse, possesse,
comp::Inventory { comp::Inventory {
slots: vec![Some(comp::Item::Debug( slots: vec![Some(assets::load_expect_cloned(
comp::item::Debug::Possess, "common.items.debug.possess",
))], ))],
}, },
); );

View File

@ -1,7 +1,8 @@
use super::SysTimer; use super::SysTimer;
use crate::{auth_provider::AuthProvider, client::Client, CLIENT_TIMEOUT}; use crate::{auth_provider::AuthProvider, client::Client, CLIENT_TIMEOUT};
use common::{ use common::{
comp::{Admin, Body, CanBuild, Controller, Item, Ori, Player, Pos, Vel}, assets,
comp::{Admin, Body, CanBuild, Controller, Ori, Player, Pos, Vel},
event::{EventBus, ServerEvent}, event::{EventBus, ServerEvent},
msg::{validate_chat_msg, ChatMsgValidationError, MAX_BYTES_CHAT_MSG}, msg::{validate_chat_msg, ChatMsgValidationError, MAX_BYTES_CHAT_MSG},
msg::{ClientMsg, ClientState, RequestStateError, ServerMsg}, msg::{ClientMsg, ClientState, RequestStateError, ServerMsg},
@ -168,14 +169,7 @@ impl<'a> System<'a> for Sys {
entity, entity,
name, name,
body, body,
main: main.map(|t| Item::Tool { main: main.and_then(|specifier| assets::load_cloned(&specifier)),
kind: t,
power: 10,
stamina: 0,
strength: 0,
dexterity: 0,
intelligence: 0,
}),
}); });
} }
ClientState::Character => client.error_state(RequestStateError::Already), ClientState::Character => client.error_state(RequestStateError::Already),

View File

@ -1,6 +1,7 @@
use super::SysTimer; use super::SysTimer;
use crate::{chunk_generator::ChunkGenerator, client::Client, Tick}; use crate::{chunk_generator::ChunkGenerator, client::Client, Tick};
use common::{ use common::{
assets,
comp::{self, Player, Pos}, comp::{self, Player, Pos},
event::{EventBus, ServerEvent}, event::{EventBus, ServerEvent},
msg::ServerMsg, msg::ServerMsg,
@ -95,14 +96,9 @@ impl<'a> System<'a> for Sys {
let (mut stats, mut body) = if rand::random() { let (mut stats, mut body) = if rand::random() {
let stats = comp::Stats::new( let stats = comp::Stats::new(
"Humanoid".to_string(), "Humanoid".to_string(),
Some(comp::Item::Tool { Some(assets::load_expect_cloned(
kind: comp::item::Tool::Sword, "common.items.weapons.starter_sword",
power: 5, )),
stamina: 0,
strength: 0,
dexterity: 0,
intelligence: 0,
}),
); );
let body = comp::Body::Humanoid(comp::humanoid::Body::random()); let body = comp::Body::Humanoid(comp::humanoid::Body::random());
(stats, body) (stats, body)
@ -120,14 +116,9 @@ impl<'a> System<'a> for Sys {
if rand::random::<f32>() < 0.8 { if rand::random::<f32>() < 0.8 {
stats = comp::Stats::new( stats = comp::Stats::new(
"Humanoid".to_string(), "Humanoid".to_string(),
Some(comp::Item::Tool { Some(assets::load_expect_cloned(
kind: comp::item::Tool::Sword, "common.items.weapons.starter_sword",
power: 10, )),
stamina: 0,
strength: 0,
dexterity: 0,
intelligence: 0,
}),
); );
body = comp::Body::Humanoid(comp::humanoid::Body::random()); body = comp::Body::Humanoid(comp::humanoid::Body::random());
} }

View File

@ -1,6 +1,6 @@
use super::{ use super::{
img_ids::{Imgs, ImgsRot}, img_ids::{Imgs, ImgsRot},
item_imgs::{ItemImgs, ItemKind}, item_imgs::{ItemImgs, ItemKey},
Event as HudEvent, Fonts, TEXT_COLOR, Event as HudEvent, Fonts, TEXT_COLOR,
}; };
use crate::ui::{ImageFrame, Tooltip, TooltipManager, Tooltipable}; use crate::ui::{ImageFrame, Tooltip, TooltipManager, Tooltipable};
@ -65,7 +65,7 @@ impl<'a> Bag<'a> {
pub struct State { pub struct State {
ids: Ids, ids: Ids,
img_id_cache: Vec<Option<(ItemKind, image::Id)>>, img_id_cache: Vec<Option<(ItemKey, image::Id)>>,
selected_slot: Option<usize>, selected_slot: Option<usize>,
} }
@ -195,8 +195,8 @@ impl<'a> Widget for Bag<'a> {
slot_widget slot_widget
.with_tooltip( .with_tooltip(
self.tooltip_manager, self.tooltip_manager,
&item.title(), &item.name(),
&format!("{}\n{}", item.info(), item.description()), &format!("{}\n{}", item.name(), item.description()),
&item_tooltip, &item_tooltip,
) )
.set(state.ids.inv_slots[i], ui) .set(state.ids.inv_slots[i], ui)
@ -222,7 +222,7 @@ impl<'a> Widget for Bag<'a> {
state.update(|s| s.selected_slot = selected_slot); state.update(|s| s.selected_slot = selected_slot);
} }
// Item // Item
if let Some(kind) = item.as_ref().map(|i| ItemKind::from(i)) { if let Some(kind) = item.as_ref().map(|i| ItemKey::from(i)) {
Button::image(match &state.img_id_cache[i] { Button::image(match &state.img_id_cache[i] {
Some((cached_kind, id)) if cached_kind == &kind => *id, Some((cached_kind, id)) if cached_kind == &kind => *id,
_ => { _ => {

View File

@ -1,7 +1,7 @@
use crate::ui::{Graphic, Transform, Ui}; use crate::ui::{Graphic, Transform, Ui};
use common::{ use common::{
assets::{self, watch::ReloadIndicator, Asset}, assets::{self, watch::ReloadIndicator, Asset},
comp::item::{Armor, Consumable, Debug, Ingredient, Item, Tool}, comp::item::{Armor, Consumable, Debug, Ingredient, Item, ItemKind, Tool},
}; };
use conrod_core::image::Id; use conrod_core::image::Id;
use dot_vox::DotVoxData; use dot_vox::DotVoxData;
@ -13,21 +13,21 @@ use std::{fs::File, io::BufReader, sync::Arc};
use vek::*; use vek::*;
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum ItemKind { pub enum ItemKey {
Tool(Tool), Tool(Tool),
Armor(Armor), Armor(Armor),
Consumable(Consumable), Consumable(Consumable),
Ingredient(Ingredient), Ingredient(Ingredient),
Debug(Debug), Debug(Debug),
} }
impl From<&Item> for ItemKind { impl From<&Item> for ItemKey {
fn from(item: &Item) -> Self { fn from(item: &Item) -> Self {
match item { match &item.kind {
Item::Tool { kind, .. } => ItemKind::Tool(kind.clone()), ItemKind::Tool { kind, .. } => ItemKey::Tool(kind.clone()),
Item::Armor { kind, .. } => ItemKind::Armor(kind.clone()), ItemKind::Armor { kind, .. } => ItemKey::Armor(kind.clone()),
Item::Consumable { kind, .. } => ItemKind::Consumable(kind.clone()), ItemKind::Consumable { kind, .. } => ItemKey::Consumable(kind.clone()),
Item::Ingredient { kind, .. } => ItemKind::Ingredient(kind.clone()), ItemKind::Ingredient(kind) => ItemKey::Ingredient(kind.clone()),
Item::Debug(kind) => ItemKind::Debug(kind.clone()), ItemKind::Debug(kind) => ItemKey::Debug(kind.clone()),
} }
} }
} }
@ -68,7 +68,7 @@ impl ImageSpec {
} }
} }
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
struct ItemImagesSpec(HashMap<ItemKind, ImageSpec>); struct ItemImagesSpec(HashMap<ItemKey, ImageSpec>);
impl Asset for ItemImagesSpec { impl Asset for ItemImagesSpec {
const ENDINGS: &'static [&'static str] = &["ron"]; const ENDINGS: &'static [&'static str] = &["ron"];
fn parse(buf_reader: BufReader<File>) -> Result<Self, assets::Error> { fn parse(buf_reader: BufReader<File>) -> Result<Self, assets::Error> {
@ -77,7 +77,7 @@ impl Asset for ItemImagesSpec {
} }
pub struct ItemImgs { pub struct ItemImgs {
map: HashMap<ItemKind, Id>, map: HashMap<ItemKey, Id>,
indicator: ReloadIndicator, indicator: ReloadIndicator,
} }
impl ItemImgs { impl ItemImgs {
@ -110,7 +110,7 @@ impl ItemImgs {
// See if we already have an id we can use // See if we already have an id we can use
match self.map.get(&kind) { match self.map.get(&kind) {
Some(id) => ui.replace_graphic(*id, graphic), Some(id) => ui.replace_graphic(*id, graphic),
// Otherwise, generate new id and insert it into our Id -> ItemKind map // Otherwise, generate new id and insert it into our Id -> ItemKey map
None => { None => {
self.map.insert(kind.clone(), ui.add_graphic(graphic)); self.map.insert(kind.clone(), ui.add_graphic(graphic));
} }
@ -118,7 +118,7 @@ impl ItemImgs {
} }
} }
} }
pub fn img_id(&self, item_kind: ItemKind) -> Option<Id> { pub fn img_id(&self, item_kind: ItemKey) -> Option<Id> {
match self.map.get(&item_kind) { match self.map.get(&item_kind) {
Some(id) => Some(*id), Some(id) => Some(*id),
// There was no specification in the ron // There was no specification in the ron

View File

@ -3,8 +3,7 @@ use super::{
/*FOCUS_COLOR, RAGE_COLOR,*/ HP_COLOR, LOW_HP_COLOR, MANA_COLOR, TEXT_COLOR, XP_COLOR, /*FOCUS_COLOR, RAGE_COLOR,*/ HP_COLOR, LOW_HP_COLOR, MANA_COLOR, TEXT_COLOR, XP_COLOR,
}; };
use crate::GlobalState; use crate::GlobalState;
use common::comp::{item::Debug, item::Tool, Item, Stats}; use common::comp::{item::Debug, item::Tool, Item, ItemKind, Stats};
use conrod_core::{ use conrod_core::{
color, color,
widget::{self, Button, Image, Rectangle, Text}, widget::{self, Button, Image, Rectangle, Text},
@ -506,8 +505,8 @@ impl<'a> Widget for Skillbar<'a> {
// M1 Slot // M1 Slot
Image::new(self.imgs.skillbar_slot_big_bg) Image::new(self.imgs.skillbar_slot_big_bg)
.w_h(36.0 * scale, 36.0 * scale) .w_h(36.0 * scale, 36.0 * scale)
.color(match self.stats.equipment.main { .color(match self.stats.equipment.main.as_ref().map(|i| &i.kind) {
Some(Item::Tool { kind, .. }) => match kind { Some(ItemKind::Tool { kind, .. }) => match kind {
Tool::Bow => Some(BG_COLOR_2), Tool::Bow => Some(BG_COLOR_2),
Tool::Staff => Some(BG_COLOR_2), Tool::Staff => Some(BG_COLOR_2),
_ => Some(BG_COLOR_2), _ => Some(BG_COLOR_2),
@ -516,20 +515,20 @@ impl<'a> Widget for Skillbar<'a> {
}) })
.middle_of(state.ids.m1_slot) .middle_of(state.ids.m1_slot)
.set(state.ids.m1_slot_bg, ui); .set(state.ids.m1_slot_bg, ui);
Button::image(match self.stats.equipment.main { Button::image(match self.stats.equipment.main.as_ref().map(|i| &i.kind) {
Some(Item::Tool { kind, .. }) => match kind { Some(ItemKind::Tool { kind, .. }) => match kind {
Tool::Sword => self.imgs.twohsword_m1, Tool::Sword => self.imgs.twohsword_m1,
Tool::Hammer => self.imgs.twohhammer_m1, Tool::Hammer => self.imgs.twohhammer_m1,
Tool::Axe => self.imgs.twohaxe_m1, Tool::Axe => self.imgs.twohaxe_m1,
Tool::Bow => self.imgs.bow_m1, Tool::Bow => self.imgs.bow_m1,
Tool::Staff => self.imgs.staff_m1, Tool::Staff => self.imgs.staff_m1,
Tool::Debug(Debug::Boost) => self.imgs.flyingrod_m1,
_ => self.imgs.twohaxe_m1, _ => self.imgs.twohaxe_m1,
}, },
Some(Item::Debug(Debug::Boost)) => self.imgs.flyingrod_m1,
_ => self.imgs.twohaxe_m1, _ => self.imgs.twohaxe_m1,
}) // Insert Icon here }) // Insert Icon here
.w(match self.stats.equipment.main { .w(match self.stats.equipment.main.as_ref().map(|i| &i.kind) {
Some(Item::Tool { kind, .. }) => match kind { Some(ItemKind::Tool { kind, .. }) => match kind {
Tool::Bow => 30.0 * scale, Tool::Bow => 30.0 * scale,
Tool::Staff => 30.0 * scale, Tool::Staff => 30.0 * scale,
_ => 38.0 * scale, _ => 38.0 * scale,
@ -537,7 +536,7 @@ impl<'a> Widget for Skillbar<'a> {
_ => 38.0 * scale, _ => 38.0 * scale,
}) })
.h(match self.stats.equipment.main { .h(match self.stats.equipment.main {
Some(Item::Tool { kind, .. }) => match kind { Some(ItemKind::Tool { kind, .. }) => match kind {
Tool::Bow => 30.0 * scale, Tool::Bow => 30.0 * scale,
Tool::Staff => 36.0 * scale, Tool::Staff => 36.0 * scale,
_ => 38.0 * scale, _ => 38.0 * scale,
@ -563,20 +562,20 @@ impl<'a> Widget for Skillbar<'a> {
}) })
.middle_of(state.ids.m2_slot) .middle_of(state.ids.m2_slot)
.set(state.ids.m2_slot_bg, ui); .set(state.ids.m2_slot_bg, ui);
Button::image(match self.stats.equipment.main { Button::image(match self.stats.equipment.main.as_ref().map(|i| &i.kind) {
Some(Item::Tool { kind, .. }) => match kind { Some(ItemKind::Tool { kind, .. }) => match kind {
Tool::Sword => self.imgs.twohsword_m2, Tool::Sword => self.imgs.twohsword_m2,
Tool::Hammer => self.imgs.twohhammer_m2, Tool::Hammer => self.imgs.twohhammer_m2,
Tool::Axe => self.imgs.twohaxe_m2, Tool::Axe => self.imgs.twohaxe_m2,
Tool::Bow => self.imgs.bow_m2, Tool::Bow => self.imgs.bow_m2,
Tool::Staff => self.imgs.staff_m2, Tool::Staff => self.imgs.staff_m2,
Tool::Debug(Debug::Boost) => self.imgs.flyingrod_m2,
_ => self.imgs.twohaxe_m2, _ => self.imgs.twohaxe_m2,
}, },
Some(Item::Debug(Debug::Boost)) => self.imgs.flyingrod_m2,
_ => self.imgs.twohaxe_m2, _ => self.imgs.twohaxe_m2,
}) // Insert Icon here }) // Insert Icon here
.w(match self.stats.equipment.main { .w(match self.stats.equipment.main {
Some(Item::Tool { kind, .. }) => match kind { Some(ItemKind::Tool { kind, .. }) => match kind {
Tool::Bow => 30.0 * scale, Tool::Bow => 30.0 * scale,
Tool::Staff => 30.0 * scale, Tool::Staff => 30.0 * scale,
_ => 38.0 * scale, _ => 38.0 * scale,
@ -584,7 +583,7 @@ impl<'a> Widget for Skillbar<'a> {
_ => 38.0 * scale, _ => 38.0 * scale,
}) })
.h(match self.stats.equipment.main { .h(match self.stats.equipment.main {
Some(Item::Tool { kind, .. }) => match kind { Some(ItemKind::Tool { kind, .. }) => match kind {
Tool::Bow => 30.0 * scale, Tool::Bow => 30.0 * scale,
Tool::Staff => 30.0 * scale, Tool::Staff => 30.0 * scale,
_ => 38.0 * scale, _ => 38.0 * scale,

View File

@ -6,7 +6,7 @@ use crate::{
PlayStateResult, PlayStateResult,
}; };
use client::{self, Client}; use client::{self, Client};
use common::{clock::Clock, comp, msg::ClientState}; use common::{assets, clock::Clock, comp, msg::ClientState};
use log::error; use log::error;
use scene::Scene; use scene::Scene;
use std::{cell::RefCell, rc::Rc, time::Duration}; use std::{cell::RefCell, rc::Rc, time::Duration};
@ -67,7 +67,9 @@ impl PlayState for CharSelectionState {
self.client.borrow_mut().request_character( self.client.borrow_mut().request_character(
self.char_selection_ui.character_name.clone(), self.char_selection_ui.character_name.clone(),
comp::Body::Humanoid(self.char_selection_ui.character_body), comp::Body::Humanoid(self.char_selection_ui.character_body),
self.char_selection_ui.character_tool, self.char_selection_ui
.character_tool
.map(|specifier| specifier.to_owned()),
); );
return PlayStateResult::Push(Box::new(SessionState::new( return PlayStateResult::Push(Box::new(SessionState::new(
global_state, global_state,
@ -93,18 +95,10 @@ impl PlayState for CharSelectionState {
&self.client.borrow(), &self.client.borrow(),
self.char_selection_ui.character_body, self.char_selection_ui.character_body,
&comp::Equipment { &comp::Equipment {
main: if let Some(kind) = self.char_selection_ui.character_tool { main: self
Some(comp::Item::Tool { .char_selection_ui
kind: kind, .character_tool
power: 10, .and_then(|specifier| assets::load_cloned(&specifier)),
stamina: 0,
strength: 0,
dexterity: 0,
intelligence: 0,
})
} else {
None
},
alt: None, alt: None,
}, },
); );

View File

@ -17,6 +17,13 @@ use conrod_core::{
widget_ids, Borderable, Color, Colorable, Labelable, Positionable, Sizeable, UiCell, Widget, widget_ids, Borderable, Color, Colorable, Labelable, Positionable, Sizeable, UiCell, Widget,
}; };
const STARTER_HAMMER: &str = "common.items.weapons.starter_hammer";
const STARTER_BOW: &str = "common.items.weapons.starter_bow";
const STARTER_AXE: &str = "common.items.weapons.starter_axe";
const STARTER_STAFF: &str = "common.items.weapons.starter_staff";
const STARTER_SWORD: &str = "common.items.weapons.starter_sword";
const STARTER_DAGGER: &str = "common.items.weapons.starter_dagger";
widget_ids! { widget_ids! {
struct Ids { struct Ids {
// Background and logo // Background and logo
@ -249,7 +256,7 @@ pub struct CharSelectionUi {
//deletion_confirmation: bool, //deletion_confirmation: bool,
pub character_name: String, pub character_name: String,
pub character_body: humanoid::Body, pub character_body: humanoid::Body,
pub character_tool: Option<Tool>, pub character_tool: Option<&'static str>,
} }
impl CharSelectionUi { impl CharSelectionUi {
@ -280,7 +287,7 @@ impl CharSelectionUi {
character_creation: false, character_creation: false,
character_name: "Character Name".to_string(), character_name: "Character Name".to_string(),
character_body: humanoid::Body::random(), character_body: humanoid::Body::random(),
character_tool: Some(Tool::Sword), character_tool: Some(STARTER_SWORD),
} }
} }
@ -469,7 +476,7 @@ impl CharSelectionUi {
.was_clicked() .was_clicked()
{ {
self.character_creation = true; self.character_creation = true;
self.character_tool = Some(Tool::Sword); self.character_tool = Some(STARTER_SWORD);
} }
// Alpha Version // Alpha Version
@ -852,7 +859,7 @@ impl CharSelectionUi {
.w_h(70.0, 70.0) .w_h(70.0, 70.0)
.bottom_left_with_margins_on(self.ids.creation_buttons_alignment_2, 0.0, 0.0) .bottom_left_with_margins_on(self.ids.creation_buttons_alignment_2, 0.0, 0.0)
.set(self.ids.hammer, ui_widgets); .set(self.ids.hammer, ui_widgets);
if Button::image(if let Some(Tool::Hammer) = self.character_tool { if Button::image(if let Some(STARTER_HAMMER) = self.character_tool {
self.imgs.icon_border_pressed self.imgs.icon_border_pressed
} else { } else {
self.imgs.icon_border self.imgs.icon_border
@ -864,7 +871,7 @@ impl CharSelectionUi {
.set(self.ids.hammer_button, ui_widgets) .set(self.ids.hammer_button, ui_widgets)
.was_clicked() .was_clicked()
{ {
self.character_tool = Some(Tool::Hammer); self.character_tool = Some(STARTER_HAMMER);
} }
// REMOVE THIS AFTER IMPLEMENTATION // REMOVE THIS AFTER IMPLEMENTATION
/*Rectangle::fill_with([67.0, 67.0], color::rgba(0.0, 0.0, 0.0, 0.8)) /*Rectangle::fill_with([67.0, 67.0], color::rgba(0.0, 0.0, 0.0, 0.8))
@ -877,7 +884,7 @@ impl CharSelectionUi {
.w_h(70.0, 70.0) .w_h(70.0, 70.0)
.right_from(self.ids.hammer, 2.0) .right_from(self.ids.hammer, 2.0)
.set(self.ids.bow, ui_widgets); .set(self.ids.bow, ui_widgets);
if Button::image(if let Some(Tool::Bow) = self.character_tool { if Button::image(if let Some(STARTER_BOW) = self.character_tool {
self.imgs.icon_border_pressed self.imgs.icon_border_pressed
} else { } else {
self.imgs.icon_border self.imgs.icon_border
@ -889,7 +896,7 @@ impl CharSelectionUi {
.set(self.ids.bow_button, ui_widgets) .set(self.ids.bow_button, ui_widgets)
.was_clicked() .was_clicked()
{ {
self.character_tool = Some(Tool::Bow); self.character_tool = Some(STARTER_BOW);
} }
// REMOVE THIS AFTER IMPLEMENTATION // REMOVE THIS AFTER IMPLEMENTATION
/*Rectangle::fill_with([67.0, 67.0], color::rgba(0.0, 0.0, 0.0, 0.8)) /*Rectangle::fill_with([67.0, 67.0], color::rgba(0.0, 0.0, 0.0, 0.8))
@ -900,7 +907,7 @@ impl CharSelectionUi {
.w_h(70.0, 70.0) .w_h(70.0, 70.0)
.right_from(self.ids.bow, 2.0) .right_from(self.ids.bow, 2.0)
.set(self.ids.staff, ui_widgets); .set(self.ids.staff, ui_widgets);
if Button::image(if let Some(Tool::Staff) = self.character_tool { if Button::image(if let Some(STARTER_STAFF) = self.character_tool {
self.imgs.icon_border_pressed self.imgs.icon_border_pressed
} else { } else {
self.imgs.icon_border self.imgs.icon_border
@ -912,7 +919,7 @@ impl CharSelectionUi {
.set(self.ids.staff_button, ui_widgets) .set(self.ids.staff_button, ui_widgets)
.was_clicked() .was_clicked()
{ {
self.character_tool = Some(Tool::Staff); self.character_tool = Some(STARTER_STAFF);
} }
// REMOVE THIS AFTER IMPLEMENTATION // REMOVE THIS AFTER IMPLEMENTATION
/*Rectangle::fill_with([67.0, 67.0], color::rgba(0.0, 0.0, 0.0, 0.8)) /*Rectangle::fill_with([67.0, 67.0], color::rgba(0.0, 0.0, 0.0, 0.8))
@ -923,7 +930,7 @@ impl CharSelectionUi {
.w_h(70.0, 70.0) .w_h(70.0, 70.0)
.up_from(self.ids.hammer, 2.0) .up_from(self.ids.hammer, 2.0)
.set(self.ids.sword, ui_widgets); .set(self.ids.sword, ui_widgets);
if Button::image(if let Some(Tool::Sword) = self.character_tool { if Button::image(if let Some(STARTER_SWORD) = self.character_tool {
self.imgs.icon_border_pressed self.imgs.icon_border_pressed
} else { } else {
self.imgs.icon_border self.imgs.icon_border
@ -935,7 +942,7 @@ impl CharSelectionUi {
.set(self.ids.sword_button, ui_widgets) .set(self.ids.sword_button, ui_widgets)
.was_clicked() .was_clicked()
{ {
self.character_tool = Some(Tool::Sword); self.character_tool = Some(STARTER_SWORD);
} }
// Daggers // Daggers
@ -943,7 +950,7 @@ impl CharSelectionUi {
.w_h(70.0, 70.0) .w_h(70.0, 70.0)
.right_from(self.ids.sword, 2.0) .right_from(self.ids.sword, 2.0)
.set(self.ids.daggers, ui_widgets); .set(self.ids.daggers, ui_widgets);
if Button::image(if let Some(Tool::Dagger) = self.character_tool { if Button::image(if let Some(STARTER_DAGGER) = self.character_tool {
self.imgs.icon_border_pressed self.imgs.icon_border_pressed
} else { } else {
self.imgs.icon_border self.imgs.icon_border
@ -955,7 +962,7 @@ impl CharSelectionUi {
.set(self.ids.daggers_button, ui_widgets) .set(self.ids.daggers_button, ui_widgets)
.was_clicked() .was_clicked()
{ {
// self.character_tool = Some(Tool::Daggers); // self.character_tool = Some(STARTER_DAGGER);
} // REMOVE THIS AFTER IMPLEMENTATION } // REMOVE THIS AFTER IMPLEMENTATION
Rectangle::fill_with([67.0, 67.0], color::rgba(0.0, 0.0, 0.0, 0.8)) Rectangle::fill_with([67.0, 67.0], color::rgba(0.0, 0.0, 0.0, 0.8))
.middle_of(self.ids.daggers) .middle_of(self.ids.daggers)
@ -966,7 +973,7 @@ impl CharSelectionUi {
.w_h(70.0, 70.0) .w_h(70.0, 70.0)
.right_from(self.ids.daggers, 2.0) .right_from(self.ids.daggers, 2.0)
.set(self.ids.axe, ui_widgets); .set(self.ids.axe, ui_widgets);
if Button::image(if let Some(Tool::Axe) = self.character_tool { if Button::image(if let Some(STARTER_AXE) = self.character_tool {
self.imgs.icon_border_pressed self.imgs.icon_border_pressed
} else { } else {
self.imgs.icon_border self.imgs.icon_border
@ -978,7 +985,7 @@ impl CharSelectionUi {
.set(self.ids.axe_button, ui_widgets) .set(self.ids.axe_button, ui_widgets)
.was_clicked() .was_clicked()
{ {
self.character_tool = Some(Tool::Axe); self.character_tool = Some(STARTER_AXE);
} }
// REMOVE THIS AFTER IMPLEMENTATION // REMOVE THIS AFTER IMPLEMENTATION
/*Rectangle::fill_with([67.0, 67.0], color::rgba(0.0, 0.0, 0.0, 0.8)) /*Rectangle::fill_with([67.0, 67.0], color::rgba(0.0, 0.0, 0.0, 0.8))

View File

@ -10,7 +10,7 @@ use common::{
Belt, BodyType, Chest, EyeColor, Eyebrows, Foot, Hand, Pants, Race, Shoulder, Skin, Belt, BodyType, Chest, EyeColor, Eyebrows, Foot, Hand, Pants, Race, Shoulder, Skin,
}, },
item::Tool, item::Tool,
object, quadruped, quadruped_medium, Item, object, quadruped, quadruped_medium, Item, ItemKind,
}, },
figure::{DynaUnionizer, MatSegment, Material, Segment}, figure::{DynaUnionizer, MatSegment, Material, Segment},
}; };
@ -511,8 +511,8 @@ impl HumArmorFootSpec {
pub fn mesh_main(item: Option<&Item>) -> Mesh<FigurePipeline> { pub fn mesh_main(item: Option<&Item>) -> Mesh<FigurePipeline> {
if let Some(item) = item { if let Some(item) = item {
let (name, offset) = match item { let (name, offset) = match item.kind {
Item::Tool { kind, .. } => match kind { ItemKind::Tool { kind, .. } => match kind {
Tool::Sword => ("weapon.sword.rusty_2h", Vec3::new(-1.5, -6.5, -4.0)), Tool::Sword => ("weapon.sword.rusty_2h", Vec3::new(-1.5, -6.5, -4.0)),
Tool::Axe => ("weapon.axe.rusty_2h", Vec3::new(-1.5, -5.0, -4.0)), Tool::Axe => ("weapon.axe.rusty_2h", Vec3::new(-1.5, -5.0, -4.0)),
Tool::Hammer => ("weapon.hammer.rusty_2h", Vec3::new(-2.5, -5.5, -4.0)), Tool::Hammer => ("weapon.hammer.rusty_2h", Vec3::new(-2.5, -5.5, -4.0)),
@ -521,7 +521,7 @@ pub fn mesh_main(item: Option<&Item>) -> Mesh<FigurePipeline> {
Tool::Bow => ("weapon.bow.simple-bow", Vec3::new(-1.0, -6.0, -2.0)), Tool::Bow => ("weapon.bow.simple-bow", Vec3::new(-1.0, -6.0, -2.0)),
Tool::Staff => ("weapon.staff.wood-fire", Vec3::new(-1.0, -6.0, -3.0)), Tool::Staff => ("weapon.staff.wood-fire", Vec3::new(-1.0, -6.0, -3.0)),
}, },
Item::Debug(_) => ("weapon.debug_wand", Vec3::new(-1.5, -9.5, -4.0)), ItemKind::Debug(_) => ("weapon.debug_wand", Vec3::new(-1.5, -9.5, -4.0)),
_ => return Mesh::new(), _ => return Mesh::new(),
}; };
load_mesh(name, offset) load_mesh(name, offset)