mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Merge branch 'better-crafting' into 'master'
Crafting station sprites in towns See merge request veloren/veloren!2160
This commit is contained in:
commit
bcf9a8089f
@ -36,7 +36,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
- Players can now opt-in to server-authoritiative physics in gameplay settings.
|
||||
- Added `/server_physics` admin command.
|
||||
- Sort inventory button
|
||||
- Option to change the master volume when window is unfocused
|
||||
- Option to change the master volume when window is unfocused
|
||||
- Crafting stations in towns
|
||||
|
||||
|
||||
### Changed
|
||||
|
@ -1,9 +0,0 @@
|
||||
ItemDef(
|
||||
name: "Craftsman Hammer",
|
||||
description: "Used to craft various items.",
|
||||
kind: Ingredient(
|
||||
kind: "CraftsmanHammer",
|
||||
),
|
||||
quality: Moderate,
|
||||
tags: [CraftingTool],
|
||||
)
|
18
assets/common/items/tool/craftsman_hammer.ron
Normal file
18
assets/common/items/tool/craftsman_hammer.ron
Normal file
@ -0,0 +1,18 @@
|
||||
ItemDef(
|
||||
name: "Craftsman Hammer",
|
||||
description: "Used to craft various items.",
|
||||
kind: Tool((
|
||||
kind: Hammer,
|
||||
hands: One,
|
||||
stats: Direct((
|
||||
equip_time_secs: 0.25,
|
||||
power: 0.2,
|
||||
poise_strength: 0.25,
|
||||
speed: 1.5,
|
||||
crit_chance: 0.0,
|
||||
crit_mult: 0.0,
|
||||
)),
|
||||
)),
|
||||
quality: Common,
|
||||
tags: [CraftingTool],
|
||||
)
|
@ -1,344 +1,375 @@
|
||||
{
|
||||
"crafting_hammer": (
|
||||
("common.items.crafting_tools.craftsman_hammer", 1),
|
||||
[
|
||||
output: ("common.items.tool.craftsman_hammer", 1),
|
||||
inputs: [
|
||||
(Item("common.items.crafting_ing.twigs"), 6),
|
||||
(Item("common.items.crafting_ing.stones"), 6),
|
||||
],
|
||||
craft_sprite: Some(Anvil),
|
||||
),
|
||||
"mortar_pestle": (
|
||||
("common.items.crafting_tools.mortar_pestle", 1),
|
||||
[
|
||||
output: ("common.items.crafting_tools.mortar_pestle", 1),
|
||||
inputs: [
|
||||
(Item("common.items.crafting_ing.stones"), 6),
|
||||
(Item("common.items.food.coconut"), 1),
|
||||
(Item("common.items.crafting_tools.craftsman_hammer"), 0),
|
||||
(Item("common.items.tool.craftsman_hammer"), 0),
|
||||
],
|
||||
craft_sprite: Some(CraftingBench),
|
||||
),
|
||||
"sewing_set": (
|
||||
("common.items.crafting_tools.sewing_set", 1),
|
||||
[
|
||||
output: ("common.items.crafting_tools.sewing_set", 1),
|
||||
inputs: [
|
||||
(Item("common.items.crafting_ing.leather_scraps"), 2),
|
||||
(Item("common.items.crafting_ing.twigs"), 4),
|
||||
(Item("common.items.crafting_ing.stones"), 2),
|
||||
],
|
||||
craft_sprite: Some(CraftingBench),
|
||||
),
|
||||
"velorite_frag": (
|
||||
("common.items.ore.veloritefrag", 2),
|
||||
[
|
||||
output: ("common.items.ore.veloritefrag", 2),
|
||||
inputs: [
|
||||
(Item("common.items.ore.velorite"), 1),
|
||||
(Item("common.items.crafting_tools.craftsman_hammer"), 0),
|
||||
(Item("common.items.tool.craftsman_hammer"), 0),
|
||||
],
|
||||
craft_sprite: Some(Anvil),
|
||||
),
|
||||
"potion_s": (
|
||||
("common.items.consumable.potion_minor", 1),
|
||||
[
|
||||
output: ("common.items.consumable.potion_minor", 1),
|
||||
inputs: [
|
||||
(Item("common.items.crafting_ing.empty_vial"), 1),
|
||||
(Item("common.items.food.apple"), 4),
|
||||
(Item("common.items.crafting_ing.honey"), 1),
|
||||
],
|
||||
craft_sprite: Some(Cauldron),
|
||||
),
|
||||
"potion_m": (
|
||||
("common.items.consumable.potion_med", 1),
|
||||
[
|
||||
output: ("common.items.consumable.potion_med", 1),
|
||||
inputs: [
|
||||
(Item("common.items.consumable.potion_minor"), 2),
|
||||
(Item("common.items.ore.veloritefrag"), 4),
|
||||
],
|
||||
craft_sprite: Some(Cauldron),
|
||||
),
|
||||
"collar_basic": (
|
||||
("common.items.utility.collar", 1),
|
||||
[
|
||||
output: ("common.items.utility.collar", 1),
|
||||
inputs: [
|
||||
(Item("common.items.crafting_ing.leather_scraps"), 5),
|
||||
(Item("common.items.crafting_ing.ruby"), 1),
|
||||
],
|
||||
),
|
||||
"bomb_coconut": (
|
||||
("common.items.utility.bomb", 1),
|
||||
[
|
||||
output: ("common.items.utility.bomb", 1),
|
||||
inputs: [
|
||||
(Item("common.items.crafting_ing.stones"), 10),
|
||||
(Item("common.items.food.coconut"), 2),
|
||||
(Item("common.items.ore.veloritefrag"), 2),
|
||||
(Item("common.items.crafting_tools.mortar_pestle"), 0),
|
||||
],
|
||||
craft_sprite: Some(CraftingBench),
|
||||
),
|
||||
"firework_blue": (
|
||||
("common.items.utility.firework_blue", 1),
|
||||
[
|
||||
output: ("common.items.utility.firework_blue", 1),
|
||||
inputs: [
|
||||
(Item("common.items.crafting_ing.twigs"), 1),
|
||||
(Item("common.items.crafting_ing.stones"), 1),
|
||||
(Item("common.items.food.coconut"), 1),
|
||||
(Item("common.items.ore.veloritefrag"), 1),
|
||||
(Item("common.items.crafting_tools.mortar_pestle"), 0),
|
||||
],
|
||||
craft_sprite: Some(CraftingBench),
|
||||
),
|
||||
"firework_green": (
|
||||
("common.items.utility.firework_green", 1),
|
||||
[
|
||||
output: ("common.items.utility.firework_green", 1),
|
||||
inputs: [
|
||||
(Item("common.items.crafting_ing.twigs"), 1),
|
||||
(Item("common.items.crafting_ing.stones"), 1),
|
||||
(Item("common.items.food.coconut"), 1),
|
||||
(Item("common.items.ore.veloritefrag"), 1),
|
||||
(Item("common.items.crafting_tools.mortar_pestle"), 0),
|
||||
],
|
||||
craft_sprite: Some(CraftingBench),
|
||||
),
|
||||
"firework_purple": (
|
||||
("common.items.utility.firework_purple", 1),
|
||||
[
|
||||
output: ("common.items.utility.firework_purple", 1),
|
||||
inputs: [
|
||||
(Item("common.items.crafting_ing.twigs"), 1),
|
||||
(Item("common.items.crafting_ing.stones"), 1),
|
||||
(Item("common.items.food.coconut"), 1),
|
||||
(Item("common.items.ore.veloritefrag"), 1),
|
||||
(Item("common.items.crafting_tools.mortar_pestle"), 0),
|
||||
],
|
||||
craft_sprite: Some(CraftingBench),
|
||||
),
|
||||
"firework_red": (
|
||||
("common.items.utility.firework_red", 1),
|
||||
[
|
||||
output: ("common.items.utility.firework_red", 1),
|
||||
inputs: [
|
||||
(Item("common.items.crafting_ing.twigs"), 1),
|
||||
(Item("common.items.crafting_ing.stones"), 1),
|
||||
(Item("common.items.food.coconut"), 1),
|
||||
(Item("common.items.ore.veloritefrag"), 1),
|
||||
(Item("common.items.crafting_tools.mortar_pestle"), 0),
|
||||
],
|
||||
craft_sprite: Some(CraftingBench),
|
||||
),
|
||||
"firework_white": (
|
||||
("common.items.utility.firework_white", 1),
|
||||
[
|
||||
output: ("common.items.utility.firework_white", 1),
|
||||
inputs: [
|
||||
(Item("common.items.crafting_ing.twigs"), 1),
|
||||
(Item("common.items.crafting_ing.stones"), 1),
|
||||
(Item("common.items.food.coconut"), 1),
|
||||
(Item("common.items.ore.veloritefrag"), 1),
|
||||
(Item("common.items.crafting_tools.mortar_pestle"), 0),
|
||||
],
|
||||
craft_sprite: Some(CraftingBench),
|
||||
),
|
||||
"firework_yellow": (
|
||||
("common.items.utility.firework_yellow", 1),
|
||||
[
|
||||
output: ("common.items.utility.firework_yellow", 1),
|
||||
inputs: [
|
||||
(Item("common.items.crafting_ing.twigs"), 1),
|
||||
(Item("common.items.crafting_ing.stones"), 1),
|
||||
(Item("common.items.food.coconut"), 1),
|
||||
(Item("common.items.ore.veloritefrag"), 1),
|
||||
(Item("common.items.crafting_tools.mortar_pestle"), 0),
|
||||
],
|
||||
craft_sprite: Some(CraftingBench),
|
||||
),
|
||||
"apple_shroom_curry": (
|
||||
("common.items.food.apple_mushroom_curry", 1),
|
||||
[
|
||||
output: ("common.items.food.apple_mushroom_curry", 1),
|
||||
inputs: [
|
||||
(Item("common.items.food.mushroom"), 8),
|
||||
(Item("common.items.food.coconut"), 1),
|
||||
(Item("common.items.food.apple"), 4),
|
||||
(Item("common.items.crafting_tools.mortar_pestle"), 0),
|
||||
],
|
||||
craft_sprite: Some(CookingPot),
|
||||
),
|
||||
"salad_plain": (
|
||||
("common.items.food.plainsalad", 1),
|
||||
[
|
||||
output: ("common.items.food.plainsalad", 1),
|
||||
inputs: [
|
||||
(Item("common.items.food.lettuce"), 1),
|
||||
(Item("common.items.crafting_ing.bowl"), 1),
|
||||
],
|
||||
],
|
||||
),
|
||||
"salad_tomato": (
|
||||
("common.items.food.tomatosalad", 1),
|
||||
[
|
||||
output: ("common.items.food.tomatosalad", 1),
|
||||
inputs: [
|
||||
(Item("common.items.food.lettuce"), 1),
|
||||
(Item("common.items.food.tomato"), 2),
|
||||
(Item("common.items.crafting_ing.bowl"), 1),
|
||||
],
|
||||
),
|
||||
"apples_stick": (
|
||||
("common.items.food.apple_stick", 1),
|
||||
[
|
||||
output: ("common.items.food.apple_stick", 1),
|
||||
inputs: [
|
||||
(Item("common.items.crafting_ing.twigs"), 2),
|
||||
(Item("common.items.food.apple"), 2)
|
||||
],
|
||||
),
|
||||
"mushroom_stick": (
|
||||
("common.items.food.mushroom_stick", 1),
|
||||
[
|
||||
output: ("common.items.food.mushroom_stick", 1),
|
||||
inputs: [
|
||||
(Item("common.items.crafting_ing.twigs"), 2),
|
||||
(Item("common.items.food.mushroom"), 3),
|
||||
],
|
||||
),
|
||||
"sunflower_icetea": (
|
||||
("common.items.food.sunflower_icetea", 4),
|
||||
[
|
||||
output: ("common.items.food.sunflower_icetea", 4),
|
||||
inputs: [
|
||||
(Item("common.items.crafting_ing.empty_vial"), 1),
|
||||
(Item("common.items.crafting_ing.icy_fang"), 1),
|
||||
(Item("common.items.flowers.sunflower"), 4),
|
||||
(Item("common.items.crafting_ing.honey"), 1),
|
||||
],
|
||||
craft_sprite: Some(Cauldron),
|
||||
),
|
||||
"Plain Cloth Glider": (
|
||||
("common.items.glider.glider_basic_white", 1),
|
||||
[
|
||||
output: ("common.items.glider.glider_basic_white", 1),
|
||||
inputs: [
|
||||
(Item("common.items.crafting_ing.twigs"), 5),
|
||||
(Item("common.items.crafting_ing.leather_scraps"), 5),
|
||||
(Item("common.items.crafting_ing.cloth_scraps"), 10),
|
||||
(Item("common.items.crafting_tools.craftsman_hammer"), 0),
|
||||
(Item("common.items.tool.craftsman_hammer"), 0),
|
||||
(Item("common.items.crafting_tools.sewing_set"), 0),
|
||||
],
|
||||
craft_sprite: Some(CraftingBench),
|
||||
),
|
||||
"Red Cloth Glider": (
|
||||
("common.items.glider.glider_basic_red", 1),
|
||||
[
|
||||
output: ("common.items.glider.glider_basic_red", 1),
|
||||
inputs: [
|
||||
(Item("common.items.crafting_ing.twigs"), 5),
|
||||
(Item("common.items.crafting_ing.cloth_scraps_red"), 10),
|
||||
(Item("common.items.crafting_ing.leather_scraps"), 5),
|
||||
(Item("common.items.crafting_tools.craftsman_hammer"), 0),
|
||||
(Item("common.items.tool.craftsman_hammer"), 0),
|
||||
(Item("common.items.crafting_tools.sewing_set"), 0),
|
||||
],
|
||||
craft_sprite: Some(CraftingBench),
|
||||
),
|
||||
"Leaves Glider": (
|
||||
("common.items.glider.glider_leaves", 1),
|
||||
[
|
||||
output: ("common.items.glider.glider_leaves", 1),
|
||||
inputs: [
|
||||
(Item("common.items.crafting_ing.twigs"), 5),
|
||||
(Item("common.items.crafting_ing.leather_scraps"), 5),
|
||||
(Item("common.items.crafting_ing.cloth_scraps"), 5),
|
||||
(Item("common.items.crafting_ing.emerald"), 1),
|
||||
(Item("common.items.crafting_tools.craftsman_hammer"), 0),
|
||||
(Item("common.items.tool.craftsman_hammer"), 0),
|
||||
(Item("common.items.crafting_tools.sewing_set"), 0),
|
||||
],
|
||||
craft_sprite: Some(CraftingBench),
|
||||
),
|
||||
"Sand Raptor Wings": (
|
||||
("common.items.glider.glider_sandraptor", 1),
|
||||
[
|
||||
output: ("common.items.glider.glider_sandraptor", 1),
|
||||
inputs: [
|
||||
(Item("common.items.crafting_ing.raptor_feather"), 6),
|
||||
(Item("common.items.crafting_ing.twigs"), 5),
|
||||
(Item("common.items.crafting_ing.leather_scraps"), 5),
|
||||
(Item("common.items.crafting_ing.cloth_scraps"), 5),
|
||||
(Item("common.items.crafting_ing.ruby"), 1),
|
||||
(Item("common.items.crafting_tools.craftsman_hammer"), 0),
|
||||
(Item("common.items.tool.craftsman_hammer"), 0),
|
||||
(Item("common.items.crafting_tools.sewing_set"), 0),
|
||||
],
|
||||
craft_sprite: Some(CraftingBench),
|
||||
),
|
||||
"Snow Raptor Wings": (
|
||||
("common.items.glider.glider_snowraptor", 1),
|
||||
[
|
||||
output: ("common.items.glider.glider_snowraptor", 1),
|
||||
inputs: [
|
||||
(Item("common.items.crafting_ing.raptor_feather"), 6),
|
||||
(Item("common.items.crafting_ing.twigs"), 5),
|
||||
(Item("common.items.crafting_ing.leather_scraps"), 5),
|
||||
(Item("common.items.crafting_ing.cloth_scraps"), 5),
|
||||
(Item("common.items.crafting_ing.icy_fang"), 1),
|
||||
(Item("common.items.crafting_ing.ruby"), 1),
|
||||
(Item("common.items.crafting_tools.craftsman_hammer"), 0),
|
||||
(Item("common.items.tool.craftsman_hammer"), 0),
|
||||
(Item("common.items.crafting_tools.sewing_set"), 0),
|
||||
],
|
||||
craft_sprite: Some(CraftingBench),
|
||||
),
|
||||
"Wood Raptor Wings": (
|
||||
("common.items.glider.glider_woodraptor", 1),
|
||||
[
|
||||
output: ("common.items.glider.glider_woodraptor", 1),
|
||||
inputs: [
|
||||
(Item("common.items.crafting_ing.raptor_feather"), 6),
|
||||
(Item("common.items.crafting_ing.twigs"), 15),
|
||||
(Item("common.items.crafting_ing.leather_scraps"), 5),
|
||||
(Item("common.items.crafting_ing.cloth_scraps"), 5),
|
||||
(Item("common.items.crafting_ing.ruby"), 1),
|
||||
(Item("common.items.crafting_tools.craftsman_hammer"), 0),
|
||||
(Item("common.items.tool.craftsman_hammer"), 0),
|
||||
(Item("common.items.crafting_tools.sewing_set"), 0),
|
||||
],
|
||||
craft_sprite: Some(CraftingBench),
|
||||
),
|
||||
"Soothing Loop": (
|
||||
("common.items.weapons.sceptre.loops0", 1),
|
||||
[
|
||||
output: ("common.items.weapons.sceptre.loops0", 1),
|
||||
inputs: [
|
||||
(Item("common.items.crafting_ing.twigs"), 20),
|
||||
(Item("common.items.ore.veloritefrag"), 8),
|
||||
(Item("common.items.crafting_ing.ruby"), 4),
|
||||
(Item("common.items.crafting_tools.craftsman_hammer"), 0),
|
||||
(Item("common.items.tool.craftsman_hammer"), 0),
|
||||
],
|
||||
),
|
||||
"Hunting Bow": (
|
||||
("common.items.weapons.bow.wood-2", 1),
|
||||
[
|
||||
output: ("common.items.weapons.bow.wood-2", 1),
|
||||
inputs: [
|
||||
(Item("common.items.crafting_ing.leather_scraps"), 8),
|
||||
(Item("common.items.crafting_ing.twigs"), 6),
|
||||
(Item("common.items.crafting_ing.stones"), 0),
|
||||
],
|
||||
craft_sprite: Some(CraftingBench),
|
||||
),
|
||||
"Forest Spirit": (
|
||||
("common.items.weapons.sword.wood-2", 1),
|
||||
[
|
||||
output: ("common.items.weapons.sword.wood-2", 1),
|
||||
inputs: [
|
||||
(Item("common.items.crafting_ing.leather_scraps"), 4),
|
||||
(Item("common.items.crafting_ing.twigs"), 10),
|
||||
(Item("common.items.ore.veloritefrag"), 1),
|
||||
(Item("common.items.crafting_ing.stones"), 0),
|
||||
],
|
||||
craft_sprite: Some(Anvil),
|
||||
),
|
||||
"adventure back": (
|
||||
("common.items.armor.agile.back", 1),
|
||||
[(Item("common.items.crafting_ing.leather_scraps"), 4)],
|
||||
output: ("common.items.armor.agile.back", 1),
|
||||
inputs: [(Item("common.items.crafting_ing.leather_scraps"), 4)],
|
||||
craft_sprite: Some(CraftingBench),
|
||||
),
|
||||
"adventure belt": (
|
||||
("common.items.armor.agile.belt", 1),
|
||||
[(Item("common.items.crafting_ing.leather_scraps"), 2)],
|
||||
output: ("common.items.armor.agile.belt", 1),
|
||||
inputs: [(Item("common.items.crafting_ing.leather_scraps"), 2)],
|
||||
craft_sprite: Some(CraftingBench),
|
||||
),
|
||||
"adventure chest": (
|
||||
("common.items.armor.agile.chest", 1),
|
||||
[(Item("common.items.crafting_ing.leather_scraps"), 12)],
|
||||
output: ("common.items.armor.agile.chest", 1),
|
||||
inputs: [(Item("common.items.crafting_ing.leather_scraps"), 12)],
|
||||
craft_sprite: Some(CraftingBench),
|
||||
),
|
||||
"adventure feet": (
|
||||
("common.items.armor.agile.foot", 1),
|
||||
[(Item("common.items.crafting_ing.leather_scraps"), 3)],
|
||||
output: ("common.items.armor.agile.foot", 1),
|
||||
inputs: [(Item("common.items.crafting_ing.leather_scraps"), 3)],
|
||||
craft_sprite: Some(CraftingBench),
|
||||
),
|
||||
"adventure hands": (
|
||||
("common.items.armor.agile.hand", 1),
|
||||
[(Item("common.items.crafting_ing.leather_scraps"), 4)],
|
||||
output: ("common.items.armor.agile.hand", 1),
|
||||
inputs: [(Item("common.items.crafting_ing.leather_scraps"), 4)],
|
||||
craft_sprite: Some(CraftingBench),
|
||||
),
|
||||
"adventure pants": (
|
||||
("common.items.armor.agile.pants", 1),
|
||||
[(Item("common.items.crafting_ing.leather_scraps"), 8)],
|
||||
output: ("common.items.armor.agile.pants", 1),
|
||||
inputs: [(Item("common.items.crafting_ing.leather_scraps"), 8)],
|
||||
craft_sprite: Some(CraftingBench),
|
||||
),
|
||||
"adventure shoulder": (
|
||||
("common.items.armor.agile.shoulder", 1),
|
||||
[(Item("common.items.crafting_ing.leather_scraps"), 12)],
|
||||
output: ("common.items.armor.agile.shoulder", 1),
|
||||
inputs: [(Item("common.items.crafting_ing.leather_scraps"), 12)],
|
||||
craft_sprite: Some(CraftingBench),
|
||||
),
|
||||
"Seashell Necklace": (
|
||||
("common.items.armor.misc.neck.shell", 1),
|
||||
[
|
||||
output: ("common.items.armor.misc.neck.shell", 1),
|
||||
inputs: [
|
||||
(Item("common.items.crafting_ing.cloth_scraps"), 2),
|
||||
(Item("common.items.crafting_ing.sapphire"), 1),
|
||||
(Item("common.items.crafting_ing.seashells"), 3),
|
||||
(Item("common.items.crafting_tools.sewing_set"), 0),
|
||||
],
|
||||
craft_sprite: Some(CraftingBench),
|
||||
),
|
||||
"red cloth": (
|
||||
("common.items.crafting_ing.cloth_scraps_red", 1),
|
||||
[
|
||||
output: ("common.items.crafting_ing.cloth_scraps_red", 1),
|
||||
inputs: [
|
||||
(Item("common.items.crafting_ing.cloth_scraps"), 1),
|
||||
(Item("common.items.flowers.red"), 1),
|
||||
(Item("common.items.crafting_tools.mortar_pestle"), 0),
|
||||
],
|
||||
),
|
||||
"tiny red pouch": (
|
||||
("common.items.armor.misc.bag.tiny_red_pouch", 1),
|
||||
[
|
||||
output: ("common.items.armor.misc.bag.tiny_red_pouch", 1),
|
||||
inputs: [
|
||||
(Item("common.items.crafting_ing.cloth_scraps_red"), 3),
|
||||
(Item("common.items.crafting_tools.sewing_set"), 0),
|
||||
],
|
||||
),
|
||||
"tiny leather pouch": (
|
||||
("common.items.armor.misc.bag.tiny_leather_pouch", 1),
|
||||
[
|
||||
output: ("common.items.armor.misc.bag.tiny_leather_pouch", 1),
|
||||
inputs: [
|
||||
(Item("common.items.crafting_ing.leather_scraps"), 6),
|
||||
(Item("common.items.crafting_tools.sewing_set"), 0),
|
||||
],
|
||||
),
|
||||
"knitted red pouch": (
|
||||
("common.items.armor.misc.bag.knitted_red_pouch", 1),
|
||||
[
|
||||
output: ("common.items.armor.misc.bag.knitted_red_pouch", 1),
|
||||
inputs: [
|
||||
(Item("common.items.crafting_ing.cloth_scraps_red"), 3),
|
||||
(Item("common.items.armor.misc.bag.tiny_red_pouch"), 2),
|
||||
(Item("common.items.crafting_tools.sewing_set"), 0),
|
||||
],
|
||||
),
|
||||
"woven red bag": (
|
||||
("common.items.armor.misc.bag.woven_red_bag", 1),
|
||||
[
|
||||
output: ("common.items.armor.misc.bag.woven_red_bag", 1),
|
||||
inputs: [
|
||||
(Item("common.items.crafting_ing.cloth_scraps_red"), 6),
|
||||
(Item("common.items.armor.misc.bag.knitted_red_pouch"), 1),
|
||||
(Item("common.items.crafting_tools.sewing_set"), 0),
|
||||
],
|
||||
),
|
||||
"traveler backpack": (
|
||||
("common.items.armor.misc.back.backpack", 1),
|
||||
[
|
||||
output: ("common.items.armor.misc.back.backpack", 1),
|
||||
inputs: [
|
||||
(Item("common.items.crafting_ing.diamond"), 2),
|
||||
(Item("common.items.crafting_ing.twigs"), 2),
|
||||
(Item("common.items.crafting_ing.cloth_scraps"), 3),
|
||||
@ -346,10 +377,11 @@
|
||||
(Item("common.items.armor.misc.bag.tiny_leather_pouch"), 2),
|
||||
(Item("common.items.crafting_tools.sewing_set"), 0),
|
||||
],
|
||||
craft_sprite: Some(CraftingBench),
|
||||
),
|
||||
"sturdy red backpack": (
|
||||
("common.items.armor.misc.bag.sturdy_red_backpack", 1),
|
||||
[
|
||||
output: ("common.items.armor.misc.bag.sturdy_red_backpack", 1),
|
||||
inputs: [
|
||||
(Item("common.items.crafting_ing.diamond"), 2),
|
||||
(Item("common.items.crafting_ing.cloth_scraps_red"), 3),
|
||||
(Item("common.items.armor.misc.bag.woven_red_bag"), 1),
|
||||
@ -357,8 +389,8 @@
|
||||
],
|
||||
),
|
||||
"troll hide pack": (
|
||||
("common.items.armor.misc.bag.troll_hide_pack", 1),
|
||||
[
|
||||
output: ("common.items.armor.misc.bag.troll_hide_pack", 1),
|
||||
inputs: [
|
||||
(Item("common.items.crafting_ing.leather_troll"), 10),
|
||||
(Item("common.items.crafting_ing.leather_scraps"), 10),
|
||||
(Item("common.items.crafting_ing.diamond"), 1),
|
||||
@ -366,8 +398,8 @@
|
||||
],
|
||||
),
|
||||
"Mindflayer Spellbag": (
|
||||
("common.items.armor.misc.bag.mindflayer_spellbag", 1),
|
||||
[
|
||||
output: ("common.items.armor.misc.bag.mindflayer_spellbag", 1),
|
||||
inputs: [
|
||||
(Item("common.items.crafting_ing.mindflayer_bag_damaged"), 1),
|
||||
(Item("common.items.crafting_ing.leather_scraps"), 10),
|
||||
(Item("common.items.crafting_ing.diamond"), 4),
|
||||
@ -376,33 +408,34 @@
|
||||
],
|
||||
),
|
||||
"pickaxe": (
|
||||
("common.items.tool.pick", 1),
|
||||
[
|
||||
output: ("common.items.tool.pick", 1),
|
||||
inputs: [
|
||||
(Item("common.items.crafting_ing.cloth_scraps"), 1), // TODO: Replace with plant fiber when obtainable
|
||||
(Item("common.items.crafting_ing.stones"), 5), // TODO: Replace with iron ingots when obtainable
|
||||
(Item("common.items.crafting_ing.twigs"), 4),
|
||||
(Item("common.items.crafting_tools.craftsman_hammer"), 0),
|
||||
(Item("common.items.tool.craftsman_hammer"), 0),
|
||||
],
|
||||
craft_sprite: Some(Anvil),
|
||||
),
|
||||
"cloth_scraps": (
|
||||
("common.items.crafting_ing.cloth_scraps", 1),
|
||||
[
|
||||
output: ("common.items.crafting_ing.cloth_scraps", 1),
|
||||
inputs: [
|
||||
(Tag(ClothItem), 1),
|
||||
(Item("common.items.crafting_tools.sewing_set"), 0),
|
||||
],
|
||||
),
|
||||
"leather_scraps": (
|
||||
("common.items.crafting_ing.leather_scraps", 1),
|
||||
[
|
||||
output: ("common.items.crafting_ing.leather_scraps", 1),
|
||||
inputs: [
|
||||
(Tag(LeatherItem), 1),
|
||||
(Item("common.items.crafting_tools.sewing_set"), 0),
|
||||
],
|
||||
),
|
||||
//"metal_blade": (
|
||||
// ("common.items.crafting_ing.modular.damage.sword.metal_blade", 1),
|
||||
// [
|
||||
// output: ("common.items.crafting_ing.modular.damage.sword.metal_blade", 1),
|
||||
// inputs: [
|
||||
// (Tag(MetalIngot), 5),
|
||||
// (Item("common.items.crafting_tools.craftsman_hammer"), 0),
|
||||
// (Item("common.items.tool.craftsman_hammer"), 0),
|
||||
// ],
|
||||
//),
|
||||
}
|
||||
|
@ -8,7 +8,12 @@
|
||||
"hud.crafting.ingredients": "Ingredients:",
|
||||
"hud.crafting.craft": "Craft",
|
||||
"hud.crafting.tool_cata": "Requires:",
|
||||
|
||||
// Crafting Stations
|
||||
"hud.crafting.req_crafting_station": "Requires:",
|
||||
"hud.crafting.anvil": "Anvil",
|
||||
"hud.crafting.cauldron": "Cauldron",
|
||||
"hud.crafting.cooking_pot": "Cooking Pot",
|
||||
"hud.crafting.crafting_bench": "Crafting Bench",
|
||||
// Tabs
|
||||
"hud.crafting.tabs.all": "All",
|
||||
"hud.crafting.tabs.armor": "Armor",
|
||||
|
@ -2,6 +2,23 @@
|
||||
// Vox(specier),
|
||||
// VoxTrans(specifier, offset, (x_rot, y_rot, z_rot), zoom)
|
||||
({
|
||||
// Crafting Stations
|
||||
Tool("Anvil"): VoxTrans(
|
||||
"voxel.sprite.anvil.anvil-0",
|
||||
(0.5, 0.5, 0.0), (0.0, 60.0, 90.0), 1.0,
|
||||
),
|
||||
Tool("Cauldron"): VoxTrans(
|
||||
"voxel.sprite.cauldron.cauldron-0",
|
||||
(0.0, 0.0, 0.0), (-50.0, 40.0, 30.0), 1.0,
|
||||
),
|
||||
Tool("CookingPot"): VoxTrans(
|
||||
"voxel.sprite.cooking_pot.pot-0",
|
||||
(0.0, 0.0, 0.0), (0.0, 90.0, 90.0), 1.2,
|
||||
),
|
||||
Tool("CraftingBench"): VoxTrans(
|
||||
"voxel.sprite.crafting_bench.crafting_bench-0",
|
||||
(0.0, 0.0, 0.0), (-50.0, 40.0, 20.0), 1.0,
|
||||
),
|
||||
// Weapons
|
||||
// Diary Example Images
|
||||
Tool("example_utility"): VoxTrans(
|
||||
@ -1920,11 +1937,11 @@
|
||||
"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!
|
||||
// Ingredients
|
||||
Tool("common.items.tool.craftsman_hammer"): VoxTrans(
|
||||
"voxel.weapon.hammer.craftsman",
|
||||
(1.0, 1.0, 0.0), (-135.0, 90.0, 0.0), 1.0,
|
||||
),
|
||||
(1.0, -1.0, 0.0), (-135.0, 90.0, 0.0), 0.9,
|
||||
),
|
||||
Ingredient("SewingSet"): Png(
|
||||
"element.items.sewing_set",
|
||||
),
|
||||
|
@ -18,7 +18,7 @@
|
||||
|
||||
in vec3 f_pos;
|
||||
flat in vec3 f_norm;
|
||||
flat in float f_light;
|
||||
flat in float f_select;
|
||||
// flat in vec3 f_pos_norm;
|
||||
in vec2 f_uv_pos;
|
||||
in vec2 f_inst_light;
|
||||
@ -181,9 +181,11 @@ void main() {
|
||||
emitted_light *= ao;
|
||||
reflected_light *= ao;
|
||||
|
||||
surf_color = illuminate(max_light, view_dir, surf_color * emitted_light, surf_color * reflected_light) * f_light;
|
||||
surf_color = illuminate(max_light, view_dir, surf_color * emitted_light, surf_color * reflected_light);
|
||||
// vec3 surf_color = illuminate(f_col, light, diffuse_light, ambient_light);
|
||||
|
||||
surf_color += f_select * (surf_color + 0.1) * vec3(0.15, 0.15, 0.15);
|
||||
|
||||
// tgt_color = vec4(color, 1.0);
|
||||
tgt_color = vec4(surf_color, 1.0 - clamp((distance(focus_pos.xy, f_pos.xy) - (sprite_render_distance - FADE_DIST)) / FADE_DIST, 0, 1));
|
||||
}
|
||||
|
@ -72,7 +72,7 @@ uniform u_terrain_locals {
|
||||
|
||||
out vec3 f_pos;
|
||||
flat out vec3 f_norm;
|
||||
flat out float f_light;
|
||||
flat out float f_select;
|
||||
// flat out vec3 f_pos_norm;
|
||||
// out vec3 f_col;
|
||||
// out float f_ao;
|
||||
@ -228,7 +228,7 @@ void main() {
|
||||
// f_light = 1.0;
|
||||
// if (select_pos.w > 0) */{
|
||||
vec3 sprite_pos = /*round*/floor(((inst_mat * vec4(-offs.xyz, 1)).xyz) * SCALE/* - vec3(0.5, 0.5, 0.0)*/) + inst_offs;
|
||||
f_light = (select_pos.w > 0 && select_pos.xyz == sprite_pos/* - vec3(0.5, 0.5, 0.0) * SCALE*/) ? 10.0 : 1.0;
|
||||
f_select = (select_pos.w > 0 && select_pos.xyz == sprite_pos/* - vec3(0.5, 0.5, 0.0) * SCALE*/) ? 1.0 : 0.0;
|
||||
// }
|
||||
|
||||
gl_Position =
|
||||
|
@ -268,9 +268,6 @@ void main() {
|
||||
vec3 glow = glow_light(f_pos) * (pow(f_glow, 6) * 5 + pow(f_glow, 1.5) * 2);
|
||||
reflected_light += glow;
|
||||
|
||||
float f_select = (select_pos.w > 0 && select_pos.xyz == floor(f_pos - f_norm * 0.5)) ? 0.2 / PERSISTENT_AMBIANCE : 0.0;
|
||||
reflected_light += f_select;
|
||||
|
||||
max_light += lights_at(f_pos, f_norm, view_dir, mu, cam_attenuation, fluid_alt, k_a, k_d, k_s, alpha, f_norm, 1.0, emitted_light, reflected_light);
|
||||
|
||||
// float f_ao = 1.0;
|
||||
@ -371,5 +368,8 @@ void main() {
|
||||
// vec3 col = /*srgb_to_linear*/(f_col + hash(vec4(floor(f_pos * 3.0 - f_norm * 0.5), 0)) * 0.01); // Small-scale noise
|
||||
vec3 surf_color = illuminate(max_light, view_dir, col * emitted_light, col * reflected_light);
|
||||
|
||||
float f_select = (select_pos.w > 0 && select_pos.xyz == floor(f_pos - f_norm * 0.5)) ? 1.0 : 0.0;
|
||||
surf_color += f_select * (surf_color + 0.1) * vec3(0.5, 0.5, 0.5);
|
||||
|
||||
tgt_color = vec4(surf_color, 1.0);
|
||||
}
|
||||
|
BIN
assets/voxygen/voxel/armor/bonerattler/chest.vox
(Stored with Git LFS)
BIN
assets/voxygen/voxel/armor/bonerattler/chest.vox
(Stored with Git LFS)
Binary file not shown.
@ -462,7 +462,11 @@
|
||||
vox_spec: ("weapon.axe_1h.wood-1", (-1.5, -5.0, -3.0)),
|
||||
color: None
|
||||
),
|
||||
// Hammers
|
||||
// Hammers
|
||||
"common.items.tool.craftsman_hammer": (
|
||||
vox_spec: ("weapon.hammer.craftsman", (-2.5, -5.5, -4.5)),
|
||||
color: None
|
||||
),
|
||||
"common.items.weapons.hammer.hammer_1": (
|
||||
vox_spec: ("weapon.hammer.2hhammer_rusty", (-2.5, -5.5, -4.5)),
|
||||
color: None
|
||||
|
BIN
assets/voxygen/voxel/glider/glider_cultists.vox
(Stored with Git LFS)
BIN
assets/voxygen/voxel/glider/glider_cultists.vox
(Stored with Git LFS)
Binary file not shown.
BIN
assets/voxygen/voxel/sprite/anvil/anvil-0.vox
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/voxel/sprite/anvil/anvil-0.vox
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/voxel/sprite/cauldron/cauldron-0.vox
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/voxel/sprite/cauldron/cauldron-0.vox
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/voxel/sprite/cooking_pot/pot-0.vox
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/voxel/sprite/cooking_pot/pot-0.vox
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/voxel/sprite/crafting_bench/crafting_bench-0.vox
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/voxel/sprite/crafting_bench/crafting_bench-0.vox
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/voxel/sprite/forge/forge-0.vox
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/voxel/sprite/forge/forge-0.vox
(Stored with Git LFS)
Normal file
Binary file not shown.
@ -2852,4 +2852,59 @@ Lantern: Some((
|
||||
],
|
||||
wind_sway: 0.0,
|
||||
)),
|
||||
// Anvil
|
||||
Anvil: Some((
|
||||
variations: [
|
||||
(
|
||||
model: "voxygen.voxel.sprite.anvil.anvil-0",
|
||||
offset: (-5.5, -7.0, 0.0),
|
||||
lod_axes: (0.0, 0.0, 0.0),
|
||||
),
|
||||
],
|
||||
wind_sway: 0.0,
|
||||
)),
|
||||
// Cauldron
|
||||
Cauldron: Some((
|
||||
variations: [
|
||||
(
|
||||
model: "voxygen.voxel.sprite.cauldron.cauldron-0",
|
||||
offset: (-10.0, -10.0, 0.0),
|
||||
lod_axes: (0.0, 0.0, 0.0),
|
||||
),
|
||||
],
|
||||
wind_sway: 0.0,
|
||||
)),
|
||||
// Forge
|
||||
Forge: Some((
|
||||
variations: [
|
||||
(
|
||||
model: "voxygen.voxel.sprite.forge.forge-0",
|
||||
offset: (-20.0, -20.0, 0.0),
|
||||
lod_axes: (0.0, 0.0, 0.0),
|
||||
),
|
||||
],
|
||||
wind_sway: 0.0,
|
||||
)),
|
||||
// Crafting Bench
|
||||
CraftingBench: Some((
|
||||
variations: [
|
||||
(
|
||||
model: "voxygen.voxel.sprite.crafting_bench.crafting_bench-0",
|
||||
offset: (-9.5, -7.0, 0.0),
|
||||
lod_axes: (0.0, 0.0, 0.0),
|
||||
),
|
||||
],
|
||||
wind_sway: 0.0,
|
||||
)),
|
||||
// Cooking Pot
|
||||
CookingPot: Some((
|
||||
variations: [
|
||||
(
|
||||
model: "voxygen.voxel.sprite.cooking_pot.pot-0",
|
||||
offset: (-9.0, -10.0, 0.0),
|
||||
lod_axes: (0.0, 0.0, 0.0),
|
||||
),
|
||||
],
|
||||
wind_sway: 0.0,
|
||||
)),
|
||||
)
|
||||
|
BIN
assets/voxygen/voxel/weapon/hammer/craftsman.vox
(Stored with Git LFS)
BIN
assets/voxygen/voxel/weapon/hammer/craftsman.vox
(Stored with Git LFS)
Binary file not shown.
@ -35,7 +35,7 @@ use common::{
|
||||
recipe::RecipeBook,
|
||||
resources::{DeltaTime, PlayerEntity, TimeOfDay},
|
||||
terrain::{
|
||||
block::Block, map::MapConfig, neighbors, BiomeKind, SitesKind, TerrainChunk,
|
||||
block::Block, map::MapConfig, neighbors, BiomeKind, SitesKind, SpriteKind, TerrainChunk,
|
||||
TerrainChunkSize,
|
||||
},
|
||||
trade::{PendingTrade, SitePrices, TradeAction, TradeId, TradeResult},
|
||||
@ -152,7 +152,7 @@ pub struct Client {
|
||||
sites: HashMap<SiteId, SiteInfoRich>,
|
||||
pub chat_mode: ChatMode,
|
||||
recipe_book: RecipeBook,
|
||||
available_recipes: HashSet<String>,
|
||||
available_recipes: HashMap<String, Option<SpriteKind>>,
|
||||
|
||||
max_group_size: u32,
|
||||
// Client has received an invite (inviter uid, time out instant)
|
||||
@ -655,7 +655,7 @@ impl Client {
|
||||
})
|
||||
.collect(),
|
||||
recipe_book,
|
||||
available_recipes: HashSet::default(),
|
||||
available_recipes: HashMap::default(),
|
||||
chat_mode: ChatMode::default(),
|
||||
|
||||
max_group_size,
|
||||
@ -970,20 +970,38 @@ impl Client {
|
||||
|
||||
pub fn recipe_book(&self) -> &RecipeBook { &self.recipe_book }
|
||||
|
||||
pub fn available_recipes(&self) -> &HashSet<String> { &self.available_recipes }
|
||||
pub fn available_recipes(&self) -> &HashMap<String, Option<SpriteKind>> {
|
||||
&self.available_recipes
|
||||
}
|
||||
|
||||
pub fn can_craft_recipe(&self, recipe: &str) -> bool {
|
||||
/// Returns whether the specified recipe can be crafted and the sprite, if
|
||||
/// any, that is required to do so.
|
||||
pub fn can_craft_recipe(&self, recipe: &str) -> (bool, Option<SpriteKind>) {
|
||||
self.recipe_book
|
||||
.get(recipe)
|
||||
.zip(self.inventories().get(self.entity()))
|
||||
.map(|(recipe, inv)| inv.contains_ingredients(&*recipe).is_ok())
|
||||
.unwrap_or(false)
|
||||
.map(|(recipe, inv)| {
|
||||
(
|
||||
inv.contains_ingredients(&*recipe).is_ok(),
|
||||
recipe.craft_sprite,
|
||||
)
|
||||
})
|
||||
.unwrap_or((false, None))
|
||||
}
|
||||
|
||||
pub fn craft_recipe(&mut self, recipe: &str) -> bool {
|
||||
if self.can_craft_recipe(recipe) {
|
||||
pub fn craft_recipe(
|
||||
&mut self,
|
||||
recipe: &str,
|
||||
craft_sprite: Option<(Vec3<i32>, SpriteKind)>,
|
||||
) -> bool {
|
||||
let (can_craft, required_sprite) = self.can_craft_recipe(recipe);
|
||||
let has_sprite = required_sprite.map_or(true, |s| Some(s) == craft_sprite.map(|(_, s)| s));
|
||||
if can_craft && has_sprite {
|
||||
self.send_msg(ClientGeneral::ControlEvent(ControlEvent::InventoryEvent(
|
||||
InventoryEvent::CraftRecipe(recipe.to_string()),
|
||||
InventoryEvent::CraftRecipe {
|
||||
recipe: recipe.to_string(),
|
||||
craft_sprite: craft_sprite.map(|(pos, _)| pos),
|
||||
},
|
||||
)));
|
||||
true
|
||||
} else {
|
||||
@ -996,7 +1014,14 @@ impl Client {
|
||||
.recipe_book
|
||||
.iter()
|
||||
.map(|(name, _)| name.clone())
|
||||
.filter(|name| self.can_craft_recipe(name))
|
||||
.filter_map(|name| {
|
||||
let (can_craft, required_sprite) = self.can_craft_recipe(&name);
|
||||
if can_craft {
|
||||
Some((name, required_sprite))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
}
|
||||
|
||||
|
@ -22,8 +22,11 @@ pub enum InventoryEvent {
|
||||
SplitSwap(InvSlotId, InvSlotId),
|
||||
Drop(InvSlotId),
|
||||
SplitDrop(InvSlotId),
|
||||
CraftRecipe(String),
|
||||
Sort,
|
||||
CraftRecipe {
|
||||
recipe: String,
|
||||
craft_sprite: Option<Vec3<i32>>,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)]
|
||||
@ -43,8 +46,11 @@ pub enum InventoryManip {
|
||||
SplitSwap(Slot, Slot),
|
||||
Drop(Slot),
|
||||
SplitDrop(Slot),
|
||||
CraftRecipe(String),
|
||||
Sort,
|
||||
CraftRecipe {
|
||||
recipe: String,
|
||||
craft_sprite: Option<Vec3<i32>>,
|
||||
},
|
||||
}
|
||||
|
||||
impl From<InventoryAction> for InventoryManip {
|
||||
@ -71,8 +77,14 @@ impl From<InventoryEvent> for InventoryManip {
|
||||
},
|
||||
InventoryEvent::Drop(inv) => Self::Drop(Slot::Inventory(inv)),
|
||||
InventoryEvent::SplitDrop(inv) => Self::SplitDrop(Slot::Inventory(inv)),
|
||||
InventoryEvent::CraftRecipe(recipe) => Self::CraftRecipe(recipe),
|
||||
InventoryEvent::Sort => Self::Sort,
|
||||
InventoryEvent::CraftRecipe {
|
||||
recipe,
|
||||
craft_sprite,
|
||||
} => Self::CraftRecipe {
|
||||
recipe,
|
||||
craft_sprite,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
use super::{tool, ItemKind, ItemTag, Quality, RawItemDef, TagExampleInfo, ToolKind};
|
||||
use crate::recipe::{RawRecipeBook, RawRecipeInput};
|
||||
use crate::recipe::{RawRecipe, RawRecipeBook, RawRecipeInput};
|
||||
use hashbrown::HashMap;
|
||||
use lazy_static::lazy_static;
|
||||
use serde::{Deserialize, Serialize};
|
||||
@ -234,11 +234,8 @@ fn make_weapon_def(toolkind: ToolKind) -> (String, RawItemDef) {
|
||||
(identifier, item)
|
||||
}
|
||||
|
||||
fn make_recipe_def(
|
||||
identifier: String,
|
||||
toolkind: ToolKind,
|
||||
) -> ((String, u32), Vec<(RawRecipeInput, u32)>) {
|
||||
let outputs = (identifier, 1);
|
||||
fn make_recipe_def(identifier: String, toolkind: ToolKind) -> RawRecipe {
|
||||
let output = (identifier, 1);
|
||||
let mut inputs = Vec::new();
|
||||
for &modkind in &MODKINDS {
|
||||
let input = RawRecipeInput::Tag(ItemTag::ModularComponent(ModularComponentTag {
|
||||
@ -247,7 +244,11 @@ fn make_recipe_def(
|
||||
}));
|
||||
inputs.push((input, 1));
|
||||
}
|
||||
(outputs, inputs)
|
||||
RawRecipe {
|
||||
output,
|
||||
inputs,
|
||||
craft_sprite: None,
|
||||
}
|
||||
}
|
||||
|
||||
fn make_tagexample_def(
|
||||
|
@ -4,6 +4,7 @@ use crate::{
|
||||
item::{modular, ItemDef, ItemTag, MaterialStatManifest},
|
||||
Inventory, Item,
|
||||
},
|
||||
terrain::SpriteKind,
|
||||
};
|
||||
use hashbrown::HashMap;
|
||||
use serde::{Deserialize, Serialize};
|
||||
@ -19,6 +20,7 @@ pub enum RecipeInput {
|
||||
pub struct Recipe {
|
||||
pub output: (Arc<ItemDef>, u32),
|
||||
pub inputs: Vec<(RecipeInput, u32)>,
|
||||
pub craft_sprite: Option<SpriteKind>,
|
||||
}
|
||||
|
||||
#[allow(clippy::type_complexity)]
|
||||
@ -86,12 +88,17 @@ pub enum RawRecipeInput {
|
||||
Tag(ItemTag),
|
||||
}
|
||||
|
||||
#[derive(Clone, Deserialize)]
|
||||
pub(crate) struct RawRecipe {
|
||||
pub(crate) output: (String, u32),
|
||||
pub(crate) inputs: Vec<(RawRecipeInput, u32)>,
|
||||
#[serde(default)]
|
||||
pub(crate) craft_sprite: Option<SpriteKind>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Deserialize)]
|
||||
#[serde(transparent)]
|
||||
#[allow(clippy::type_complexity)]
|
||||
pub(crate) struct RawRecipeBook(
|
||||
pub(crate) HashMap<String, ((String, u32), Vec<(RawRecipeInput, u32)>)>,
|
||||
);
|
||||
pub(crate) struct RawRecipeBook(pub(crate) HashMap<String, RawRecipe>);
|
||||
|
||||
impl assets::Asset for RawRecipeBook {
|
||||
type Loader = assets::RonLoader;
|
||||
@ -134,14 +141,27 @@ impl assets::Compound for RecipeBook {
|
||||
let recipes = raw
|
||||
.0
|
||||
.iter()
|
||||
.map(|(name, (output, inputs))| {
|
||||
let inputs = inputs
|
||||
.iter()
|
||||
.map(load_recipe_input)
|
||||
.collect::<Result<_, _>>()?;
|
||||
let output = load_item_def(output)?;
|
||||
Ok((name.clone(), Recipe { output, inputs }))
|
||||
})
|
||||
.map(
|
||||
|(
|
||||
name,
|
||||
RawRecipe {
|
||||
output,
|
||||
inputs,
|
||||
craft_sprite,
|
||||
},
|
||||
)| {
|
||||
let inputs = inputs
|
||||
.iter()
|
||||
.map(load_recipe_input)
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
let output = load_item_def(output)?;
|
||||
Ok((name.clone(), Recipe {
|
||||
output,
|
||||
inputs,
|
||||
craft_sprite: *craft_sprite,
|
||||
}))
|
||||
},
|
||||
)
|
||||
.collect::<Result<_, assets::Error>>()?;
|
||||
|
||||
Ok(RecipeBook { recipes })
|
||||
|
@ -171,12 +171,12 @@ impl Block {
|
||||
match self.get_sprite()? {
|
||||
SpriteKind::StreetLamp | SpriteKind::StreetLampTall => Some(24),
|
||||
SpriteKind::Ember => Some(20),
|
||||
SpriteKind::WallLamp => Some(16),
|
||||
SpriteKind::WallLampSmall => Some(16),
|
||||
SpriteKind::WallSconce => Some(16),
|
||||
SpriteKind::FireBowlGround => Some(16),
|
||||
SpriteKind::WallLamp
|
||||
| SpriteKind::WallLampSmall
|
||||
| SpriteKind::WallSconce
|
||||
| SpriteKind::FireBowlGround => Some(16),
|
||||
SpriteKind::Velorite | SpriteKind::VeloriteFrag => Some(6),
|
||||
SpriteKind::CaveMushroom => Some(12),
|
||||
SpriteKind::CaveMushroom | SpriteKind::CookingPot => Some(12),
|
||||
SpriteKind::Amethyst
|
||||
| SpriteKind::Ruby
|
||||
| SpriteKind::Sapphire
|
||||
|
@ -143,6 +143,11 @@ make_case_elim!(
|
||||
RedAlgae = 0x74,
|
||||
UnderwaterVent = 0x75,
|
||||
Lantern = 0x76,
|
||||
CraftingBench = 0x77,
|
||||
Forge = 0x78,
|
||||
Cauldron = 0x79,
|
||||
Anvil = 0x7A,
|
||||
CookingPot = 0x7B,
|
||||
}
|
||||
);
|
||||
|
||||
@ -184,6 +189,11 @@ impl SpriteKind {
|
||||
SpriteKind::Mud => 0.36,
|
||||
SpriteKind::ChestBuried => 0.91,
|
||||
SpriteKind::StonyCoral => 1.4,
|
||||
SpriteKind::CraftingBench => 1.18,
|
||||
SpriteKind::Forge => 2.7,
|
||||
SpriteKind::Cauldron => 1.27,
|
||||
SpriteKind::Anvil => 1.1,
|
||||
SpriteKind::CookingPot => 1.36,
|
||||
// TODO: Find suitable heights.
|
||||
SpriteKind::BarrelCactus
|
||||
| SpriteKind::RoundCactus
|
||||
@ -309,6 +319,11 @@ impl SpriteKind {
|
||||
| SpriteKind::VialEmpty
|
||||
| SpriteKind::FireBowlGround
|
||||
| SpriteKind::Lantern
|
||||
| SpriteKind::CraftingBench
|
||||
| SpriteKind::Forge
|
||||
| SpriteKind::Cauldron
|
||||
| SpriteKind::Anvil
|
||||
| SpriteKind::CookingPot
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -576,15 +576,49 @@ pub fn handle_inventory(server: &mut Server, entity: EcsEntity, manip: comp::Inv
|
||||
.expect("We know entity exists since we got its inventory.");
|
||||
drop(inventories);
|
||||
},
|
||||
comp::InventoryManip::CraftRecipe(recipe) => {
|
||||
comp::InventoryManip::CraftRecipe {
|
||||
recipe,
|
||||
craft_sprite,
|
||||
} => {
|
||||
let recipe_book = default_recipe_book().read();
|
||||
let craft_result = recipe_book.get(&recipe).and_then(|r| {
|
||||
r.perform(
|
||||
&mut inventory,
|
||||
&state.ecs().read_resource::<item::MaterialStatManifest>(),
|
||||
)
|
||||
.ok()
|
||||
});
|
||||
let craft_result = recipe_book
|
||||
.get(&recipe)
|
||||
.filter(|r| {
|
||||
if let Some(needed_sprite) = r.craft_sprite {
|
||||
let sprite = craft_sprite
|
||||
.filter(|pos| {
|
||||
let entity_cylinder = get_cylinder(state, entity);
|
||||
if !within_pickup_range(entity_cylinder, || {
|
||||
Some(find_dist::Cube {
|
||||
min: pos.as_(),
|
||||
side_length: 1.0,
|
||||
})
|
||||
}) {
|
||||
debug!(
|
||||
?entity_cylinder,
|
||||
"Failed to craft recipe as not within range of required \
|
||||
sprite, sprite pos: {}",
|
||||
pos
|
||||
);
|
||||
false
|
||||
} else {
|
||||
true
|
||||
}
|
||||
})
|
||||
.and_then(|pos| state.terrain().get(pos).ok().copied())
|
||||
.and_then(|block| block.get_sprite());
|
||||
Some(needed_sprite) == sprite
|
||||
} else {
|
||||
true
|
||||
}
|
||||
})
|
||||
.and_then(|r| {
|
||||
r.perform(
|
||||
&mut inventory,
|
||||
&state.ecs().read_resource::<item::MaterialStatManifest>(),
|
||||
)
|
||||
.ok()
|
||||
});
|
||||
drop(inventories);
|
||||
|
||||
// FIXME: We should really require the drop and write to be atomic!
|
||||
|
3
server/src/migrations/V35__rename_craftsman_hammer.sql
Normal file
3
server/src/migrations/V35__rename_craftsman_hammer.sql
Normal file
@ -0,0 +1,3 @@
|
||||
-- Replace old crafting hammer ingredient with functional 1h-hammer variant
|
||||
|
||||
UPDATE item SET item_definition_id = 'common.items.tool.craftsman_hammer' WHERE item_definition_id = 'common.items.crafting_tools.craftsman_hammer';
|
@ -1,6 +1,6 @@
|
||||
use super::{
|
||||
img_ids::{Imgs, ImgsRot},
|
||||
item_imgs::{animate_by_pulse, ItemImgs},
|
||||
item_imgs::{animate_by_pulse, ItemImgs, ItemKey::Tool},
|
||||
Show, TEXT_COLOR, TEXT_DULL_RED_COLOR, TEXT_GRAY_COLOR, UI_HIGHLIGHT_0, UI_MAIN,
|
||||
};
|
||||
use crate::{
|
||||
@ -20,6 +20,7 @@ use common::{
|
||||
Inventory,
|
||||
},
|
||||
recipe::RecipeInput,
|
||||
terrain::SpriteKind,
|
||||
};
|
||||
use conrod_core::{
|
||||
color, image,
|
||||
@ -59,6 +60,9 @@ widget_ids! {
|
||||
ingredient_img[],
|
||||
req_text[],
|
||||
ingredients_txt,
|
||||
req_station_title,
|
||||
req_station_img,
|
||||
req_station_txt,
|
||||
output_img_frame,
|
||||
output_img,
|
||||
output_amount,
|
||||
@ -127,7 +131,7 @@ impl<'a> Crafting<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, EnumIter, PartialEq)]
|
||||
#[derive(Copy, Clone, Debug, EnumIter, PartialEq)]
|
||||
pub enum CraftingTab {
|
||||
All,
|
||||
Armor,
|
||||
@ -434,7 +438,16 @@ impl<'a> Widget for Crafting<'a> {
|
||||
.unwrap_or(false)
|
||||
})
|
||||
});
|
||||
let state = if self.client.available_recipes().contains(name.as_str()) {
|
||||
let show_craft_sprite =
|
||||
self.client
|
||||
.available_recipes()
|
||||
.get(name.as_str())
|
||||
.map_or(false, |cs| {
|
||||
cs.map_or(true, |cs| {
|
||||
Some(cs) == self.show.craft_sprite.map(|(_, s)| s)
|
||||
})
|
||||
});
|
||||
let state = if show_craft_sprite {
|
||||
RecipeIngredientQuantity::All
|
||||
} else if at_least_some_ingredients {
|
||||
RecipeIngredientQuantity::Some
|
||||
@ -528,7 +541,12 @@ impl<'a> Widget for Crafting<'a> {
|
||||
let can_perform = self
|
||||
.client
|
||||
.available_recipes()
|
||||
.contains(recipe_name.as_str());
|
||||
.get(recipe_name.as_str())
|
||||
.map_or(false, |cs| {
|
||||
cs.map_or(true, |cs| {
|
||||
Some(cs) == self.show.craft_sprite.map(|(_, s)| s)
|
||||
})
|
||||
});
|
||||
|
||||
// Craft button
|
||||
if Button::image(self.imgs.button)
|
||||
@ -642,14 +660,68 @@ impl<'a> Widget for Crafting<'a> {
|
||||
.set(state.ids.tags_ing[i], ui);
|
||||
}
|
||||
}
|
||||
|
||||
// Ingredients Text
|
||||
Text::new(&self.localized_strings.get("hud.crafting.ingredients"))
|
||||
// Crafting Station Info
|
||||
if recipe.craft_sprite.is_some() {
|
||||
Text::new(
|
||||
&self
|
||||
.localized_strings
|
||||
.get("hud.crafting.req_crafting_station"),
|
||||
)
|
||||
.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);
|
||||
.set(state.ids.req_station_title, ui);
|
||||
let station_img = match recipe.craft_sprite {
|
||||
Some(SpriteKind::Anvil) => "Anvil",
|
||||
Some(SpriteKind::Cauldron) => "Cauldron",
|
||||
Some(SpriteKind::CookingPot) => "CookingPot",
|
||||
Some(SpriteKind::CraftingBench) => "CraftingBench",
|
||||
None => "CraftsmanHammer",
|
||||
_ => "CraftsmanHammer",
|
||||
};
|
||||
Image::new(animate_by_pulse(
|
||||
&self
|
||||
.item_imgs
|
||||
.img_ids_or_not_found_img(Tool(station_img.to_string())),
|
||||
self.pulse,
|
||||
))
|
||||
.w_h(25.0, 25.0)
|
||||
.down_from(state.ids.req_station_title, 10.0)
|
||||
.parent(state.ids.align_ing)
|
||||
.set(state.ids.req_station_img, ui);
|
||||
|
||||
let station_name = match recipe.craft_sprite {
|
||||
Some(SpriteKind::Anvil) => "hud.crafting.anvil",
|
||||
Some(SpriteKind::Cauldron) => "hud.crafting.cauldron",
|
||||
Some(SpriteKind::CookingPot) => "hud.crafting.cooking_pot",
|
||||
Some(SpriteKind::CraftingBench) => "hud.crafting.crafting_bench",
|
||||
_ => "",
|
||||
};
|
||||
Text::new(&self.localized_strings.get(station_name))
|
||||
.right_from(state.ids.req_station_img, 10.0)
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
.font_size(self.fonts.cyri.scale(14))
|
||||
.color(
|
||||
if self.show.craft_sprite.map(|(_, s)| s) == recipe.craft_sprite {
|
||||
TEXT_COLOR
|
||||
} else {
|
||||
TEXT_DULL_RED_COLOR
|
||||
},
|
||||
)
|
||||
.set(state.ids.req_station_txt, ui);
|
||||
}
|
||||
// Ingredients Text
|
||||
let mut ing_txt = Text::new(&self.localized_strings.get("hud.crafting.ingredients"))
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
.font_size(self.fonts.cyri.scale(18))
|
||||
.color(TEXT_COLOR);
|
||||
if recipe.craft_sprite.is_some() {
|
||||
ing_txt = ing_txt.down_from(state.ids.req_station_img, 10.0);
|
||||
} else {
|
||||
ing_txt = ing_txt.top_left_with_margins_on(state.ids.align_ing, 10.0, 5.0);
|
||||
};
|
||||
ing_txt.set(state.ids.ingredients_txt, ui);
|
||||
|
||||
// Ingredient images with tooltip
|
||||
if state.ids.ingredient_frame.len() < recipe.inputs().len() {
|
||||
@ -684,6 +756,7 @@ impl<'a> Widget for Crafting<'a> {
|
||||
.resize(recipe.inputs().len(), &mut ui.widget_id_generator())
|
||||
});
|
||||
};
|
||||
|
||||
// Widget generation for every ingredient
|
||||
for (i, (recipe_input, amount)) in recipe.inputs.iter().enumerate() {
|
||||
let item_def = match recipe_input {
|
||||
|
@ -22,6 +22,7 @@ mod social;
|
||||
mod trade;
|
||||
pub mod util;
|
||||
|
||||
pub use crafting::CraftingTab;
|
||||
pub use hotbar::{SlotContents as HotbarSlotContents, State as HotbarState};
|
||||
pub use item_imgs::animate_by_pulse;
|
||||
pub use settings_window::ScaleChange;
|
||||
@ -31,7 +32,7 @@ use buffs::BuffsBar;
|
||||
use buttons::Buttons;
|
||||
use chat::Chat;
|
||||
use chrono::NaiveTime;
|
||||
use crafting::{Crafting, CraftingTab};
|
||||
use crafting::Crafting;
|
||||
use diary::{Diary, SelectedSkillTree};
|
||||
use esc_menu::EscMenu;
|
||||
use group::Group;
|
||||
@ -73,8 +74,9 @@ use common::{
|
||||
skills::{Skill, SkillGroupKind},
|
||||
BuffKind, Item,
|
||||
},
|
||||
consts::MAX_PICKUP_RANGE,
|
||||
outcome::Outcome,
|
||||
terrain::TerrainChunk,
|
||||
terrain::{SpriteKind, TerrainChunk},
|
||||
trade::{ReducedInventory, TradeAction},
|
||||
uid::Uid,
|
||||
util::srgba_to_linear,
|
||||
@ -380,7 +382,10 @@ pub enum Event {
|
||||
Logout,
|
||||
Quit,
|
||||
|
||||
CraftRecipe(String),
|
||||
CraftRecipe {
|
||||
recipe: String,
|
||||
craft_sprite: Option<(Vec3<i32>, SpriteKind)>,
|
||||
},
|
||||
InviteMember(Uid),
|
||||
AcceptInvite,
|
||||
DeclineInvite,
|
||||
@ -492,6 +497,7 @@ pub struct Show {
|
||||
skilltreetab: SelectedSkillTree,
|
||||
crafting_tab: CraftingTab,
|
||||
crafting_search_key: Option<String>,
|
||||
craft_sprite: Option<(Vec3<i32>, SpriteKind)>,
|
||||
social_search_key: Option<String>,
|
||||
want_grab: bool,
|
||||
stats: bool,
|
||||
@ -558,6 +564,16 @@ impl Show {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn open_crafting_tab(
|
||||
&mut self,
|
||||
tab: CraftingTab,
|
||||
craft_sprite: Option<(Vec3<i32>, SpriteKind)>,
|
||||
) {
|
||||
self.selected_crafting_tab(tab);
|
||||
self.crafting(true);
|
||||
self.craft_sprite = craft_sprite;
|
||||
}
|
||||
|
||||
fn diary(&mut self, open: bool) {
|
||||
if !self.esc_menu {
|
||||
self.social = false;
|
||||
@ -734,7 +750,7 @@ pub struct Hud {
|
||||
new_messages: VecDeque<comp::ChatMsg>,
|
||||
new_notifications: VecDeque<Notification>,
|
||||
speech_bubbles: HashMap<Uid, comp::SpeechBubble>,
|
||||
show: Show,
|
||||
pub show: Show,
|
||||
//never_show: bool,
|
||||
//intro: bool,
|
||||
//intro_2: bool,
|
||||
@ -840,6 +856,7 @@ impl Hud {
|
||||
skilltreetab: SelectedSkillTree::General,
|
||||
crafting_tab: CraftingTab::All,
|
||||
crafting_search_key: None,
|
||||
craft_sprite: None,
|
||||
social_search_key: None,
|
||||
want_grab: true,
|
||||
ingame: true,
|
||||
@ -1363,7 +1380,7 @@ impl Hud {
|
||||
}
|
||||
|
||||
// Render overtime for an interactable block
|
||||
if let Some(Interactable::Block(block, pos)) = interactable {
|
||||
if let Some(Interactable::Block(block, pos, _)) = interactable {
|
||||
let overitem_id = overitem_walker.next(
|
||||
&mut self.ids.overitems,
|
||||
&mut ui_widgets.widget_id_generator(),
|
||||
@ -1395,6 +1412,20 @@ impl Hud {
|
||||
&self.fonts,
|
||||
)
|
||||
.set(overitem_id, ui_widgets);
|
||||
} else if let Some(sprite) = block.get_sprite() {
|
||||
overitem::Overitem::new(
|
||||
format!("{:?}", sprite).into(), /* TODO: A better way to generate text
|
||||
* for this */
|
||||
overitem::TEXT_COLOR,
|
||||
pos.distance_squared(player_pos),
|
||||
&self.fonts,
|
||||
&global_state.settings.controls,
|
||||
true,
|
||||
&global_state.window.key_layout,
|
||||
)
|
||||
.x_y(0.0, 100.0)
|
||||
.position_ingame(over_pos)
|
||||
.set(overitem_id, ui_widgets);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2420,8 +2451,11 @@ impl Hud {
|
||||
.set(self.ids.crafting_window, ui_widgets)
|
||||
{
|
||||
match event {
|
||||
crafting::Event::CraftRecipe(r) => {
|
||||
events.push(Event::CraftRecipe(r));
|
||||
crafting::Event::CraftRecipe(recipe) => {
|
||||
events.push(Event::CraftRecipe {
|
||||
recipe,
|
||||
craft_sprite: self.show.craft_sprite,
|
||||
});
|
||||
},
|
||||
crafting::Event::Close => {
|
||||
self.show.stats = false;
|
||||
@ -2434,7 +2468,7 @@ impl Hud {
|
||||
};
|
||||
},
|
||||
crafting::Event::ChangeCraftingTab(sel_cat) => {
|
||||
self.show.selected_crafting_tab(sel_cat);
|
||||
self.show.open_crafting_tab(sel_cat, None);
|
||||
},
|
||||
crafting::Event::Focus(widget_id) => {
|
||||
self.to_focus = Some(Some(widget_id));
|
||||
@ -3328,6 +3362,16 @@ impl Hud {
|
||||
.handle_event(conrod_core::event::Input::Text("\t".to_string()));
|
||||
}
|
||||
|
||||
// Stop selecting a sprite to perform crafting with when out of range
|
||||
self.show.craft_sprite = self.show.craft_sprite.filter(|(pos, _)| {
|
||||
self.show.crafting
|
||||
&& if let Some(player_pos) = client.position() {
|
||||
pos.map(|e| e as f32 + 0.5).distance(player_pos) < MAX_PICKUP_RANGE
|
||||
} else {
|
||||
false
|
||||
}
|
||||
});
|
||||
|
||||
// Optimization: skip maintaining UI when it's off.
|
||||
if !self.show.ui {
|
||||
return std::mem::take(&mut self.events);
|
||||
@ -3443,11 +3487,11 @@ fn try_hotbar_slot_from_input(input: GameInput) -> Option<hotbar::Slot> {
|
||||
}
|
||||
|
||||
pub fn cr_color(combat_rating: f32) -> Color {
|
||||
let common = 4.3;
|
||||
let moderate = 6.0;
|
||||
let high = 8.0;
|
||||
let epic = 10.0;
|
||||
let legendary = 79.0;
|
||||
let common = 2.0;
|
||||
let moderate = 3.5;
|
||||
let high = 6.5;
|
||||
let epic = 8.5;
|
||||
let legendary = 10.4;
|
||||
let artifact = 122.0;
|
||||
let debug = 200.0;
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
mod watcher;
|
||||
pub use self::watcher::BlocksOfInterest;
|
||||
pub use self::watcher::{BlocksOfInterest, Interaction};
|
||||
|
||||
use crate::{
|
||||
mesh::{greedy::GreedyMesh, terrain::SUNLIGHT, Meshable},
|
||||
|
@ -1,3 +1,4 @@
|
||||
use crate::hud::CraftingTab;
|
||||
use common::{
|
||||
terrain::{BlockKind, SpriteKind, TerrainChunk},
|
||||
vol::{IntoVolIterator, RectRasterableVol},
|
||||
@ -6,6 +7,12 @@ use common_base::span;
|
||||
use rand::prelude::*;
|
||||
use vek::*;
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub enum Interaction {
|
||||
Collect,
|
||||
Craft(CraftingTab),
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct BlocksOfInterest {
|
||||
pub leaves: Vec<Vec3<i32>>,
|
||||
@ -26,7 +33,7 @@ pub struct BlocksOfInterest {
|
||||
pub frogs: Vec<Vec3<i32>>,
|
||||
// Note: these are only needed for chunks within the iteraction range so this is a potential
|
||||
// area for optimization
|
||||
pub interactables: Vec<Vec3<i32>>,
|
||||
pub interactables: Vec<(Vec3<i32>, Interaction)>,
|
||||
pub lights: Vec<(Vec3<i32>, u8)>,
|
||||
}
|
||||
|
||||
@ -108,11 +115,26 @@ impl BlocksOfInterest {
|
||||
Some(SpriteKind::WhiteFlower) => flowers.push(pos),
|
||||
Some(SpriteKind::YellowFlower) => flowers.push(pos),
|
||||
Some(SpriteKind::Sunflower) => flowers.push(pos),
|
||||
Some(SpriteKind::CraftingBench) => {
|
||||
interactables.push((pos, Interaction::Craft(CraftingTab::All)))
|
||||
},
|
||||
Some(SpriteKind::Forge) => {
|
||||
interactables.push((pos, Interaction::Craft(CraftingTab::Dismantle)))
|
||||
},
|
||||
Some(SpriteKind::Cauldron) => {
|
||||
interactables.push((pos, Interaction::Craft(CraftingTab::Potion)))
|
||||
},
|
||||
Some(SpriteKind::Anvil) => {
|
||||
interactables.push((pos, Interaction::Craft(CraftingTab::Weapon)))
|
||||
},
|
||||
Some(SpriteKind::CookingPot) => {
|
||||
interactables.push((pos, Interaction::Craft(CraftingTab::Food)))
|
||||
},
|
||||
_ => {},
|
||||
},
|
||||
}
|
||||
if block.is_collectible() {
|
||||
interactables.push(pos);
|
||||
interactables.push((pos, Interaction::Collect));
|
||||
}
|
||||
if let Some(glow) = block.get_glow() {
|
||||
lights.push((pos, glow));
|
||||
|
@ -38,7 +38,7 @@ use crate::{
|
||||
key_state::KeyState,
|
||||
menu::char_selection::CharSelectionState,
|
||||
render::Renderer,
|
||||
scene::{camera, CameraMode, Scene, SceneData},
|
||||
scene::{camera, terrain::Interaction, CameraMode, Scene, SceneData},
|
||||
settings::Settings,
|
||||
window::{AnalogGameInput, Event, GameInput},
|
||||
Direction, Error, GlobalState, PlayState, PlayStateResult,
|
||||
@ -359,7 +359,7 @@ impl PlayState for SessionState {
|
||||
.map(|sp| sp.map(|e| e.floor() as i32))
|
||||
.filter(|_| can_build || is_mining)
|
||||
.or_else(|| match self.interactable {
|
||||
Some(Interactable::Block(_, block_pos)) => Some(block_pos),
|
||||
Some(Interactable::Block(_, block_pos, _)) => Some(block_pos),
|
||||
_ => None,
|
||||
}),
|
||||
);
|
||||
@ -591,9 +591,19 @@ impl PlayState for SessionState {
|
||||
if let Some(interactable) = self.interactable {
|
||||
let mut client = self.client.borrow_mut();
|
||||
match interactable {
|
||||
Interactable::Block(block, pos) => {
|
||||
if block.is_collectible() {
|
||||
client.collect_block(pos);
|
||||
Interactable::Block(block, pos, interaction) => {
|
||||
match interaction {
|
||||
Interaction::Collect => {
|
||||
if block.is_collectible() {
|
||||
client.collect_block(pos);
|
||||
}
|
||||
},
|
||||
Interaction::Craft(tab) => {
|
||||
self.hud.show.open_crafting_tab(
|
||||
tab,
|
||||
block.get_sprite().map(|s| (pos, s)),
|
||||
)
|
||||
},
|
||||
}
|
||||
},
|
||||
Interactable::Entity(entity) => {
|
||||
@ -618,7 +628,7 @@ impl PlayState for SessionState {
|
||||
if let Some(interactable) = self.interactable {
|
||||
let mut client = self.client.borrow_mut();
|
||||
match interactable {
|
||||
Interactable::Block(_, _) => {},
|
||||
Interactable::Block(_, _, _) => {},
|
||||
Interactable::Entity(entity) => {
|
||||
if let Some(uid) =
|
||||
client.state().ecs().uid_from_entity(entity)
|
||||
@ -1181,8 +1191,11 @@ impl PlayState for SessionState {
|
||||
client.request_site_economy(id);
|
||||
},
|
||||
|
||||
HudEvent::CraftRecipe(r) => {
|
||||
self.client.borrow_mut().craft_recipe(&r);
|
||||
HudEvent::CraftRecipe {
|
||||
recipe,
|
||||
craft_sprite,
|
||||
} => {
|
||||
self.client.borrow_mut().craft_recipe(&recipe, craft_sprite);
|
||||
},
|
||||
HudEvent::InviteMember(uid) => {
|
||||
self.client.borrow_mut().send_invite(uid, InviteKind::Group);
|
||||
@ -1440,7 +1453,7 @@ fn under_cursor(
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub enum Interactable {
|
||||
Block(Block, Vec3<i32>),
|
||||
Block(Block, Vec3<i32>, Interaction),
|
||||
Entity(specs::Entity),
|
||||
}
|
||||
|
||||
@ -1448,7 +1461,7 @@ impl Interactable {
|
||||
pub fn entity(self) -> Option<specs::Entity> {
|
||||
match self {
|
||||
Self::Entity(e) => Some(e),
|
||||
Self::Block(_, _) => None,
|
||||
Self::Block(_, _, _) => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1476,7 +1489,7 @@ fn select_interactable(
|
||||
.or_else(|| selected_pos.and_then(|sp|
|
||||
client.state().terrain().get(sp).ok().copied()
|
||||
.filter(|b| hit(*b))
|
||||
.map(|b| Interactable::Block(b, sp))
|
||||
.map(|b| Interactable::Block(b, sp, Interaction::Collect))
|
||||
))
|
||||
.or_else(|| {
|
||||
let ecs = client.state().ecs();
|
||||
@ -1540,22 +1553,23 @@ fn select_interactable(
|
||||
.blocks_of_interest
|
||||
.interactables
|
||||
.iter()
|
||||
.map(move |block_offset| chunk_pos + block_offset)
|
||||
.map(move |(block_offset, interaction)| (chunk_pos + block_offset, interaction))
|
||||
})
|
||||
.map(|block_pos| (
|
||||
.map(|(block_pos, interaction)| (
|
||||
block_pos,
|
||||
block_pos.map(|e| e as f32 + 0.5)
|
||||
.distance_squared(player_pos)
|
||||
.distance_squared(player_pos),
|
||||
interaction,
|
||||
))
|
||||
.min_by_key(|(_, dist_sqr)| OrderedFloat(*dist_sqr))
|
||||
.map(|(block_pos, _)| block_pos);
|
||||
.min_by_key(|(_, dist_sqr, _)| OrderedFloat(*dist_sqr))
|
||||
.map(|(block_pos, _, interaction)| (block_pos, interaction));
|
||||
|
||||
// Pick closer one if they exist
|
||||
closest_interactable_block_pos
|
||||
.filter(|block_pos| player_cylinder.min_distance(Cube { min: block_pos.as_(), side_length: 1.0}) < search_dist)
|
||||
.and_then(|block_pos|
|
||||
.filter(|(block_pos, _)| player_cylinder.min_distance(Cube { min: block_pos.as_(), side_length: 1.0}) < search_dist)
|
||||
.and_then(|(block_pos, interaction)|
|
||||
client.state().terrain().get(block_pos).ok().copied()
|
||||
.map(|b| Interactable::Block(b, block_pos))
|
||||
.map(|b| Interactable::Block(b, block_pos, *interaction))
|
||||
)
|
||||
.or_else(|| closest_interactable_entity.map(|(e, _)| Interactable::Entity(e)))
|
||||
})
|
||||
|
@ -151,9 +151,9 @@ impl Attr {
|
||||
pub fn generate<R: Rng>(rng: &mut R, _locus: i32) -> Self {
|
||||
Self {
|
||||
central_supports: rng.gen(),
|
||||
storey_fill: match rng.gen_range(0..2) {
|
||||
//0 => StoreyFill::None,
|
||||
0 => StoreyFill::Upper,
|
||||
storey_fill: match rng.gen_range(0..3) {
|
||||
0 => StoreyFill::None,
|
||||
1 => StoreyFill::Upper,
|
||||
_ => StoreyFill::All,
|
||||
},
|
||||
roof_style: match rng.gen_range(0..3) {
|
||||
@ -295,13 +295,12 @@ impl Archetype for House {
|
||||
const EMPTY: BlockMask = BlockMask::nothing();
|
||||
// TODO: Take environment into account.
|
||||
let internal = BlockMask::new(Block::air(SpriteKind::Empty), internal_layer);
|
||||
let end_ori = match ori {
|
||||
Ori::East => 2,
|
||||
Ori::North => 4,
|
||||
};
|
||||
let end_window = BlockMask::new(
|
||||
Block::air(attr.window)
|
||||
.with_ori(match ori {
|
||||
Ori::East => 2,
|
||||
Ori::North => 0,
|
||||
})
|
||||
.unwrap(),
|
||||
Block::air(attr.window).with_ori(end_ori).unwrap(),
|
||||
structural_layer,
|
||||
);
|
||||
let fire = BlockMask::new(Block::air(SpriteKind::Ember), foundation_layer);
|
||||
@ -519,6 +518,32 @@ impl Archetype for House {
|
||||
// Ceiling
|
||||
return floor;
|
||||
}
|
||||
} else if !attr.storey_fill.has_lower()
|
||||
&& center_offset.sum() % 2 == 0
|
||||
&& profile.y == 1
|
||||
&& center_offset.map(|e| e % 3 == 0).reduce_and()
|
||||
&& self
|
||||
.noise
|
||||
.chance(Vec3::new(center_offset.x, center_offset.y, z), 0.2)
|
||||
{
|
||||
let furniture = match self.noise.get(Vec3::new(
|
||||
center_offset.x,
|
||||
center_offset.y,
|
||||
z + 100,
|
||||
)) % 8
|
||||
{
|
||||
0..=1 => SpriteKind::Crate,
|
||||
2 => SpriteKind::Bench,
|
||||
3 => SpriteKind::Anvil,
|
||||
4 => SpriteKind::CookingPot,
|
||||
5 => SpriteKind::CraftingBench,
|
||||
6 => SpriteKind::FireBowlGround,
|
||||
7 => SpriteKind::Cauldron,
|
||||
//8 => SpriteKind::Forge,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
return BlockMask::new(Block::air(furniture).with_ori(end_ori).unwrap(), 1);
|
||||
} else if (!attr.storey_fill.has_lower() && profile.y < ceil_height)
|
||||
|| (!attr.storey_fill.has_upper() && profile.y >= ceil_height)
|
||||
{
|
||||
@ -592,10 +617,12 @@ impl Archetype for House {
|
||||
match self
|
||||
.noise
|
||||
.get(Vec3::new(center_offset.x, center_offset.y, z + 100))
|
||||
% 4
|
||||
% 6
|
||||
{
|
||||
0 => SpriteKind::HangingSign,
|
||||
1 | 2 | 3 => SpriteKind::HangingBasket,
|
||||
4 => SpriteKind::WallSconce,
|
||||
5 => SpriteKind::WallLampSmall,
|
||||
_ => SpriteKind::DungeonWallDecor,
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user