From 9a025cfcc8aa0fd01ee4862c04093ab51a26e2fe Mon Sep 17 00:00:00 2001 From: Monty Marz Date: Fri, 3 Mar 2023 23:21:37 +0000 Subject: [PATCH] More spot features --- CHANGELOG.md | 4 + assets/common/entity/spot/wizard/adept.ron | 20 ++ assets/common/entity/spot/wizard/novice.ron | 19 ++ assets/common/entity/spot/wizard/overseer.ron | 17 ++ .../common/entity/spot/wizard/spellbinder.ron | 17 ++ .../common/entity/spot/wizard/wizard_argo.ron | 19 ++ .../common/entity/spot/wizard/wizard_haku.ron | 19 ++ .../entity/spot/wizard/wizard_trish.ron | 19 ++ assets/common/entity/village/bowman.ron | 25 ++ assets/common/entity/village/skinner.ron | 25 ++ assets/common/items/keys/rusty_tower_key.ron | 11 + assets/common/items/utility/lockpick_0.ron | 11 + .../spots/wizard_tower/wizard_boss.ron | 19 ++ .../loadout/spots/wizard_tower/wizard_low.ron | 19 ++ .../spots/wizard_tower/wizard_novice.ron | 19 ++ .../spots/wizard_tower/wizard_overseer.ron | 19 ++ .../spots/wizard_tower/wizard_spellbinder.ron | 19 ++ assets/common/recipe_book.ron | 8 + assets/voxygen/background/bg_12.jpg | 4 +- assets/voxygen/background/bg_13.jpg | 4 +- assets/voxygen/background/bg_2.jpg | 4 +- assets/voxygen/background/bg_7.jpg | 4 +- assets/voxygen/element/items/key_rusty-0.vox | 3 + assets/voxygen/element/items/lockpick.vox | 3 + assets/voxygen/i18n/en/hud/misc.ftl | 14 +- assets/voxygen/i18n/en/main.ftl | 2 +- assets/voxygen/item_image_manifest.ron | 10 + .../armor/velorite_battlemage/chest-0.vox | 3 + .../armor/velorite_battlemage/hand-0.vox | 3 + .../voxel/armor/velorite_battlemage/hat.vox | 3 + .../armor/velorite_battlemage/pants-0.vox | 3 + .../armor/velorite_battlemage/shoulder-0.vox | 3 + .../voxygen/voxel/armor/warlock/shoulder.vox | 3 - .../voxel/armor/warlock/spellbinder-set.vox | 3 + assets/voxygen/voxel/item_drop_manifest.ron | 3 + assets/voxygen/voxel/object/tent.vox | 4 +- assets/voxygen/voxel/sprite/camp/camp.vox | 3 + .../voxygen/voxel/sprite/camp/camp_pirate.vox | 3 + .../voxygen/voxel/sprite/camp/camp_snow.vox | 3 + .../voxygen/voxel/sprite/door/door_dark-0.vox | 3 + .../voxel/sprite/furniture/door_block.vox | 3 + .../voxel/sprite/furniture/keyhole_block.vox | 3 + .../voxel/sprite/furniture/lamp_wall-2.vox | 3 + assets/voxygen/voxel/sprite/grave/grave_0.vox | 3 + assets/voxygen/voxel/sprite/grave/grave_1.vox | 3 + assets/voxygen/voxel/sprite/grave/grave_2.vox | 3 + assets/voxygen/voxel/sprite/grave/mud.vox | 3 + .../voxygen/voxel/sprite/window/window-1.vox | 4 +- assets/voxygen/voxel/sprite/wizard/candle.vox | 3 + .../voxel/sprite/wizard/magical_barrier.vox | 3 + .../voxel/sprite/wizard/magical_seal.vox | 3 + assets/voxygen/voxel/sprite_manifest.ron | 172 ++++++++++++- .../site_structures/gnarling/totem.ron | 2 +- assets/world/manifests/spots/camp_forest.ron | 20 ++ assets/world/manifests/spots/camp_pirate.ron | 15 ++ assets/world/manifests/spots/camp_snow.ron | 15 ++ assets/world/manifests/spots/gnome_spring.ron | 2 +- assets/world/manifests/spots/grave_small.ron | 16 ++ .../world/manifests/spots/jungle/outpost.ron | 13 + .../manifests/spots/jungle/saurok-altar.ron | 2 +- .../manifests/spots/jungle/saurok_totem.ron | 12 + .../manifests/spots/jungle/temple_small.ron | 12 + .../world/manifests/spots/myrmidon-temple.ron | 2 +- .../world/manifests/spots/water/shipwreck.ron | 2 +- .../manifests/spots/water/shipwreck2.ron | 2 +- .../world/manifests/spots_general/igloo.ron | 2 +- .../manifests/spots_general/mage_tower.ron | 32 +++ .../spots_general/pirate_hideout.ron | 2 +- .../manifests/spots_general/troll_cave.ron | 11 +- .../spots_general/troll_cave_mountain.ron | 16 ++ .../spots_general/troll_cave_swamp.ron | 16 ++ .../manifests/spots_general/witch_hut.ron | 6 +- .../spots_grasslands/dwarven_grave.ron | 2 +- .../world/manifests/trees/airship_crash.ron | 2 +- .../world/structure/natural/dwarven_grave.vox | 3 - assets/world/structure/natural/tree-house.vox | 3 - assets/world/structure/natural/troll_cave.vox | 4 +- assets/world/structure/natural/untitled.vox | 3 + .../structure/natural/witch-hut-black_0.vox | 3 - .../airship-crashsite_0.vox | 0 assets/world/structure/spots/camp.vox | 3 + .../world/structure/spots/dwarven_grave.vox | 3 + .../{natural => spots}/gnarling_totem.vox | 0 .../{natural => spots}/gnome_spring.vox | 0 assets/world/structure/spots/grave_small.vox | 3 + .../structure/{natural => spots}/igloo.vox | 0 .../world/structure/spots/jungle_outpost.vox | 3 + assets/world/structure/spots/mage_tower.vox | 3 + .../{natural => spots}/myrmidon-temple.vox | 0 .../{natural => spots}/pirate_hideout.vox | 0 .../{natural => spots}/saurok-altar.vox | 0 .../world/structure/spots/saurok_totem_0.vox | 3 + .../world/structure/spots/saurok_totem_1.vox | 3 + .../{natural => spots}/shipwreck.vox | 0 .../{natural => spots}/shipwreck2.vox | 0 .../world/structure/spots/temple_small_0.vox | 3 + .../world/structure/spots/temple_small_1.vox | 3 + assets/world/structure/spots/tree-house.vox | 3 + .../structure/spots/witch-hut-black_0.vox | 3 + .../{natural => spots}/witch-hut.vox | 0 common/src/comp/controller.rs | 17 +- common/src/comp/inventory/item/mod.rs | 14 +- common/src/comp/inventory/mod.rs | 8 +- common/src/outcome.rs | 10 +- common/src/states/behavior.rs | 5 +- common/src/states/sprite_interact.rs | 75 +++--- common/src/states/utils.rs | 94 +++++-- common/src/terrain/block.rs | 14 +- common/src/terrain/mod.rs | 18 +- common/src/terrain/sprite.rs | 82 ++++++- common/src/terrain/structure.rs | 18 +- common/src/volumes/vol_grid_2d.rs | 5 + common/systems/src/character_behavior.rs | 7 +- common/systems/tests/character_state.rs | 5 +- common/systems/tests/phys/utils.rs | 2 + server/src/events/inventory_manip.rs | 84 +++++-- voxygen/src/audio/sfx/mod.rs | 20 ++ voxygen/src/hud/mod.rs | 72 +++--- voxygen/src/scene/particle.rs | 12 + voxygen/src/scene/terrain.rs | 2 +- voxygen/src/scene/terrain/watcher.rs | 19 +- voxygen/src/session/interactable.rs | 8 +- voxygen/src/session/mod.rs | 35 +-- voxygen/src/session/target.rs | 3 +- world/src/block/mod.rs | 64 ++++- world/src/canvas.rs | 45 +++- world/src/layer/spot.rs | 232 +++++++++++++++++- world/src/layer/tree.rs | 14 +- world/src/site2/gen.rs | 10 +- 129 files changed, 1600 insertions(+), 250 deletions(-) create mode 100644 assets/common/entity/spot/wizard/adept.ron create mode 100644 assets/common/entity/spot/wizard/novice.ron create mode 100644 assets/common/entity/spot/wizard/overseer.ron create mode 100644 assets/common/entity/spot/wizard/spellbinder.ron create mode 100644 assets/common/entity/spot/wizard/wizard_argo.ron create mode 100644 assets/common/entity/spot/wizard/wizard_haku.ron create mode 100644 assets/common/entity/spot/wizard/wizard_trish.ron create mode 100644 assets/common/entity/village/bowman.ron create mode 100644 assets/common/entity/village/skinner.ron create mode 100644 assets/common/items/keys/rusty_tower_key.ron create mode 100644 assets/common/items/utility/lockpick_0.ron create mode 100644 assets/common/loadout/spots/wizard_tower/wizard_boss.ron create mode 100644 assets/common/loadout/spots/wizard_tower/wizard_low.ron create mode 100644 assets/common/loadout/spots/wizard_tower/wizard_novice.ron create mode 100644 assets/common/loadout/spots/wizard_tower/wizard_overseer.ron create mode 100644 assets/common/loadout/spots/wizard_tower/wizard_spellbinder.ron create mode 100644 assets/voxygen/element/items/key_rusty-0.vox create mode 100644 assets/voxygen/element/items/lockpick.vox create mode 100644 assets/voxygen/voxel/armor/velorite_battlemage/chest-0.vox create mode 100644 assets/voxygen/voxel/armor/velorite_battlemage/hand-0.vox create mode 100644 assets/voxygen/voxel/armor/velorite_battlemage/hat.vox create mode 100644 assets/voxygen/voxel/armor/velorite_battlemage/pants-0.vox create mode 100644 assets/voxygen/voxel/armor/velorite_battlemage/shoulder-0.vox delete mode 100644 assets/voxygen/voxel/armor/warlock/shoulder.vox create mode 100644 assets/voxygen/voxel/armor/warlock/spellbinder-set.vox create mode 100644 assets/voxygen/voxel/sprite/camp/camp.vox create mode 100644 assets/voxygen/voxel/sprite/camp/camp_pirate.vox create mode 100644 assets/voxygen/voxel/sprite/camp/camp_snow.vox create mode 100644 assets/voxygen/voxel/sprite/door/door_dark-0.vox create mode 100644 assets/voxygen/voxel/sprite/furniture/door_block.vox create mode 100644 assets/voxygen/voxel/sprite/furniture/keyhole_block.vox create mode 100644 assets/voxygen/voxel/sprite/furniture/lamp_wall-2.vox create mode 100644 assets/voxygen/voxel/sprite/grave/grave_0.vox create mode 100644 assets/voxygen/voxel/sprite/grave/grave_1.vox create mode 100644 assets/voxygen/voxel/sprite/grave/grave_2.vox create mode 100644 assets/voxygen/voxel/sprite/grave/mud.vox create mode 100644 assets/voxygen/voxel/sprite/wizard/candle.vox create mode 100644 assets/voxygen/voxel/sprite/wizard/magical_barrier.vox create mode 100644 assets/voxygen/voxel/sprite/wizard/magical_seal.vox create mode 100644 assets/world/manifests/spots/camp_forest.ron create mode 100644 assets/world/manifests/spots/camp_pirate.ron create mode 100644 assets/world/manifests/spots/camp_snow.ron create mode 100644 assets/world/manifests/spots/grave_small.ron create mode 100644 assets/world/manifests/spots/jungle/outpost.ron create mode 100644 assets/world/manifests/spots/jungle/saurok_totem.ron create mode 100644 assets/world/manifests/spots/jungle/temple_small.ron create mode 100644 assets/world/manifests/spots_general/mage_tower.ron create mode 100644 assets/world/manifests/spots_general/troll_cave_mountain.ron create mode 100644 assets/world/manifests/spots_general/troll_cave_swamp.ron delete mode 100644 assets/world/structure/natural/dwarven_grave.vox delete mode 100644 assets/world/structure/natural/tree-house.vox create mode 100644 assets/world/structure/natural/untitled.vox delete mode 100644 assets/world/structure/natural/witch-hut-black_0.vox rename assets/world/structure/{natural => spots}/airship-crashsite_0.vox (100%) create mode 100644 assets/world/structure/spots/camp.vox create mode 100644 assets/world/structure/spots/dwarven_grave.vox rename assets/world/structure/{natural => spots}/gnarling_totem.vox (100%) rename assets/world/structure/{natural => spots}/gnome_spring.vox (100%) create mode 100644 assets/world/structure/spots/grave_small.vox rename assets/world/structure/{natural => spots}/igloo.vox (100%) create mode 100644 assets/world/structure/spots/jungle_outpost.vox create mode 100644 assets/world/structure/spots/mage_tower.vox rename assets/world/structure/{natural => spots}/myrmidon-temple.vox (100%) rename assets/world/structure/{natural => spots}/pirate_hideout.vox (100%) rename assets/world/structure/{natural => spots}/saurok-altar.vox (100%) create mode 100644 assets/world/structure/spots/saurok_totem_0.vox create mode 100644 assets/world/structure/spots/saurok_totem_1.vox rename assets/world/structure/{natural => spots}/shipwreck.vox (100%) rename assets/world/structure/{natural => spots}/shipwreck2.vox (100%) create mode 100644 assets/world/structure/spots/temple_small_0.vox create mode 100644 assets/world/structure/spots/temple_small_1.vox create mode 100644 assets/world/structure/spots/tree-house.vox create mode 100644 assets/world/structure/spots/witch-hut-black_0.vox rename assets/world/structure/{natural => spots}/witch-hut.vox (100%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 092fe00733..f2deec77f2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Suggests commands when an invalid one is entered in chat and added Client-side commands to /help. - Moderator badge in the chat. - More aggressive scene culling based on camera position to improve performance. +- Some chests requiring lockpicks or keys. +- Unlockable door blocks. +- Sprite rotation for Spots. +- Better entity placement options for spots. ### Changed - Bats move slower and use a simple proportional controller to maintain altitude diff --git a/assets/common/entity/spot/wizard/adept.ron b/assets/common/entity/spot/wizard/adept.ron new file mode 100644 index 0000000000..e381070f47 --- /dev/null +++ b/assets/common/entity/spot/wizard/adept.ron @@ -0,0 +1,20 @@ +#![enable(implicit_some)] +( + name: Name("Adept"), + body: RandomWith("humanoid"), + alignment: Alignment(Npc), + loot: LootTable("common.loot_tables.dungeon.tier-5.enemy"), + inventory: ( + loadout: Inline(( + inherit: Asset("common.loadout.spots.wizard_tower.wizard_low"), + active_hands: InHands((Choice([ + (2, ModularWeapon(tool: Axe, material: Orichalcum, hands: One)), + (2, ModularWeapon(tool: Hammer, material: Orichalcum, hands: One)), + + ]), None)), + )), + ), + meta: [ + SkillSetAsset("common.skillset.preset.rank5.fullskill"), + ], +) \ No newline at end of file diff --git a/assets/common/entity/spot/wizard/novice.ron b/assets/common/entity/spot/wizard/novice.ron new file mode 100644 index 0000000000..adedb21330 --- /dev/null +++ b/assets/common/entity/spot/wizard/novice.ron @@ -0,0 +1,19 @@ +#![enable(implicit_some)] +( + name: Name("Novice"), + body: RandomWith("humanoid"), + alignment: Alignment(Npc), + loot: LootTable("common.loot_tables.dungeon.tier-5.enemy"), + inventory: ( + loadout: Inline(( + inherit: Asset("common.loadout.spots.wizard_tower.wizard_low"), + active_hands: InHands((Choice([ + (2, Item("common.items.weapons.staff.cultist_staff")), + (1, Item("common.items.weapons.sceptre.sceptre_velorite_0")), + ]), None)), + )), + ), + meta: [ + SkillSetAsset("common.skillset.preset.rank5.fullskill"), + ], +) \ No newline at end of file diff --git a/assets/common/entity/spot/wizard/overseer.ron b/assets/common/entity/spot/wizard/overseer.ron new file mode 100644 index 0000000000..fddf3a1e70 --- /dev/null +++ b/assets/common/entity/spot/wizard/overseer.ron @@ -0,0 +1,17 @@ +#![enable(implicit_some)] +( + name: Name("Overseer"), + body: RandomWith("cultist_warlock"), + alignment: Alignment(Enemy), + loot: LootTable("common.loot_tables.dungeon.tier-5.enemy"), + inventory: ( + loadout: Inline(( + inherit: Asset("common.loadout.spots.wizard_tower.wizard_overseer"), + active_hands: InHands((Choice([ + (1, Item("common.items.npc_weapons.staff.bipedlarge-cultist")), + (1, Item("common.items.npc_weapons.bow.bipedlarge-velorite")), + ]), None)), + )), + ), + meta: [], +) \ No newline at end of file diff --git a/assets/common/entity/spot/wizard/spellbinder.ron b/assets/common/entity/spot/wizard/spellbinder.ron new file mode 100644 index 0000000000..fafac7eb4c --- /dev/null +++ b/assets/common/entity/spot/wizard/spellbinder.ron @@ -0,0 +1,17 @@ +#![enable(implicit_some)] +( + name: Name("Overseer"), + body: RandomWith("cultist_warlock"), + alignment: Alignment(Enemy), + loot: LootTable("common.loot_tables.dungeon.tier-5.enemy"), + inventory: ( + loadout: Inline(( + inherit: Asset("common.loadout.spots.wizard_tower.wizard_spellbinder"), + active_hands: InHands((Choice([ + (1, Item("common.items.npc_weapons.staff.bipedlarge-cultist")), + (1, Item("common.items.npc_weapons.bow.bipedlarge-velorite")), + ]), None)), + )), + ), + meta: [], +) \ No newline at end of file diff --git a/assets/common/entity/spot/wizard/wizard_argo.ron b/assets/common/entity/spot/wizard/wizard_argo.ron new file mode 100644 index 0000000000..1838aaa191 --- /dev/null +++ b/assets/common/entity/spot/wizard/wizard_argo.ron @@ -0,0 +1,19 @@ +#![enable(implicit_some)] + +( + name: Name("Argo"), + body: RandomWith("humanoid"), + alignment: Alignment(Npc), + loot: LootTable("common.loot_tables.dungeon.tier-5.miniboss"), + inventory: ( + loadout: Inline(( + inherit: Asset("common.loadout.spots.wizard_tower.wizard_boss"), + active_hands: InHands((Choice([ + (1, Item("common.items.weapons.sceptre.sceptre_velorite_0")), + ]), None)), + )), + ), + meta: [ + SkillSetAsset("common.skillset.preset.rank5.fullskill"), + ], +) \ No newline at end of file diff --git a/assets/common/entity/spot/wizard/wizard_haku.ron b/assets/common/entity/spot/wizard/wizard_haku.ron new file mode 100644 index 0000000000..88cfd6e535 --- /dev/null +++ b/assets/common/entity/spot/wizard/wizard_haku.ron @@ -0,0 +1,19 @@ +#![enable(implicit_some)] + +( + name: Name("Haku"), + body: RandomWith("humanoid"), + alignment: Alignment(Npc), + loot: LootTable("common.loot_tables.dungeon.tier-5.miniboss"), + inventory: ( + loadout: Inline(( + inherit: Asset("common.loadout.spots.wizard_tower.wizard_boss"), + active_hands: InHands((Choice([ + (1, Item("common.items.weapons.sceptre.sceptre_velorite_0")), + ]), None)), + )), + ), + meta: [ + SkillSetAsset("common.skillset.preset.rank5.fullskill"), + ], +) \ No newline at end of file diff --git a/assets/common/entity/spot/wizard/wizard_trish.ron b/assets/common/entity/spot/wizard/wizard_trish.ron new file mode 100644 index 0000000000..969a1f881c --- /dev/null +++ b/assets/common/entity/spot/wizard/wizard_trish.ron @@ -0,0 +1,19 @@ +#![enable(implicit_some)] + +( + name: Name("Trish"), + body: RandomWith("humanoid"), + alignment: Alignment(Npc), + loot: LootTable("common.loot_tables.dungeon.tier-5.miniboss"), + inventory: ( + loadout: Inline(( + inherit: Asset("common.loadout.spots.wizard_tower.wizard_boss"), + active_hands: InHands((Choice([ + (1, Item("common.items.weapons.sceptre.sceptre_velorite_0")), + ]), None)), + )), + ), + meta: [ + SkillSetAsset("common.skillset.preset.rank5.fullskill"), + ], +) \ No newline at end of file diff --git a/assets/common/entity/village/bowman.ron b/assets/common/entity/village/bowman.ron new file mode 100644 index 0000000000..cf7e634f5d --- /dev/null +++ b/assets/common/entity/village/bowman.ron @@ -0,0 +1,25 @@ +#![enable(implicit_some)] +( + name: Name("Bowman"), + body: RandomWith("humanoid"), + alignment: Alignment(Npc), + loot: LootTable("common.loot_tables.creature.humanoid"), + inventory: ( + loadout: Inline(( + inherit: Choice([ + (1, Asset("common.loadout.world.traveler1.leather")), + (1, Asset("common.loadout.world.traveler2.carapace")), + (1, Asset("common.loadout.world.traveler2.scale")), + ]), + active_hands: InHands((Choice([ + (1, ModularWeapon(tool: Bow, material: Ironwood, hands: None)), + + ]), None)), + )), + items: [ + (10, "common.items.consumable.potion_big"), + (10, "common.items.food.sunflower_icetea"), + ], + ), + meta: [], +) diff --git a/assets/common/entity/village/skinner.ron b/assets/common/entity/village/skinner.ron new file mode 100644 index 0000000000..c6f8c72112 --- /dev/null +++ b/assets/common/entity/village/skinner.ron @@ -0,0 +1,25 @@ +#![enable(implicit_some)] +( + name: Name("Skinner"), + body: RandomWith("humanoid"), + alignment: Alignment(Npc), + loot: LootTable("common.loot_tables.creature.humanoid"), + inventory: ( + loadout: Inline(( + inherit: Choice([ + (1, Asset("common.loadout.world.traveler1.leather")), + (1, Asset("common.loadout.world.traveler2.carapace")), + (1, Asset("common.loadout.world.traveler2.scale")), + ]), + active_hands: InHands((Choice([ + (1, ModularWeapon(tool: Axe, material: Cobalt, hands: None)), + + ]), None)), + )), + items: [ + (10, "common.items.consumable.potion_big"), + (10, "common.items.food.sunflower_icetea"), + ], + ), + meta: [], +) diff --git a/assets/common/items/keys/rusty_tower_key.ron b/assets/common/items/keys/rusty_tower_key.ron new file mode 100644 index 0000000000..eed77d8c32 --- /dev/null +++ b/assets/common/items/keys/rusty_tower_key.ron @@ -0,0 +1,11 @@ +ItemDef( + name: "Rusty Tower Key", + description: "Smells like magic with a bit of... cheese?", + kind: Utility( + kind: Key, + ), + amount: 1, + quality: Epic, + tags: [], +) + diff --git a/assets/common/items/utility/lockpick_0.ron b/assets/common/items/utility/lockpick_0.ron new file mode 100644 index 0000000000..3a6294113f --- /dev/null +++ b/assets/common/items/utility/lockpick_0.ron @@ -0,0 +1,11 @@ +ItemDef( + name: "Common Lockpick", + description: "Used to open common locks. Will break after use.", + kind: Utility( + kind: Key, + ), + amount: 1, + quality: Common, + tags: [Utility], +) + diff --git a/assets/common/loadout/spots/wizard_tower/wizard_boss.ron b/assets/common/loadout/spots/wizard_tower/wizard_boss.ron new file mode 100644 index 0000000000..cb219cbd98 --- /dev/null +++ b/assets/common/loadout/spots/wizard_tower/wizard_boss.ron @@ -0,0 +1,19 @@ +#![enable(implicit_some)] +( + head: Choice([ + (2, None), + (1, Item("common.items.armor.misc.head.hood")), + (1, Item("common.items.armor.misc.head.hood_dark")), + ]), + shoulders: Item("common.items.armor.velorite_mage.shoulder"), + back: Item("common.items.armor.velorite_mage.back"), + chest: Item("common.items.armor.velorite_mage.chest"), + gloves: Item("common.items.armor.velorite_mage.hand"), + belt: Item("common.items.armor.velorite_mage.belt"), + legs: Item("common.items.armor.velorite_mage.pants"), + feet: Item("common.items.armor.velorite_mage.foot"), + lantern: Choice([ + (1, Item("common.items.lantern.geode_purp")), + (2, None), + ]), +) \ No newline at end of file diff --git a/assets/common/loadout/spots/wizard_tower/wizard_low.ron b/assets/common/loadout/spots/wizard_tower/wizard_low.ron new file mode 100644 index 0000000000..cb219cbd98 --- /dev/null +++ b/assets/common/loadout/spots/wizard_tower/wizard_low.ron @@ -0,0 +1,19 @@ +#![enable(implicit_some)] +( + head: Choice([ + (2, None), + (1, Item("common.items.armor.misc.head.hood")), + (1, Item("common.items.armor.misc.head.hood_dark")), + ]), + shoulders: Item("common.items.armor.velorite_mage.shoulder"), + back: Item("common.items.armor.velorite_mage.back"), + chest: Item("common.items.armor.velorite_mage.chest"), + gloves: Item("common.items.armor.velorite_mage.hand"), + belt: Item("common.items.armor.velorite_mage.belt"), + legs: Item("common.items.armor.velorite_mage.pants"), + feet: Item("common.items.armor.velorite_mage.foot"), + lantern: Choice([ + (1, Item("common.items.lantern.geode_purp")), + (2, None), + ]), +) \ No newline at end of file diff --git a/assets/common/loadout/spots/wizard_tower/wizard_novice.ron b/assets/common/loadout/spots/wizard_tower/wizard_novice.ron new file mode 100644 index 0000000000..cb219cbd98 --- /dev/null +++ b/assets/common/loadout/spots/wizard_tower/wizard_novice.ron @@ -0,0 +1,19 @@ +#![enable(implicit_some)] +( + head: Choice([ + (2, None), + (1, Item("common.items.armor.misc.head.hood")), + (1, Item("common.items.armor.misc.head.hood_dark")), + ]), + shoulders: Item("common.items.armor.velorite_mage.shoulder"), + back: Item("common.items.armor.velorite_mage.back"), + chest: Item("common.items.armor.velorite_mage.chest"), + gloves: Item("common.items.armor.velorite_mage.hand"), + belt: Item("common.items.armor.velorite_mage.belt"), + legs: Item("common.items.armor.velorite_mage.pants"), + feet: Item("common.items.armor.velorite_mage.foot"), + lantern: Choice([ + (1, Item("common.items.lantern.geode_purp")), + (2, None), + ]), +) \ No newline at end of file diff --git a/assets/common/loadout/spots/wizard_tower/wizard_overseer.ron b/assets/common/loadout/spots/wizard_tower/wizard_overseer.ron new file mode 100644 index 0000000000..cb219cbd98 --- /dev/null +++ b/assets/common/loadout/spots/wizard_tower/wizard_overseer.ron @@ -0,0 +1,19 @@ +#![enable(implicit_some)] +( + head: Choice([ + (2, None), + (1, Item("common.items.armor.misc.head.hood")), + (1, Item("common.items.armor.misc.head.hood_dark")), + ]), + shoulders: Item("common.items.armor.velorite_mage.shoulder"), + back: Item("common.items.armor.velorite_mage.back"), + chest: Item("common.items.armor.velorite_mage.chest"), + gloves: Item("common.items.armor.velorite_mage.hand"), + belt: Item("common.items.armor.velorite_mage.belt"), + legs: Item("common.items.armor.velorite_mage.pants"), + feet: Item("common.items.armor.velorite_mage.foot"), + lantern: Choice([ + (1, Item("common.items.lantern.geode_purp")), + (2, None), + ]), +) \ No newline at end of file diff --git a/assets/common/loadout/spots/wizard_tower/wizard_spellbinder.ron b/assets/common/loadout/spots/wizard_tower/wizard_spellbinder.ron new file mode 100644 index 0000000000..cb219cbd98 --- /dev/null +++ b/assets/common/loadout/spots/wizard_tower/wizard_spellbinder.ron @@ -0,0 +1,19 @@ +#![enable(implicit_some)] +( + head: Choice([ + (2, None), + (1, Item("common.items.armor.misc.head.hood")), + (1, Item("common.items.armor.misc.head.hood_dark")), + ]), + shoulders: Item("common.items.armor.velorite_mage.shoulder"), + back: Item("common.items.armor.velorite_mage.back"), + chest: Item("common.items.armor.velorite_mage.chest"), + gloves: Item("common.items.armor.velorite_mage.hand"), + belt: Item("common.items.armor.velorite_mage.belt"), + legs: Item("common.items.armor.velorite_mage.pants"), + feet: Item("common.items.armor.velorite_mage.foot"), + lantern: Choice([ + (1, Item("common.items.lantern.geode_purp")), + (2, None), + ]), +) \ No newline at end of file diff --git a/assets/common/recipe_book.ron b/assets/common/recipe_book.ron index f775e50f90..04b662e43d 100644 --- a/assets/common/recipe_book.ron +++ b/assets/common/recipe_book.ron @@ -2197,4 +2197,12 @@ craft_sprite: Some(CraftingBench), is_recycling: false, ), + "lockpick": ( + output: ("common.items.utility.lockpick_0", 10), + inputs: [ + (Item("common.items.mineral.ingot.copper"), 3, false), + (Item("common.items.tool.craftsman_hammer"), 0, false), + ], + craft_sprite: Some(CraftingBench), + ), } diff --git a/assets/voxygen/background/bg_12.jpg b/assets/voxygen/background/bg_12.jpg index 6cc50a49e3..063e7cc158 100644 --- a/assets/voxygen/background/bg_12.jpg +++ b/assets/voxygen/background/bg_12.jpg @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:265d50fd4dc7603c17d82025aa2268f7f3cd12c4b2f53f63b5d7381c54485c6e -size 176886 +oid sha256:98c74062ae262d4aefe5dbbf51c8c71f04dabb0dc3b7a490c80a35d8b5ce3d86 +size 929463 diff --git a/assets/voxygen/background/bg_13.jpg b/assets/voxygen/background/bg_13.jpg index 6c382beb33..5d3e3f4201 100644 --- a/assets/voxygen/background/bg_13.jpg +++ b/assets/voxygen/background/bg_13.jpg @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e6e1994598f4924d57de68daaf0a47a819eff64b019b81a517bfe5e6e73ce118 -size 438566 +oid sha256:1789125f606a8b2b05853e951bbfca902b3eab344ed930e693b64ad46e20f896 +size 1262921 diff --git a/assets/voxygen/background/bg_2.jpg b/assets/voxygen/background/bg_2.jpg index 87a1055aa7..0a783293cf 100644 --- a/assets/voxygen/background/bg_2.jpg +++ b/assets/voxygen/background/bg_2.jpg @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:dd22d7418e96bbaf0692a1fc7da3d086d57744345c3382643ad339896b7d935b -size 445849 +oid sha256:2d8c47e8ee020b8434d1790c105aa94ee0147de5ee769d47696c6e5ec242aa60 +size 1154067 diff --git a/assets/voxygen/background/bg_7.jpg b/assets/voxygen/background/bg_7.jpg index 386c1d6d1b..b957eefe8e 100644 --- a/assets/voxygen/background/bg_7.jpg +++ b/assets/voxygen/background/bg_7.jpg @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5af3bfd4d4f5232043ac8d5e826c8a1615cbba51248d1b79caacca830efa283a -size 273010 +oid sha256:a8c55dab8c81342a5f026e7754a3ded9a837696c9226b2079bb5bc7b3f865a26 +size 755373 diff --git a/assets/voxygen/element/items/key_rusty-0.vox b/assets/voxygen/element/items/key_rusty-0.vox new file mode 100644 index 0000000000..edcf880bab --- /dev/null +++ b/assets/voxygen/element/items/key_rusty-0.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f1d211a3a95ed00db697cd86d0f6fb1df152798d80b7c3be686ea766c484e192 +size 22630 diff --git a/assets/voxygen/element/items/lockpick.vox b/assets/voxygen/element/items/lockpick.vox new file mode 100644 index 0000000000..ddf8bb8e2e --- /dev/null +++ b/assets/voxygen/element/items/lockpick.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:96892bc35e0b2e06966eb0f12a0f4da99e82d230fc2ccb445826e8f09ad8733f +size 22598 diff --git a/assets/voxygen/i18n/en/hud/misc.ftl b/assets/voxygen/i18n/en/hud/misc.ftl index 6511d5b878..ef5d48c584 100644 --- a/assets/voxygen/i18n/en/hud/misc.ftl +++ b/assets/voxygen/i18n/en/hud/misc.ftl @@ -20,15 +20,15 @@ hud-tutorial_elements = Crafting hud-temp_quest_headline = Greetings Traveller! hud-temp_quest_text = To begin your journey you could start looking through this village and gather some supplies. - + You are welcome to take whatever you need on your journey! - + Look at the bottom right of the screen to find various things like your bag, the crafting menu and the map. - + The crafting stations allow you to create armor, weapons, food and much more! - + The wild animals all around town are a great source of Animal Hide to create some protection against the dangers of the world. - + Whenever you feel ready, try to get even better equipment from the many challenges marked on your map! hud-spell = Spells hud-diary = Diary @@ -39,8 +39,10 @@ hud-collect = Collect hud-pick_up = Pick up hud-open = Open hud-use = Use +hud-unlock-requires = Open with { $item } +hud-unlock-consumes = Use { $item } to open hud-mine = Mine hud-talk = Talk hud-trade = Trade hud-mount = Mount -hud-sit = Sit \ No newline at end of file +hud-sit = Sit diff --git a/assets/voxygen/i18n/en/main.ftl b/assets/voxygen/i18n/en/main.ftl index 84ae49843d..e3eb4d30a1 100644 --- a/assets/voxygen/i18n/en/main.ftl +++ b/assets/voxygen/i18n/en/main.ftl @@ -92,4 +92,4 @@ loading-tips = .a18 = Need more bags or better armor to continue your journey? Press '{ $gameinput-crafting }' to open the crafting menu! .a19 = Press '{ $gameinput-roll }' to roll. Rolling can be used to move faster and dodge enemy attacks. .a20 = Wondering what an item is used for? Search 'input:' in crafting to see what recipes it's used in. - .a21 = Find something cool? Take a screenshot of it with '{ $gameinput-screenshot }'. \ No newline at end of file + .a21 = You can take screenshots with '{ $gameinput-screenshot }'. \ No newline at end of file diff --git a/assets/voxygen/item_image_manifest.ron b/assets/voxygen/item_image_manifest.ron index 59d61f494d..81ca68ff4f 100644 --- a/assets/voxygen/item_image_manifest.ron +++ b/assets/voxygen/item_image_manifest.ron @@ -4820,4 +4820,14 @@ "voxel.weapon.component.sceptre.core.light", (0.0, 0.0, 0.0), (-100.0, 250.0, 15.0), 0.7, ), + // Keys + Simple("common.items.keys.rusty_tower_key"): VoxTrans( + "element.items.key_rusty-0", + (0.0, 0.0, 0.0), (-100.0, 250.0, 15.0), 1.0, + ), + // Lockpicks + Simple("common.items.utility.lockpick_0"): VoxTrans( + "element.items.lockpick", + (0.0, 0.0, 0.0), (-100.0, 250.0, 15.0), 1.0, + ), }) diff --git a/assets/voxygen/voxel/armor/velorite_battlemage/chest-0.vox b/assets/voxygen/voxel/armor/velorite_battlemage/chest-0.vox new file mode 100644 index 0000000000..07a18bacbb --- /dev/null +++ b/assets/voxygen/voxel/armor/velorite_battlemage/chest-0.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:59f73d9ece6ddde25a8920a98c538109b482ece75a69a3d606f7a392d483d3e7 +size 2816 diff --git a/assets/voxygen/voxel/armor/velorite_battlemage/hand-0.vox b/assets/voxygen/voxel/armor/velorite_battlemage/hand-0.vox new file mode 100644 index 0000000000..6057816a13 --- /dev/null +++ b/assets/voxygen/voxel/armor/velorite_battlemage/hand-0.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a3f884ba5a46887571834c770f765e5084dd536cccb298c34e9ea8731e7af145 +size 44355 diff --git a/assets/voxygen/voxel/armor/velorite_battlemage/hat.vox b/assets/voxygen/voxel/armor/velorite_battlemage/hat.vox new file mode 100644 index 0000000000..e9aaea3951 --- /dev/null +++ b/assets/voxygen/voxel/armor/velorite_battlemage/hat.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0deb47aa93186071a8a83b6626f5a4a595b53ab828117a5099585dc0c9f7e990 +size 21032 diff --git a/assets/voxygen/voxel/armor/velorite_battlemage/pants-0.vox b/assets/voxygen/voxel/armor/velorite_battlemage/pants-0.vox new file mode 100644 index 0000000000..189ad17baf --- /dev/null +++ b/assets/voxygen/voxel/armor/velorite_battlemage/pants-0.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:971e4f24b01b2e61fe636d6e0cc5e4d03f796e8778d236125542df76a59f4632 +size 45363 diff --git a/assets/voxygen/voxel/armor/velorite_battlemage/shoulder-0.vox b/assets/voxygen/voxel/armor/velorite_battlemage/shoulder-0.vox new file mode 100644 index 0000000000..c99f8768f9 --- /dev/null +++ b/assets/voxygen/voxel/armor/velorite_battlemage/shoulder-0.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7c9917d441376540d9615da2ca16a8dae7236f807ef89c170ef8397ebe94b8c4 +size 1564 diff --git a/assets/voxygen/voxel/armor/warlock/shoulder.vox b/assets/voxygen/voxel/armor/warlock/shoulder.vox deleted file mode 100644 index 1b99ab2ebe..0000000000 --- a/assets/voxygen/voxel/armor/warlock/shoulder.vox +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:fd195cdd8de946cf0042fd7795463070927edc02d58dfa0feaaa7ee10bd63850 -size 1564 diff --git a/assets/voxygen/voxel/armor/warlock/spellbinder-set.vox b/assets/voxygen/voxel/armor/warlock/spellbinder-set.vox new file mode 100644 index 0000000000..59f4c956ce --- /dev/null +++ b/assets/voxygen/voxel/armor/warlock/spellbinder-set.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:317fd2b0bb9850bc37f5f68ace68395e9015c808a08895ea59cfae51cea2263b +size 54107 diff --git a/assets/voxygen/voxel/item_drop_manifest.ron b/assets/voxygen/voxel/item_drop_manifest.ron index 9e9e24d786..e7ecee284c 100644 --- a/assets/voxygen/voxel/item_drop_manifest.ron +++ b/assets/voxygen/voxel/item_drop_manifest.ron @@ -919,6 +919,9 @@ Simple("common.items.log.hardwood"): "voxel.sprite.wood.item.hardwood", Simple("common.items.log.ironwood"): "voxel.sprite.wood.item.ironwood", Simple("common.items.log.wood"): "voxel.sprite.wood.item.wood", + // Keys and Lockpicks + Simple("common.items.keys.rusty_tower_key"): "element.items.key_rusty-0", + Simple("common.items.utility.lockpick_0"): "element.items.lockpick", // Gliders Simple("common.items.glider.cloverleaf"): "voxel.glider.starter", Simple("common.items.glider.basic_white"): "voxel.glider.basic_white", diff --git a/assets/voxygen/voxel/object/tent.vox b/assets/voxygen/voxel/object/tent.vox index 309ec9e4ff..2e6548ef80 100644 --- a/assets/voxygen/voxel/object/tent.vox +++ b/assets/voxygen/voxel/object/tent.vox @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:61b3234033b22364675297c9064eb61b2fc796a4d05e3154ae95fa744d25d0d2 -size 11248 +oid sha256:3db49adf0f6e5a413697de65022540e64706338cc83d0f38e39919214b440e09 +size 29592 diff --git a/assets/voxygen/voxel/sprite/camp/camp.vox b/assets/voxygen/voxel/sprite/camp/camp.vox new file mode 100644 index 0000000000..33eec72403 --- /dev/null +++ b/assets/voxygen/voxel/sprite/camp/camp.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d356f7f76580f67ab7badab5e03298dc82103463ed7867083ddb07efa7d1788f +size 6304 diff --git a/assets/voxygen/voxel/sprite/camp/camp_pirate.vox b/assets/voxygen/voxel/sprite/camp/camp_pirate.vox new file mode 100644 index 0000000000..0654cf1176 --- /dev/null +++ b/assets/voxygen/voxel/sprite/camp/camp_pirate.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8760c78d8a37f773072755633d546dc0d94840f3e6c0b05e867f6aece35888b4 +size 5608 diff --git a/assets/voxygen/voxel/sprite/camp/camp_snow.vox b/assets/voxygen/voxel/sprite/camp/camp_snow.vox new file mode 100644 index 0000000000..64324b6a4e --- /dev/null +++ b/assets/voxygen/voxel/sprite/camp/camp_snow.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:aa62610f9f620eefcbf781fd29789303e2bd85ba826114d0f2bf1a087d00cb28 +size 9072 diff --git a/assets/voxygen/voxel/sprite/door/door_dark-0.vox b/assets/voxygen/voxel/sprite/door/door_dark-0.vox new file mode 100644 index 0000000000..26650e6747 --- /dev/null +++ b/assets/voxygen/voxel/sprite/door/door_dark-0.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:54846fa7655881c6a125a136cc888de8736e939cea6f1e8ce1f041da4b0212de +size 5980 diff --git a/assets/voxygen/voxel/sprite/furniture/door_block.vox b/assets/voxygen/voxel/sprite/furniture/door_block.vox new file mode 100644 index 0000000000..384763e295 --- /dev/null +++ b/assets/voxygen/voxel/sprite/furniture/door_block.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f488f91f63aa9855b7189b520af0e8e24f12127db97e9035191242cea1f092a1 +size 30102 diff --git a/assets/voxygen/voxel/sprite/furniture/keyhole_block.vox b/assets/voxygen/voxel/sprite/furniture/keyhole_block.vox new file mode 100644 index 0000000000..5c64d38c33 --- /dev/null +++ b/assets/voxygen/voxel/sprite/furniture/keyhole_block.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d0d5ac3ab75ab91c4b522dd40444b6f3a44d4b277de41e0c55809562036df858 +size 4384 diff --git a/assets/voxygen/voxel/sprite/furniture/lamp_wall-2.vox b/assets/voxygen/voxel/sprite/furniture/lamp_wall-2.vox new file mode 100644 index 0000000000..a6d1e74b58 --- /dev/null +++ b/assets/voxygen/voxel/sprite/furniture/lamp_wall-2.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ffb45760a029b1018f79a85c58aa33498c342d60180dbada744b6c42669aa6f8 +size 25706 diff --git a/assets/voxygen/voxel/sprite/grave/grave_0.vox b/assets/voxygen/voxel/sprite/grave/grave_0.vox new file mode 100644 index 0000000000..e8847ea351 --- /dev/null +++ b/assets/voxygen/voxel/sprite/grave/grave_0.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c74c489c9392cb2f9255d7076141f6eff19b379aa670966e6edbce86d8b2d173 +size 28094 diff --git a/assets/voxygen/voxel/sprite/grave/grave_1.vox b/assets/voxygen/voxel/sprite/grave/grave_1.vox new file mode 100644 index 0000000000..03753a0f92 --- /dev/null +++ b/assets/voxygen/voxel/sprite/grave/grave_1.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:802eabec8646220167c21edb4de7b9b73409eddab1137e19595542954c2f73d0 +size 28954 diff --git a/assets/voxygen/voxel/sprite/grave/grave_2.vox b/assets/voxygen/voxel/sprite/grave/grave_2.vox new file mode 100644 index 0000000000..7d93662647 --- /dev/null +++ b/assets/voxygen/voxel/sprite/grave/grave_2.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3ac2456b83d4120b0fbbb5d690a2a2c6f2abaa4508d3ac90a7d1a7d34088b5c7 +size 29122 diff --git a/assets/voxygen/voxel/sprite/grave/mud.vox b/assets/voxygen/voxel/sprite/grave/mud.vox new file mode 100644 index 0000000000..a1efc01e36 --- /dev/null +++ b/assets/voxygen/voxel/sprite/grave/mud.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b4768b1a1ff7d286dbe49604ce9c2c7b43199167ce72e4e81a22e9d440711aca +size 30494 diff --git a/assets/voxygen/voxel/sprite/window/window-1.vox b/assets/voxygen/voxel/sprite/window/window-1.vox index 24e3d6877f..5f7ff52652 100644 --- a/assets/voxygen/voxel/sprite/window/window-1.vox +++ b/assets/voxygen/voxel/sprite/window/window-1.vox @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e4beef6bee7cfdef4f41336775cdaac73376a8edc40a0e22bfb3e8d620fb9f49 -size 1544 +oid sha256:4ba64740cc122f55cc7fc8d79f2677debb45ce7b6059e3b46c8cf1d630cf1866 +size 30446 diff --git a/assets/voxygen/voxel/sprite/wizard/candle.vox b/assets/voxygen/voxel/sprite/wizard/candle.vox new file mode 100644 index 0000000000..75972ef21c --- /dev/null +++ b/assets/voxygen/voxel/sprite/wizard/candle.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:30b62d31e6f8ed643f637c615cb5302e29601476d5dc9e992ed90e55663903d9 +size 1320 diff --git a/assets/voxygen/voxel/sprite/wizard/magical_barrier.vox b/assets/voxygen/voxel/sprite/wizard/magical_barrier.vox new file mode 100644 index 0000000000..04f0f0665e --- /dev/null +++ b/assets/voxygen/voxel/sprite/wizard/magical_barrier.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:de837935f9ca58674583c882d221fac1c7c902f4a61675e400d385b352300732 +size 36115 diff --git a/assets/voxygen/voxel/sprite/wizard/magical_seal.vox b/assets/voxygen/voxel/sprite/wizard/magical_seal.vox new file mode 100644 index 0000000000..73e584d72e --- /dev/null +++ b/assets/voxygen/voxel/sprite/wizard/magical_seal.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2c415858825db09d4df669bfcb222c52fde3427eeafe7b651c17296ea5f5f80d +size 4528 diff --git a/assets/voxygen/voxel/sprite_manifest.ron b/assets/voxygen/voxel/sprite_manifest.ron index f7e1fb3307..5d5e61aa0c 100644 --- a/assets/voxygen/voxel/sprite_manifest.ron +++ b/assets/voxygen/voxel/sprite_manifest.ron @@ -784,12 +784,7 @@ Chest: Some(( model: "voxygen.voxel.sprite.chests.chest", offset: (-7.0, -5.0, -0.0), lod_axes: (1.0, 1.0, 1.0), - ), - ( - model: "voxygen.voxel.sprite.chests.chest_gold", - offset: (-7.0, -5.0, -0.0), - lod_axes: (1.0, 1.0, 1.0), - ), + ), ( model: "voxygen.voxel.sprite.chests.chest_dark", offset: (-7.0, -5.0, -0.0), @@ -803,6 +798,17 @@ Chest: Some(( ], wind_sway: 0.0, )), +CommonLockedChest: Some(( + variations: [ + ( + model: "voxygen.voxel.sprite.chests.chest_gold", + offset: (-7.0, -5.0, -0.0), + lod_axes: (1.0, 1.0, 1.0), + ), + + ], + wind_sway: 0.0, +)), // Dungeon Chests DungeonChest0: Some(( variations: [ @@ -1889,6 +1895,7 @@ StreetLampTall: Some(( wind_sway: 0.0, )), // Door +// To make doors swing add them in voxygen\src\scene\terrain L. 333 Door: Some(( variations: [ ( @@ -1899,6 +1906,16 @@ Door: Some(( ], wind_sway: 0.0, )), +DoorDark: Some(( + variations: [ + ( + model: "voxygen.voxel.sprite.door.door_dark-0", + offset: (-5.5, -5.5, 0.0), + lod_axes: (1.0, 1.0, 1.0), + ), + ], + wind_sway: 0.0, +)), // Bed Bed: Some(( variations: [ @@ -2162,6 +2179,16 @@ WallLampSmall: Some(( ], wind_sway: 0.0, )), +WallLampWizard: Some(( + variations: [ + ( + model: "voxygen.voxel.sprite.furniture.lamp_wall-2", + offset: (-5.5, -5.5, 0.0), + lod_axes: (1.0, 1.0, 1.0), + ), + ], + wind_sway: 0.0, +)), ChristmasOrnament: Some(( variations: [ ( @@ -2566,6 +2593,16 @@ PotionMinor: Some(( ], wind_sway: 0.0, )), +PotionDummy: Some(( + variations: [ + ( + model: "voxygen.voxel.object.potion_green", + offset: (-5.0, -5.0, 0.0), + lod_axes: (1.0, 1.0, 1.0), + ), +], + wind_sway: 0.0, +)), // Ground Fire Bowls FireBowlGround: Some(( variations: [ @@ -3784,6 +3821,26 @@ WitchWindow: Some(( ], wind_sway: 0.0, )), +Keyhole: Some(( + variations: [ + ( + model: "voxygen.voxel.sprite.furniture.keyhole_block", + offset: (-5.5, -5.5, 0.0), + lod_axes: (0.5, 0.5, 0.5), + ), + ], + wind_sway: 0.0, +)), +KeyDoor: Some(( + variations: [ + ( + model: "voxygen.voxel.sprite.furniture.door_block", + offset: (-5.5, -5.5, 0.0), + lod_axes: (0.5, 0.5, 0.5), + ), + ], + wind_sway: 0.0, +)), // Bones Bones: Some(( variations: [ @@ -4118,4 +4175,107 @@ Eldwood: Some(( ], wind_sway: 0.0, )), +// Bedrolls +Bedroll: Some(( + variations: [ + ( + model: "voxygen.voxel.sprite.camp.camp", + offset: (-8.0, -16.0, 0.0), + lod_axes: (0.0, 0.0, 0.0), + ), + ], + wind_sway: 0.0, +)), +Tent: Some(( + variations: [ + ( + model: "voxygen.voxel.object.tent", + offset: (-7.5, -15.5, 0.0), + lod_axes: (0.0, 0.0, 0.0), + ), + ], + wind_sway: 0.0, +)), +BedrollSnow: Some(( + variations: [ + ( + model: "voxygen.voxel.sprite.camp.camp_snow", + offset: (-8.0, -16.0, 0.0), + lod_axes: (0.0, 0.0, 0.0), + ), + ], + wind_sway: 0.0, +)), +BedrollPirate: Some(( + variations: [ + ( + model: "voxygen.voxel.sprite.camp.camp_pirate", + offset: (-8.0, -16.0, 0.0), + lod_axes: (0.0, 0.0, 0.0), + ), + ], + wind_sway: 0.0, +)), +// Graves +Grave: Some(( + variations: [ + ( + model: "voxygen.voxel.sprite.grave.mud", + offset: (-6.0, -7.0, 0.0), + lod_axes: (0.0, 0.0, 0.0), + ), + ], + wind_sway: 0.0, +)), +Gravestone: Some(( + variations: [ + ( + model: "voxygen.voxel.sprite.grave.grave_0", + offset: (1.0, -6.0, 0.0), + lod_axes: (0.0, 0.0, 0.0), + ), + ( + model: "voxygen.voxel.sprite.grave.grave_1", + offset: (1.0, -6.0, 0.0), + lod_axes: (0.0, 0.0, 0.0), + ), + ( + model: "voxygen.voxel.sprite.grave.grave_2", + offset: (1.0, -6.0, 0.0), + lod_axes: (0.0, 0.0, 0.0), + ), + ], + wind_sway: 0.0, +)), +// Wizard assets +MagicalBarrier: Some(( + variations: [ + ( + model: "voxygen.voxel.sprite.wizard.magical_barrier", + offset: (-10.0, -0.0, 0.0), + lod_axes: (0.0, 0.0, 0.0), + ), + ], + wind_sway: 0.0, +)), +MagicalSeal: Some(( + variations: [ + ( + model: "voxygen.voxel.sprite.wizard.magical_seal", + offset: (-16.0, -16.0, -1.0), + lod_axes: (0.0, 0.0, 0.0), + ), + ], + wind_sway: 0.0, +)), +Candle: Some(( + variations: [ + ( + model: "voxygen.voxel.sprite.wizard.candle", + offset: (-5.5, -5.5, 0.0), + lod_axes: (0.0, 0.0, 0.0), + ), + ], + wind_sway: 0.0, +)), } diff --git a/assets/world/manifests/site_structures/gnarling/totem.ron b/assets/world/manifests/site_structures/gnarling/totem.ron index 78e93ff1a9..eb7ccc89a4 100644 --- a/assets/world/manifests/site_structures/gnarling/totem.ron +++ b/assets/world/manifests/site_structures/gnarling/totem.ron @@ -2,7 +2,7 @@ [ ( - specifier: "world.structure.natural.gnarling_totem", + specifier: "world.structure.spots.gnarling_totem", center: (9, 5, 5), custom_indices: { 217: Filled(GlowingRock, (r: 0, g: 255, b: 246)), diff --git a/assets/world/manifests/spots/camp_forest.ron b/assets/world/manifests/spots/camp_forest.ron new file mode 100644 index 0000000000..b8fed35e05 --- /dev/null +++ b/assets/world/manifests/spots/camp_forest.ron @@ -0,0 +1,20 @@ +#![enable(unwrap_newtypes)] + +[ + ( + specifier: "world.structure.spots.camp", + center: (3, 3, 1), + custom_indices: { + 8: Filled(Air, (r: 255, g: 255, b: 255)), + 9: RotatedSprite(Bedroll, 0), + 10: Grass, + 11: Sprite(CookingPot), + 12: Sprite(Chest), + 13: RotatedSprite(Tent, 0), + 14: RotatedSprite(Tent, 4), + 15: RotatedSprite(Tent, 6), + 16: RotatedSprite(Tent, 2), + 251: Sprite(SmokeDummy), + }, + ), +] diff --git a/assets/world/manifests/spots/camp_pirate.ron b/assets/world/manifests/spots/camp_pirate.ron new file mode 100644 index 0000000000..f3f4180bf7 --- /dev/null +++ b/assets/world/manifests/spots/camp_pirate.ron @@ -0,0 +1,15 @@ +#![enable(unwrap_newtypes)] + +[ + ( + specifier: "world.structure.spots.camp", + center: (3, 3, 1), + custom_indices: { + 8: Filled(Air, (r: 255, g: 255, b: 255)), + 9: Sprite(BedrollPirate), + 10: Grass, + 11: Sprite(Chest), + 251: Grass, + }, + ), +] \ No newline at end of file diff --git a/assets/world/manifests/spots/camp_snow.ron b/assets/world/manifests/spots/camp_snow.ron new file mode 100644 index 0000000000..5e0ab7c1de --- /dev/null +++ b/assets/world/manifests/spots/camp_snow.ron @@ -0,0 +1,15 @@ +#![enable(unwrap_newtypes)] + +[ + ( + specifier: "world.structure.spots.camp", + center: (3, 3, 1), + custom_indices: { + 8: Filled(Air, (r: 255, g: 255, b: 255)), + 9: Sprite(BedrollSnow), + 10: None, + 11: Sprite(CookingPot), + 251: Sprite(SmokeDummy), + }, + ), +] diff --git a/assets/world/manifests/spots/gnome_spring.ron b/assets/world/manifests/spots/gnome_spring.ron index e8b2de1968..318fe3c985 100644 --- a/assets/world/manifests/spots/gnome_spring.ron +++ b/assets/world/manifests/spots/gnome_spring.ron @@ -2,7 +2,7 @@ [ ( - specifier: "world.structure.natural.gnome_spring", + specifier: "world.structure.spots.gnome_spring", center: (10, 10, 4), custom_indices: { 136: Filled(GlowingRock, (r: 0, g: 255, b: 255)), diff --git a/assets/world/manifests/spots/grave_small.ron b/assets/world/manifests/spots/grave_small.ron new file mode 100644 index 0000000000..684573cc8f --- /dev/null +++ b/assets/world/manifests/spots/grave_small.ron @@ -0,0 +1,16 @@ +#![enable(unwrap_newtypes)] + +[ + ( + specifier: "world.structure.spots.grave_small", + center: (2, 2, 1), + custom_indices: { + 8: Filled(Air, (r: 255, g: 255, b: 255)), + 9: RotatedSprite(Grave, 6), + 10: RotatedSprite(Gravestone, 6), + 11: Grass, + 12: None, + 13: RotatedSprite(Bones, 4), + }, + ), +] \ No newline at end of file diff --git a/assets/world/manifests/spots/jungle/outpost.ron b/assets/world/manifests/spots/jungle/outpost.ron new file mode 100644 index 0000000000..7e572035e3 --- /dev/null +++ b/assets/world/manifests/spots/jungle/outpost.ron @@ -0,0 +1,13 @@ +#![enable(unwrap_newtypes)] + +[ + ( + specifier: "world.structure.spots.jungle_outpost", + center: (32, 28, 33), + custom_indices: { + 8: Filled(Air, (r: 255, g: 255, b: 255)), + 156: Sprite(FireBowlGround), + 157: EntitySpawner("common.entity.wild.aggressive.occult_saurok", 1.0), + }, + ), +] diff --git a/assets/world/manifests/spots/jungle/saurok-altar.ron b/assets/world/manifests/spots/jungle/saurok-altar.ron index 480bee2539..0f68bb51da 100644 --- a/assets/world/manifests/spots/jungle/saurok-altar.ron +++ b/assets/world/manifests/spots/jungle/saurok-altar.ron @@ -2,7 +2,7 @@ [ ( - specifier: "world.structure.natural.saurok-altar", + specifier: "world.structure.spots.saurok-altar", center: (10, 13, 3), custom_indices: { 105: Filled(GlowingRock, (r: 161, g: 255, b: 133)), diff --git a/assets/world/manifests/spots/jungle/saurok_totem.ron b/assets/world/manifests/spots/jungle/saurok_totem.ron new file mode 100644 index 0000000000..2fc6dbd01d --- /dev/null +++ b/assets/world/manifests/spots/jungle/saurok_totem.ron @@ -0,0 +1,12 @@ +#![enable(unwrap_newtypes)] + +[ + ( + specifier: "world.structure.spots.saurok_totem_0", + center: (8, 8, 20) + ), + ( + specifier: "world.structure.spots.saurok_totem_1", + center: (8, 8, 20) + ), +] diff --git a/assets/world/manifests/spots/jungle/temple_small.ron b/assets/world/manifests/spots/jungle/temple_small.ron new file mode 100644 index 0000000000..de8703f77c --- /dev/null +++ b/assets/world/manifests/spots/jungle/temple_small.ron @@ -0,0 +1,12 @@ +#![enable(unwrap_newtypes)] + +[ + ( + specifier: "world.structure.spots.temple_small_0", + center: (11, 25, 27) + ), + ( + specifier: "world.structure.spots.temple_small_1", + center: (11, 11, 27) + ), +] \ No newline at end of file diff --git a/assets/world/manifests/spots/myrmidon-temple.ron b/assets/world/manifests/spots/myrmidon-temple.ron index 4aa19c5a80..bb580757d5 100644 --- a/assets/world/manifests/spots/myrmidon-temple.ron +++ b/assets/world/manifests/spots/myrmidon-temple.ron @@ -2,7 +2,7 @@ [ ( - specifier: "world.structure.natural.myrmidon-temple", + specifier: "world.structure.spots.myrmidon-temple", center: (13, 23, 5), ), ] diff --git a/assets/world/manifests/spots/water/shipwreck.ron b/assets/world/manifests/spots/water/shipwreck.ron index 352bd0439c..b61cf57101 100644 --- a/assets/world/manifests/spots/water/shipwreck.ron +++ b/assets/world/manifests/spots/water/shipwreck.ron @@ -2,7 +2,7 @@ [ ( - specifier: "world.structure.natural.shipwreck", + specifier: "world.structure.spots.shipwreck", center: (32, 14, 16), ), ] diff --git a/assets/world/manifests/spots/water/shipwreck2.ron b/assets/world/manifests/spots/water/shipwreck2.ron index 9ae113001d..2009b185a1 100644 --- a/assets/world/manifests/spots/water/shipwreck2.ron +++ b/assets/world/manifests/spots/water/shipwreck2.ron @@ -2,7 +2,7 @@ [ ( - specifier: "world.structure.natural.shipwreck2", + specifier: "world.structure.spots.shipwreck2", center: (32, 31, 14), /// ( X, Y, Z, ) custom_indices: { diff --git a/assets/world/manifests/spots_general/igloo.ron b/assets/world/manifests/spots_general/igloo.ron index c391e400f5..64731586ff 100644 --- a/assets/world/manifests/spots_general/igloo.ron +++ b/assets/world/manifests/spots_general/igloo.ron @@ -2,7 +2,7 @@ [ ( - specifier: "world.structure.natural.igloo", + specifier: "world.structure.spots.igloo", center: (14, 13, 3), ), ] diff --git a/assets/world/manifests/spots_general/mage_tower.ron b/assets/world/manifests/spots_general/mage_tower.ron new file mode 100644 index 0000000000..de62b14184 --- /dev/null +++ b/assets/world/manifests/spots_general/mage_tower.ron @@ -0,0 +1,32 @@ +#![enable(unwrap_newtypes)] + +[ + ( + specifier: "world.structure.spots.mage_tower", + center: (32, 32, 19), + custom_indices: { + 8: Filled(Air, (r: 255, g: 255, b: 255)), + 10: Sprite(WitchWindow), + 11: RotatedSprite(Window1, 0), + 12: RotatedSprite(Window1, 2), + 44: Filled(GlowingRock, (r: 46, g: 10, b: 27)), + 45: Filled(GlowingRock, (r: 0, g: 204, b: 204)), + 233: RotatedSprite(DoorDark, 2), + 234: RotatedSprite(DoorDark, 6), + 239: EntitySpawner("common.entity.spot.wizard.wizard_argo", 1.0), + 240: EntitySpawner("common.entity.spot.wizard.wizard_trish", 1.0), + 241: EntitySpawner("common.entity.spot.wizard.wizard_haku", 1.0), + 242: EntitySpawner("common.entity.spot.wizard.novice", 1.0), + 243: EntitySpawner("common.entity.spot.wizard.adept", 1.0), + 245: EntitySpawner("common.entity.wild.aggressive.bat", 0.4), + 246: Sprite(WallLampWizard), + 249: RotatedSprite(DoorDark, 8), + 250: RotatedSprite(DoorDark, 4), + 252: Keyhole("common.items.keys.rusty_tower_key"), + 253: Sprite(KeyDoor), + 235: Sprite(Candle), + }, + ), +] + + diff --git a/assets/world/manifests/spots_general/pirate_hideout.ron b/assets/world/manifests/spots_general/pirate_hideout.ron index 70120b05e7..58a239e799 100644 --- a/assets/world/manifests/spots_general/pirate_hideout.ron +++ b/assets/world/manifests/spots_general/pirate_hideout.ron @@ -2,7 +2,7 @@ [ ( - specifier: "world.structure.natural.pirate_hideout", + specifier: "world.structure.spots.pirate_hideout", center: (32, 27, 5), custom_indices: { 12: Sprite(Cauldron), diff --git a/assets/world/manifests/spots_general/troll_cave.ron b/assets/world/manifests/spots_general/troll_cave.ron index 2461241f24..2f9f1b39ff 100644 --- a/assets/world/manifests/spots_general/troll_cave.ron +++ b/assets/world/manifests/spots_general/troll_cave.ron @@ -3,7 +3,14 @@ [ ( specifier: "world.structure.natural.troll_cave", - center: (23, 25, 12), - /// ( X, Y, Z, ) + center: (23, 25, 17), + custom_indices: { + 8: Filled(Air, (r: 255, g: 255, b: 255)), + 241: EntitySpawner("common.entity.wild.aggressive.cave_troll", 1.0), + 242: Sprite(Mushroom), + 243: Sprite(CommonLockedChest), + 244: Sprite(Bones), + 245: EntitySpawner("common.entity.wild.aggressive.bat", 0.4), + }, ), ] diff --git a/assets/world/manifests/spots_general/troll_cave_mountain.ron b/assets/world/manifests/spots_general/troll_cave_mountain.ron new file mode 100644 index 0000000000..2d7778cf6a --- /dev/null +++ b/assets/world/manifests/spots_general/troll_cave_mountain.ron @@ -0,0 +1,16 @@ +#![enable(unwrap_newtypes)] + +[ + ( + specifier: "world.structure.natural.troll_cave", + center: (23, 25, 17), + custom_indices: { + 8: Filled(Air, (r: 255, g: 255, b: 255)), + 241: EntitySpawner("common.entity.wild.aggressive.mountain_troll", 1.0), + 242: Sprite(Mushroom), + 243: Sprite(CommonLockedChest), + 244: Sprite(Bones), + 245: EntitySpawner("common.entity.wild.aggressive.bat", 0.4), + }, + ), +] diff --git a/assets/world/manifests/spots_general/troll_cave_swamp.ron b/assets/world/manifests/spots_general/troll_cave_swamp.ron new file mode 100644 index 0000000000..05d7ab35df --- /dev/null +++ b/assets/world/manifests/spots_general/troll_cave_swamp.ron @@ -0,0 +1,16 @@ +#![enable(unwrap_newtypes)] + +[ + ( + specifier: "world.structure.natural.troll_cave", + center: (23, 25, 17), + custom_indices: { + 8: Filled(Air, (r: 255, g: 255, b: 255)), + 241: EntitySpawner("common.entity.wild.aggressive.swamp_troll", 1.0), + 242: Sprite(Mushroom), + 243: Sprite(CommonLockedChest), + 244: Sprite(Bones), + 245: EntitySpawner("common.entity.wild.aggressive.bat", 0.4), + }, + ), +] diff --git a/assets/world/manifests/spots_general/witch_hut.ron b/assets/world/manifests/spots_general/witch_hut.ron index dd6003e882..304b75c005 100644 --- a/assets/world/manifests/spots_general/witch_hut.ron +++ b/assets/world/manifests/spots_general/witch_hut.ron @@ -2,14 +2,16 @@ [ ( - specifier: "world.structure.natural.witch-hut-black_0", + specifier: "world.structure.spots.witch-hut-black_0", center: (10, 13, 16), custom_indices: { 12: Sprite(Cauldron), 10: Sprite(WitchWindow), 44: Filled(GlowingRock, (r: 54, g: 180, b: 64)), 8: Filled(Air, (r: 255, g: 255, b: 255)), - 249: Sprite(PotionMinor), + 247: RotatedSprite(DoorDark, 4), + 248: RotatedSprite(DoorDark, 0), + 249: Sprite(PotionDummy), 251: Sprite(SmokeDummy), }, ), diff --git a/assets/world/manifests/spots_grasslands/dwarven_grave.ron b/assets/world/manifests/spots_grasslands/dwarven_grave.ron index 64217ca79f..725d5bad58 100644 --- a/assets/world/manifests/spots_grasslands/dwarven_grave.ron +++ b/assets/world/manifests/spots_grasslands/dwarven_grave.ron @@ -2,7 +2,7 @@ [ ( - specifier: "world.structure.natural.dwarven_grave", + specifier: "world.structure.spots.dwarven_grave", center: (20, 23, 5), custom_indices: { 151: Filled(GlowingRock, (r: 50, g: 255, b: 210)), diff --git a/assets/world/manifests/trees/airship_crash.ron b/assets/world/manifests/trees/airship_crash.ron index 8ae9dbef19..446a64e53a 100644 --- a/assets/world/manifests/trees/airship_crash.ron +++ b/assets/world/manifests/trees/airship_crash.ron @@ -2,7 +2,7 @@ [ ( - specifier: "world.structure.natural.airship-crashsite_0", + specifier: "world.structure.spots.airship-crashsite_0", center: (28, 40, 14), ), ] diff --git a/assets/world/structure/natural/dwarven_grave.vox b/assets/world/structure/natural/dwarven_grave.vox deleted file mode 100644 index 4778038f80..0000000000 --- a/assets/world/structure/natural/dwarven_grave.vox +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:6c07a78dfc0d3725021951802f8229e0b59b329121af577d404cc1862fd42a35 -size 25784 diff --git a/assets/world/structure/natural/tree-house.vox b/assets/world/structure/natural/tree-house.vox deleted file mode 100644 index b40d782e0b..0000000000 --- a/assets/world/structure/natural/tree-house.vox +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:a0ab1dd6743173738e4f0e1be34848c3cbe0e9eb1f551e21e700b795fc68fc40 -size 55316 diff --git a/assets/world/structure/natural/troll_cave.vox b/assets/world/structure/natural/troll_cave.vox index 3759bc84cb..4f138dcc60 100644 --- a/assets/world/structure/natural/troll_cave.vox +++ b/assets/world/structure/natural/troll_cave.vox @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6b0c0a19909b964e51c341eaf564555385f4f8f7107e915b7c387cde092248e3 -size 154628 +oid sha256:11eb81d1ef8a86fdbd31bbf5efc6415d36745bad6eff25a35f5d180bc1a3943e +size 196340 diff --git a/assets/world/structure/natural/untitled.vox b/assets/world/structure/natural/untitled.vox new file mode 100644 index 0000000000..23f9657f88 --- /dev/null +++ b/assets/world/structure/natural/untitled.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9109ba246bee5bb985ea16ccc907de949a988e0e0624f8a11e8bf2ce62ae1917 +size 2536 diff --git a/assets/world/structure/natural/witch-hut-black_0.vox b/assets/world/structure/natural/witch-hut-black_0.vox deleted file mode 100644 index 47a68f4895..0000000000 --- a/assets/world/structure/natural/witch-hut-black_0.vox +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:a24c4dab24601c30564959f2e2db5daf59fdfdae9e74ec34045f9d5de17cba06 -size 34376 diff --git a/assets/world/structure/natural/airship-crashsite_0.vox b/assets/world/structure/spots/airship-crashsite_0.vox similarity index 100% rename from assets/world/structure/natural/airship-crashsite_0.vox rename to assets/world/structure/spots/airship-crashsite_0.vox diff --git a/assets/world/structure/spots/camp.vox b/assets/world/structure/spots/camp.vox new file mode 100644 index 0000000000..d4b8b2da1b --- /dev/null +++ b/assets/world/structure/spots/camp.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ce83b599702c5ee908d42b4b5959de8ab672b60deb41ab29514d7d9f4acf0fe0 +size 27071 diff --git a/assets/world/structure/spots/dwarven_grave.vox b/assets/world/structure/spots/dwarven_grave.vox new file mode 100644 index 0000000000..f5344b316c --- /dev/null +++ b/assets/world/structure/spots/dwarven_grave.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e01858d5a43dcac79a01da60847767ef1963422007ef71bf5f6d8c18d44e4707 +size 1248 diff --git a/assets/world/structure/natural/gnarling_totem.vox b/assets/world/structure/spots/gnarling_totem.vox similarity index 100% rename from assets/world/structure/natural/gnarling_totem.vox rename to assets/world/structure/spots/gnarling_totem.vox diff --git a/assets/world/structure/natural/gnome_spring.vox b/assets/world/structure/spots/gnome_spring.vox similarity index 100% rename from assets/world/structure/natural/gnome_spring.vox rename to assets/world/structure/spots/gnome_spring.vox diff --git a/assets/world/structure/spots/grave_small.vox b/assets/world/structure/spots/grave_small.vox new file mode 100644 index 0000000000..a44087c169 --- /dev/null +++ b/assets/world/structure/spots/grave_small.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0d3d16c8bf81a3f2a9805ad4d62727f73c99c9691ee11919ae34099ae16d41fd +size 26818 diff --git a/assets/world/structure/natural/igloo.vox b/assets/world/structure/spots/igloo.vox similarity index 100% rename from assets/world/structure/natural/igloo.vox rename to assets/world/structure/spots/igloo.vox diff --git a/assets/world/structure/spots/jungle_outpost.vox b/assets/world/structure/spots/jungle_outpost.vox new file mode 100644 index 0000000000..ade6f85dd1 --- /dev/null +++ b/assets/world/structure/spots/jungle_outpost.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:82f56235daad2fe1ff4cd0f9e8b6a289553425e5024e114cb22e09d89b161643 +size 242972 diff --git a/assets/world/structure/spots/mage_tower.vox b/assets/world/structure/spots/mage_tower.vox new file mode 100644 index 0000000000..d924088a38 --- /dev/null +++ b/assets/world/structure/spots/mage_tower.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5d6b694480cd65cecbe5bf07239c3617a3d6a3238ae6d7b58a7fd620749383dc +size 1231288 diff --git a/assets/world/structure/natural/myrmidon-temple.vox b/assets/world/structure/spots/myrmidon-temple.vox similarity index 100% rename from assets/world/structure/natural/myrmidon-temple.vox rename to assets/world/structure/spots/myrmidon-temple.vox diff --git a/assets/world/structure/natural/pirate_hideout.vox b/assets/world/structure/spots/pirate_hideout.vox similarity index 100% rename from assets/world/structure/natural/pirate_hideout.vox rename to assets/world/structure/spots/pirate_hideout.vox diff --git a/assets/world/structure/natural/saurok-altar.vox b/assets/world/structure/spots/saurok-altar.vox similarity index 100% rename from assets/world/structure/natural/saurok-altar.vox rename to assets/world/structure/spots/saurok-altar.vox diff --git a/assets/world/structure/spots/saurok_totem_0.vox b/assets/world/structure/spots/saurok_totem_0.vox new file mode 100644 index 0000000000..3643edc682 --- /dev/null +++ b/assets/world/structure/spots/saurok_totem_0.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:693b148efac37a6cd09be7759a552cdf1e2ed2972eeb6388ad108126c4b98f3e +size 41384 diff --git a/assets/world/structure/spots/saurok_totem_1.vox b/assets/world/structure/spots/saurok_totem_1.vox new file mode 100644 index 0000000000..4dc86a410e --- /dev/null +++ b/assets/world/structure/spots/saurok_totem_1.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:685e27ce83fcbf3d8a43783eb31c558f4a511c8d1e9dce2c26b76fe8738e5f67 +size 56108 diff --git a/assets/world/structure/natural/shipwreck.vox b/assets/world/structure/spots/shipwreck.vox similarity index 100% rename from assets/world/structure/natural/shipwreck.vox rename to assets/world/structure/spots/shipwreck.vox diff --git a/assets/world/structure/natural/shipwreck2.vox b/assets/world/structure/spots/shipwreck2.vox similarity index 100% rename from assets/world/structure/natural/shipwreck2.vox rename to assets/world/structure/spots/shipwreck2.vox diff --git a/assets/world/structure/spots/temple_small_0.vox b/assets/world/structure/spots/temple_small_0.vox new file mode 100644 index 0000000000..ae512fc1c1 --- /dev/null +++ b/assets/world/structure/spots/temple_small_0.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:07a0aa3fedfc92a43f6f1dd0c38e4ff45715c5406412b640dbd76da806a349c3 +size 132860 diff --git a/assets/world/structure/spots/temple_small_1.vox b/assets/world/structure/spots/temple_small_1.vox new file mode 100644 index 0000000000..107209f3f7 --- /dev/null +++ b/assets/world/structure/spots/temple_small_1.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4dcba37263c8412a7cdd58da9862cc0365b2625249bb7db38761861fc2d8b86f +size 103280 diff --git a/assets/world/structure/spots/tree-house.vox b/assets/world/structure/spots/tree-house.vox new file mode 100644 index 0000000000..fa9de000b9 --- /dev/null +++ b/assets/world/structure/spots/tree-house.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0d030302b65129996b22fd43cca3019611120780cb1d56492d5b110e0b2a03af +size 55608 diff --git a/assets/world/structure/spots/witch-hut-black_0.vox b/assets/world/structure/spots/witch-hut-black_0.vox new file mode 100644 index 0000000000..bee2775f6a --- /dev/null +++ b/assets/world/structure/spots/witch-hut-black_0.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1ef1286556d94aa9aaa86b425f7a06641ca9e2aa13af87c636e3d48b984edcda +size 59971 diff --git a/assets/world/structure/natural/witch-hut.vox b/assets/world/structure/spots/witch-hut.vox similarity index 100% rename from assets/world/structure/natural/witch-hut.vox rename to assets/world/structure/spots/witch-hut.vox diff --git a/common/src/comp/controller.rs b/common/src/comp/controller.rs index 83a219536b..2a2758f15b 100644 --- a/common/src/comp/controller.rs +++ b/common/src/comp/controller.rs @@ -43,7 +43,10 @@ pub enum InventoryAction { #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] pub enum InventoryManip { Pickup(Uid), - Collect(Vec3), + Collect { + sprite_pos: Vec3, + required_item: Option<(InvSlotId, bool)>, + }, Use(Slot), Swap(Slot, Slot), SplitSwap(Slot, Slot), @@ -57,18 +60,6 @@ pub enum InventoryManip { SwapEquippedWeapons, } -impl From for InventoryManip { - fn from(inv_action: InventoryAction) -> Self { - match inv_action { - InventoryAction::Use(slot) => Self::Use(slot), - InventoryAction::Swap(equip, slot) => Self::Swap(Slot::Equip(equip), slot), - InventoryAction::Drop(equip) => Self::Drop(Slot::Equip(equip)), - InventoryAction::Sort => Self::Sort, - InventoryAction::Collect(collect) => Self::Collect(collect), - } - } -} - impl From for InventoryManip { fn from(inv_event: InventoryEvent) -> Self { match inv_event { diff --git a/common/src/comp/inventory/item/mod.rs b/common/src/comp/inventory/item/mod.rs index 88ebec582f..3766512560 100644 --- a/common/src/comp/inventory/item/mod.rs +++ b/common/src/comp/inventory/item/mod.rs @@ -48,6 +48,7 @@ pub enum Reagent { pub enum Utility { Coins, Collar, + Key, } #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] @@ -474,7 +475,7 @@ pub enum ItemDefinitionId<'a> { }, } -#[derive(Clone, Debug, Eq, Hash, PartialEq)] +#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] pub enum ItemDefinitionIdOwned { Simple(String), Modular { @@ -1032,6 +1033,15 @@ impl Item { }) } + /// Generate a human-readable description of the item and amount. + pub fn describe(&self) -> String { + if self.amount() > 1 { + format!("{} x {}", self.amount(), self.name()) + } else { + self.name().to_string() + } + } + pub fn name(&self) -> Cow { match &self.item_base { ItemBase::Simple(item_def) => { @@ -1112,7 +1122,7 @@ impl Item { pub fn slot_mut(&mut self, slot: usize) -> Option<&mut InvSlot> { self.slots.get_mut(slot) } pub fn try_reclaim_from_block(block: Block) -> Option { - block.get_sprite()?.collectible_id()?.to_item() + block.get_sprite()?.collectible_id()??.to_item() } pub fn ability_spec(&self) -> Option> { diff --git a/common/src/comp/inventory/mod.rs b/common/src/comp/inventory/mod.rs index a60c159a14..6eed4ace70 100644 --- a/common/src/comp/inventory/mod.rs +++ b/common/src/comp/inventory/mod.rs @@ -400,9 +400,11 @@ impl Inventory { self.slots_with_id() .find(|&(_, it)| { if let Some(it) = it { - // TODO: add a ComponentKey struct to compare components, see issue #1226 - debug_assert!(it.components().is_empty()); - debug_assert!(item.components().is_empty()); + if it.components().len() == item.components().len() { + // TODO: add a ComponentKey struct to compare components, see issue #1226 + debug_assert!(it.components().is_empty()); + debug_assert!(item.components().is_empty()); + } it.item_definition_id() == item.item_definition_id() } else { false diff --git a/common/src/outcome.rs b/common/src/outcome.rs index effdc16810..4110b6bb8c 100644 --- a/common/src/outcome.rs +++ b/common/src/outcome.rs @@ -110,6 +110,12 @@ pub enum Outcome { pos: Vec3, sprite: SpriteKind, }, + SpriteUnlocked { + pos: Vec3, + }, + FailedSpriteUnlock { + pos: Vec3, + }, } impl Outcome { @@ -133,7 +139,9 @@ impl Outcome { | Outcome::Utterance { pos, .. } | Outcome::SpriteDelete { pos, .. } | Outcome::Glider { pos, .. } => Some(*pos), - Outcome::BreakBlock { pos, .. } => Some(pos.map(|e| e as f32 + 0.5)), + Outcome::BreakBlock { pos, .. } + | Outcome::SpriteUnlocked { pos } + | Outcome::FailedSpriteUnlock { pos } => Some(pos.map(|e| e as f32 + 0.5)), Outcome::ExpChange { .. } | Outcome::ComboChange { .. } | Outcome::Lightning { .. } diff --git a/common/src/states/behavior.rs b/common/src/states/behavior.rs index 57d9724663..e681d5952b 100644 --- a/common/src/states/behavior.rs +++ b/common/src/states/behavior.rs @@ -1,6 +1,6 @@ use crate::{ comp::{ - self, character_state::OutputEvents, item::MaterialStatManifest, ActiveAbilities, Beam, + self, character_state::OutputEvents, item::{tool::AbilityMap, MaterialStatManifest}, ActiveAbilities, Beam, Body, CharacterState, Combo, ControlAction, Controller, ControllerInputs, Density, Energy, Health, InputAttr, InputKind, Inventory, InventoryAction, Mass, Melee, Ori, PhysicsState, Pos, SkillSet, StateUpdate, Stats, Vel, @@ -135,6 +135,7 @@ pub struct JoinData<'a> { pub stats: &'a Stats, pub skill_set: &'a SkillSet, pub active_abilities: Option<&'a ActiveAbilities>, + pub ability_map: &'a AbilityMap, pub msm: &'a MaterialStatManifest, pub combo: Option<&'a Combo>, pub alignment: Option<&'a comp::Alignment>, @@ -174,6 +175,7 @@ impl<'a> JoinData<'a> { updater: &'a LazyUpdate, dt: &'a DeltaTime, msm: &'a MaterialStatManifest, + ability_map: &'a AbilityMap, ) -> Self { Self { entity: j.entity, @@ -197,6 +199,7 @@ impl<'a> JoinData<'a> { updater, dt, msm, + ability_map, combo: j.combo, alignment: j.alignment, terrain: j.terrain, diff --git a/common/src/states/sprite_interact.rs b/common/src/states/sprite_interact.rs index 3fe8f31bc1..9a05fdc56a 100644 --- a/common/src/states/sprite_interact.rs +++ b/common/src/states/sprite_interact.rs @@ -1,7 +1,8 @@ use super::utils::*; use crate::{ - comp::{character_state::OutputEvents, CharacterState, InventoryManip, StateUpdate}, - event::ServerEvent, + comp::{character_state::OutputEvents, CharacterState, InventoryManip, StateUpdate, item::{Item, ItemDefinitionIdOwned}}, + event::{ServerEvent, LocalEvent}, + outcome::Outcome, states::{ behavior::{CharacterBehavior, JoinData}, }, @@ -13,7 +14,7 @@ use std::time::Duration; use vek::Vec3; /// Separated out to condense update portions of character state -#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct StaticData { /// Buildup to sprite interaction pub buildup_duration: Duration, @@ -29,11 +30,14 @@ pub struct StaticData { pub was_wielded: bool, /// Was sneaking pub was_sneak: bool, + /// The item required to interact with the sprite, if one was required + // If second field is true, item should be consumed on collection + pub required_item: Option<(ItemDefinitionIdOwned, bool)>, /// Miscellaneous information about the ability pub ability_info: AbilityInfo, } -#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct Data { /// Struct containing data that does not change over the course of the /// character state @@ -58,46 +62,54 @@ impl CharacterBehavior for Data { StageSection::Buildup => { if self.timer < self.static_data.buildup_duration { // Build up - update.character = CharacterState::SpriteInteract(Data { - timer: tick_attack_or_default(data, self.timer, None), - ..*self - }); + if let CharacterState::SpriteInteract(c) = &mut update.character { + c.timer = tick_attack_or_default(data, self.timer, None); + } } else { // Transitions to use section of stage - update.character = CharacterState::SpriteInteract(Data { - timer: Duration::default(), - stage_section: StageSection::Action, - ..*self - }); + if let CharacterState::SpriteInteract(c) = &mut update.character { + c.timer = Duration::default(); + c.stage_section = StageSection::Action; + } } }, StageSection::Action => { if self.timer < self.static_data.use_duration { // sprite interaction - update.character = CharacterState::SpriteInteract(Data { - timer: tick_attack_or_default(data, self.timer, None), - ..*self - }); + if let CharacterState::SpriteInteract(c) = &mut update.character { + c.timer = tick_attack_or_default(data, self.timer, None); + } } else { // Transitions to recover section of stage - update.character = CharacterState::SpriteInteract(Data { - timer: Duration::default(), - stage_section: StageSection::Recover, - ..*self - }); + if let CharacterState::SpriteInteract(c) = &mut update.character { + c.timer = Duration::default(); + c.stage_section = StageSection::Recover; + } } }, StageSection::Recover => { if self.timer < self.static_data.recover_duration { // Recovery - update.character = CharacterState::SpriteInteract(Data { - timer: tick_attack_or_default(data, self.timer, None), - ..*self - }); + if let CharacterState::SpriteInteract(c) = &mut update.character { + c.timer = tick_attack_or_default(data, self.timer, None); + } } else { // Create inventory manipulation event - let inv_manip = InventoryManip::Collect(self.static_data.sprite_pos); - output_events.emit_server(ServerEvent::InventoryManip(data.entity, inv_manip)); + let required_item = self.static_data.required_item + .as_ref() + .and_then(|(i, consume)| Some(( + Item::new_from_item_definition_id(i.as_ref(), data.ability_map, data.msm).ok()?, + *consume, + ))); + let has_required_item = required_item.as_ref().map_or(true, |(item, _consume)| data.inventory.map_or(false, |inv| inv.contains(item))); + if has_required_item { + let inv_slot = required_item.and_then(|(item, consume)| Some((data.inventory.and_then(|inv| inv.get_slot_of_item(&item))?, consume))); + let inv_manip = InventoryManip::Collect { sprite_pos: self.static_data.sprite_pos, required_item: inv_slot }; + output_events.emit_server(ServerEvent::InventoryManip(data.entity, inv_manip)); + output_events.emit_local(LocalEvent::CreateOutcome(Outcome::SpriteUnlocked { + pos: self.static_data.sprite_pos, + })); + } // Done end_ability(data, &mut update); } @@ -124,6 +136,7 @@ pub enum SpriteInteractKind { Chest, Harvestable, Collectible, + Unlock, Fallback, } @@ -156,6 +169,7 @@ impl From for Option { | SpriteKind::PotionMinor | SpriteKind::Seashells | SpriteKind::Bomb => Some(SpriteInteractKind::Collectible), + SpriteKind::Keyhole => Some(SpriteInteractKind::Unlock), // Collectible checked in addition to container for case that sprite requires a tool to // collect and cannot be collected by hand, yet still meets the container check _ if sprite_kind.is_container() && sprite_kind.is_collectible() => { @@ -191,6 +205,11 @@ impl SpriteInteractKind { Duration::from_secs_f32(5.0), Duration::from_secs_f32(5.0), ), + Self::Unlock => ( + Duration::from_secs_f32(0.8), + Duration::from_secs_f32(0.5), + Duration::from_secs_f32(0.3), + ), } } } diff --git a/common/src/states/utils.rs b/common/src/states/utils.rs index 14a4d7006f..bffda154b7 100644 --- a/common/src/states/utils.rs +++ b/common/src/states/utils.rs @@ -5,8 +5,9 @@ use crate::{ ability::{Ability, AbilityInput, AbilityMeta, Capability}, arthropod, biped_large, biped_small, bird_medium, character_state::OutputEvents, + controller::InventoryManip, inventory::slot::{ArmorSlot, EquipSlot, Slot}, - item::{armor::Friction, tool::AbilityContext, Hands, ItemKind, ToolKind}, + item::{armor::Friction, tool::AbilityContext, Hands, ItemKind, ToolKind, Item}, quadruped_low, quadruped_medium, quadruped_small, skills::{Skill, SwimSkill, SKILL_MODIFIERS}, theropod, Body, CharacterAbility, CharacterState, Density, InputAttr, InputKind, @@ -17,7 +18,8 @@ use crate::{ outcome::Outcome, states::{behavior::JoinData, utils::CharacterState::Idle, *}, util::Dir, - vol::ReadVol, + vol::{ReadVol, RectVolSize}, + terrain::{TerrainChunkSize, UnlockKind}, }; use core::hash::BuildHasherDefault; use fxhash::FxHasher64; @@ -794,7 +796,7 @@ pub fn handle_manipulate_loadout( inv_action: InventoryAction, ) { match inv_action { - InventoryAction::Use(Slot::Inventory(inv_slot)) => { + InventoryAction::Use(slot @ Slot::Inventory(inv_slot)) => { // If inventory action is using a slot, and slot is in the inventory // TODO: Do some non lazy way of handling the possibility that items equipped in // the loadout will have effects that are desired to be non-instantaneous @@ -823,8 +825,9 @@ pub fn handle_manipulate_loadout( }); } else { // Else emit inventory action instantaneously + let inv_manip = InventoryManip::Use(slot); output_events - .emit_server(ServerEvent::InventoryManip(data.entity, inv_action.into())); + .emit_server(ServerEvent::InventoryManip(data.entity, inv_manip)); } }, InventoryAction::Collect(sprite_pos) => { @@ -842,6 +845,14 @@ pub fn handle_manipulate_loadout( if close_to_sprite { // First, get sprite data for position, if there is a sprite use sprite_interact::SpriteInteractKind; + let sprite_chunk_pos = sprite_pos + .xy() + .map2(TerrainChunkSize::RECT_SIZE, |e, sz| e.rem_euclid(sz as i32)) + .with_z(sprite_pos.z); + let sprite_cfg = data + .terrain + .pos_chunk(sprite_pos) + .and_then(|chunk| chunk.meta().sprite_cfg_at(sprite_chunk_pos)); let sprite_at_pos = data .terrain .get(sprite_pos) @@ -902,37 +913,66 @@ pub fn handle_manipulate_loadout( .into_path() .is_some(); + let required_item = sprite_at_pos.and_then(|s| match s.unlock_condition(sprite_cfg.cloned()) { + UnlockKind::Free => None, + UnlockKind::Requires(item) => Some((item, false)), + UnlockKind::Consumes(item) => Some((item, true)), + }); + let has_required_items = required_item + .as_ref() + .and_then(|(i, _consume)| Item::new_from_item_definition_id(i.as_ref(), data.ability_map, data.msm).ok()) + .map_or(true, |i| data.inventory.map_or(false, |inv| inv.contains(&i))); + // If path can be found between entity interacting with sprite and entity, start // interaction with sprite if not_blocked_by_terrain { - // If the sprite is collectible, enter the sprite interaction character - // state TODO: Handle cases for sprite being - // interactible, but not collectible (none currently - // exist) - let (buildup_duration, use_duration, recover_duration) = - sprite_interact.durations(); + if has_required_items { + // If the sprite is collectible, enter the sprite interaction character + // state TODO: Handle cases for sprite being + // interactible, but not collectible (none currently + // exist) + let (buildup_duration, use_duration, recover_duration) = + sprite_interact.durations(); - update.character = CharacterState::SpriteInteract(sprite_interact::Data { - static_data: sprite_interact::StaticData { - buildup_duration, - use_duration, - recover_duration, - sprite_pos, - sprite_kind: sprite_interact, - was_wielded: data.character.is_wield(), - was_sneak: data.character.is_stealthy(), - ability_info: AbilityInfo::from_forced_state_change(data.character), - }, - timer: Duration::default(), - stage_section: StageSection::Buildup, - }) + update.character = CharacterState::SpriteInteract(sprite_interact::Data { + static_data: sprite_interact::StaticData { + buildup_duration, + use_duration, + recover_duration, + sprite_pos, + sprite_kind: sprite_interact, + was_wielded: data.character.is_wield(), + was_sneak: data.character.is_stealthy(), + required_item, + ability_info: AbilityInfo::from_forced_state_change(data.character), + }, + timer: Duration::default(), + stage_section: StageSection::Buildup, + }) + } else { + output_events.emit_local(LocalEvent::CreateOutcome(Outcome::FailedSpriteUnlock { + pos: sprite_pos, + })); + } } } } }, - _ => { - // Else just do event instantaneously - output_events.emit_server(ServerEvent::InventoryManip(data.entity, inv_action.into())); + // For inventory actions without a dedicated character state, just do action instantaneously + InventoryAction::Swap(equip, slot) => { + let inv_manip = InventoryManip::Swap(Slot::Equip(equip), slot); + output_events.emit_server(ServerEvent::InventoryManip(data.entity, inv_manip)); + }, + InventoryAction::Drop(equip) => { + let inv_manip = InventoryManip::Drop(Slot::Equip(equip)); + output_events.emit_server(ServerEvent::InventoryManip(data.entity, inv_manip)); + }, + InventoryAction::Sort => { + output_events.emit_server(ServerEvent::InventoryManip(data.entity, InventoryManip::Sort)); + }, + InventoryAction::Use(slot @ Slot::Equip(_)) => { + let inv_manip = InventoryManip::Use(slot); + output_events.emit_server(ServerEvent::InventoryManip(data.entity, inv_manip)); }, } } diff --git a/common/src/terrain/block.rs b/common/src/terrain/block.rs index de79ba1833..2f57882f4e 100644 --- a/common/src/terrain/block.rs +++ b/common/src/terrain/block.rs @@ -2,6 +2,7 @@ use super::SpriteKind; use crate::{ comp::{fluid_dynamics::LiquidKind, tool::ToolKind}, consts::FRIC_GROUND, + lottery::LootSpec, make_case_elim, }; use num_derive::FromPrimitive; @@ -281,6 +282,8 @@ impl Block { BlockKind::Lava => None, _ => self.get_sprite().and_then(|sprite| match sprite { sprite if sprite.is_container() => None, + SpriteKind::Keyhole + | SpriteKind::KeyDoor => None, SpriteKind::Anvil | SpriteKind::Cauldron | SpriteKind::CookingPot @@ -313,10 +316,15 @@ impl Block { } #[inline] - pub fn is_collectible(&self) -> bool { + pub fn collectible_id(&self) -> Option>> { self.get_sprite() - .map(|s| s.is_collectible()) - .unwrap_or(false) + .map(|s| s.collectible_id()) + .unwrap_or(None) + } + + #[inline] + pub fn is_collectible(&self) -> bool { + self.collectible_id().is_some() && self.mine_tool().is_none() } #[inline] diff --git a/common/src/terrain/mod.rs b/common/src/terrain/mod.rs index 3db2b2c92b..622d321049 100644 --- a/common/src/terrain/mod.rs +++ b/common/src/terrain/mod.rs @@ -12,11 +12,12 @@ pub use self::{ block::{Block, BlockKind}, map::MapSizeLg, site::SiteKindMeta, - sprite::SpriteKind, + sprite::{SpriteKind, SpriteCfg, UnlockKind}, structure::{Structure, StructuresGroup}, }; use roots::find_roots_cubic; use serde::{Deserialize, Serialize}; +use hashbrown::HashMap; use crate::{ vol::{ReadVol, RectVolSize}, @@ -110,6 +111,7 @@ pub struct TerrainChunkMeta { tracks: Vec>, debug_points: Vec>, debug_lines: Vec>, + sprite_cfgs: HashMap, SpriteCfg>, } impl TerrainChunkMeta { @@ -139,6 +141,7 @@ impl TerrainChunkMeta { tracks: Vec::new(), debug_points: Vec::new(), debug_lines: Vec::new(), + sprite_cfgs: HashMap::default(), } } @@ -157,6 +160,7 @@ impl TerrainChunkMeta { tracks: Vec::new(), debug_points: Vec::new(), debug_lines: Vec::new(), + sprite_cfgs: HashMap::default(), } } @@ -190,7 +194,17 @@ impl TerrainChunkMeta { pub fn debug_lines(&self) -> &[LineSegment3] { &self.debug_lines } - pub fn add_debug_line(&mut self, line: LineSegment3) { self.debug_lines.push(line); } + pub fn add_debug_line(&mut self, line: LineSegment3) { + self.debug_lines.push(line); + } + + pub fn sprite_cfg_at(&self, rpos: Vec3) -> Option<&SpriteCfg> { + self.sprite_cfgs.get(&rpos) + } + + pub fn set_sprite_cfg_at(&mut self, rpos: Vec3, sprite_cfg: SpriteCfg) { + self.sprite_cfgs.insert(rpos, sprite_cfg); + } } // Terrain type aliases diff --git a/common/src/terrain/sprite.rs b/common/src/terrain/sprite.rs index 53612421e8..f7e92b7e49 100644 --- a/common/src/terrain/sprite.rs +++ b/common/src/terrain/sprite.rs @@ -1,4 +1,8 @@ -use crate::{comp::tool::ToolKind, lottery::LootSpec, make_case_elim}; +use crate::{ + comp::{item::{ItemDefinitionId, ItemDefinitionIdOwned}, tool::ToolKind}, + lottery::LootSpec, + make_case_elim, +}; use strum::EnumIter; use hashbrown::HashMap; use lazy_static::lazy_static; @@ -226,7 +230,22 @@ make_case_elim!( SeaDecorPillar = 0xC7, SeashellLantern = 0xC8, Rope = 0xC9, - IceSpike = 0xDA, + IceSpike = 0xCA, + Bedroll = 0xCB, + BedrollSnow = 0xCC, + BedrollPirate = 0xCD, + Tent = 0xCE, + Grave = 0xCF, + Gravestone = 0xD0, + PotionDummy = 0xD1, + DoorDark = 0xD2, + MagicalBarrier = 0xD3, + MagicalSeal = 0xD4, + WallLampWizard = 0xD5, + Candle = 0xD6, + Keyhole = 0xD7, + KeyDoor = 0xD8, + CommonLockedChest = 0xD9, } ); @@ -236,6 +255,9 @@ impl SpriteKind { // Beware: the height *must* be <= `MAX_HEIGHT` or the collision system will not // properly detect it! Some(match self { + SpriteKind::Bedroll => 0.3, + SpriteKind::BedrollSnow => 0.4, + SpriteKind::BedrollPirate => 0.3, SpriteKind::Tomato => 1.65, SpriteKind::LargeCactus => 2.5, SpriteKind::Scarecrow => 3.0, @@ -243,6 +265,7 @@ impl SpriteKind { SpriteKind::Pumpkin => 0.81, SpriteKind::Cabbage => 0.45, SpriteKind::Chest => 1.09, + SpriteKind::CommonLockedChest => 1.09, SpriteKind::DungeonChest0 => 1.09, SpriteKind::DungeonChest1 => 1.09, SpriteKind::DungeonChest2 => 1.09, @@ -261,8 +284,6 @@ impl SpriteKind { SpriteKind::Carrot => 0.18, SpriteKind::Radish => 0.18, SpriteKind::FireBowlGround => 0.55, - // TODO: Uncomment this when we have a way to open doors - // SpriteKind::Door => 3.0, SpriteKind::Bed => 1.54, SpriteKind::Bench => 0.5, SpriteKind::ChairSingle => 0.5, @@ -313,6 +334,8 @@ impl SpriteKind { | SpriteKind::WitchWindow | SpriteKind::SeaUrchin | SpriteKind::GlassBarrier + | SpriteKind::Keyhole + | SpriteKind::KeyDoor | SpriteKind::Bomb => 1.0, // TODO: Figure out if this should be solid or not. SpriteKind::Shelf => 1.0, @@ -353,16 +376,21 @@ impl SpriteKind { | SpriteKind::Frostwood | SpriteKind::Eldwood => 7.0 / 11.0, SpriteKind::Bamboo => 9.0 / 11.0, + SpriteKind::MagicalBarrier => 3.0, + SpriteKind::MagicalSeal => 1.0, _ => return None, }) } /// What loot table does collecting this sprite draw from? + /// None = block cannot be collected + /// Some(None) = block can be collected, but does not give back an item + /// Some(Some(_)) = block can be collected and gives back an item #[inline] - pub fn collectible_id(&self) -> Option> { + pub fn collectible_id(&self) -> Option>> { let item = LootSpec::Item; let table = LootSpec::LootTable; - Some(match self { + Some(Some(match self { SpriteKind::Apple => item("common.items.food.apple"), SpriteKind::Mushroom => item("common.items.food.mushroom"), SpriteKind::Velorite => item("common.items.mineral.ore.velorite"), @@ -420,9 +448,11 @@ impl SpriteKind { SpriteKind::DungeonChest4 => table("common.loot_tables.dungeon.tier-4.chest"), SpriteKind::DungeonChest5 => table("common.loot_tables.dungeon.tier-5.chest"), SpriteKind::Chest => table("common.loot_tables.sprite.chest"), + SpriteKind::CommonLockedChest => table("common.loot_tables.dungeon.tier-2.chest"), SpriteKind::ChestBuried => table("common.loot_tables.sprite.chest-buried"), SpriteKind::CoralChest => table("common.loot_tables.dungeon.sea_chapel.chest_coral"), SpriteKind::Mud => table("common.loot_tables.sprite.mud"), + SpriteKind::Grave => table("common.loot_tables.sprite.mud"), SpriteKind::Crate => table("common.loot_tables.sprite.crate"), SpriteKind::Wood => item("common.items.log.wood"), SpriteKind::Bamboo => item("common.items.log.bamboo"), @@ -430,8 +460,10 @@ impl SpriteKind { SpriteKind::Ironwood => item("common.items.log.ironwood"), SpriteKind::Frostwood => item("common.items.log.frostwood"), SpriteKind::Eldwood => item("common.items.log.eldwood"), + SpriteKind::MagicalBarrier => table("common.loot_tables.sprite.chest"), + SpriteKind::Keyhole => return Some(None), _ => return None, - }) + })) } /// Can this sprite be picked up to yield an item without a tool? @@ -443,7 +475,7 @@ impl SpriteKind { /// Is the sprite a container that will emit a mystery item? #[inline] pub fn is_container(&self) -> bool { - matches!(self.collectible_id(), Some(LootSpec::LootTable(_))) + matches!(self.collectible_id(), Some(Some(LootSpec::LootTable(_)))) } /// Which tool (if any) is needed to collect this sprite? @@ -478,6 +510,18 @@ impl SpriteKind { } } + /// Requires this item in the inventory to harvest, uses item_definition_id + // TODO: Do we want to consolidate this with mine_tool at all? Main differences are that mine tool requires item to be an equippable tool, be equipped, and does not consume item while required_item requires that the item be in the inventory and will consume the item on collecting the sprite. + pub fn unlock_condition(&self, cfg: Option) -> UnlockKind { + cfg + .and_then(|cfg| cfg.unlock) + .unwrap_or_else(|| match self { + // Example, do not let this merge with twigs requiring cheese to pick up + SpriteKind::CommonLockedChest => UnlockKind::Requires(ItemDefinitionId::Simple("common.items.utility.lockpick_0").to_owned()), + _ => UnlockKind::Free, + }) + } + #[inline] pub fn has_ori(&self) -> bool { matches!( @@ -522,8 +566,10 @@ impl SpriteKind { | SpriteKind::DropGate | SpriteKind::DropGateBottom | SpriteKind::Door + | SpriteKind::DoorDark | SpriteKind::Beehive | SpriteKind::PotionMinor + | SpriteKind::PotionDummy | SpriteKind::Bowl | SpriteKind::VialEmpty | SpriteKind::FireBowlGround @@ -551,6 +597,11 @@ impl SpriteKind { | SpriteKind::OvenArabic | SpriteKind::Hearth | SpriteKind::ForgeTools + | SpriteKind::Tent + | SpriteKind::Bedroll + | SpriteKind::Grave + | SpriteKind::Gravestone + | SpriteKind::MagicalBarrier ) } } @@ -573,3 +624,18 @@ impl<'a> TryFrom<&'a str> for SpriteKind { #[inline] fn try_from(s: &'a str) -> Result { SPRITE_KINDS.get(s).copied().ok_or(()) } } + +#[derive(Clone, Debug, Serialize, Deserialize)] +pub enum UnlockKind { + /// The sprite can be freely unlocked without any conditions + Free, + /// The sprite requires that the opening character has a given item in their inventory + Requires(ItemDefinitionIdOwned), + /// The sprite will consume the given item from the opening character's inventory + Consumes(ItemDefinitionIdOwned), +} + +#[derive(Default, Clone, Debug, Serialize, Deserialize)] +pub struct SpriteCfg { + pub unlock: Option, +} diff --git a/common/src/terrain/structure.rs b/common/src/terrain/structure.rs index 9a90dbf8f9..ababf2c9f2 100644 --- a/common/src/terrain/structure.rs +++ b/common/src/terrain/structure.rs @@ -10,9 +10,10 @@ use serde::Deserialize; use std::{num::NonZeroU8, sync::Arc}; use vek::*; + make_case_elim!( structure_block, - #[derive(Copy, Clone, PartialEq, Eq, Debug, Deserialize)] + #[derive(Clone, PartialEq, Debug, Deserialize)] #[repr(u8)] pub enum StructureBlock { None = 0, @@ -38,6 +39,9 @@ make_case_elim!( Baobab = 20, BirchWood = 21, FrostpineLeaves = 22, + RotatedSprite(kind: SpriteKind, ori: u8) = 23, + EntitySpawner(entitykind: String, spawn_chance: f32) = 24, + Keyhole(consumes: String) = 25, } ); @@ -81,12 +85,12 @@ impl assets::Compound for StructuresGroup { center: Vec3::from(sp.center), base, custom_indices: { - let mut indices = [None; 256]; - for (&idx, &custom) in default_custom_indices() + let mut indices = std::array::from_fn(|_| None); + for (&idx, custom) in default_custom_indices() .iter() .chain(sp.custom_indices.iter()) { - indices[idx as usize] = Some(custom); + indices[idx as usize] = Some(custom.clone()); } indices }, @@ -141,7 +145,7 @@ impl assets::Compound for BaseStructure { let dot_vox_data = &dot_vox_data.0; if let Some(model) = dot_vox_data.models.get(0) { - let mut palette = [StructureBlock::None; 256]; + let mut palette = std::array::from_fn(|_| StructureBlock::None); for (i, col) in dot_vox_data .palette @@ -169,7 +173,7 @@ impl assets::Compound for BaseStructure { } else { Ok(BaseStructure { vol: Dyna::filled(Vec3::zero(), None, ()), - palette: [StructureBlock::None; 256], + palette: std::array::from_fn(|_| StructureBlock::None), }) } } @@ -206,7 +210,7 @@ fn default_custom_indices() -> HashMap { blocks .iter() .enumerate() - .filter_map(|(i, sb)| Some((i as u8 + 1, (*sb)?))) + .filter_map(|(i, sb)| sb.as_ref().map(|sb| (i as u8 + 1, sb.clone()))) .collect() } diff --git a/common/src/volumes/vol_grid_2d.rs b/common/src/volumes/vol_grid_2d.rs index 6a389e24c4..821e7e1d3f 100644 --- a/common/src/volumes/vol_grid_2d.rs +++ b/common/src/volumes/vol_grid_2d.rs @@ -224,6 +224,11 @@ impl VolGrid2d { #[inline(always)] pub fn pos_key(&self, pos: Vec3) -> Vec2 { Self::chunk_key(pos) } + #[inline(always)] + pub fn pos_chunk(&self, pos: Vec3) -> Option<&V> { + self.get_key(self.pos_key(pos)) + } + pub fn iter(&self) -> ChunkIter { ChunkIter { iter: self.chunks.iter(), diff --git a/common/systems/src/character_behavior.rs b/common/systems/src/character_behavior.rs index f36b5a795b..d9e1eaf974 100644 --- a/common/systems/src/character_behavior.rs +++ b/common/systems/src/character_behavior.rs @@ -5,7 +5,9 @@ use specs::{ use common::{ comp::{ - self, character_state::OutputEvents, inventory::item::MaterialStatManifest, + self, + character_state::OutputEvents, + inventory::item::{tool::AbilityMap, MaterialStatManifest}, ActiveAbilities, Beam, Body, CharacterState, Combo, Controller, Density, Energy, Health, Inventory, InventoryManip, Mass, Melee, Ori, PhysicsState, Poise, Pos, SkillSet, StateUpdate, Stats, Vel, @@ -44,6 +46,7 @@ pub struct ReadData<'a> { skill_sets: ReadStorage<'a, SkillSet>, active_abilities: ReadStorage<'a, ActiveAbilities>, msm: ReadExpect<'a, MaterialStatManifest>, + ability_map: ReadExpect<'a, AbilityMap>, combos: ReadStorage<'a, Combo>, alignments: ReadStorage<'a, comp::Alignment>, terrain: ReadExpect<'a, TerrainGrid>, @@ -205,6 +208,7 @@ impl<'a> System<'a> for Sys { &read_data.lazy_update, &read_data.dt, &read_data.msm, + &read_data.ability_map, ); let state_update = j.character.handle_event(&j, &mut output_events, action); Self::publish_state_update(&mut join_struct, state_update, &mut output_events); @@ -223,6 +227,7 @@ impl<'a> System<'a> for Sys { &read_data.lazy_update, &read_data.dt, &read_data.msm, + &read_data.ability_map, ); let state_update = j.character.behavior(&j, &mut output_events); diff --git a/common/systems/tests/character_state.rs b/common/systems/tests/character_state.rs index 467308c546..f3fbfcf619 100644 --- a/common/systems/tests/character_state.rs +++ b/common/systems/tests/character_state.rs @@ -2,8 +2,8 @@ mod tests { use common::{ comp::{ - item::MaterialStatManifest, skills::GeneralSkill, CharacterState, Controller, Energy, - Ori, PhysicsState, Poise, Pos, Skill, Stats, Vel, + item::MaterialStatManifest, skills::GeneralSkill, tool::AbilityMap, CharacterState, + Controller, Energy, Ori, PhysicsState, Poise, Pos, Skill, Stats, Vel, }, resources::{DeltaTime, GameMode, Time}, terrain::{MapSizeLg, TerrainChunk}, @@ -36,6 +36,7 @@ mod tests { ); let msm = MaterialStatManifest::load().cloned(); state.ecs_mut().insert(msm); + state.ecs_mut().insert(AbilityMap::load().cloned()); state.ecs_mut().read_resource::