diff --git a/CHANGELOG.md b/CHANGELOG.md index 66cec07206..94cc10600e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -43,6 +43,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Added spin attack for axe - Creature specific stats - Minimap compass +- Initial crafting system implementation ### Changed diff --git a/assets/common/items/potion_big.ron b/assets/common/items/consumable/potion_big.ron similarity index 85% rename from assets/common/items/potion_big.ron rename to assets/common/items/consumable/potion_big.ron index 42553d58e2..60ddf64298 100644 --- a/assets/common/items/potion_big.ron +++ b/assets/common/items/consumable/potion_big.ron @@ -2,11 +2,10 @@ Item( name: "Large Potion", description: "Restores 100 Health\n\n", kind: Consumable( - kind: PotionMinor, + kind: PotionLarge, effect: Health(( amount: 100, cause: Item, )), - , ), ) diff --git a/assets/common/items/potion_med.ron b/assets/common/items/consumable/potion_med.ron similarity index 89% rename from assets/common/items/potion_med.ron rename to assets/common/items/consumable/potion_med.ron index 61cf612204..ece9348e1b 100644 --- a/assets/common/items/potion_med.ron +++ b/assets/common/items/consumable/potion_med.ron @@ -2,7 +2,7 @@ Item( name: "Medium Potion", description: "Restores 70 Health\n\n", kind: Consumable( - kind: PotionMinor, + kind: PotionMed, effect: Health(( amount: 70, cause: Item, diff --git a/assets/common/items/potion_minor.ron b/assets/common/items/consumable/potion_minor.ron similarity index 100% rename from assets/common/items/potion_minor.ron rename to assets/common/items/consumable/potion_minor.ron diff --git a/assets/common/items/crafting_ing/empty_vial.ron b/assets/common/items/crafting_ing/empty_vial.ron new file mode 100644 index 0000000000..422a2870dd --- /dev/null +++ b/assets/common/items/crafting_ing/empty_vial.ron @@ -0,0 +1,7 @@ +Item( + name: "Empty Vial", + description: "Can be filled with fluids.", + kind: Ingredient( + kind: EmptyVial, + ) +) diff --git a/assets/common/items/crafting_ing/leather_scraps.ron b/assets/common/items/crafting_ing/leather_scraps.ron new file mode 100644 index 0000000000..cc546f8639 --- /dev/null +++ b/assets/common/items/crafting_ing/leather_scraps.ron @@ -0,0 +1,7 @@ +Item( + name: "Leather Scraps", + description: "Used to craft various items.", + kind: Ingredient( + kind: LeatherScraps, + ) +) diff --git a/assets/common/items/crafting_ing/shiny_gem.ron b/assets/common/items/crafting_ing/shiny_gem.ron new file mode 100644 index 0000000000..ec396047fa --- /dev/null +++ b/assets/common/items/crafting_ing/shiny_gem.ron @@ -0,0 +1,7 @@ +Item( + name: "Shiny Gem", + description: "It's so shiny!", + kind: Ingredient( + kind: ShinyGem, + ) +) diff --git a/assets/common/items/crafting_ing/stones.ron b/assets/common/items/crafting_ing/stones.ron new file mode 100644 index 0000000000..20d5842255 --- /dev/null +++ b/assets/common/items/crafting_ing/stones.ron @@ -0,0 +1,7 @@ +Item( + name: "Stones", + description: "Pebbles from the ground.", + kind: Ingredient( + kind: Stones, + ) +) diff --git a/assets/common/items/crafting_ing/twigs.ron b/assets/common/items/crafting_ing/twigs.ron new file mode 100644 index 0000000000..3eaba0f24a --- /dev/null +++ b/assets/common/items/crafting_ing/twigs.ron @@ -0,0 +1,7 @@ +Item( + name: "Twigs", + description: "Dry.", + kind: Ingredient( + kind: Twigs, + ) +) diff --git a/assets/common/items/crafting_tools/craftsman_hammer.ron b/assets/common/items/crafting_tools/craftsman_hammer.ron new file mode 100644 index 0000000000..30bdb55506 --- /dev/null +++ b/assets/common/items/crafting_tools/craftsman_hammer.ron @@ -0,0 +1,7 @@ +Item( + name: "Craftsman Hammer", + description: "Used to craft various items.", + kind: Ingredient( + kind: CraftsmanHammer, + ) +) diff --git a/assets/common/items/crafting_tools/mortar_pestle.ron b/assets/common/items/crafting_tools/mortar_pestle.ron new file mode 100644 index 0000000000..d983f15b3f --- /dev/null +++ b/assets/common/items/crafting_tools/mortar_pestle.ron @@ -0,0 +1,7 @@ +Item( + name: "Mortar and Pestle", + description: "Crushes and grinds things into\na fine powder or paste.\nUsed to craft various items.", + kind: Ingredient( + kind: MortarPestle, + ) +) diff --git a/assets/common/items/debug/empty_vial.ron b/assets/common/items/debug/empty_vial.ron new file mode 100644 index 0000000000..422a2870dd --- /dev/null +++ b/assets/common/items/debug/empty_vial.ron @@ -0,0 +1,7 @@ +Item( + name: "Empty Vial", + description: "Can be filled with fluids.", + kind: Ingredient( + kind: EmptyVial, + ) +) diff --git a/assets/common/items/debug/leather_scraps.ron b/assets/common/items/debug/leather_scraps.ron new file mode 100644 index 0000000000..cc546f8639 --- /dev/null +++ b/assets/common/items/debug/leather_scraps.ron @@ -0,0 +1,7 @@ +Item( + name: "Leather Scraps", + description: "Used to craft various items.", + kind: Ingredient( + kind: LeatherScraps, + ) +) diff --git a/assets/common/items/debug/shiny_gem.ron b/assets/common/items/debug/shiny_gem.ron new file mode 100644 index 0000000000..ec396047fa --- /dev/null +++ b/assets/common/items/debug/shiny_gem.ron @@ -0,0 +1,7 @@ +Item( + name: "Shiny Gem", + description: "It's so shiny!", + kind: Ingredient( + kind: ShinyGem, + ) +) diff --git a/assets/common/items/debug/stones.ron b/assets/common/items/debug/stones.ron new file mode 100644 index 0000000000..20d5842255 --- /dev/null +++ b/assets/common/items/debug/stones.ron @@ -0,0 +1,7 @@ +Item( + name: "Stones", + description: "Pebbles from the ground.", + kind: Ingredient( + kind: Stones, + ) +) diff --git a/assets/common/items/debug/twigs.ron b/assets/common/items/debug/twigs.ron new file mode 100644 index 0000000000..3eaba0f24a --- /dev/null +++ b/assets/common/items/debug/twigs.ron @@ -0,0 +1,7 @@ +Item( + name: "Twigs", + description: "Dry.", + kind: Ingredient( + kind: Twigs, + ) +) diff --git a/assets/common/items/apple.ron b/assets/common/items/food/apple.ron similarity index 100% rename from assets/common/items/apple.ron rename to assets/common/items/food/apple.ron diff --git a/assets/common/items/food/apple_mushroom_curry.ron b/assets/common/items/food/apple_mushroom_curry.ron new file mode 100644 index 0000000000..d8146e4c82 --- /dev/null +++ b/assets/common/items/food/apple_mushroom_curry.ron @@ -0,0 +1,11 @@ +Item( + name: "Mushroom Curry", + description: "Restores 120 Health\n\nWho could say no to that?\n\n", + kind: Consumable( + kind: AppleShroomCurry, + effect: Health(( + amount: 120, + cause: Item, + )), + ), +) diff --git a/assets/common/items/food/apple_stick.ron b/assets/common/items/food/apple_stick.ron new file mode 100644 index 0000000000..78bd97ce66 --- /dev/null +++ b/assets/common/items/food/apple_stick.ron @@ -0,0 +1,11 @@ +Item( + name: "Apple Stick", + description: "Restores 60 Health\n\n", + kind: Consumable( + kind: AppleStick, + effect: Health(( + amount: 60, + cause: Item, + )), + ), +) diff --git a/assets/common/items/cheese.ron b/assets/common/items/food/cheese.ron similarity index 100% rename from assets/common/items/cheese.ron rename to assets/common/items/food/cheese.ron diff --git a/assets/common/items/coconut.ron b/assets/common/items/food/coconut.ron similarity index 100% rename from assets/common/items/coconut.ron rename to assets/common/items/food/coconut.ron diff --git a/assets/common/items/mushroom.ron b/assets/common/items/food/mushroom.ron similarity index 100% rename from assets/common/items/mushroom.ron rename to assets/common/items/food/mushroom.ron diff --git a/assets/common/items/food/mushroom_stick.ron b/assets/common/items/food/mushroom_stick.ron new file mode 100644 index 0000000000..d44bbbec48 --- /dev/null +++ b/assets/common/items/food/mushroom_stick.ron @@ -0,0 +1,11 @@ +Item( + name: "Mushroom Stick", + description: "Restores 50 Health\n\n", + kind: Consumable( + kind: MushroomStick, + effect: Health(( + amount: 50, + cause: Item, + )), + ), +) diff --git a/assets/common/items/velorite.ron b/assets/common/items/ore/velorite.ron similarity index 100% rename from assets/common/items/velorite.ron rename to assets/common/items/ore/velorite.ron diff --git a/assets/common/items/veloritefrag.ron b/assets/common/items/ore/veloritefrag.ron similarity index 100% rename from assets/common/items/veloritefrag.ron rename to assets/common/items/ore/veloritefrag.ron diff --git a/assets/common/items/bomb.ron b/assets/common/items/utility/bomb.ron similarity index 100% rename from assets/common/items/bomb.ron rename to assets/common/items/utility/bomb.ron diff --git a/assets/common/items/bomb_pile.ron b/assets/common/items/utility/bomb_pile.ron similarity index 100% rename from assets/common/items/bomb_pile.ron rename to assets/common/items/utility/bomb_pile.ron diff --git a/assets/common/items/collar.ron b/assets/common/items/utility/collar.ron similarity index 100% rename from assets/common/items/collar.ron rename to assets/common/items/utility/collar.ron diff --git a/assets/common/items/training_dummy.ron b/assets/common/items/utility/training_dummy.ron similarity index 100% rename from assets/common/items/training_dummy.ron rename to assets/common/items/utility/training_dummy.ron diff --git a/assets/common/loot_table.ron b/assets/common/loot_table.ron index 61f7d939cd..7358a55729 100644 --- a/assets/common/loot_table.ron +++ b/assets/common/loot_table.ron @@ -1,18 +1,23 @@ [ // All loot rates go here // food - (3, "common.items.cheese"), - (3, "common.items.apple"), - (3, "common.items.mushroom"), + (3, "common.items.food.cheese"), + (3, "common.items.food.apple"), + (3, "common.items.food.mushroom"), + (1, "common.items.food.coconut"), // miscellaneous - (0.4, "common.items.velorite"), - (0.6, "common.items.veloritefrag"), - (0.6, "common.items.cheese"), - (0.6, "common.items.apple"), - (1.5, "common.items.potion_minor"), - (0.5, "common.items.collar"), - (0.5, "common.items.bomb_pile"), - (1, "common.items.bomb"), + (0.4, "common.items.ore.velorite"), + (0.6, "common.items.ore.veloritefrag"), + (0.1, "common.items.consumable.potion_minor"), + (0.01, "common.items.utility.collar"), + (0.01, "common.items.utility.bomb_pile"), + (0.1, "common.items.utility.bomb"), + // crafting ingredients + (0.5, "common.items.crafting_ing.shiny_gem"), + (2, "common.items.crafting_ing.leather_scraps"), + (1, "common.items.crafting_ing.empty_vial"), + (2, "common.items.crafting_ing.stones"), + (3, "common.items.crafting_ing.twigs"), // swords (0.1, "common.items.weapons.sword.starter_sword"), (0.1, "common.items.weapons.sword.wood_sword"), diff --git a/assets/common/recipe_book.ron b/assets/common/recipe_book.ron new file mode 100644 index 0000000000..cda3378172 --- /dev/null +++ b/assets/common/recipe_book.ron @@ -0,0 +1,12 @@ +{ + "crafting_hammer": (("common.items.crafting_tools.craftsman_hammer", 1),[("common.items.crafting_ing.twigs", 10), ("common.items.crafting_ing.stones", 10)]), + "mortar_pestle": (("common.items.crafting_tools.mortar_pestle", 1), [("common.items.crafting_ing.stones", 6), ("common.items.food.coconut", 2), ("common.items.crafting_tools.craftsman_hammer", 0)]), + "velorite_frag": (("common.items.ore.veloritefrag", 2), [("common.items.ore.velorite", 1), ("common.items.crafting_tools.craftsman_hammer", 0)]), + "potion_s": (("common.items.consumable.potion_minor", 1), [("common.items.crafting_ing.empty_vial", 1), ("common.items.ore.veloritefrag", 2)]), + "potion_m": (("common.items.consumable.potion_med", 1), [("common.items.consumable.potion_minor", 2), ("common.items.ore.veloritefrag", 4)]), + "collar_basic": (("common.items.utility.collar", 1), [("common.items.crafting_ing.leather_scraps", 5), ("common.items.crafting_ing.shiny_gem", 1)]), + "bomb_coconut": (("common.items.utility.bomb", 1), [("common.items.crafting_ing.stones", 10), ("common.items.food.coconut", 2), ("common.items.ore.veloritefrag", 2), ("common.items.crafting_tools.mortar_pestle", 0)]), + "apple_shroom_curry": (("common.items.food.apple_mushroom_curry", 1), [("common.items.food.mushroom", 10), ("common.items.food.coconut", 1), ("common.items.food.apple", 5), ("common.items.crafting_tools.mortar_pestle", 0)]), + "apples_stick": (("common.items.food.apple_stick", 1),[("common.items.crafting_ing.twigs", 1), ("common.items.food.apple", 3)]), + "mushroom_stick": (("common.items.food.mushroom_stick", 1),[("common.items.crafting_ing.twigs", 1), ("common.items.food.mushroom", 5)]), +} diff --git a/assets/voxygen/audio/sfx/crafting/hammer.wav b/assets/voxygen/audio/sfx/crafting/hammer.wav new file mode 100644 index 0000000000..03223c4ee4 --- /dev/null +++ b/assets/voxygen/audio/sfx/crafting/hammer.wav @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:be15f45edcf757e9e2135323d5d9d96069022ef21dcff72df80a49637bd31bc3 +size 185678 diff --git a/assets/voxygen/background/bg_8.png b/assets/voxygen/background/bg_8.png index 1688dee237..d429e5eec4 100644 --- a/assets/voxygen/background/bg_8.png +++ b/assets/voxygen/background/bg_8.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:74e8aab0abd64fe190607c87a6e70a3d3b4409947d8698754ff3c31e0e6debc9 -size 403497 +oid sha256:bd6507de7afa3bbc697fb2867fadc44184298dc9026f30fe91613c06dc72723d +size 906501 diff --git a/assets/voxygen/element/animation/gears/1.png b/assets/voxygen/element/animation/gears/1.png new file mode 100644 index 0000000000..fd1946be6b --- /dev/null +++ b/assets/voxygen/element/animation/gears/1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:798293778955ec9bfe8ae9a2fb6de33adff8a1ba457d693689de644f71bc8f9e +size 843 diff --git a/assets/voxygen/element/animation/gears/2.png b/assets/voxygen/element/animation/gears/2.png new file mode 100644 index 0000000000..d248a4b4cf --- /dev/null +++ b/assets/voxygen/element/animation/gears/2.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:63da1eb3c7663a921ef7f0995c8a5beee3121fa8cb2d4d3f50d6c5d8ade6ef64 +size 2067 diff --git a/assets/voxygen/element/animation/gears/3.png b/assets/voxygen/element/animation/gears/3.png new file mode 100644 index 0000000000..f4f76e1fea --- /dev/null +++ b/assets/voxygen/element/animation/gears/3.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5336ccfb5c8668959f376475dd32c48b5850c527da56a7924140027dd904a921 +size 2066 diff --git a/assets/voxygen/element/animation/gears/4.png b/assets/voxygen/element/animation/gears/4.png new file mode 100644 index 0000000000..b70867e7a0 --- /dev/null +++ b/assets/voxygen/element/animation/gears/4.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7cb70f05b0e179d1c99f9878148a8a93f7347e8610a74348e5a3d7100f0303d0 +size 2073 diff --git a/assets/voxygen/element/animation/gears/5.png b/assets/voxygen/element/animation/gears/5.png new file mode 100644 index 0000000000..7652f808cb --- /dev/null +++ b/assets/voxygen/element/animation/gears/5.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3ca60d03c82bc855cfda2e1fb61273f00a355e2c80cc7882c5f79c56c7de67c8 +size 2101 diff --git a/assets/voxygen/element/buttons/anvil.png b/assets/voxygen/element/buttons/anvil.png new file mode 100644 index 0000000000..1782d62f65 --- /dev/null +++ b/assets/voxygen/element/buttons/anvil.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c23cc6edcc9af1e2d82432d9b4f60cbf905cf3d970e6ae467f333cffdcb86e06 +size 355 diff --git a/assets/voxygen/element/buttons/anvil_hover.png b/assets/voxygen/element/buttons/anvil_hover.png new file mode 100644 index 0000000000..e57ba7b1e0 --- /dev/null +++ b/assets/voxygen/element/buttons/anvil_hover.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:be5dd7c186a92d519fcbb991308abb911889c5f830028ae4345f190fd7115a99 +size 437 diff --git a/assets/voxygen/element/buttons/anvil_press.png b/assets/voxygen/element/buttons/anvil_press.png new file mode 100644 index 0000000000..075d36e93b --- /dev/null +++ b/assets/voxygen/element/buttons/anvil_press.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9eccb36375e2ddf203f42809783dfd5382ab59a1cec50e16da85b6b03d8552f3 +size 412 diff --git a/assets/voxygen/element/frames/selection.png b/assets/voxygen/element/frames/selection.png new file mode 100644 index 0000000000..24566a3030 --- /dev/null +++ b/assets/voxygen/element/frames/selection.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:66bb0ef05d8ba8a73c1c49ea12dcd401d52b3c69db312dc5edca91fb79dfad4e +size 261 diff --git a/assets/voxygen/element/frames/selection.vox b/assets/voxygen/element/frames/selection.vox deleted file mode 100644 index dece7feb54..0000000000 --- a/assets/voxygen/element/frames/selection.vox +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:9e800abd210e23b0ba3125929dfbaa191de75ee1f6c54e2d9634c56192023ba2 -size 55156 diff --git a/assets/voxygen/element/frames/selection_frame.png b/assets/voxygen/element/frames/selection_frame.png new file mode 100644 index 0000000000..235d84c356 --- /dev/null +++ b/assets/voxygen/element/frames/selection_frame.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:61c241e368224bbbbf010a188308729de733927dd764d727c08c575216016fec +size 184 diff --git a/assets/voxygen/element/frames/selection_frame.vox b/assets/voxygen/element/frames/selection_frame.vox deleted file mode 100644 index b8c6bc32ae..0000000000 --- a/assets/voxygen/element/frames/selection_frame.vox +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:43867e582d418ed695eed2802729b6038e96484473c4b01840256119313c4a36 -size 2288 diff --git a/assets/voxygen/element/frames/selection_hover.png b/assets/voxygen/element/frames/selection_hover.png new file mode 100644 index 0000000000..d72c4bbf53 --- /dev/null +++ b/assets/voxygen/element/frames/selection_hover.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:10239624d63369d53b42af95865ee29bec81157a1b085891554d24309bdf544c +size 259 diff --git a/assets/voxygen/element/frames/selection_hover.vox b/assets/voxygen/element/frames/selection_hover.vox deleted file mode 100644 index 7b806be7a9..0000000000 --- a/assets/voxygen/element/frames/selection_hover.vox +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:6bd73f31f77e3e4d4f65dbff3b37dda8afefbaf21e226a5f7debdaac8439f2f9 -size 66532 diff --git a/assets/voxygen/element/frames/selection_press.png b/assets/voxygen/element/frames/selection_press.png new file mode 100644 index 0000000000..2aa3260773 --- /dev/null +++ b/assets/voxygen/element/frames/selection_press.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9e8d4043fa966b772cfc0222b9996c06407fd3bf756256a4eff3548f2928e2db +size 250 diff --git a/assets/voxygen/element/frames/selection_press.vox b/assets/voxygen/element/frames/selection_press.vox deleted file mode 100644 index e981536ef1..0000000000 --- a/assets/voxygen/element/frames/selection_press.vox +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:beccc5d12589e2467a6803d6e13824a2a5e8e4ff31c0d02e139de7bd0f2a3f99 -size 66532 diff --git a/assets/voxygen/element/frames/tt_test_corner_tr.png b/assets/voxygen/element/frames/tt_test_corner_tr.png new file mode 100644 index 0000000000..a66a135760 --- /dev/null +++ b/assets/voxygen/element/frames/tt_test_corner_tr.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f0de494ff10082d841254a96d3ea5d87d3bc77e2b7e10662584c86957b810460 +size 134 diff --git a/assets/voxygen/element/frames/tt_test_corner_tr.vox b/assets/voxygen/element/frames/tt_test_corner_tr.vox deleted file mode 100644 index f191188d7c..0000000000 --- a/assets/voxygen/element/frames/tt_test_corner_tr.vox +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:8d9a0b4cc32a126ec3b31d2074bfaf9a03f6d177632d407df1f115242cfe8e8b -size 56468 diff --git a/assets/voxygen/element/frames/tt_test_edge.png b/assets/voxygen/element/frames/tt_test_edge.png new file mode 100644 index 0000000000..b28d1e380c --- /dev/null +++ b/assets/voxygen/element/frames/tt_test_edge.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3a44ab4a366dd977cd2ece967991b1eb98c271b4c07ee763739af3a50478acb4 +size 117 diff --git a/assets/voxygen/element/frames/tt_test_edge.vox b/assets/voxygen/element/frames/tt_test_edge.vox deleted file mode 100644 index 7a090f9e98..0000000000 --- a/assets/voxygen/element/frames/tt_test_edge.vox +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:c7ab1c724d9c0b4b7bc80a4cea39e2b483a50a2291b6d497ed1baa0f8595b43b -size 56220 diff --git a/assets/voxygen/element/icons/2hsword_m1.png b/assets/voxygen/element/icons/2hsword_m1.png index 1b36b8a46f..582a57af16 100644 --- a/assets/voxygen/element/icons/2hsword_m1.png +++ b/assets/voxygen/element/icons/2hsword_m1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f442cb6ef061bfee9e66168b9c32e5bdb7e59fde790c0be31f93785857779e6f -size 784 +oid sha256:3f27d1046c6e1a2832b7f43750f27c2aeeb7f44a874e558b5380bcdde5bfe935 +size 466 diff --git a/assets/voxygen/element/icons/2hsword_m2.png b/assets/voxygen/element/icons/2hsword_m2.png index d54cda0e92..bf991d0c42 100644 --- a/assets/voxygen/element/icons/2hsword_m2.png +++ b/assets/voxygen/element/icons/2hsword_m2.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2b7a2ab9fac21eade39278def1c4e76ce793737c6bd3f4d55037a930ad304e34 -size 929 +oid sha256:9e679ee275cec6cf72962770364d9cf39d164af66ebd03969a0c33fca2dc2ec0 +size 357 diff --git a/assets/voxygen/element/icons/2hsword_slash.png b/assets/voxygen/element/icons/2hsword_slash.png deleted file mode 100644 index 18d36aef24..0000000000 --- a/assets/voxygen/element/icons/2hsword_slash.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:b827aa50558455a6ba821e4f032d45ae04d7bfdcecd2597fc1cb6c0b0e6d1973 -size 782 diff --git a/assets/voxygen/element/icons/anvil.png b/assets/voxygen/element/icons/anvil.png new file mode 100644 index 0000000000..d65e6c43d5 --- /dev/null +++ b/assets/voxygen/element/icons/anvil.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a7f9c7eecc22a0be5add0a17f7bdfb0967c7d44b605fd3de1ad29ae07a69851a +size 355 diff --git a/assets/voxygen/element/icons/bow_aoe.png b/assets/voxygen/element/icons/bow_aoe.png new file mode 100644 index 0000000000..9fd92299ab --- /dev/null +++ b/assets/voxygen/element/icons/bow_aoe.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:05080ad4fdb4ad813e7fc21bac32a18a93f5c0cd049b457844ebedca527ae80b +size 248 diff --git a/assets/voxygen/element/icons/bow_m1.png b/assets/voxygen/element/icons/bow_m1.png index b9cb8af63d..126a0acdd5 100644 --- a/assets/voxygen/element/icons/bow_m1.png +++ b/assets/voxygen/element/icons/bow_m1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ff1b52d259aafa8384e05dc5ae2ca3dcd7a88c7a4456149cc7a37e9e0c106ad5 -size 808 +oid sha256:ec6cf7010b6254b782286e087aa84175a78841b89945de90a50f5989e91880d7 +size 317 diff --git a/assets/voxygen/element/icons/bow_m2.png b/assets/voxygen/element/icons/bow_m2.png index 31627cde58..d28141f333 100644 --- a/assets/voxygen/element/icons/bow_m2.png +++ b/assets/voxygen/element/icons/bow_m2.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b580f448d4d3d0f86a5f3382842c6ef29507b7717d5c2994e902a0d9d82d8f0b -size 16863 +oid sha256:c689c982806aeefd1608afc5c8bcdf62873e2d0b6ce63d7296e882126c522b84 +size 275 diff --git a/assets/voxygen/element/icons/gem.png b/assets/voxygen/element/icons/gem.png new file mode 100644 index 0000000000..29f7af2101 --- /dev/null +++ b/assets/voxygen/element/icons/gem.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:52dcdf8dac9caa6c43a10ac35f11439dcc8669f9e34ce8d152ff676f5cf1aaac +size 260 diff --git a/assets/voxygen/element/icons/heal_0.png b/assets/voxygen/element/icons/heal_0.png index bac626be04..e63fee6398 100644 --- a/assets/voxygen/element/icons/heal_0.png +++ b/assets/voxygen/element/icons/heal_0.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e68b8d6a36b444e17797015e439ed711b865f53a1992762139db2228ca25b686 -size 730 +oid sha256:9231d976f42b42f097a2cf247142ecb837869a33ff4451467e018667fd5d76f3 +size 700 diff --git a/assets/voxygen/element/icons/item_apple.png b/assets/voxygen/element/icons/item_apple.png new file mode 100644 index 0000000000..406c97f13a --- /dev/null +++ b/assets/voxygen/element/icons/item_apple.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:01852fbd88c3d390ba33c8aeb64da7eec54eb6ccc798ddc56525ed55ba41f822 +size 338 diff --git a/assets/voxygen/element/icons/item_apple.vox b/assets/voxygen/element/icons/item_apple.vox deleted file mode 100644 index b4a60bd3fb..0000000000 --- a/assets/voxygen/element/icons/item_apple.vox +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:bec86131cd09411c3b1516d602ecf0db3632d7c7ca5db0408743325e8d2ccfff -size 1748 diff --git a/assets/voxygen/element/icons/item_apple_curry.png b/assets/voxygen/element/icons/item_apple_curry.png new file mode 100644 index 0000000000..5b25b38538 --- /dev/null +++ b/assets/voxygen/element/icons/item_apple_curry.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a1dc441e3117b737cb08ab39858c341accbd69916de2c7f539f660a17ed28fee +size 358 diff --git a/assets/voxygen/element/icons/item_apple_stick.png b/assets/voxygen/element/icons/item_apple_stick.png new file mode 100644 index 0000000000..1e0d6b5738 --- /dev/null +++ b/assets/voxygen/element/icons/item_apple_stick.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8f0b96e1f3c109908165dad8646d0a6f5d943e8c380ce8f26fd2ed0ff56f7e4a +size 366 diff --git a/assets/voxygen/element/icons/item_cheese.png b/assets/voxygen/element/icons/item_cheese.png index e20c21aa7e..3975d73506 100644 --- a/assets/voxygen/element/icons/item_cheese.png +++ b/assets/voxygen/element/icons/item_cheese.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6b73e44bddd679b83b8d2e668589e06316b419777c9ac3818c00fdd01a18affe -size 245 +oid sha256:02643618be3bd63bcf69c41eedbecfa20d28fa510683ac6bad6c26cfec66f463 +size 244 diff --git a/assets/voxygen/element/icons/item_cheese.vox b/assets/voxygen/element/icons/item_cheese.vox deleted file mode 100644 index 5bfc15c670..0000000000 --- a/assets/voxygen/element/icons/item_cheese.vox +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:f086a745accda8521bcb21215024b40b111bae815b73937d87a8fd838038e61f -size 1680 diff --git a/assets/voxygen/element/icons/item_leather0.png b/assets/voxygen/element/icons/item_leather0.png new file mode 100644 index 0000000000..f8f60e9180 --- /dev/null +++ b/assets/voxygen/element/icons/item_leather0.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ec7cc129c46d1daeee085366798f9df2d7d4525d7ccbd21087466d6d1a25a2bc +size 416 diff --git a/assets/voxygen/element/icons/item_mortarpestlecoco.png b/assets/voxygen/element/icons/item_mortarpestlecoco.png new file mode 100644 index 0000000000..f3612606e4 --- /dev/null +++ b/assets/voxygen/element/icons/item_mortarpestlecoco.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c3de3c3c6ffc2edea096e10a718022583db28f9a64207adc27f06ce3ec162b1f +size 304 diff --git a/assets/voxygen/element/icons/item_shroom_stick.png b/assets/voxygen/element/icons/item_shroom_stick.png new file mode 100644 index 0000000000..e152d4cb6a --- /dev/null +++ b/assets/voxygen/element/icons/item_shroom_stick.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b213392e6df9d7e45c576aa7a6ce846156beae0777b05852fc87c79eaf307d49 +size 348 diff --git a/assets/voxygen/element/icons/skill_charge_3.png b/assets/voxygen/element/icons/skill_charge_3.png deleted file mode 100644 index 82c5cfae2e..0000000000 --- a/assets/voxygen/element/icons/skill_charge_3.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:1c872af7c35dced7c6b11f2838b6ecc2c0176da2f5e3767c2d76b437a9b2e837 -size 1213 diff --git a/assets/voxygen/element/icons/skill_sword_pierce.png b/assets/voxygen/element/icons/skill_sword_pierce.png new file mode 100644 index 0000000000..6ba4b0b090 --- /dev/null +++ b/assets/voxygen/element/icons/skill_sword_pierce.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d14a405f1e2bdbaaa68dff706fd62437de970323e43c9f4f764a2095b524d8fc +size 389 diff --git a/assets/voxygen/element/icons/staff_m1.png b/assets/voxygen/element/icons/staff_m1.png index 3955caf46a..717c22eac6 100644 --- a/assets/voxygen/element/icons/staff_m1.png +++ b/assets/voxygen/element/icons/staff_m1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0b743bbccb12309114e55a35d21b196f6a97b458d4ea208b48654019c2d24e90 -size 795 +oid sha256:b975bbbcb1573af4c2af4dac991e4b474b15d0eb7e568e24ea68928982e3100a +size 429 diff --git a/assets/voxygen/element/icons/staff_m2.png b/assets/voxygen/element/icons/staff_m2.png index f22841c798..8a62997419 100644 --- a/assets/voxygen/element/icons/staff_m2.png +++ b/assets/voxygen/element/icons/staff_m2.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:813f0d30ac437525faa2adb022ce4f57d1beac2ec60d0e9b671c16111eef379c -size 1091 +oid sha256:393fe7cbf2e6626ff83074120b6a89d9ddfdd2435c13c79a493789a41c1403f4 +size 462 diff --git a/assets/voxygen/element/misc_bg/crafting.png b/assets/voxygen/element/misc_bg/crafting.png new file mode 100644 index 0000000000..bd6cc4ac0d --- /dev/null +++ b/assets/voxygen/element/misc_bg/crafting.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1800710a64a8bb5be612f4cc6c88acd2c560d9125cf69899b5f35bf9e137aa42 +size 7737 diff --git a/assets/voxygen/element/misc_bg/crafting_frame.png b/assets/voxygen/element/misc_bg/crafting_frame.png new file mode 100644 index 0000000000..602b96bc20 --- /dev/null +++ b/assets/voxygen/element/misc_bg/crafting_frame.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cfa17b2872fc21a8974e3955c14efda8017e87a8de9f72f42b9d5207eeaa1053 +size 15174 diff --git a/assets/voxygen/element/misc_bg/inv_bg.png b/assets/voxygen/element/misc_bg/inv_bg.png index 0c2c9ccf9a..54ad64bfcf 100644 --- a/assets/voxygen/element/misc_bg/inv_bg.png +++ b/assets/voxygen/element/misc_bg/inv_bg.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:68aa80432b2ec6ff15179a5092b976b8938aa0fa2dba5248536b90ba4838ecd6 -size 58872 +oid sha256:96af9310d82d646b8a1b109e433069ee753d6cf7f5dfd24a2979ecc711fb0048 +size 53053 diff --git a/assets/voxygen/element/misc_bg/map_bg.png b/assets/voxygen/element/misc_bg/map_bg.png index 5afd1cb248..fba5549934 100644 --- a/assets/voxygen/element/misc_bg/map_bg.png +++ b/assets/voxygen/element/misc_bg/map_bg.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a9e597d8bc0327e5802d68eed05b68953e5c1511ee7698a5091fa31ead38a0e5 -size 5494 +oid sha256:0f1c93ac6021ddd3509fb7b0303cb3e1936a6486bcf3c9de322ee44e0e029339 +size 5070 diff --git a/assets/voxygen/element/misc_bg/window.png b/assets/voxygen/element/misc_bg/window.png new file mode 100644 index 0000000000..a3f9d7fca5 --- /dev/null +++ b/assets/voxygen/element/misc_bg/window.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4aeb912ea4143418b5d90026d094733f442241b6a1e80a9417e5c969778adb3d +size 6415 diff --git a/assets/voxygen/i18n/de_DE.ron b/assets/voxygen/i18n/de_DE.ron index 32e371ca31..b669edc521 100644 --- a/assets/voxygen/i18n/de_DE.ron +++ b/assets/voxygen/i18n/de_DE.ron @@ -304,6 +304,8 @@ magischen Gegenstände ergattern?"#, "hud.settings.audio_device": "Ausgabegerät", "hud.settings.awaitingkey": "Drückt eine Taste...", + "hud.settings.unbound": "-", + "hud.settings.reset_keybinds": "Auf Standard zurücksetzen", "hud.social": "Sozial", "hud.social.online": "Online", @@ -314,6 +316,12 @@ magischen Gegenstände ergattern?"#, "hud.spell": "Zauber", + "hud.crafting": "Herstellen", + "hud.crafting.recipes": "Rezepte", + "hud.crafting.ingredients": "Zutaten:", + "hud.crafting.craft": "Herstellen", + "hud.crafting.tool_cata": "Benötigt:", + "hud.free_look_indicator": "Freie Sicht aktiv", "hud.auto_walk_indicator": "Automatisches Laufen aktiv", diff --git a/assets/voxygen/i18n/en.ron b/assets/voxygen/i18n/en.ron index 91073a0a08..d727a07c90 100644 --- a/assets/voxygen/i18n/en.ron +++ b/assets/voxygen/i18n/en.ron @@ -118,8 +118,6 @@ Thanks for taking the time to read this notice, we hope you enjoy the game! // Login process description "main.login_process": r#"Information on the Login Process: -If you are having issues signing in: - Please note that you now need an account to play on auth-enabled servers. @@ -313,7 +311,13 @@ magically infused items?"#, "hud.social.faction": "Faction", "hud.social.play_online_fmt": "{nb_player} player(s) online", - "hud.spell": "Spells", + "hud.crafting": "Crafting", + "hud.crafting.recipes": "Recipes", + "hud.crafting.ingredients": "Ingredients:", + "hud.crafting.craft": "Craft", + "hud.crafting.tool_cata": "Requires:", + + "hud.spell": "Spells", "hud.free_look_indicator": "Free look active", "hud.auto_walk_indicator": "Auto walk active", diff --git a/assets/voxygen/item_image_manifest.ron b/assets/voxygen/item_image_manifest.ron index 68c68ffc4f..af27a24813 100644 --- a/assets/voxygen/item_image_manifest.ron +++ b/assets/voxygen/item_image_manifest.ron @@ -191,7 +191,7 @@ Tool(Hammer(BasicHammer)): VoxTrans( "voxel.weapon.hammer.rusty_2h", (2.0, -1.0, 0.0), (-135.0, 90.0, 0.0), 1.1, - ), + ), // Staffs Tool(Staff(BasicStaff)): VoxTrans( "voxel.weapon.staff.wood-fire", @@ -743,24 +743,30 @@ ), // Consumables Consumable(Apple): - VoxTrans( + Png( "element.icons.item_apple", - (0.0, 0.0, 0.0), (-90.0, 90.0, 0.0), 1.0, ), Consumable(Coconut): Png( "element.icons.item_coconut", ), + Consumable(PotionMed): VoxTrans( + "voxel.object.potion_red", + (0.0, 0.0, 0.0), (-50.0, 30.0, 20.0), 0.7, + ), Consumable(PotionMinor): VoxTrans( "voxel.object.potion_red", - (0.0, 0.0, 0.0), (-50.0, 30.0, 20.0), 0.8, + (0.0, 0.0, 0.0), (-50.0, 30.0, 20.0), 0.5, + ), + Consumable(PotionLarge): VoxTrans( + "voxel.object.potion_red", + (0.0, 0.0, 0.0), (-50.0, 30.0, 20.0), 0.9, ), Consumable(PotionExp): VoxTrans( "voxel.object.potion_turq", (0.0, 0.0, 0.0), (-50.0, 30.0, 20.0), 0.8, ), - Consumable(Cheese): VoxTrans( + Consumable(Cheese): Png( "element.icons.item_cheese", - (0.0, 0.0, 0.0), (-90.0, 90.0, 0.0), 0.9, ), Consumable(Potion): VoxTrans( "voxel.object.potion_red", @@ -776,18 +782,32 @@ ), Consumable(VeloriteFrag): VoxTrans( "voxel.sprite.velorite.velorite_1", - (0.0, -1.0, 0.0), (-50.0, 40.0, 20.0), 0.8, + (0.0, 0.0, 0.0), (-50.0, 40.0, 20.0), 0.8, ), + Consumable(AppleShroomCurry): Png( + "element.icons.item_apple_curry", + ), + Consumable(AppleStick): Png( + "element.icons.item_apple_stick", + ), + Consumable(MushroomStick): Png( + "element.icons.item_shroom_stick", + ), + // Throwables Throwable(Bomb): VoxTrans( "voxel.object.bomb", - (0.0, -1.0, 0.0), (-50.0, 40.0, 20.0), 0.8, + (0.0, 0.5, 0.0), (-50.0, 40.0, 20.0), 0.8, ), Throwable(TrainingDummy): VoxTrans( "voxel.object.training_dummy", (0.0, -1.0, 0.0), (-50.0, 40.0, 20.0), 0.8, ), // Ingredients + Ingredient(CraftsmanHammer): VoxTrans( //TODO This should be a 1h hammer! + "voxel.weapon.hammer.craftsman", + (1.0, 1.0, 0.0), (-135.0, 90.0, 0.0), 1.0, + ), Ingredient(Flower): VoxTrans( "voxel.sprite.flowers.flower_red_2", (0.0, -1.0, 0.0), (-50.0, 40.0, 20.0), 0.8, @@ -796,6 +816,27 @@ "voxel.sprite.grass.grass_long_5", (0.0, 0.0, 0.0), (-90.0, 50.0, 0.0), 1.0, ), + Ingredient(Stones): VoxTrans( + "voxel.sprite.rocks.rock-0", + (0.0, 0.0, 0.0), (-50.0, 40.0, 20.0), 0.8, + ), + Ingredient(Twigs): VoxTrans( + "voxel.sprite.twigs.twigs-0", + (0.0, 0.0, 0.0), (-20.0, 10.0, 20.0), 0.9, + ), + Ingredient(LeatherScraps): Png( + "element.icons.item_leather0", + ), + Ingredient(ShinyGem): Png( + "element.icons.gem", + ), + Ingredient(MortarPestle): Png( + "element.icons.item_mortarpestlecoco", + ), + Ingredient(EmptyVial): VoxTrans( + "voxel.object.potion_empty", + (0.0, 0.0, 0.0), (-50.0, 30.0, 20.0), 0.8, + ), // Debug Items Tool(Debug(Boost)): VoxTrans( "voxel.weapon.tool.broom_belzeshrub_purple", diff --git a/assets/voxygen/voxel/humanoid_main_weapon_manifest.ron b/assets/voxygen/voxel/humanoid_main_weapon_manifest.ron index 3ca33ada52..3efea95da9 100644 --- a/assets/voxygen/voxel/humanoid_main_weapon_manifest.ron +++ b/assets/voxygen/voxel/humanoid_main_weapon_manifest.ron @@ -176,6 +176,10 @@ vox_spec: ("weapon.hammer.rusty_2h", (-2.5, -5.5, -4.0)), color: None ), + /*Dagger(Craftsman): ( //TODO This should be a 1h hammer! + vox_spec: ("weapon.hammer.craftsman", (-2.0, -5.0, -5.5)), + color: None + ),*/ // Daggers Dagger(BasicDagger): ( vox_spec: ("weapon.dagger.dagger_rusty", (-1.5, -3.0, -3.0)), diff --git a/assets/voxygen/voxel/object/potion_empty.vox b/assets/voxygen/voxel/object/potion_empty.vox new file mode 100644 index 0000000000..4f4bd99856 --- /dev/null +++ b/assets/voxygen/voxel/object/potion_empty.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0e7d2dc44a3bd0035ea3ef934cd9420360dd118ada159ac18a187fc0308a246f +size 1400 diff --git a/assets/voxygen/voxel/sprite/gem/gem_blue.vox b/assets/voxygen/voxel/sprite/gem/gem_blue.vox new file mode 100644 index 0000000000..e8ab838a40 --- /dev/null +++ b/assets/voxygen/voxel/sprite/gem/gem_blue.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5b00fd0d2018c4923134e675e0ccb5db8e0f0f8da5387a7fca4cf299b07a300e +size 1184 diff --git a/assets/voxygen/voxel/sprite/gem/gem_green.vox b/assets/voxygen/voxel/sprite/gem/gem_green.vox new file mode 100644 index 0000000000..285d6170eb --- /dev/null +++ b/assets/voxygen/voxel/sprite/gem/gem_green.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7238b7eb2d8a2ba98afdf3cfd7eeadf5a5832a6fc0f285e00008487553309f91 +size 1208 diff --git a/assets/voxygen/voxel/sprite/gem/gem_red.vox b/assets/voxygen/voxel/sprite/gem/gem_red.vox new file mode 100644 index 0000000000..6765230e7b --- /dev/null +++ b/assets/voxygen/voxel/sprite/gem/gem_red.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:61c11c616e3ed4d011ead74acf1273823936a85deae7b3db214a2aa6ab54ee72 +size 1336 diff --git a/assets/voxygen/voxel/sprite/rocks/rock-0.vox b/assets/voxygen/voxel/sprite/rocks/rock-0.vox new file mode 100644 index 0000000000..bd0c85c9be --- /dev/null +++ b/assets/voxygen/voxel/sprite/rocks/rock-0.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:219f3cfd7e310284e17397a59441cfc79d27281ca09bea8a4740eee4173dab89 +size 1336 diff --git a/assets/voxygen/voxel/sprite/rocks/rock-1.vox b/assets/voxygen/voxel/sprite/rocks/rock-1.vox new file mode 100644 index 0000000000..ca13137003 --- /dev/null +++ b/assets/voxygen/voxel/sprite/rocks/rock-1.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2c9365b3ddee1c873a9dbbe0a9e5c86280561562e14cda6540235d9d58bc58d0 +size 1936 diff --git a/assets/voxygen/voxel/sprite/rocks/rock-2.vox b/assets/voxygen/voxel/sprite/rocks/rock-2.vox new file mode 100644 index 0000000000..42466dd089 --- /dev/null +++ b/assets/voxygen/voxel/sprite/rocks/rock-2.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:64e5992e0833d6f22ffb833e83ee967b1edb55d52414d45ce3afada7b0fc8e82 +size 1368 diff --git a/assets/voxygen/voxel/sprite/twigs/twigs-0.vox b/assets/voxygen/voxel/sprite/twigs/twigs-0.vox new file mode 100644 index 0000000000..e91efb6c3b --- /dev/null +++ b/assets/voxygen/voxel/sprite/twigs/twigs-0.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fd6c3dedba6acda92de5d70400ec8fe886f73015f3a2f088c7907ecbf57a6319 +size 1144 diff --git a/assets/voxygen/voxel/sprite/twigs/twigs-1.vox b/assets/voxygen/voxel/sprite/twigs/twigs-1.vox new file mode 100644 index 0000000000..4584d748e2 --- /dev/null +++ b/assets/voxygen/voxel/sprite/twigs/twigs-1.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e7829f29cd6bc68c9d9f5a04ab7c9feefb73031f438b777ddd81d1f67415c7f8 +size 1120 diff --git a/assets/voxygen/voxel/sprite/twigs/twigs-2.vox b/assets/voxygen/voxel/sprite/twigs/twigs-2.vox new file mode 100644 index 0000000000..5647afff1f --- /dev/null +++ b/assets/voxygen/voxel/sprite/twigs/twigs-2.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:77a7ead81babcbbd6c5954df0692a7e13e018a250f379f42a755914546ad189c +size 1184 diff --git a/assets/voxygen/voxel/weapon/hammer/craftsman.vox b/assets/voxygen/voxel/weapon/hammer/craftsman.vox new file mode 100644 index 0000000000..7501e83d4f --- /dev/null +++ b/assets/voxygen/voxel/weapon/hammer/craftsman.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d4dccf2543585a5d0a18dea671d9b25347715a89ccab44e793faf735a0d52e62 +size 2240 diff --git a/client/src/lib.rs b/client/src/lib.rs index 9e939c91c8..482739defe 100644 --- a/client/src/lib.rs +++ b/client/src/lib.rs @@ -1,5 +1,5 @@ #![deny(unsafe_code)] -#![feature(label_break_value)] +#![feature(label_break_value, option_zip)] pub mod cmd; pub mod error; @@ -25,6 +25,7 @@ use common::{ PlayerInfo, PlayerListUpdate, RegisterError, RequestStateError, ServerInfo, ServerMsg, MAX_BYTES_CHAT_MSG, }, + recipe::RecipeBook, state::State, sync::{Uid, UidAllocator, WorldSyncExt}, terrain::{block::Block, TerrainChunk, TerrainChunkSize}, @@ -33,7 +34,7 @@ use common::{ use futures_executor::block_on; use futures_timer::Delay; use futures_util::{select, FutureExt}; -use hashbrown::HashMap; +use hashbrown::{HashMap, HashSet}; use image::DynamicImage; use network::{ Network, Participant, Pid, ProtocolAddr, Stream, PROMISES_CONSISTENCY, PROMISES_ORDERED, @@ -75,6 +76,8 @@ pub struct Client { pub player_list: HashMap, pub character_list: CharacterList, pub active_character_id: Option, + recipe_book: RecipeBook, + available_recipes: HashSet, _network: Network, participant: Option, @@ -123,7 +126,7 @@ impl Client { let mut stream = block_on(participant.open(10, PROMISES_ORDERED | PROMISES_CONSISTENCY))?; // Wait for initial sync - let (state, entity, server_info, world_map) = block_on(async { + let (state, entity, server_info, world_map, recipe_book) = block_on(async { loop { match stream.recv().await? { ServerMsg::InitialSync { @@ -131,6 +134,7 @@ impl Client { server_info, time_of_day, world_map: (map_size, world_map), + recipe_book, } => { // TODO: Display that versions don't match in Voxygen if &server_info.git_hash != *common::util::GIT_HASH { @@ -174,7 +178,13 @@ impl Client { ); debug!("Done preparing image..."); - break Ok((state, entity, server_info, (world_map, map_size))); + break Ok(( + state, + entity, + server_info, + (world_map, map_size), + recipe_book, + )); }, ServerMsg::TooManyPlayers => break Err(Error::TooManyPlayers), err => { @@ -200,6 +210,8 @@ impl Client { player_list: HashMap::new(), character_list: CharacterList::default(), active_character_id: None, + recipe_book, + available_recipes: HashSet::default(), _network: network, participant: Some(participant), @@ -372,6 +384,40 @@ impl Client { } } + pub fn recipe_book(&self) -> &RecipeBook { &self.recipe_book } + + pub fn available_recipes(&self) -> &HashSet { &self.available_recipes } + + pub fn can_craft_recipe(&self, recipe: &str) -> bool { + self.recipe_book + .get(recipe) + .zip(self.inventories().get(self.entity)) + .map(|(recipe, inv)| inv.contains_ingredients(&*recipe).is_ok()) + .unwrap_or(false) + } + + pub fn craft_recipe(&mut self, recipe: &str) -> bool { + if self.can_craft_recipe(recipe) { + self.singleton_stream + .send(ClientMsg::ControlEvent(ControlEvent::InventoryManip( + InventoryManip::CraftRecipe(recipe.to_string()), + ))) + .unwrap(); + true + } else { + false + } + } + + fn update_available_recipes(&mut self) { + self.available_recipes = self + .recipe_book + .iter() + .map(|(name, _)| name.clone()) + .filter(|name| self.can_craft_recipe(name)) + .collect(); + } + pub fn toggle_lantern(&mut self) { self.singleton_stream .send(ClientMsg::ControlEvent(ControlEvent::ToggleLantern)) @@ -949,6 +995,8 @@ impl Client { }, } + self.update_available_recipes(); + frontend_events.push(Event::InventoryUpdated(event)); }, ServerMsg::TerrainChunkUpdate { key, chunk } => { diff --git a/common/src/assets/mod.rs b/common/src/assets/mod.rs index e3737728b6..f23ba05632 100644 --- a/common/src/assets/mod.rs +++ b/common/src/assets/mod.rs @@ -80,13 +80,14 @@ pub fn load_map A>( specifier: &str, f: F, ) -> Result, Error> { - let mut assets_write = ASSETS.write().unwrap(); + let assets_write = ASSETS.read().unwrap(); match assets_write.get(specifier) { Some(asset) => Ok(Arc::clone(asset).downcast()?), None => { + drop(assets_write); // Drop the asset hashmap to permit recursive loading let asset = Arc::new(f(A::parse(load_file(specifier, A::ENDINGS)?)?)); let clone = Arc::clone(&asset); - assets_write.insert(specifier.to_owned(), clone); + ASSETS.write().unwrap().insert(specifier.to_owned(), clone); Ok(asset) }, } diff --git a/common/src/comp/controller.rs b/common/src/comp/controller.rs index ca8bcda1b0..01942d68f1 100644 --- a/common/src/comp/controller.rs +++ b/common/src/comp/controller.rs @@ -15,6 +15,7 @@ pub enum InventoryManip { Use(Slot), Swap(Slot, Slot), Drop(Slot), + CraftRecipe(String), } #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] diff --git a/common/src/comp/inventory/item/armor.rs b/common/src/comp/inventory/item/armor.rs index 3715c88b0b..65e1ebe560 100644 --- a/common/src/comp/inventory/item/armor.rs +++ b/common/src/comp/inventory/item/armor.rs @@ -349,5 +349,14 @@ pub enum Armor { Tabard(Tabard), } +impl Armor { + /// Determines whether two pieces of armour are superficially equivalent to + /// one another (i.e: one may be substituted for the other in crafting + /// recipes or item possession checks). + pub fn superficially_eq(&self, other: &Self) -> bool { + std::mem::discriminant(self) == std::mem::discriminant(other) + } +} + #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] pub struct Stats(pub u32); diff --git a/common/src/comp/inventory/item/mod.rs b/common/src/comp/inventory/item/mod.rs index 8ebb2ba2b7..a210ae2d8b 100644 --- a/common/src/comp/inventory/item/mod.rs +++ b/common/src/comp/inventory/item/mod.rs @@ -26,7 +26,12 @@ pub enum Consumable { Velorite, VeloriteFrag, PotionMinor, + PotionMed, + PotionLarge, PotionExp, + AppleShroomCurry, + AppleStick, + MushroomStick, } #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] @@ -44,6 +49,13 @@ pub enum Utility { pub enum Ingredient { Flower, Grass, + EmptyVial, + LeatherScraps, + ShinyGem, + Stones, + Twigs, + MortarPestle, + CraftsmanHammer, } #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] @@ -159,13 +171,25 @@ impl Item { pub fn description(&self) -> &str { &self.description } + pub fn amount(&self) -> u32 { + match &self.kind { + ItemKind::Tool(_) => 1, + ItemKind::Lantern(_) => 1, + ItemKind::Armor { .. } => 1, + ItemKind::Consumable { amount, .. } => *amount, + ItemKind::Throwable { amount, .. } => *amount, + ItemKind::Utility { amount, .. } => *amount, + ItemKind::Ingredient { amount, .. } => *amount, + } + } + pub fn try_reclaim_from_block(block: Block) -> Option { 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::Apple => Some(assets::load_expect_cloned("common.items.food.apple")), + BlockKind::Mushroom => Some(assets::load_expect_cloned("common.items.food.mushroom")), + BlockKind::Velorite => Some(assets::load_expect_cloned("common.items.ore.velorite")), BlockKind::VeloriteFrag => { - Some(assets::load_expect_cloned("common.items.veloritefrag")) + Some(assets::load_expect_cloned("common.items.ore.veloritefrag")) }, BlockKind::BlueFlower => Some(assets::load_expect_cloned("common.items.flowers.blue")), BlockKind::PinkFlower => Some(assets::load_expect_cloned("common.items.flowers.pink")), @@ -185,16 +209,44 @@ impl Item { Some(assets::load_expect_cloned("common.items.grasses.medium")) }, BlockKind::ShortGrass => Some(assets::load_expect_cloned("common.items.grasses.short")), - BlockKind::Coconut => Some(assets::load_expect_cloned("common.items.coconut")), + BlockKind::Coconut => Some(assets::load_expect_cloned("common.items.food.coconut")), BlockKind::Chest => { let chosen = assets::load_expect::>("common.loot_table"); let chosen = chosen.choose(); Some(assets::load_expect_cloned(chosen)) }, + BlockKind::Stones => Some(assets::load_expect_cloned( + "common.items.crafting_ing.stones", + )), + BlockKind::Twigs => Some(assets::load_expect_cloned( + "common.items.crafting_ing.twigs", + )), + BlockKind::ShinyGem => Some(assets::load_expect_cloned( + "common.items.crafting_ing.shiny_gem", + )), _ => None, } } + + /// Determines whether two items are superficially equivalent to one another + /// (i.e: one may be substituted for the other in crafting recipes or + /// item possession checks). + pub fn superficially_eq(&self, other: &Self) -> bool { + match (&self.kind, &other.kind) { + (ItemKind::Tool(a), ItemKind::Tool(b)) => a.superficially_eq(b), + // TODO: Differentiate between lantern colors? + (ItemKind::Lantern(_), ItemKind::Lantern(_)) => true, + (ItemKind::Armor { kind: a, .. }, ItemKind::Armor { kind: b, .. }) => { + a.superficially_eq(b) + }, + (ItemKind::Consumable { kind: a, .. }, ItemKind::Consumable { kind: b, .. }) => a == b, + (ItemKind::Throwable { kind: a, .. }, ItemKind::Throwable { kind: b, .. }) => a == b, + (ItemKind::Utility { kind: a, .. }, ItemKind::Utility { kind: b, .. }) => a == b, + (ItemKind::Ingredient { kind: a, .. }, ItemKind::Ingredient { kind: b, .. }) => a == b, + _ => false, + } + } } impl Component for Item { diff --git a/common/src/comp/inventory/item/tool.rs b/common/src/comp/inventory/item/tool.rs index abeb4a04c9..4409551306 100644 --- a/common/src/comp/inventory/item/tool.rs +++ b/common/src/comp/inventory/item/tool.rs @@ -453,4 +453,11 @@ impl Tool { }], } } + + /// Determines whether two tools are superficially equivalent to one another + /// (i.e: one may be substituted for the other in crafting recipes or + /// item possession checks). + pub fn superficially_eq(&self, other: &Self) -> bool { + ToolCategory::from(self.kind) == ToolCategory::from(other.kind) + } } diff --git a/common/src/comp/inventory/mod.rs b/common/src/comp/inventory/mod.rs index 657386fec5..22b3622971 100644 --- a/common/src/comp/inventory/mod.rs +++ b/common/src/comp/inventory/mod.rs @@ -1,7 +1,7 @@ pub mod item; pub mod slot; -use crate::assets; +use crate::{assets, recipe::Recipe}; use item::{Consumable, Item, ItemKind}; use serde::{Deserialize, Serialize}; use specs::{Component, FlaggedStorage, HashMapStorage}; @@ -185,14 +185,11 @@ impl Inventory { /// Add a series of items to inventory, returning any which do not fit as an /// error. - pub fn push_all>(&mut self, mut items: I) -> Result<(), Error> { + pub fn push_all>(&mut self, items: I) -> Result<(), Error> { // Vec doesn't allocate for zero elements so this should be cheap let mut leftovers = Vec::new(); - let mut slots = self.slots.iter_mut(); - for item in &mut items { - if let Some(slot) = slots.find(|slot| slot.is_none()) { - slot.replace(item); - } else { + for item in items { + if let Some(item) = self.push(item) { leftovers.push(item); } } @@ -340,6 +337,52 @@ impl Inventory { None } } + + /// Determine how many of a particular item there is in the inventory. + pub fn item_count(&self, item: &Item) -> usize { + self.slots() + .iter() + .flatten() + .filter(|it| it.superficially_eq(item)) + .map(|it| it.amount() as usize) + .sum() + } + + /// Determine whether the inventory contains the ingredients for a recipe. + /// If it does, return a vector of numbers, where is number corresponds + /// to an inventory slot, along with the number of items that need + /// removing from it. It items are missing, return the missing items, and + /// how many are missing. + pub fn contains_ingredients<'a>( + &self, + recipe: &'a Recipe, + ) -> Result, Vec<(&'a Item, usize)>> { + let mut slot_claims = vec![0; self.slots.len()]; + let mut missing = Vec::new(); + + for (input, mut needed) in recipe.inputs() { + let mut contains_any = false; + + for (i, slot) in self.slots().iter().enumerate() { + if let Some(item) = slot.as_ref().filter(|item| item.superficially_eq(input)) { + let can_claim = (item.amount() as usize - slot_claims[i]).min(needed); + slot_claims[i] += can_claim; + needed -= can_claim; + contains_any = true; + } + } + + if needed > 0 || !contains_any { + missing.push((input, needed)); + } + } + + if missing.len() == 0 { + Ok(slot_claims) + } else { + Err(missing) + } + } } impl Default for Inventory { @@ -348,8 +391,8 @@ impl Default for Inventory { slots: vec![None; 36], amount: 0, }; - inventory.push(assets::load_expect_cloned("common.items.cheese")); - inventory.push(assets::load_expect_cloned("common.items.apple")); + inventory.push(assets::load_expect_cloned("common.items.food.cheese")); + inventory.push(assets::load_expect_cloned("common.items.food.apple")); inventory } } @@ -371,6 +414,7 @@ pub enum InventoryUpdateEvent { CollectFailed, Possession, Debug, + Craft, } impl Default for InventoryUpdateEvent { diff --git a/common/src/lib.rs b/common/src/lib.rs index c2d04628e3..fb04ff28b1 100644 --- a/common/src/lib.rs +++ b/common/src/lib.rs @@ -26,6 +26,7 @@ pub mod msg; pub mod npc; pub mod path; pub mod ray; +pub mod recipe; pub mod region; pub mod spiral; pub mod state; diff --git a/common/src/msg/server.rs b/common/src/msg/server.rs index a766a7ef37..a83dc6216e 100644 --- a/common/src/msg/server.rs +++ b/common/src/msg/server.rs @@ -1,7 +1,9 @@ use super::{ClientState, EcsCompPacket}; use crate::{ character::CharacterItem, - comp, state, sync, + comp, + recipe::RecipeBook, + state, sync, sync::Uid, terrain::{Block, TerrainChunk}, }; @@ -58,6 +60,7 @@ pub enum ServerMsg { server_info: ServerInfo, time_of_day: state::TimeOfDay, world_map: (Vec2, Vec), + recipe_book: RecipeBook, }, /// An error occurred while loading character data CharacterDataLoadError(String), diff --git a/common/src/recipe.rs b/common/src/recipe.rs new file mode 100644 index 0000000000..bad5a81abf --- /dev/null +++ b/common/src/recipe.rs @@ -0,0 +1,99 @@ +use crate::{ + assets::{self, Asset}, + comp::{Inventory, Item}, +}; +use hashbrown::HashMap; +use serde::{Deserialize, Serialize}; +use std::{fs::File, io::BufReader, sync::Arc}; + +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct Recipe { + pub output: (Item, usize), + pub inputs: Vec<(Item, usize)>, +} + +#[allow(clippy::type_complexity)] +impl Recipe { + /// Perform a recipe, returning a list of missing items on failure + pub fn perform( + &self, + inv: &mut Inventory, + ) -> Result, Vec<(&Item, usize)>> { + // Get ingredient cells from inventory, + inv.contains_ingredients(self)? + .into_iter() + .enumerate() + .for_each(|(i, n)| { + (0..n).for_each(|_| { + inv.take(i).expect("Expected item to exist in inventory"); + }) + }); + + for i in 0..self.output.1 { + if let Some(item) = inv.push(self.output.0.clone()) { + return Ok(Some((item, self.output.1 - i))); + } + } + + Ok(None) + } + + pub fn inputs(&self) -> impl ExactSizeIterator { + self.inputs.iter().map(|(item, amount)| (item, *amount)) + } +} + +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct RecipeBook { + recipes: HashMap, +} + +impl RecipeBook { + pub fn get(&self, recipe: &str) -> Option<&Recipe> { self.recipes.get(recipe) } + + pub fn iter(&self) -> impl ExactSizeIterator { self.recipes.iter() } + + pub fn get_available(&self, inv: &Inventory) -> Vec<(String, Recipe)> { + self.recipes + .iter() + .filter(|(_, recipe)| inv.contains_ingredients(recipe).is_ok()) + .map(|(name, recipe)| (name.clone(), recipe.clone())) + .collect() + } +} + +impl Asset for RecipeBook { + const ENDINGS: &'static [&'static str] = &["ron"]; + + fn parse(buf_reader: BufReader) -> Result { + ron::de::from_reader::< + BufReader, + HashMap)>, + >(buf_reader) + .map_err(assets::Error::parse_error) + .and_then(|recipes| { + Ok(RecipeBook { + recipes: recipes + .into_iter() + .map::, _>( + |(name, ((output, amount), inputs))| { + Ok((name, Recipe { + output: ((&*assets::load::(&output)?).clone(), amount), + inputs: inputs + .into_iter() + .map::, _>( + |(name, amount)| { + Ok(((&*assets::load::(&name)?).clone(), amount)) + }, + ) + .collect::>()?, + })) + }, + ) + .collect::>()?, + }) + }) + } +} + +pub fn default_recipe_book() -> Arc { assets::load_expect("common.recipe_book") } diff --git a/common/src/terrain/block.rs b/common/src/terrain/block.rs index 6c69a9ee35..bf6886c0ca 100644 --- a/common/src/terrain/block.rs +++ b/common/src/terrain/block.rs @@ -83,6 +83,9 @@ pub enum BlockKind { WardrobeDouble, LargeGrass, Pot, + Stones, + Twigs, + ShinyGem, } impl BlockKind { @@ -167,6 +170,9 @@ impl BlockKind { BlockKind::WardrobeSingle => false, BlockKind::WardrobeDouble => false, BlockKind::Pot => false, + BlockKind::Stones => true, + BlockKind::Twigs => true, + BlockKind::ShinyGem => true, _ => false, } } @@ -252,6 +258,9 @@ impl BlockKind { BlockKind::WardrobeDouble => false, BlockKind::LargeGrass => false, BlockKind::Pot => false, + BlockKind::Stones => false, + BlockKind::Twigs => false, + BlockKind::ShinyGem => false, _ => true, } } @@ -323,6 +332,9 @@ impl BlockKind { BlockKind::WardrobeSingle => true, BlockKind::WardrobeDouble => true, BlockKind::Pot => true, + BlockKind::Stones => false, + BlockKind::Twigs => false, + BlockKind::ShinyGem => false, _ => true, } } @@ -389,6 +401,9 @@ impl BlockKind { BlockKind::VeloriteFrag => true, BlockKind::Chest => true, BlockKind::Coconut => true, + BlockKind::Stones => true, + BlockKind::Twigs => true, + BlockKind::ShinyGem => true, _ => false, } } diff --git a/server/src/events/inventory_manip.rs b/server/src/events/inventory_manip.rs index b33a170e0b..7c1d4ee71d 100644 --- a/server/src/events/inventory_manip.rs +++ b/server/src/events/inventory_manip.rs @@ -5,6 +5,7 @@ use common::{ slot::{self, Slot}, Pos, MAX_PICKUP_RANGE_SQR, }, + recipe::default_recipe_book, sync::{Uid, WorldSyncExt}, terrain::block::Block, vol::{ReadVol, Vox}, @@ -165,16 +166,10 @@ pub fn handle_inventory(server: &mut Server, entity: EcsEntity, manip: comp::Inv thrown_items.push(( *pos, state - .ecs() - .read_storage::() - .get(entity) - .copied() + .read_component_cloned::(entity) .unwrap_or_default(), state - .ecs() - .read_storage::() - .get(entity) - .copied() + .read_component_cloned::(entity) .unwrap_or_default(), *kind, )); @@ -317,10 +312,7 @@ pub fn handle_inventory(server: &mut Server, entity: EcsEntity, manip: comp::Inv dropped_items.push(( *pos, state - .ecs() - .read_storage::() - .get(entity) - .copied() + .read_component_cloned::(entity) .unwrap_or_default(), item, )); @@ -330,6 +322,39 @@ pub fn handle_inventory(server: &mut Server, entity: EcsEntity, manip: comp::Inv comp::InventoryUpdate::new(comp::InventoryUpdateEvent::Dropped), ); }, + + comp::InventoryManip::CraftRecipe(recipe) => { + if let Some(inv) = state + .ecs() + .write_storage::() + .get_mut(entity) + { + let recipe_book = default_recipe_book(); + let craft_result = recipe_book.get(&recipe).and_then(|r| r.perform(inv).ok()); + + if craft_result.is_some() { + let _ = state.ecs().write_storage().insert( + entity, + comp::InventoryUpdate::new(comp::InventoryUpdateEvent::Craft), + ); + } + + // Drop the item if there wasn't enough space + if let Some(Some((item, amount))) = craft_result { + for _ in 0..amount { + dropped_items.push(( + state + .read_component_cloned::(entity) + .unwrap_or_default(), + state + .read_component_cloned::(entity) + .unwrap_or_default(), + item.clone(), + )); + } + } + } + }, } // Drop items diff --git a/server/src/lib.rs b/server/src/lib.rs index 11d7d95093..88166f25e9 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -32,6 +32,7 @@ use common::{ comp::{self, ChatType}, event::{EventBus, ServerEvent}, msg::{ClientState, ServerInfo, ServerMsg}, + recipe::default_recipe_book, state::{State, TimeOfDay}, sync::WorldSyncExt, terrain::TerrainChunkSize, @@ -636,6 +637,7 @@ impl Server { server_info: self.get_server_info(), time_of_day: *self.state.ecs().read_resource(), world_map: (WORLD_SIZE.map(|e| e as u32), self.map.clone()), + recipe_book: (&*default_recipe_book()).clone(), }); frontend_events.push(Event::ClientConnected { entity }); diff --git a/voxygen/src/hud/bag.rs b/voxygen/src/hud/bag.rs index 7e38e47cf5..65f6e34d6d 100644 --- a/voxygen/src/hud/bag.rs +++ b/voxygen/src/hud/bag.rs @@ -30,7 +30,6 @@ widget_ids! { inv_grid_2, inv_scrollbar, inv_slots_0, - map_title, inv_slots[], //tooltip[], bg, diff --git a/voxygen/src/hud/buttons.rs b/voxygen/src/hud/buttons.rs index 167aa0f117..e1925a065e 100644 --- a/voxygen/src/hud/buttons.rs +++ b/voxygen/src/hud/buttons.rs @@ -37,6 +37,11 @@ widget_ids! { spellbook_button_bg, spellbook_text, spellbook_text_bg, + crafting_button, + crafting_button_bg, + crafting_text, + crafting_text_bg, + } } const TOOLTIP_UPSHIFT: f64 = 40.0; @@ -93,6 +98,7 @@ pub enum Event { ToggleMap, ToggleSocial, ToggleSpell, + ToggleCrafting, } impl<'a> Widget for Buttons<'a> { @@ -360,6 +366,43 @@ impl<'a> Widget for Buttons<'a> { .color(TEXT_COLOR) .set(state.ids.spellbook_text, ui); } + // Crafting + if Button::image(self.imgs.crafting_icon) + .w_h(25.0, 25.0) + .left_from(state.ids.spellbook_button, 10.0) + .hover_image(self.imgs.crafting_icon_hover) + .press_image(self.imgs.crafting_icon_press) + .with_tooltip( + self.tooltip_manager, + &localized_strings.get("hud.crafting"), + "", + &button_tooltip, + ) + .bottom_offset(TOOLTIP_UPSHIFT) + .set(state.ids.crafting_button, ui) + .was_clicked() + { + return Some(Event::ToggleCrafting); + } + if let Some(crafting) = &self + .global_state + .settings + .controls + .get_binding(GameInput::Crafting) + { + Text::new(crafting.to_string().as_str()) + .bottom_right_with_margins_on(state.ids.crafting_button, 0.0, 0.0) + .font_size(10) + .font_id(self.fonts.cyri.conrod_id) + .color(BLACK) + .set(state.ids.crafting_text_bg, ui); + Text::new(crafting.to_string().as_str()) + .bottom_right_with_margins_on(state.ids.crafting_text_bg, 1.0, 1.0) + .font_size(10) + .font_id(self.fonts.cyri.conrod_id) + .color(TEXT_COLOR) + .set(state.ids.crafting_text, ui); + } None } } diff --git a/voxygen/src/hud/crafting.rs b/voxygen/src/hud/crafting.rs new file mode 100644 index 0000000000..19fff3dfa6 --- /dev/null +++ b/voxygen/src/hud/crafting.rs @@ -0,0 +1,505 @@ +use super::{ + img_ids::{Imgs, ImgsRot}, + item_imgs::ItemImgs, + TEXT_COLOR, TEXT_DULL_RED_COLOR, TEXT_GRAY_COLOR, UI_HIGHLIGHT_0, UI_MAIN, +}; +use crate::{ + i18n::VoxygenLocalization, + ui::{fonts::ConrodVoxygenFonts, ImageFrame, Tooltip, TooltipManager, Tooltipable}, +}; +use client::{self, Client}; +use common::comp::Inventory; +use conrod_core::{ + color, + widget::{self, Button, Image, Rectangle, Scrollbar, Text}, + widget_ids, Color, Colorable, Labelable, Positionable, Sizeable, Widget, WidgetCommon, +}; + +widget_ids! { + pub struct Ids { + window, + window_frame, + close, + icon, + title_main, + title_rec, + align_rec, + scrollbar_rec, + title_ing, + align_ing, + scrollbar_ing, + btn_craft, + recipe_names[], + recipe_img_frame[], + recipe_img[], + ingredients[], + ingredient_frame[], + ingredient_img[], + req_text[], + ingredients_txt, + output_img_frame, + output_img, + } +} + +pub enum Event { + CraftRecipe(String), + Close, +} + +#[derive(WidgetCommon)] +pub struct Crafting<'a> { + client: &'a Client, + imgs: &'a Imgs, + fonts: &'a ConrodVoxygenFonts, + localized_strings: &'a std::sync::Arc, + rot_imgs: &'a ImgsRot, + tooltip_manager: &'a mut TooltipManager, + item_imgs: &'a ItemImgs, + inventory: &'a Inventory, + #[conrod(common_builder)] + common: widget::CommonBuilder, +} +#[allow(clippy::too_many_arguments)] +impl<'a> Crafting<'a> { + pub fn new( + client: &'a Client, + imgs: &'a Imgs, + fonts: &'a ConrodVoxygenFonts, + localized_strings: &'a std::sync::Arc, + rot_imgs: &'a ImgsRot, + tooltip_manager: &'a mut TooltipManager, + item_imgs: &'a ItemImgs, + inventory: &'a Inventory, + ) -> Self { + Self { + client, + imgs, + fonts, + localized_strings, + rot_imgs, + tooltip_manager, + item_imgs, + inventory, + common: widget::CommonBuilder::default(), + } + } +} + +pub struct State { + ids: Ids, + selected_recipe: Option, +} + +impl<'a> Widget for Crafting<'a> { + type Event = Vec; + type State = State; + type Style = (); + + fn init_state(&self, id_gen: widget::id::Generator) -> Self::State { + State { + ids: Ids::new(id_gen), + selected_recipe: None, + } + } + + #[allow(clippy::unused_unit)] // TODO: Pending review in #587 + fn style(&self) -> Self::Style { () } + + fn update(self, args: widget::UpdateArgs) -> Self::Event { + let widget::UpdateArgs { state, ui, .. } = args; + + if state.ids.recipe_names.len() < self.client.recipe_book().iter().len() { + state.update(|state| { + state.ids.recipe_names.resize( + self.client.recipe_book().iter().len(), + &mut ui.widget_id_generator(), + ) + }); + } + /*if state.ids.recipe_img_frame.len() < self.client.recipe_book().iter().len() { + state.update(|state| { + state.ids.recipe_img_frame.resize( + self.client.recipe_book().iter().len(), + &mut ui.widget_id_generator(), + ) + }); + } + if state.ids.recipe_img.len() < self.client.recipe_book().iter().len() { + state.update(|state| { + state.ids.recipe_img.resize( + self.client.recipe_book().iter().len(), + &mut ui.widget_id_generator(), + ) + }); + }*/ + + let ids = &state.ids; + + let mut events = Vec::new(); + + // Tooltips + let item_tooltip = Tooltip::new({ + let edge = &self.rot_imgs.tt_side; + let corner = &self.rot_imgs.tt_corner; + ImageFrame::new( + [edge.cw180, edge.none, edge.cw270, edge.cw90], + [corner.none, corner.cw270, corner.cw90, corner.cw180], + Color::Rgba(0.08, 0.07, 0.04, 1.0), + 5.0, + ) + }) + .title_font_size(self.fonts.cyri.scale(15)) + .parent(ui.window) + .desc_font_size(self.fonts.cyri.scale(12)) + .title_text_color(TEXT_COLOR) + .font_id(self.fonts.cyri.conrod_id) + .desc_text_color(TEXT_COLOR); + + Image::new(self.imgs.crafting_window) + .bottom_right_with_margins_on(ui.window, 308.0, 450.0) + .color(Some(UI_MAIN)) + .w_h(422.0, 460.0) + .set(ids.window, ui); + Image::new(self.imgs.crafting_frame) + .middle_of(ids.window) + .color(Some(UI_HIGHLIGHT_0)) + .w_h(422.0, 460.0) + .set(ids.window_frame, ui); + Image::new(self.imgs.crafting_icon_bordered) + .w_h(38.0, 38.0) + .top_left_with_margins_on(state.ids.window_frame, 4.0, 4.0) + .set(state.ids.icon, ui); + // Close Button + if Button::image(self.imgs.close_button) + .w_h(24.0, 25.0) + .hover_image(self.imgs.close_button_hover) + .press_image(self.imgs.close_button_press) + .top_right_with_margins_on(ids.window, 0.0, 0.0) + .set(ids.close, ui) + .was_clicked() + { + events.push(Event::Close); + } + + // Title + Text::new(&self.localized_strings.get("hud.crafting")) + .mid_top_with_margin_on(ids.window_frame, 9.0) + .font_id(self.fonts.cyri.conrod_id) + .font_size(self.fonts.cyri.scale(22)) + .color(TEXT_COLOR) + .set(ids.title_main, ui); + + // Alignment + Rectangle::fill_with([136.0, 378.0], color::TRANSPARENT) + .top_left_with_margins_on(ids.window_frame, 74.0, 5.0) + .set(ids.align_rec, ui); + Rectangle::fill_with([274.0, 340.0], color::TRANSPARENT) + .top_right_with_margins_on(ids.window, 74.0, 5.0) + .set(ids.align_ing, ui); + let client = &self.client; + // First available recipes, then unavailable ones + let recipe_iter = self + .client + .recipe_book() + .iter() + .filter(|(name, _)| client.available_recipes().contains(name.as_str())) + .map(|(name, recipe)| (name, recipe, true)) + .chain( + client + .recipe_book() + .iter() + .filter(|(name, _)| !client.available_recipes().contains(name.as_str())) + .map(|(name, recipe)| (name, recipe, false)), + ); + match &state.selected_recipe { + None => {}, + Some(recipe) => { + let can_perform = client.available_recipes().contains(recipe.as_str()); + // Ingredients Text + Text::new(&self.localized_strings.get("hud.crafting.ingredients")) + .top_left_with_margins_on(state.ids.align_ing, 10.0, 5.0) + .font_id(self.fonts.cyri.conrod_id) + .font_size(self.fonts.cyri.scale(18)) + .color(TEXT_COLOR) + .set(state.ids.ingredients_txt, ui); + // Craft button + if Button::image(self.imgs.button) + .w_h(105.0, 25.0) + .hover_image( + can_perform + .then_some(self.imgs.button_hover) + .unwrap_or(self.imgs.button), + ) + .press_image( + can_perform + .then_some(self.imgs.button_press) + .unwrap_or(self.imgs.button), + ) + .label(&self.localized_strings.get("hud.crafting.craft")) + .label_y(conrod_core::position::Relative::Scalar(1.0)) + .label_color(can_perform.then_some(TEXT_COLOR).unwrap_or(TEXT_GRAY_COLOR)) + .label_font_size(self.fonts.cyri.scale(12)) + .label_font_id(self.fonts.cyri.conrod_id) + .image_color(can_perform.then_some(TEXT_COLOR).unwrap_or(TEXT_GRAY_COLOR)) + .mid_bottom_with_margin_on(ids.align_ing, -31.0) + .set(ids.btn_craft, ui) + .was_clicked() + { + events.push(Event::CraftRecipe(recipe.clone())); + } + // Result Image BG + Image::new(self.imgs.inv_slot) + .w_h(60.0, 60.0) + .top_right_with_margins_on(state.ids.align_ing, 15.0, 10.0) + .parent(ids.align_ing) + .set(ids.output_img_frame, ui); + + if let Some(recipe) = state + .selected_recipe + .as_ref() + .and_then(|r| self.client.recipe_book().get(r.as_str())) + { + let output_text = format!("x{}", &recipe.output.1.to_string()); + // Output Image + Button::image( + self.item_imgs + .img_id_or_not_found_img((&recipe.output.0).into()), + ) + .w_h(55.0, 55.0) + .middle_of(state.ids.output_img_frame) + .label(if recipe.output.1 > 1 {&output_text} else {""}) // Only show output amount for amounts > 1 + .label_color(TEXT_COLOR) + .label_font_size(self.fonts.cyri.scale(14)) + .label_font_id(self.fonts.cyri.conrod_id) + .label_y(conrod_core::position::Relative::Scalar(-24.0)) + .label_x(conrod_core::position::Relative::Scalar(24.0)) + .with_tooltip( + self.tooltip_manager, + recipe.output.0.name(), + recipe.output.0.description(), + &item_tooltip, + ) + .set(state.ids.output_img, ui); + } + }, + } + + // Recipe list + for (i, (name, recipe, can_perform)) in recipe_iter.enumerate() { + let button = Button::image( + if state + .selected_recipe + .as_ref() + .map(|s| s != name) + .unwrap_or(false) + { + self.imgs.nothing + } else { + match state.selected_recipe { + None => self.imgs.nothing, + Some(_) => self.imgs.selection, + } + }, + ); + // Recipe Button + let button = if i == 0 { + button.mid_top_with_margin_on(state.ids.align_rec, 2.0) + } else { + button.mid_bottom_with_margin_on(state.ids.recipe_names[i - 1], -25.0) + }; + if button + .label(recipe.output.0.name()) + .w_h(130.0, 20.0) + .hover_image(self.imgs.selection_hover) + .press_image(self.imgs.selection_press) + .label_color(can_perform.then_some(TEXT_COLOR).unwrap_or(TEXT_GRAY_COLOR)) + .label_font_size(self.fonts.cyri.scale(12)) + .label_font_id(self.fonts.cyri.conrod_id) + .label_y(conrod_core::position::Relative::Scalar(2.0)) + .set(state.ids.recipe_names[i], ui) + .was_clicked() + { + if state + .selected_recipe + .as_ref() + .map(|s| s == name) + .unwrap_or(false) + { + state.update(|s| s.selected_recipe = None); + } else { + state.update(|s| s.selected_recipe = Some(name.clone())); + } + } + // Image BG + /*Rectangle::fill_with([10.0, 10.0], color::TRANSPARENT) + .w_h(20.0, 20.0) + .mid_left_of(state.ids.recipe_names[i]) + .set(state.ids.recipe_img_frame[i], ui); + //Item Image + Image::new( + self.item_imgs + .img_id_or_not_found_img((&recipe.output.0).into()), + ) + .w_h(18.0, 18.0) + .color( + can_perform + .then_some(Some(TEXT_COLOR)) + .unwrap_or(Some(TEXT_GRAY_COLOR)), + ) + .middle_of(state.ids.recipe_img_frame[i]) + .set(state.ids.recipe_img[i], ui);*/ + } + + //Ingredients + if let Some(recipe) = state + .selected_recipe + .as_ref() + .and_then(|r| self.client.recipe_book().get(r.as_str())) + { + // Title + Text::new(&recipe.output.0.name().to_string()) + .mid_top_with_margin_on(state.ids.align_ing, -22.0) + .font_id(self.fonts.cyri.conrod_id) + .font_size(self.fonts.cyri.scale(14)) + .color(TEXT_COLOR) + .parent(state.ids.window) + .set(state.ids.title_ing, ui); + // Ingredient images with tooltip + if state.ids.ingredient_frame.len() < recipe.inputs().len() { + state.update(|state| { + state + .ids + .ingredient_frame + .resize(recipe.inputs().len(), &mut ui.widget_id_generator()) + }); + }; + if state.ids.ingredients.len() < recipe.inputs().len() { + state.update(|state| { + state + .ids + .ingredients + .resize(recipe.inputs().len(), &mut ui.widget_id_generator()) + }); + }; + if state.ids.ingredient_img.len() < recipe.inputs().len() { + state.update(|state| { + state + .ids + .ingredient_img + .resize(recipe.inputs().len(), &mut ui.widget_id_generator()) + }); + }; + if state.ids.req_text.len() < recipe.inputs().len() { + state.update(|state| { + state + .ids + .req_text + .resize(recipe.inputs().len(), &mut ui.widget_id_generator()) + }); + }; + // Widget generation for every ingredient + for (i, (item, amount)) in recipe.inputs.iter().enumerate() { + // Grey color for images and text if their amount is too low to craft the item + let col = if self.inventory.item_count(item) as f32 / *amount as f32 >= 1.0 { + TEXT_COLOR + } else { + TEXT_DULL_RED_COLOR + }; + // Slot BG + let frame_pos = if i == 0 { + state.ids.ingredients_txt + } else { + state.ids.ingredient_frame[i - 1] + }; + // add a larger offset for the the first ingredient and the "Required Text for + // Catalysts/Tools" + let frame_offset = if i == 0 { + 10.0 + } else if *amount == 0 { + 5.0 + } else { + 0.0 + }; + let frame = Image::new(self.imgs.inv_slot).w_h(25.0, 25.0); + let frame = if *amount == 0 { + frame.down_from(state.ids.req_text[i], 10.0 + frame_offset) + } else { + frame.down_from(frame_pos, 10.0 + frame_offset) + }; + frame.set(state.ids.ingredient_frame[i], ui); + //Item Image + let title = item.name(); + let desc = item.description(); + Button::image(self.item_imgs.img_id_or_not_found_img(item.into())) + .w_h(22.0, 22.0) + .middle_of(state.ids.ingredient_frame[i]) + //.image_color(col) + .with_tooltip(self.tooltip_manager, title, desc, &item_tooltip) + .set(state.ids.ingredient_img[i], ui); + // Ingredients text and amount + // Don't show inventory amounts above 999 to avoid the widget clipping + let over9k = "999+"; + let in_inv: &str = &self.inventory.item_count(item).to_string(); + // Show Ingredients + // Align "Required" Text below last ingredient + if *amount == 0 { + // Catalysts/Tools + Text::new(&self.localized_strings.get("hud.crafting.tool_cata")) + .down_from(state.ids.ingredient_frame[i - 1], 20.0) + .font_id(self.fonts.cyri.conrod_id) + .font_size(self.fonts.cyri.scale(14)) + .color(col) + .set(state.ids.req_text[i], ui); + Text::new(item.name()) + .right_from(state.ids.ingredient_frame[i], 10.0) + .font_id(self.fonts.cyri.conrod_id) + .font_size(self.fonts.cyri.scale(14)) + .color(col) + .set(state.ids.ingredients[i], ui); + } else { + // Ingredients + let input = format!( + "{}x {} ({})", + amount, + item.name(), + if self.inventory.item_count(item) > 999 { + over9k + } else { + in_inv + } + ); + // Ingredient Text + Text::new(&input) + .right_from(state.ids.ingredient_frame[i], 10.0) + .font_id(self.fonts.cyri.conrod_id) + .font_size(self.fonts.cyri.scale(14)) + .color(col) + .set(state.ids.ingredients[i], ui); + } + } + } + + let ids = &state.ids; + // Scrollbars + Scrollbar::y_axis(ids.align_rec) + .thickness(5.0) + .rgba(0.33, 0.33, 0.33, 1.0) + .set(ids.scrollbar_rec, ui); + Scrollbar::y_axis(ids.align_ing) + .thickness(5.0) + .rgba(0.33, 0.33, 0.33, 1.0) + .set(ids.scrollbar_ing, ui); + + // Title Recipes and Ingredients + Text::new(&self.localized_strings.get("hud.crafting.recipes")) + .mid_top_with_margin_on(ids.align_rec, -22.0) + .font_id(self.fonts.cyri.conrod_id) + .font_size(self.fonts.cyri.scale(14)) + .color(TEXT_COLOR) + .parent(ids.window) + .set(ids.title_rec, ui); + + events + } +} diff --git a/voxygen/src/hud/img_ids.rs b/voxygen/src/hud/img_ids.rs index 50fff76512..17e87924de 100644 --- a/voxygen/src/hud/img_ids.rs +++ b/voxygen/src/hud/img_ids.rs @@ -1,16 +1,15 @@ -use crate::ui::img_ids::{BlankGraphic, ImageGraphic, VoxelGraphic, VoxelPixArtGraphic}; +use crate::ui::img_ids::{BlankGraphic, ImageGraphic, VoxelPixArtGraphic}; // TODO: Combine with image_ids, see macro definition rotation_image_ids! { pub struct ImgsRot { - // Tooltip Test - tt_side: "voxygen/element/frames/tt_test_edge", - tt_corner: "voxygen/element/frames/tt_test_corner_tr", - indicator_mmap_small: "voxygen.element.buttons.indicator_mmap_small", + // Tooltip Test + tt_side: "voxygen/element/frames/tt_test_edge", + tt_corner: "voxygen/element/frames/tt_test_corner_tr", ////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -54,6 +53,10 @@ image_ids! { ////////////////////////////////////////////////////////////////////////////////////////////////////// + // Selection Frame + selection: "voxygen.element.frames.selection", + selection_hover: "voxygen.element.frames.selection_hover", + selection_press: "voxygen.element.frames.selection_press", // Social Window social_button: "voxygen.element.buttons.social_tab", @@ -62,6 +65,16 @@ image_ids! { social_button_press: "voxygen.element.buttons.social_tab_press", social_frame: "voxygen.element.frames.social_frame", + // Crafting Window + + crafting_window: "voxygen.element.misc_bg.crafting", + crafting_frame: "voxygen.element.misc_bg.crafting_frame", + crafting_icon_bordered: "voxygen.element.icons.anvil", + crafting_icon: "voxygen.element.buttons.anvil", + crafting_icon_hover: "voxygen.element.buttons.anvil_hover", + crafting_icon_press: "voxygen.element.buttons.anvil_press", + + // Chat-Arrows chat_arrow: "voxygen.element.buttons.arrow_down", chat_arrow_mo: "voxygen.element.buttons.arrow_down_hover", @@ -115,7 +128,7 @@ image_ids! { staff_m2: "voxygen.element.icons.staff_m2", flyingrod_m1: "voxygen.element.icons.debug_wand_m1", flyingrod_m2: "voxygen.element.icons.debug_wand_m2", - charge: "voxygen.element.icons.skill_charge_3", + sword_pierce: "voxygen.element.icons.skill_sword_pierce", hammerleap: "voxygen.element.icons.skill_hammerleap", axespin: "voxygen.element.icons.skill_axespin", diff --git a/voxygen/src/hud/minimap.rs b/voxygen/src/hud/minimap.rs index b696c2c66b..28d27563e7 100644 --- a/voxygen/src/hud/minimap.rs +++ b/voxygen/src/hud/minimap.rs @@ -109,7 +109,7 @@ impl<'a> Widget for MiniMap<'a> { if self.show.mini_map { Image::new(self.imgs.mmap_frame) .w_h(174.0 * SCALE, 190.0 * SCALE) - .top_right_with_margins_on(ui.window, 0.0, 5.0) + .top_right_with_margins_on(ui.window, 5.0, 5.0) .color(Some(UI_MAIN)) .set(state.ids.mmap_frame, ui); Image::new(self.imgs.mmap_frame_2) diff --git a/voxygen/src/hud/mod.rs b/voxygen/src/hud/mod.rs index 4177177ca8..89bf34089c 100644 --- a/voxygen/src/hud/mod.rs +++ b/voxygen/src/hud/mod.rs @@ -1,6 +1,7 @@ mod bag; mod buttons; mod chat; +mod crafting; mod esc_menu; mod hotbar; mod img_ids; @@ -25,6 +26,7 @@ use bag::Bag; use buttons::Buttons; use chat::Chat; use chrono::NaiveTime; +use crafting::Crafting; use esc_menu::EscMenu; use img_ids::Imgs; use item_imgs::ItemImgs; @@ -62,6 +64,8 @@ use vek::*; const XP_COLOR: Color = Color::Rgba(0.59, 0.41, 0.67, 1.0); const TEXT_COLOR: Color = Color::Rgba(1.0, 1.0, 1.0, 1.0); +const TEXT_GRAY_COLOR: Color = Color::Rgba(0.5, 0.5, 0.5, 1.0); +const TEXT_DULL_RED_COLOR: Color = Color::Rgba(0.56, 0.2, 0.2, 1.0); const TEXT_BG: Color = Color::Rgba(0.0, 0.0, 0.0, 1.0); //const TEXT_COLOR_GREY: Color = Color::Rgba(1.0, 1.0, 1.0, 0.5); const MENU_BG: Color = Color::Rgba(0.0, 0.0, 0.0, 0.4); @@ -199,6 +203,7 @@ widget_ids! { esc_menu, small_window, social_window, + crafting_window, settings_window, // Free look indicator @@ -287,6 +292,7 @@ pub enum Event { ChangeFreeLookBehavior(PressBehavior), ChangeAutoWalkBehavior(PressBehavior), ChangeStopAutoWalkOnInput(bool), + CraftRecipe(String), } // TODO: Are these the possible layouts we want? @@ -337,6 +343,7 @@ pub struct Show { ui: bool, intro: bool, help: bool, + crafting: bool, debug: bool, bag: bool, social: bool, @@ -355,29 +362,50 @@ pub struct Show { } impl Show { fn bag(&mut self, open: bool) { - self.bag = open; - self.map = false; - self.want_grab = !open; + if !self.esc_menu { + self.bag = open; + self.map = false; + self.want_grab = !open; + } } fn toggle_bag(&mut self) { self.bag(!self.bag); } fn map(&mut self, open: bool) { - self.map = open; - self.bag = false; - self.want_grab = !open; + if !self.esc_menu { + self.map = open; + self.bag = false; + self.crafting = false; + self.social = false; + self.spell = false; + self.want_grab = !open; + } } fn social(&mut self, open: bool) { - self.social = open; - self.spell = false; - self.want_grab = !open; + if !self.esc_menu { + self.social = open; + self.crafting = false; + self.spell = false; + self.want_grab = !open; + } + } + + fn crafting(&mut self, open: bool) { + if !self.esc_menu { + self.crafting = open; + self.bag = open; + self.want_grab = !open; + } } fn spell(&mut self, open: bool) { - self.social = false; - self.spell = open; - self.want_grab = !open; + if !self.esc_menu { + self.social = false; + self.crafting = false; + self.spell = open; + self.want_grab = !open; + } } fn toggle_map(&mut self) { self.map(!self.map) } @@ -385,15 +413,18 @@ impl Show { fn toggle_mini_map(&mut self) { self.mini_map = !self.mini_map; } fn settings(&mut self, open: bool) { - self.open_windows = if open { - Windows::Settings - } else { - Windows::None - }; - self.bag = false; - self.social = false; - self.spell = false; - self.want_grab = !open; + if !self.esc_menu { + self.open_windows = if open { + Windows::Settings + } else { + Windows::None + }; + self.bag = false; + self.social = false; + self.crafting = false; + self.spell = false; + self.want_grab = !open; + } } fn toggle_settings(&mut self) { @@ -412,6 +443,7 @@ impl Show { || self.esc_menu || self.map || self.social + || self.crafting || self.spell || self.help || self.intro @@ -427,6 +459,7 @@ impl Show { self.map = false; self.social = false; self.spell = false; + self.crafting = false; self.open_windows = Windows::None; self.want_grab = true; @@ -458,6 +491,8 @@ impl Show { self.spell = false; } + fn toggle_crafting(&mut self) { self.crafting(!self.crafting) } + fn open_social_tab(&mut self, social_tab: SocialTab) { self.social_tab = social_tab; self.spell = false; @@ -557,6 +592,7 @@ impl Hud { esc_menu: false, open_windows: Windows::None, map: false, + crafting: false, ui: true, social: false, spell: false, @@ -1478,6 +1514,7 @@ impl Hud { Some(buttons::Event::ToggleSocial) => self.show.toggle_social(), Some(buttons::Event::ToggleSpell) => self.show.toggle_spell(), Some(buttons::Event::ToggleMap) => self.show.toggle_map(), + Some(buttons::Event::ToggleCrafting) => self.show.toggle_crafting(), None => {}, } } @@ -1535,7 +1572,6 @@ impl Hud { } } } - // Skillbar // Get player stats let ecs = client.state().ecs(); @@ -1583,6 +1619,35 @@ impl Hud { .set(self.ids.skillbar, ui_widgets); } + // Crafting + if self.show.crafting { + if let Some(inventory) = inventories.get(entity) { + for event in Crafting::new( + //&self.show, + client, + &self.imgs, + &self.fonts, + &self.voxygen_i18n, + &self.rot_imgs, + tooltip_manager, + &self.item_imgs, + &inventory, + ) + .set(self.ids.crafting_window, ui_widgets) + { + match event { + crafting::Event::CraftRecipe(r) => { + events.push(Event::CraftRecipe(r)); + }, + crafting::Event::Close => { + self.show.crafting(false); + self.force_ungrab = true; + }, + } + } + } + } + // Don't put NPC messages in chat box. self.new_messages .retain(|m| !matches!(m.chat_type, comp::ChatType::Npc(_, _))); @@ -2071,6 +2136,10 @@ impl Hud { self.show.toggle_social(); true }, + GameInput::Crafting if state => { + self.show.toggle_crafting(); + true + }, GameInput::Spellbook if state => { self.show.toggle_spell(); true diff --git a/voxygen/src/hud/skillbar.rs b/voxygen/src/hud/skillbar.rs index 54a3a9e032..2e41c7a135 100644 --- a/voxygen/src/hud/skillbar.rs +++ b/voxygen/src/hud/skillbar.rs @@ -623,26 +623,7 @@ impl<'a> Widget for Skillbar<'a> { _ => self.imgs.nothing, }, ) // Insert Icon here - .w( - match self.loadout.active_item.as_ref().map(|i| &i.item.kind) { - Some(ItemKind::Tool(Tool { kind, .. })) => match kind { - ToolKind::Bow(_) => 30.0 * scale, - ToolKind::Staff(_) => 32.0 * scale, - _ => 38.0 * scale, - }, - _ => 38.0 * scale, - }, - ) - .h( - match self.loadout.active_item.as_ref().map(|i| &i.item.kind) { - Some(ItemKind::Tool(Tool { kind, .. })) => match kind { - ToolKind::Bow(_) => 30.0 * scale, - ToolKind::Staff(_) => 32.0 * scale, - _ => 38.0 * scale, - }, - _ => 38.0 * scale, - }, - ) + .w_h(32.0 * scale, 32.0 * scale) .middle_of(state.ids.m1_slot_bg) .set(state.ids.m1_content, ui); // M2 Slot @@ -704,7 +685,7 @@ impl<'a> Widget for Skillbar<'a> { .middle_of(state.ids.m2_slot) .set(state.ids.m2_slot_bg, ui); Button::image(match tool_kind { - Some(ToolKind::Sword(_)) => self.imgs.charge, + Some(ToolKind::Sword(_)) => self.imgs.twohsword_m2, Some(ToolKind::Dagger(_)) => self.imgs.onehdagger_m2, Some(ToolKind::Shield(_)) => self.imgs.onehshield_m2, Some(ToolKind::Hammer(_)) => self.imgs.hammerleap, @@ -714,17 +695,8 @@ impl<'a> Widget for Skillbar<'a> { Some(ToolKind::Staff(_)) => self.imgs.staff_m2, Some(ToolKind::Debug(DebugKind::Boost)) => self.imgs.flyingrod_m2, _ => self.imgs.nothing, - }) // Insert Icon here - .w(match tool_kind { - Some(ToolKind::Staff(_)) => 30.0 * scale, - Some(ToolKind::Bow(_)) => 30.0 * scale, - _ => 38.0 * scale, - }) - .h(match tool_kind { - Some(ToolKind::Staff(_)) => 30.0 * scale, - Some(ToolKind::Bow(_)) => 30.0 * scale, - _ => 38.0 * scale, }) + .w_h(32.0 * scale, 32.0 * scale) .middle_of(state.ids.m2_slot_bg) .image_color(match tool_kind { Some(ToolKind::Sword(_)) => { diff --git a/voxygen/src/menu/char_selection/ui.rs b/voxygen/src/menu/char_selection/ui.rs index 01a8d47cd0..9ae1c3288d 100644 --- a/voxygen/src/menu/char_selection/ui.rs +++ b/voxygen/src/menu/char_selection/ui.rs @@ -182,9 +182,6 @@ image_ids! { charlist_frame: "voxygen.element.frames.window_4", server_frame: "voxygen.element.frames.server_frame", - selection: "voxygen.element.frames.selection", - selection_hover: "voxygen.element.frames.selection_hover", - selection_press: "voxygen.element.frames.selection_press", // Info Window info_frame: "voxygen.element.frames.info_frame", @@ -195,6 +192,9 @@ image_ids! { delete_button_press: "voxygen.element.buttons.x_red_press", + selection: "voxygen.element.frames.selection", + selection_hover: "voxygen.element.frames.selection_hover", + selection_press: "voxygen.element.frames.selection_press", name_input: "voxygen.element.misc_bg.textbox_mid", @@ -241,8 +241,7 @@ image_ids! { } rotation_image_ids! { pub struct ImgsRot { - - + // Tooltip Test tt_side: "voxygen/element/frames/tt_test_edge", tt_corner: "voxygen/element/frames/tt_test_corner_tr", diff --git a/voxygen/src/menu/main/ui.rs b/voxygen/src/menu/main/ui.rs index a8d037f482..9ba01eb8a0 100644 --- a/voxygen/src/menu/main/ui.rs +++ b/voxygen/src/menu/main/ui.rs @@ -35,6 +35,7 @@ widget_ids! { alpha_text, banner, banner_top, + gears, // Disclaimer //disc_window, //disc_text_1, @@ -98,7 +99,12 @@ image_ids! { button_press: "voxygen.element.buttons.button_press", input_bg: "voxygen.element.misc_bg.textbox_mid", //disclaimer: "voxygen.element.frames.disclaimer", - + // Animation + f1: "voxygen.element.animation.gears.1", + f2: "voxygen.element.animation.gears.2", + f3: "voxygen.element.animation.gears.3", + f4: "voxygen.element.animation.gears.4", + f5: "voxygen.element.animation.gears.5", nothing: (), @@ -107,7 +113,7 @@ image_ids! { rotation_image_ids! { pub struct ImgsRot { - + // Tooltip Test tt_side: "voxygen/element/frames/tt_test_edge", @@ -155,6 +161,7 @@ pub struct MainMenuUi { show_servers: bool, //show_disclaimer: bool, time: f32, + anim_timer: f32, bg_img_id: conrod_core::image::Id, voxygen_i18n: std::sync::Arc, fonts: ConrodVoxygenFonts, @@ -221,6 +228,7 @@ impl MainMenuUi { show_servers: false, connect: false, time: 0.0, + anim_timer: 0.0, //show_disclaimer: global_state.settings.show_disclaimer, bg_img_id, voxygen_i18n, @@ -275,6 +283,23 @@ impl MainMenuUi { .middle_of(ui_widgets.window) .set(self.ids.bg, ui_widgets); + if self.connect { + self.anim_timer = (self.anim_timer + dt.as_secs_f32()) * 1.05; // Linear time function with Anim-Speed Factor + if self.anim_timer >= 4.0 { + self.anim_timer = 0.0 // Reset timer at last frame to loop + }; + Image::new(match self.anim_timer.round() as i32 { + 0 => self.imgs.f1, + 1 => self.imgs.f2, + 2 => self.imgs.f3, + 3 => self.imgs.f4, + _ => self.imgs.f5, + }) + .w_h(74.0, 62.0) + .bottom_right_with_margins_on(self.ids.bg, 10.0, 10.0) + .set(self.ids.gears, ui_widgets); + }; + // Version displayed top right corner Text::new(&version) .color(TEXT_COLOR) diff --git a/voxygen/src/scene/terrain.rs b/voxygen/src/scene/terrain.rs index e40810d398..76bd95e974 100644 --- a/voxygen/src/scene/terrain.rs +++ b/voxygen/src/scene/terrain.rs @@ -338,6 +338,18 @@ fn sprite_config_for(kind: BlockKind) -> Option { variations: 2, wind_sway: 0.0, }), + BlockKind::Stones => Some(SpriteConfig { + variations: 3, + wind_sway: 0.0, + }), + BlockKind::Twigs => Some(SpriteConfig { + variations: 3, + wind_sway: 0.0, + }), + BlockKind::ShinyGem => Some(SpriteConfig { + variations: 3, + wind_sway: 0.0, + }), _ => None, } } @@ -2646,6 +2658,81 @@ impl Terrain { Vec3::one(), ), ), + /* Stones */ + ( + (BlockKind::Stones, 0), + make_models( + "voxygen.voxel.sprite.rocks.rock-0", + Vec3::new(-3.0, -3.5, 0.0), + Vec3::one(), + ), + ), + ( + (BlockKind::Stones, 1), + make_models( + "voxygen.voxel.sprite.rocks.rock-1", + Vec3::new(-4.5, -5.5, 0.0), + Vec3::one(), + ), + ), + ( + (BlockKind::Stones, 2), + make_models( + "voxygen.voxel.sprite.rocks.rock-2", + Vec3::new(-4.5, -4.5, 0.0), + Vec3::one(), + ), + ), + /* Twigs */ + ( + (BlockKind::Twigs, 0), + make_models( + "voxygen.voxel.sprite.twigs.twigs-0", + Vec3::new(-3.5, -3.5, 0.0), + Vec3::one(), + ), + ), + ( + (BlockKind::Twigs, 1), + make_models( + "voxygen.voxel.sprite.twigs.twigs-1", + Vec3::new(-2.0, -1.5, 0.0), + Vec3::one(), + ), + ), + ( + (BlockKind::Twigs, 2), + make_models( + "voxygen.voxel.sprite.twigs.twigs-2", + Vec3::new(-4.0, -4.0, 0.0), + Vec3::one(), + ), + ), + // Shiny Gems + ( + (BlockKind::ShinyGem, 0), + make_models( + "voxygen.voxel.sprite.gem.gem_blue", + Vec3::new(-2.0, -3.0, 0.0), + Vec3::one(), + ), + ), + ( + (BlockKind::ShinyGem, 1), + make_models( + "voxygen.voxel.sprite.gem.gem_green", + Vec3::new(-2.0, -3.0, 0.0), + Vec3::one(), + ), + ), + ( + (BlockKind::ShinyGem, 2), + make_models( + "voxygen.voxel.sprite.gem.gem_red", + Vec3::new(-3.0, -2.0, -2.0), + Vec3::one(), + ), + ), ] .into_iter() .collect(), diff --git a/voxygen/src/session.rs b/voxygen/src/session.rs index d0c1c7acf9..b2a042f1af 100644 --- a/voxygen/src/session.rs +++ b/voxygen/src/session.rs @@ -936,6 +936,9 @@ impl PlayState for SessionState { HudEvent::ChangeStopAutoWalkOnInput(state) => { global_state.settings.gameplay.stop_auto_walk_on_input = state; }, + HudEvent::CraftRecipe(r) => { + self.client.borrow_mut().craft_recipe(&r); + }, } } diff --git a/voxygen/src/settings.rs b/voxygen/src/settings.rs index 373515a957..fb6f787e96 100644 --- a/voxygen/src/settings.rs +++ b/voxygen/src/settings.rs @@ -141,6 +141,7 @@ impl ControlSettings { GameInput::Map => KeyMouse::Key(VirtualKeyCode::M), GameInput::Bag => KeyMouse::Key(VirtualKeyCode::B), GameInput::Social => KeyMouse::Key(VirtualKeyCode::O), + GameInput::Crafting => KeyMouse::Key(VirtualKeyCode::C), GameInput::Spellbook => KeyMouse::Key(VirtualKeyCode::P), GameInput::Settings => KeyMouse::Key(VirtualKeyCode::N), GameInput::Help => KeyMouse::Key(VirtualKeyCode::F1), @@ -178,7 +179,63 @@ impl Default for ControlSettings { keybindings: HashMap::new(), inverse_keybindings: HashMap::new(), }; - for game_input in GameInput::iterator() { + // Sets the initial keybindings for those GameInputs. If a new one is created in + // future, you'll have to update default_binding, and you should update this vec + // too. + let game_inputs = vec![ + GameInput::Primary, + GameInput::Secondary, + GameInput::ToggleCursor, + GameInput::MoveForward, + GameInput::MoveBack, + GameInput::MoveLeft, + GameInput::MoveRight, + GameInput::Jump, + GameInput::Sit, + GameInput::Dance, + GameInput::Glide, + GameInput::Climb, + GameInput::ClimbDown, + GameInput::Swim, + //GameInput::WallLeap, + GameInput::ToggleLantern, + GameInput::Mount, + GameInput::Enter, + GameInput::Command, + GameInput::Escape, + GameInput::Map, + GameInput::Bag, + GameInput::Social, + GameInput::Crafting, + GameInput::Spellbook, + GameInput::Settings, + GameInput::ToggleInterface, + GameInput::Help, + GameInput::ToggleDebug, + GameInput::Fullscreen, + GameInput::Screenshot, + GameInput::ToggleIngameUi, + GameInput::Roll, + GameInput::Respawn, + GameInput::Interact, + GameInput::ToggleWield, + //GameInput::Charge, + GameInput::FreeLook, + GameInput::AutoWalk, + GameInput::CycleCamera, + GameInput::Slot1, + GameInput::Slot2, + GameInput::Slot3, + GameInput::Slot4, + GameInput::Slot5, + GameInput::Slot6, + GameInput::Slot7, + GameInput::Slot8, + GameInput::Slot9, + GameInput::Slot10, + GameInput::SwapLoadout, + ]; + for game_input in game_inputs { new_settings.insert_binding(game_input, ControlSettings::default_binding(game_input)); } new_settings @@ -254,6 +311,7 @@ pub mod con_settings { pub quest_log: Button, pub character_window: Button, pub social: Button, + pub crafting: Button, pub spellbook: Button, pub settings: Button, pub help: Button, @@ -343,6 +401,7 @@ pub mod con_settings { quest_log: Button::Simple(GilButton::Unknown), character_window: Button::Simple(GilButton::Unknown), social: Button::Simple(GilButton::Unknown), + crafting: Button::Simple(GilButton::Unknown), spellbook: Button::Simple(GilButton::Unknown), settings: Button::Simple(GilButton::Unknown), help: Button::Simple(GilButton::Unknown), @@ -463,7 +522,7 @@ impl Default for GameplaySettings { intro_show: Intro::Show, xp_bar: XpBar::Always, shortcut_numbers: ShortcutNumbers::On, - bar_numbers: BarNumbers::Off, + bar_numbers: BarNumbers::Values, ui_scale: ScaleMode::RelativeToWindow([1920.0, 1080.0].into()), free_look_behavior: PressBehavior::Toggle, auto_walk_behavior: PressBehavior::Toggle, diff --git a/voxygen/src/window.rs b/voxygen/src/window.rs index b3b08e3259..73b75de715 100644 --- a/voxygen/src/window.rs +++ b/voxygen/src/window.rs @@ -49,6 +49,7 @@ pub enum GameInput { Map, Bag, Social, + Crafting, Spellbook, Settings, ToggleInterface, @@ -95,6 +96,7 @@ impl GameInput { GameInput::Map => "gameinput.map", GameInput::Bag => "gameinput.bag", GameInput::Social => "gameinput.social", + GameInput::Crafting => "gameinput.crafting", GameInput::Spellbook => "gameinput.spellbook", GameInput::Settings => "gameinput.settings", GameInput::ToggleInterface => "gameinput.toggleinterface", diff --git a/world/src/block/mod.rs b/world/src/block/mod.rs index 5f1479f48e..7d3558e066 100644 --- a/world/src/block/mod.rs +++ b/world/src/block/mod.rs @@ -287,11 +287,14 @@ impl<'a> BlockGen<'a> { BlockKind::WhiteFlower, BlockKind::YellowFlower, BlockKind::Sunflower, - BlockKind::Mushroom, + BlockKind::Mushroom, //TODO: Better spawnrules BlockKind::LeafyPlant, BlockKind::Blueberry, BlockKind::LingonBerry, BlockKind::Fern, + /*BlockKind::Twigs, // TODO: Better spawnrules + *BlockKind::Stones, // TODO: Better spawnrules + *BlockKind::ShinyGem, // TODO: Better spawnrules */ ]; let grasses = [ BlockKind::LongGrass,