From ed4fd55bc39be0f09913b65989eff448de1a4ad4 Mon Sep 17 00:00:00 2001 From: flo Date: Thu, 15 Feb 2024 06:08:03 +0000 Subject: [PATCH] terracotta --- CHANGELOG.md | 2 + .../common/abilities/ability_set_manifest.ron | 64 +- .../abilities/custom/cursekeeper/beam.ron | 19 + .../custom/cursekeeper/summonbesieger.ron | 19 + .../custom/cursekeeper/summonjiangshi.ron | 19 + .../custom/cursekeeper/summonmogwai.ron | 19 + .../custom/cursekeeper/summonpursuer.ron | 19 + .../cursekeeper/summonshamanicspirit.ron | 19 + .../abilities/custom/cursekeeper/teleport.ron | 5 + .../abilities/custom/cursekeeper/trap.ron | 10 + .../abilities/custom/cursekeeper/unlive.ron | 9 + .../custom/jiangshi/poisonshockwave.ron | 24 + .../abilities/custom/jiangshi/teleport.ron | 5 + .../abilities/custom/mogwai/breathe.ron | 19 + .../custom/shamanic_spirit/ironspikes.ron | 10 + .../custom/shamanic_spirit/teleport.ron | 5 + .../terracotta_besieger/doublestrike.ron | 57 + .../custom/terracotta_besieger/multishot.ron | 16 + .../custom/terracotta_demolisher/drop.ron | 18 + .../custom/terracotta_demolisher/throw.ron | 18 + .../terracotta_punisher/doublestrike.ron | 45 + .../custom/terracotta_pursuer/dash.ron | 28 + .../terracotta_pursuer/doublestrike.ron | 57 + .../custom/terracotta_statue/blast.ron | 17 + .../custom/terracotta_statue/trap.ron | 10 + .../{steeldrum.ron => steeltonguedrum.ron} | 0 .../entity/dungeon/terracotta/besieger.ron | 11 + .../entity/dungeon/terracotta/cursekeeper.ron | 11 + .../dungeon/terracotta/cursekeeper_fake.ron | 12 + .../entity/dungeon/terracotta/demolisher.ron | 11 + .../entity/dungeon/terracotta/jiangshi.ron | 14 + .../entity/dungeon/terracotta/mogwai.ron | 11 + .../entity/dungeon/terracotta/punisher.ron | 11 + .../entity/dungeon/terracotta/pursuer.ron | 11 + .../dungeon/terracotta/shamanic_spirit.ron | 14 + .../dungeon/terracotta/terracotta_statue.ron | 11 + .../terracotta/terracotta_statue_key.ron | 11 + .../terracotta_statue_key_chance.ron | 11 + assets/common/item_i18n_manifest.ron | 73 +- .../items/keys/terracotta_key_chest.ron | 10 + .../common/items/keys/terracotta_key_door.ron | 10 + .../npc_armor/biped_large/terracotta.ron | 13 + .../biped_small/jiangshi/chest/jiangshi.ron | 13 + .../biped_small/jiangshi/foot/jiangshi.ron | 15 + .../biped_small/jiangshi/hand/jiangshi.ron | 13 + .../biped_small/jiangshi/head/jiangshi.ron | 13 + .../biped_small/jiangshi/pants/jiangshi.ron | 13 + .../shamanic_spirit/chest/shamanic_spirit.ron | 14 + .../shamanic_spirit/hand/shamanic_spirit.ron | 14 + .../shamanic_spirit/head/shamanic_spirit.ron | 14 + .../shamanic_spirit/pants/shamanic_spirit.ron | 14 + .../common/items/npc_armor/golem/mogwai.ron | 13 + .../bow/terracotta_besieger_bow.ron | 20 + .../hammer/terracotta_punisher_club.ron | 20 + .../sword/terracotta_pursuer_sword.ron | 20 + .../unique/cursekeeper_sceptre.ron | 20 + .../unique/cursekeeper_sceptre_fake.ron | 20 + .../items/npc_weapons/unique/jiangshi.ron | 20 + .../items/npc_weapons/unique/mogwai.ron | 20 + .../npc_weapons/unique/shamanic_spirit.ron | 20 + .../unique/terracotta_demolisher_fist.ron | 20 + .../npc_weapons/unique/terracotta_statue.ron | 21 + .../{steeldrum.ron => steeltonguedrum.ron} | 2 +- .../loadout/dungeon/terracotta/jiangshi.ron | 8 + .../dungeon/terracotta/shamanic_spirit.ron | 7 + .../dungeon/terracotta/chest_terracotta.ron | 4 + .../dungeon/terracotta/cursekeeper.ron | 7 + .../dungeon/terracotta/cursekeeper_extra.ron | 8 + .../loot_tables/dungeon/terracotta/enemy.ron | 6 + .../terracotta_statue_key_chance.ron | 6 + assets/common/npc_names.ron | 32 + assets/server/manifests/kits.ron | 2 +- assets/voxygen/audio/sfx.ron | 33 +- .../sfx/instrument/steeldrum/steeldrum_a.ogg | 3 - .../instrument/steeldrum/steeldrum_ac1.ogg | 3 - .../sfx/instrument/steeldrum/steeldrum_c.ogg | 3 - .../sfx/instrument/steeldrum/steeldrum_c1.ogg | 3 - .../instrument/steeldrum/steeldrum_c1ae.ogg | 3 - .../instrument/steeldrum/steeldrum_c1ag.ogg | 3 - .../instrument/steeldrum/steeldrum_c1c1.ogg | 3 - .../sfx/instrument/steeldrum/steeldrum_ce.ogg | 3 - .../sfx/instrument/steeldrum/steeldrum_d.ogg | 3 - .../sfx/instrument/steeldrum/steeldrum_d1.ogg | 3 - .../instrument/steeldrum/steeldrum_d1c1.ogg | 3 - .../sfx/instrument/steeldrum/steeldrum_e.ogg | 3 - .../instrument/steeldrum/steeldrum_ec1g.ogg | 3 - .../sfx/instrument/steeldrum/steeldrum_eg.ogg | 3 - .../sfx/instrument/steeldrum/steeldrum_g.ogg | 3 - .../steeltonguedrum/steeltonguedrum_a.ogg | 3 + .../steeltonguedrum/steeltonguedrum_ac1.ogg | 3 + .../steeltonguedrum/steeltonguedrum_c.ogg | 3 + .../steeltonguedrum/steeltonguedrum_c1.ogg | 3 + .../steeltonguedrum/steeltonguedrum_c1ae.ogg | 3 + .../steeltonguedrum/steeltonguedrum_c1ag.ogg | 3 + .../steeltonguedrum/steeltonguedrum_c1c1.ogg | 3 + .../steeltonguedrum/steeltonguedrum_ce.ogg | 3 + .../steeltonguedrum/steeltonguedrum_d.ogg | 3 + .../steeltonguedrum/steeltonguedrum_d1.ogg | 3 + .../steeltonguedrum/steeltonguedrum_d1c1.ogg | 3 + .../steeltonguedrum/steeltonguedrum_e.ogg | 3 + .../steeltonguedrum/steeltonguedrum_eg.ogg | 3 + .../steeltonguedrum/steeltonguedrum_g.ogg | 3 + .../element/ui/map/buttons/terracotta.png | 3 + .../element/ui/map/buttons/terracotta_bg.png | 3 + .../ui/map/buttons/terracotta_hover.png | 3 + assets/voxygen/i18n/en/body.ftl | 21 + assets/voxygen/i18n/en/hud/map.ftl | 1 + assets/voxygen/i18n/en/item/armor/npc.ftl | 33 + assets/voxygen/i18n/en/item/items/key.ftl | 6 + .../en/item/weapon/musical_instrument.ftl | 4 +- assets/voxygen/i18n/en/item/weapon/npc.ftl | 30 + assets/voxygen/item_image_manifest.ron | 12 +- .../voxel/biped_large_central_manifest.ron | 284 ++++- .../voxel/biped_large_lateral_manifest.ron | 412 +++++++ .../biped_small_armor_chest_manifest.ron | 6 + .../voxel/biped_small_armor_foot_manifest.ron | 8 + .../voxel/biped_small_armor_hand_manifest.ron | 16 + .../voxel/biped_small_armor_head_manifest.ron | 6 + .../biped_small_armor_pants_manifest.ron | 6 + .../voxygen/voxel/biped_weapon_manifest.ron | 38 +- .../voxygen/voxel/golem_central_manifest.ron | 42 + .../voxygen/voxel/golem_lateral_manifest.ron | 70 ++ assets/voxygen/voxel/item_drop_manifest.ron | 4 +- assets/voxygen/voxel/npc/jiangshi/chest.vox | 3 + assets/voxygen/voxel/npc/jiangshi/foot_r.vox | 3 + assets/voxygen/voxel/npc/jiangshi/hand_r.vox | 3 + assets/voxygen/voxel/npc/jiangshi/head.vox | 3 + assets/voxygen/voxel/npc/jiangshi/pants.vox | 3 + .../voxygen/voxel/npc/mogwai/male/mogwai.vox | 3 + .../voxel/npc/shamanic_spirit/chest.vox | 3 + .../voxel/npc/shamanic_spirit/hand_r.vox | 3 + .../voxel/npc/shamanic_spirit/head.vox | 3 + .../voxel/npc/shamanic_spirit/pants.vox | 3 + .../voxel/npc/terracotta/cursekeeper.vox | 3 + .../npc/terracotta/terracotta_besieger.vox | 3 + .../npc/terracotta/terracotta_demolisher.vox | 3 + .../npc/terracotta/terracotta_punisher.vox | 3 + .../npc/terracotta/terracotta_pursuer.vox | 3 + .../voxel/object/key_terracotta_chest.vox | 3 + .../voxel/object/key_terracotta_door.vox | 3 + .../object/terracotta_demolisher_bomb.vox | 3 + assets/voxygen/voxel/object_manifest.ron | 40 + .../voxel/sprite/chests/chest_terracotta.vox | 3 + .../sprite/furniture/terracotta_keydoor.vox | 3 + .../sprite/furniture/terracotta_keyhole.vox | 3 + .../sprite/furniture/terracotta_statue_0.vox | 3 + .../sprite/furniture/terracotta_statue_1.vox | 3 + .../sprite/furniture/terracotta_statue_2.vox | 3 + .../sprite/furniture/terracotta_statue_3.vox | 3 + .../sprite/furniture/terracotta_statue_4.vox | 3 + .../voxel/sprite/misc/terracotta_block-0.vox | 3 + .../voxel/sprite/misc/terracotta_block-1.vox | 3 + .../voxel/sprite/misc/terracotta_block-2.vox | 3 + .../voxel/sprite/misc/terracotta_block-3.vox | 3 + .../voxel/sprite/misc/terracotta_block-4.vox | 3 + .../voxel/sprite/misc/terracotta_block-5.vox | 3 + .../voxel/sprite/misc/terracotta_block-6.vox | 3 + assets/voxygen/voxel/sprite_manifest.ron | 86 ++ .../misc/magic_shamanic_spirit.vox | 3 + .../weapon/bow/terracotta_besieger_bow.vox | 3 + .../hammer/terracotta_punisher_club.vox | 3 + .../voxel/weapon/projectile/besieger_bolt.vox | 3 + .../weapon/projectile/laser_beam_small.vox | 3 + .../weapon/sceptre/sceptre_cursekeeper.vox | 3 + ..._sea_bishop.vox => sceptre_sea_bishop.vox} | 0 .../weapon/sword/terracotta_pursuer_sword.vox | 3 + .../voxygen/voxel/weapon/tool/steeldrum.vox | 3 - .../voxel/weapon/tool/steeltonguedrum.vox | 3 + .../terracotta/terracotta_decor_large.ron | 20 + .../terracotta/terracotta_decor_small.ron | 36 + .../terracotta/decor/terracotta_decor-0.vox | 3 + .../terracotta/decor/terracotta_decor-1.vox | 3 + .../terracotta/decor/terracotta_decor-2.vox | 3 + .../terracotta/decor/terracotta_decor-3.vox | 3 + .../terracotta/decor/terracotta_decor-4.vox | 3 + .../terracotta/decor/terracotta_decor-5.vox | 3 + common/net/src/msg/world_msg.rs | 1 + common/src/comp/agent.rs | 4 +- common/src/comp/body.rs | 36 +- common/src/comp/body/biped_large.rs | 44 +- common/src/comp/body/biped_small.rs | 10 +- common/src/comp/body/golem.rs | 6 +- common/src/comp/body/object.rs | 33 +- common/src/comp/fluid_dynamics.rs | 1 + common/src/comp/inventory/loadout_builder.rs | 48 + common/src/outcome.rs | 4 + common/src/states/basic_beam.rs | 11 +- common/src/states/basic_ranged.rs | 10 +- common/src/states/sprite_interact.rs | 3 +- common/src/states/sprite_summon.rs | 63 +- common/src/terrain/block.rs | 9 +- common/src/terrain/site.rs | 3 + common/src/terrain/sprite.rs | 32 +- common/src/terrain/structure.rs | 7 +- common/systems/src/buff.rs | 2 +- rtsim/src/gen/site.rs | 1 + server/agent/src/action_nodes.rs | 28 + server/agent/src/attack.rs | 182 +++ server/agent/src/data.rs | 6 + server/src/events/inventory_manip.rs | 3 + .../src/migrations/V55__steeltonguedrum.sql | 3 + voxygen/anim/src/biped_large/combomelee.rs | 19 +- voxygen/anim/src/biped_large/mod.rs | 67 +- voxygen/anim/src/biped_large/shoot.rs | 194 ++- voxygen/anim/src/biped_large/spritesummon.rs | 2 +- voxygen/anim/src/biped_large/summon.rs | 42 + voxygen/anim/src/biped_large/wield.rs | 2 +- voxygen/anim/src/biped_small/combomelee.rs | 2 +- voxygen/anim/src/biped_small/mod.rs | 21 +- voxygen/anim/src/biped_small/spritesummon.rs | 86 ++ voxygen/anim/src/biped_small/wield.rs | 37 +- voxygen/anim/src/character/music.rs | 5 +- voxygen/anim/src/character/wield.rs | 2 +- voxygen/anim/src/golem/beam.rs | 69 +- voxygen/anim/src/golem/mod.rs | 10 + voxygen/src/audio/sfx/mod.rs | 38 +- voxygen/src/discord.rs | 3 + voxygen/src/hud/img_ids.rs | 3 + voxygen/src/hud/map.rs | 9 +- voxygen/src/hud/minimap.rs | 3 + voxygen/src/hud/mod.rs | 3 +- voxygen/src/hud/util.rs | 2 +- voxygen/src/scene/figure/mod.rs | 42 +- voxygen/src/scene/particle.rs | 9 + voxygen/src/scene/trail.rs | 3 +- world/src/block/mod.rs | 11 + world/src/civ/mod.rs | 38 +- world/src/lib.rs | 1 + world/src/site/economy/context.rs | 1 + world/src/site/mod.rs | 15 + world/src/site/namegen.rs | 27 +- world/src/site2/mod.rs | 137 +++ world/src/site2/plot.rs | 9 +- world/src/site2/plot/terracotta_house.rs | 405 ++++++ world/src/site2/plot/terracotta_palace.rs | 1086 +++++++++++++++++ world/src/site2/plot/terracotta_yard.rs | 255 ++++ 236 files changed, 5625 insertions(+), 234 deletions(-) create mode 100644 assets/common/abilities/custom/cursekeeper/beam.ron create mode 100644 assets/common/abilities/custom/cursekeeper/summonbesieger.ron create mode 100644 assets/common/abilities/custom/cursekeeper/summonjiangshi.ron create mode 100644 assets/common/abilities/custom/cursekeeper/summonmogwai.ron create mode 100644 assets/common/abilities/custom/cursekeeper/summonpursuer.ron create mode 100644 assets/common/abilities/custom/cursekeeper/summonshamanicspirit.ron create mode 100644 assets/common/abilities/custom/cursekeeper/teleport.ron create mode 100644 assets/common/abilities/custom/cursekeeper/trap.ron create mode 100644 assets/common/abilities/custom/cursekeeper/unlive.ron create mode 100644 assets/common/abilities/custom/jiangshi/poisonshockwave.ron create mode 100644 assets/common/abilities/custom/jiangshi/teleport.ron create mode 100644 assets/common/abilities/custom/mogwai/breathe.ron create mode 100644 assets/common/abilities/custom/shamanic_spirit/ironspikes.ron create mode 100644 assets/common/abilities/custom/shamanic_spirit/teleport.ron create mode 100644 assets/common/abilities/custom/terracotta_besieger/doublestrike.ron create mode 100644 assets/common/abilities/custom/terracotta_besieger/multishot.ron create mode 100644 assets/common/abilities/custom/terracotta_demolisher/drop.ron create mode 100644 assets/common/abilities/custom/terracotta_demolisher/throw.ron create mode 100644 assets/common/abilities/custom/terracotta_punisher/doublestrike.ron create mode 100644 assets/common/abilities/custom/terracotta_pursuer/dash.ron create mode 100644 assets/common/abilities/custom/terracotta_pursuer/doublestrike.ron create mode 100644 assets/common/abilities/custom/terracotta_statue/blast.ron create mode 100644 assets/common/abilities/custom/terracotta_statue/trap.ron rename assets/common/abilities/music/{steeldrum.ron => steeltonguedrum.ron} (100%) create mode 100644 assets/common/entity/dungeon/terracotta/besieger.ron create mode 100644 assets/common/entity/dungeon/terracotta/cursekeeper.ron create mode 100644 assets/common/entity/dungeon/terracotta/cursekeeper_fake.ron create mode 100644 assets/common/entity/dungeon/terracotta/demolisher.ron create mode 100644 assets/common/entity/dungeon/terracotta/jiangshi.ron create mode 100644 assets/common/entity/dungeon/terracotta/mogwai.ron create mode 100644 assets/common/entity/dungeon/terracotta/punisher.ron create mode 100644 assets/common/entity/dungeon/terracotta/pursuer.ron create mode 100644 assets/common/entity/dungeon/terracotta/shamanic_spirit.ron create mode 100644 assets/common/entity/dungeon/terracotta/terracotta_statue.ron create mode 100644 assets/common/entity/dungeon/terracotta/terracotta_statue_key.ron create mode 100644 assets/common/entity/dungeon/terracotta/terracotta_statue_key_chance.ron create mode 100644 assets/common/items/keys/terracotta_key_chest.ron create mode 100644 assets/common/items/keys/terracotta_key_door.ron create mode 100644 assets/common/items/npc_armor/biped_large/terracotta.ron create mode 100644 assets/common/items/npc_armor/biped_small/jiangshi/chest/jiangshi.ron create mode 100644 assets/common/items/npc_armor/biped_small/jiangshi/foot/jiangshi.ron create mode 100644 assets/common/items/npc_armor/biped_small/jiangshi/hand/jiangshi.ron create mode 100644 assets/common/items/npc_armor/biped_small/jiangshi/head/jiangshi.ron create mode 100644 assets/common/items/npc_armor/biped_small/jiangshi/pants/jiangshi.ron create mode 100644 assets/common/items/npc_armor/biped_small/shamanic_spirit/chest/shamanic_spirit.ron create mode 100644 assets/common/items/npc_armor/biped_small/shamanic_spirit/hand/shamanic_spirit.ron create mode 100644 assets/common/items/npc_armor/biped_small/shamanic_spirit/head/shamanic_spirit.ron create mode 100644 assets/common/items/npc_armor/biped_small/shamanic_spirit/pants/shamanic_spirit.ron create mode 100644 assets/common/items/npc_armor/golem/mogwai.ron create mode 100644 assets/common/items/npc_weapons/bow/terracotta_besieger_bow.ron create mode 100644 assets/common/items/npc_weapons/hammer/terracotta_punisher_club.ron create mode 100644 assets/common/items/npc_weapons/sword/terracotta_pursuer_sword.ron create mode 100644 assets/common/items/npc_weapons/unique/cursekeeper_sceptre.ron create mode 100644 assets/common/items/npc_weapons/unique/cursekeeper_sceptre_fake.ron create mode 100644 assets/common/items/npc_weapons/unique/jiangshi.ron create mode 100644 assets/common/items/npc_weapons/unique/mogwai.ron create mode 100644 assets/common/items/npc_weapons/unique/shamanic_spirit.ron create mode 100644 assets/common/items/npc_weapons/unique/terracotta_demolisher_fist.ron create mode 100644 assets/common/items/npc_weapons/unique/terracotta_statue.ron rename assets/common/items/tool/instruments/{steeldrum.ron => steeltonguedrum.ron} (89%) create mode 100644 assets/common/loadout/dungeon/terracotta/jiangshi.ron create mode 100644 assets/common/loadout/dungeon/terracotta/shamanic_spirit.ron create mode 100644 assets/common/loot_tables/dungeon/terracotta/chest_terracotta.ron create mode 100644 assets/common/loot_tables/dungeon/terracotta/cursekeeper.ron create mode 100644 assets/common/loot_tables/dungeon/terracotta/cursekeeper_extra.ron create mode 100644 assets/common/loot_tables/dungeon/terracotta/enemy.ron create mode 100644 assets/common/loot_tables/dungeon/terracotta/terracotta_statue_key_chance.ron delete mode 100644 assets/voxygen/audio/sfx/instrument/steeldrum/steeldrum_a.ogg delete mode 100644 assets/voxygen/audio/sfx/instrument/steeldrum/steeldrum_ac1.ogg delete mode 100644 assets/voxygen/audio/sfx/instrument/steeldrum/steeldrum_c.ogg delete mode 100644 assets/voxygen/audio/sfx/instrument/steeldrum/steeldrum_c1.ogg delete mode 100644 assets/voxygen/audio/sfx/instrument/steeldrum/steeldrum_c1ae.ogg delete mode 100644 assets/voxygen/audio/sfx/instrument/steeldrum/steeldrum_c1ag.ogg delete mode 100644 assets/voxygen/audio/sfx/instrument/steeldrum/steeldrum_c1c1.ogg delete mode 100644 assets/voxygen/audio/sfx/instrument/steeldrum/steeldrum_ce.ogg delete mode 100644 assets/voxygen/audio/sfx/instrument/steeldrum/steeldrum_d.ogg delete mode 100644 assets/voxygen/audio/sfx/instrument/steeldrum/steeldrum_d1.ogg delete mode 100644 assets/voxygen/audio/sfx/instrument/steeldrum/steeldrum_d1c1.ogg delete mode 100644 assets/voxygen/audio/sfx/instrument/steeldrum/steeldrum_e.ogg delete mode 100644 assets/voxygen/audio/sfx/instrument/steeldrum/steeldrum_ec1g.ogg delete mode 100644 assets/voxygen/audio/sfx/instrument/steeldrum/steeldrum_eg.ogg delete mode 100644 assets/voxygen/audio/sfx/instrument/steeldrum/steeldrum_g.ogg create mode 100644 assets/voxygen/audio/sfx/instrument/steeltonguedrum/steeltonguedrum_a.ogg create mode 100644 assets/voxygen/audio/sfx/instrument/steeltonguedrum/steeltonguedrum_ac1.ogg create mode 100644 assets/voxygen/audio/sfx/instrument/steeltonguedrum/steeltonguedrum_c.ogg create mode 100644 assets/voxygen/audio/sfx/instrument/steeltonguedrum/steeltonguedrum_c1.ogg create mode 100644 assets/voxygen/audio/sfx/instrument/steeltonguedrum/steeltonguedrum_c1ae.ogg create mode 100644 assets/voxygen/audio/sfx/instrument/steeltonguedrum/steeltonguedrum_c1ag.ogg create mode 100644 assets/voxygen/audio/sfx/instrument/steeltonguedrum/steeltonguedrum_c1c1.ogg create mode 100644 assets/voxygen/audio/sfx/instrument/steeltonguedrum/steeltonguedrum_ce.ogg create mode 100644 assets/voxygen/audio/sfx/instrument/steeltonguedrum/steeltonguedrum_d.ogg create mode 100644 assets/voxygen/audio/sfx/instrument/steeltonguedrum/steeltonguedrum_d1.ogg create mode 100644 assets/voxygen/audio/sfx/instrument/steeltonguedrum/steeltonguedrum_d1c1.ogg create mode 100644 assets/voxygen/audio/sfx/instrument/steeltonguedrum/steeltonguedrum_e.ogg create mode 100644 assets/voxygen/audio/sfx/instrument/steeltonguedrum/steeltonguedrum_eg.ogg create mode 100644 assets/voxygen/audio/sfx/instrument/steeltonguedrum/steeltonguedrum_g.ogg create mode 100644 assets/voxygen/element/ui/map/buttons/terracotta.png create mode 100644 assets/voxygen/element/ui/map/buttons/terracotta_bg.png create mode 100644 assets/voxygen/element/ui/map/buttons/terracotta_hover.png create mode 100644 assets/voxygen/voxel/npc/jiangshi/chest.vox create mode 100644 assets/voxygen/voxel/npc/jiangshi/foot_r.vox create mode 100644 assets/voxygen/voxel/npc/jiangshi/hand_r.vox create mode 100644 assets/voxygen/voxel/npc/jiangshi/head.vox create mode 100644 assets/voxygen/voxel/npc/jiangshi/pants.vox create mode 100644 assets/voxygen/voxel/npc/mogwai/male/mogwai.vox create mode 100644 assets/voxygen/voxel/npc/shamanic_spirit/chest.vox create mode 100644 assets/voxygen/voxel/npc/shamanic_spirit/hand_r.vox create mode 100644 assets/voxygen/voxel/npc/shamanic_spirit/head.vox create mode 100644 assets/voxygen/voxel/npc/shamanic_spirit/pants.vox create mode 100644 assets/voxygen/voxel/npc/terracotta/cursekeeper.vox create mode 100644 assets/voxygen/voxel/npc/terracotta/terracotta_besieger.vox create mode 100644 assets/voxygen/voxel/npc/terracotta/terracotta_demolisher.vox create mode 100644 assets/voxygen/voxel/npc/terracotta/terracotta_punisher.vox create mode 100644 assets/voxygen/voxel/npc/terracotta/terracotta_pursuer.vox create mode 100644 assets/voxygen/voxel/object/key_terracotta_chest.vox create mode 100644 assets/voxygen/voxel/object/key_terracotta_door.vox create mode 100644 assets/voxygen/voxel/object/terracotta_demolisher_bomb.vox create mode 100644 assets/voxygen/voxel/sprite/chests/chest_terracotta.vox create mode 100644 assets/voxygen/voxel/sprite/furniture/terracotta_keydoor.vox create mode 100644 assets/voxygen/voxel/sprite/furniture/terracotta_keyhole.vox create mode 100644 assets/voxygen/voxel/sprite/furniture/terracotta_statue_0.vox create mode 100644 assets/voxygen/voxel/sprite/furniture/terracotta_statue_1.vox create mode 100644 assets/voxygen/voxel/sprite/furniture/terracotta_statue_2.vox create mode 100644 assets/voxygen/voxel/sprite/furniture/terracotta_statue_3.vox create mode 100644 assets/voxygen/voxel/sprite/furniture/terracotta_statue_4.vox create mode 100644 assets/voxygen/voxel/sprite/misc/terracotta_block-0.vox create mode 100644 assets/voxygen/voxel/sprite/misc/terracotta_block-1.vox create mode 100644 assets/voxygen/voxel/sprite/misc/terracotta_block-2.vox create mode 100644 assets/voxygen/voxel/sprite/misc/terracotta_block-3.vox create mode 100644 assets/voxygen/voxel/sprite/misc/terracotta_block-4.vox create mode 100644 assets/voxygen/voxel/sprite/misc/terracotta_block-5.vox create mode 100644 assets/voxygen/voxel/sprite/misc/terracotta_block-6.vox create mode 100644 assets/voxygen/voxel/weapon/biped_small/misc/magic_shamanic_spirit.vox create mode 100644 assets/voxygen/voxel/weapon/bow/terracotta_besieger_bow.vox create mode 100644 assets/voxygen/voxel/weapon/hammer/terracotta_punisher_club.vox create mode 100644 assets/voxygen/voxel/weapon/projectile/besieger_bolt.vox create mode 100644 assets/voxygen/voxel/weapon/projectile/laser_beam_small.vox create mode 100644 assets/voxygen/voxel/weapon/sceptre/sceptre_cursekeeper.vox rename assets/voxygen/voxel/weapon/sceptre/{scepter_sea_bishop.vox => sceptre_sea_bishop.vox} (100%) create mode 100644 assets/voxygen/voxel/weapon/sword/terracotta_pursuer_sword.vox delete mode 100644 assets/voxygen/voxel/weapon/tool/steeldrum.vox create mode 100644 assets/voxygen/voxel/weapon/tool/steeltonguedrum.vox create mode 100644 assets/world/manifests/site_structures/terracotta/terracotta_decor_large.ron create mode 100644 assets/world/manifests/site_structures/terracotta/terracotta_decor_small.ron create mode 100644 assets/world/structure/terracotta/decor/terracotta_decor-0.vox create mode 100644 assets/world/structure/terracotta/decor/terracotta_decor-1.vox create mode 100644 assets/world/structure/terracotta/decor/terracotta_decor-2.vox create mode 100644 assets/world/structure/terracotta/decor/terracotta_decor-3.vox create mode 100644 assets/world/structure/terracotta/decor/terracotta_decor-4.vox create mode 100644 assets/world/structure/terracotta/decor/terracotta_decor-5.vox create mode 100644 server/src/migrations/V55__steeltonguedrum.sql create mode 100644 voxygen/anim/src/biped_small/spritesummon.rs create mode 100644 world/src/site2/plot/terracotta_house.rs create mode 100644 world/src/site2/plot/terracotta_palace.rs create mode 100644 world/src/site2/plot/terracotta_yard.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index f13c959fab..1dab89493d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -46,6 +46,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - A flag argument type for commands - The ability to turn lamp-like sprites on and off - Added Autumn Forests, Cherry Blossom Forests, and Maple Trees. +- Added reworked dungeon: Haniwa Catacombs +- Added dungeon: Terracotta Ruins ### Changed diff --git a/assets/common/abilities/ability_set_manifest.ron b/assets/common/abilities/ability_set_manifest.ron index a532cb57aa..f7b907f25b 100644 --- a/assets/common/abilities/ability_set_manifest.ron +++ b/assets/common/abilities/ability_set_manifest.ron @@ -914,9 +914,9 @@ secondary: Simple(None, "common.abilities.music.sitar"), abilities: [], ), - Custom("Steeldrum"): ( - primary: Simple(None, "common.abilities.music.steeldrum"), - secondary: Simple(None, "common.abilities.music.steeldrum"), + Custom("Steeltonguedrum"): ( + primary: Simple(None, "common.abilities.music.steeltonguedrum"), + secondary: Simple(None, "common.abilities.music.steeltonguedrum"), abilities: [], ), Custom("Shamisen"): ( @@ -997,4 +997,62 @@ Simple(None, "common.abilities.haniwa.archer.explosive") ], ), + // Terracotta + Custom("TerracottaBesieger"): ( + primary: Simple(None, "common.abilities.custom.terracotta_besieger.doublestrike"), + secondary: Simple(None, "common.abilities.custom.terracotta_besieger.multishot"), + abilities: [], + ), + Custom("TerracottaDemolisher"): ( + primary: Simple(None, "common.abilities.custom.terracotta_demolisher.drop"), + secondary: Simple(None, "common.abilities.custom.terracotta_demolisher.throw"), + abilities: [], + ), + Custom("TerracottaPursuer"): ( + primary: Simple(None, "common.abilities.custom.terracotta_pursuer.doublestrike"), + secondary: Simple(None, "common.abilities.custom.terracotta_pursuer.dash"), + abilities: [], + ), + Custom("TerracottaPunisher"): ( + primary: Simple(None, "common.abilities.custom.terracotta_punisher.doublestrike"), + secondary: Simple(None, "common.abilities.custom.terracotta_punisher.doublestrike"), + abilities: [], + ), + Custom("TerracottaStatue"): ( + primary: Simple(None, "common.abilities.custom.terracotta_statue.trap"), + secondary: Simple(None, "common.abilities.custom.terracotta_statue.blast"), + abilities: [], + ), + Custom("Mogwai"): ( + primary: Simple(None, "common.abilities.custom.mogwai.breathe"), + secondary: Simple(None, "common.abilities.custom.mogwai.breathe"), + abilities: [], + ), + Custom("Cursekeeper"): ( + primary: Simple(None, "common.abilities.custom.cursekeeper.beam"), + secondary: Simple(None, "common.abilities.custom.cursekeeper.trap"), + abilities: [ + Simple(None, "common.abilities.custom.cursekeeper.summonmogwai"), + Simple(None, "common.abilities.custom.cursekeeper.summonbesieger"), + Simple(None, "common.abilities.custom.cursekeeper.summonpursuer"), + Simple(None, "common.abilities.custom.cursekeeper.summonshamanicspirit"), + Simple(None, "common.abilities.custom.cursekeeper.summonjiangshi"), + Simple(None, "common.abilities.custom.cursekeeper.teleport"), + ], + ), + Custom("CursekeeperFake"): ( + primary: Simple(None, "common.abilities.custom.cursekeeper.summonshamanicspirit"), + secondary: Simple(None, "common.abilities.custom.cursekeeper.unlive"), + abilities: [], + ), + Custom("ShamanicSpirit"): ( + primary: Simple(None, "common.abilities.custom.shamanic_spirit.ironspikes"), + secondary: Simple(None, "common.abilities.custom.shamanic_spirit.teleport"), + abilities: [], + ), + Custom("Jiangshi"): ( + primary: Simple(None, "common.abilities.custom.jiangshi.poisonshockwave"), + secondary: Simple(None, "common.abilities.custom.jiangshi.teleport"), + abilities: [], + ), }) diff --git a/assets/common/abilities/custom/cursekeeper/beam.ron b/assets/common/abilities/custom/cursekeeper/beam.ron new file mode 100644 index 0000000000..fc4419c31a --- /dev/null +++ b/assets/common/abilities/custom/cursekeeper/beam.ron @@ -0,0 +1,19 @@ +BasicBeam( + buildup_duration: 0.3, + recover_duration: 1.5, + beam_duration: 2.0, + damage: 20.0, + tick_rate: 3.0, + range: 22.0, + max_angle: 22.5, + damage_effect: Some(Buff(( + kind: Poisoned, + dur_secs: 3.0, + strength: DamageFraction(0.5), + chance: 1.0, + ))), + energy_regen: 2, + energy_drain: 0, + ori_rate: 0.5, + specifier: Poison, +) diff --git a/assets/common/abilities/custom/cursekeeper/summonbesieger.ron b/assets/common/abilities/custom/cursekeeper/summonbesieger.ron new file mode 100644 index 0000000000..2f564f8251 --- /dev/null +++ b/assets/common/abilities/custom/cursekeeper/summonbesieger.ron @@ -0,0 +1,19 @@ +BasicSummon( + buildup_duration: 0.2, + cast_duration: 0.3, + recover_duration: 4.0, + summon_amount: 1, + summon_distance: (4, 4), + summon_info: ( + body: BipedLarge(( + species: TerracottaBesieger, + body_type: Male, + )), + scale: None, + use_npc_name: true, + has_health: true, + loadout_config: None, + skillset_config: Some(Rank3), + ), + duration: None, +) diff --git a/assets/common/abilities/custom/cursekeeper/summonjiangshi.ron b/assets/common/abilities/custom/cursekeeper/summonjiangshi.ron new file mode 100644 index 0000000000..c76629da18 --- /dev/null +++ b/assets/common/abilities/custom/cursekeeper/summonjiangshi.ron @@ -0,0 +1,19 @@ +BasicSummon( + buildup_duration: 0.3, + cast_duration: 0.3, + recover_duration: 1.0, + summon_amount: 1, + summon_distance: (2, 2), + summon_info: ( + body: BipedSmall(( + species: Jiangshi, + body_type: Male, + )), + scale: None, + use_npc_name: true, + has_health: true, + loadout_config: Some(JiangshiSummon), + skillset_config: Some(Rank5), + ), + duration: None, +) diff --git a/assets/common/abilities/custom/cursekeeper/summonmogwai.ron b/assets/common/abilities/custom/cursekeeper/summonmogwai.ron new file mode 100644 index 0000000000..cb2abb8303 --- /dev/null +++ b/assets/common/abilities/custom/cursekeeper/summonmogwai.ron @@ -0,0 +1,19 @@ +BasicSummon( + buildup_duration: 0.2, + cast_duration: 0.3, + recover_duration: 4.0, + summon_amount: 1, + summon_distance: (4, 4), + summon_info: ( + body: Golem(( + species: Mogwai, + body_type: Male, + )), + scale: None, + use_npc_name: true, + has_health: true, + loadout_config: None, + skillset_config: Some(Rank3), + ), + duration: None, +) diff --git a/assets/common/abilities/custom/cursekeeper/summonpursuer.ron b/assets/common/abilities/custom/cursekeeper/summonpursuer.ron new file mode 100644 index 0000000000..676bf75db7 --- /dev/null +++ b/assets/common/abilities/custom/cursekeeper/summonpursuer.ron @@ -0,0 +1,19 @@ +BasicSummon( + buildup_duration: 0.2, + cast_duration: 0.3, + recover_duration: 4.0, + summon_amount: 1, + summon_distance: (4, 4), + summon_info: ( + body: BipedLarge(( + species: TerracottaPursuer, + body_type: Male, + )), + scale: None, + use_npc_name: true, + has_health: true, + loadout_config: None, + skillset_config: Some(Rank3), + ), + duration: None, +) diff --git a/assets/common/abilities/custom/cursekeeper/summonshamanicspirit.ron b/assets/common/abilities/custom/cursekeeper/summonshamanicspirit.ron new file mode 100644 index 0000000000..7c95960189 --- /dev/null +++ b/assets/common/abilities/custom/cursekeeper/summonshamanicspirit.ron @@ -0,0 +1,19 @@ +BasicSummon( + buildup_duration: 0.3, + cast_duration: 0.3, + recover_duration: 1.0, + summon_amount: 1, + summon_distance: (2, 2), + summon_info: ( + body: BipedSmall(( + species: ShamanicSpirit, + body_type: Male, + )), + scale: None, + use_npc_name: true, + has_health: true, + loadout_config: Some(ShamanicSpiritSummon), + skillset_config: Some(Rank5), + ), + duration: None, +) diff --git a/assets/common/abilities/custom/cursekeeper/teleport.ron b/assets/common/abilities/custom/cursekeeper/teleport.ron new file mode 100644 index 0000000000..385b8486ac --- /dev/null +++ b/assets/common/abilities/custom/cursekeeper/teleport.ron @@ -0,0 +1,5 @@ +Blink( + buildup_duration: 0.75, + recover_duration: 0.25, + max_range: 100.0, +) \ No newline at end of file diff --git a/assets/common/abilities/custom/cursekeeper/trap.ron b/assets/common/abilities/custom/cursekeeper/trap.ron new file mode 100644 index 0000000000..685a2f5234 --- /dev/null +++ b/assets/common/abilities/custom/cursekeeper/trap.ron @@ -0,0 +1,10 @@ +SpriteSummon( + buildup_duration: 1.5, + cast_duration: 0.1, + recover_duration: 3.0, + sprite: Empty, + del_timeout: Some((8, 5)), + summon_distance: (2, 50), + sparseness: 0.0, + angle: 360, +) \ No newline at end of file diff --git a/assets/common/abilities/custom/cursekeeper/unlive.ron b/assets/common/abilities/custom/cursekeeper/unlive.ron new file mode 100644 index 0000000000..cf68be5286 --- /dev/null +++ b/assets/common/abilities/custom/cursekeeper/unlive.ron @@ -0,0 +1,9 @@ +SelfBuff( + buildup_duration: 0.1, + cast_duration: 0.1, + recover_duration: 0.1, + buff_kind: Burning, + buff_strength: 2000.0, + buff_duration: Some(60.0), + energy_cost: 0, +) diff --git a/assets/common/abilities/custom/jiangshi/poisonshockwave.ron b/assets/common/abilities/custom/jiangshi/poisonshockwave.ron new file mode 100644 index 0000000000..e7a0691fbb --- /dev/null +++ b/assets/common/abilities/custom/jiangshi/poisonshockwave.ron @@ -0,0 +1,24 @@ +Shockwave( + energy_cost: 0, + buildup_duration: 0.3, + swing_duration: 0.3, + recover_duration: 2.5, + damage: 25.0, + poise_damage: 10, + knockback: (strength: 18.0, direction: Away), + shockwave_angle: 360.0, + shockwave_vertical_angle: 360.0, + shockwave_speed: 15.0, + shockwave_duration: 2.0, + dodgeable: Roll, + move_efficiency: 0.0, + damage_kind: Crushing, + specifier: Poison, + ori_rate: 1.0, + damage_effect: Some(Buff(( + kind: Poisoned, + dur_secs: 3.0, + strength: DamageFraction(0.6), + chance: 1.0, + ))), +) diff --git a/assets/common/abilities/custom/jiangshi/teleport.ron b/assets/common/abilities/custom/jiangshi/teleport.ron new file mode 100644 index 0000000000..385b8486ac --- /dev/null +++ b/assets/common/abilities/custom/jiangshi/teleport.ron @@ -0,0 +1,5 @@ +Blink( + buildup_duration: 0.75, + recover_duration: 0.25, + max_range: 100.0, +) \ No newline at end of file diff --git a/assets/common/abilities/custom/mogwai/breathe.ron b/assets/common/abilities/custom/mogwai/breathe.ron new file mode 100644 index 0000000000..fc4419c31a --- /dev/null +++ b/assets/common/abilities/custom/mogwai/breathe.ron @@ -0,0 +1,19 @@ +BasicBeam( + buildup_duration: 0.3, + recover_duration: 1.5, + beam_duration: 2.0, + damage: 20.0, + tick_rate: 3.0, + range: 22.0, + max_angle: 22.5, + damage_effect: Some(Buff(( + kind: Poisoned, + dur_secs: 3.0, + strength: DamageFraction(0.5), + chance: 1.0, + ))), + energy_regen: 2, + energy_drain: 0, + ori_rate: 0.5, + specifier: Poison, +) diff --git a/assets/common/abilities/custom/shamanic_spirit/ironspikes.ron b/assets/common/abilities/custom/shamanic_spirit/ironspikes.ron new file mode 100644 index 0000000000..33bf86e4d6 --- /dev/null +++ b/assets/common/abilities/custom/shamanic_spirit/ironspikes.ron @@ -0,0 +1,10 @@ +SpriteSummon( + buildup_duration: 0.5, + cast_duration: 0.1, + recover_duration: 2.0, + sprite: IronSpike, + del_timeout: Some((4, 5)), + summon_distance: (1, 7), + sparseness: 0.67, + angle: 360, +) diff --git a/assets/common/abilities/custom/shamanic_spirit/teleport.ron b/assets/common/abilities/custom/shamanic_spirit/teleport.ron new file mode 100644 index 0000000000..385b8486ac --- /dev/null +++ b/assets/common/abilities/custom/shamanic_spirit/teleport.ron @@ -0,0 +1,5 @@ +Blink( + buildup_duration: 0.75, + recover_duration: 0.25, + max_range: 100.0, +) \ No newline at end of file diff --git a/assets/common/abilities/custom/terracotta_besieger/doublestrike.ron b/assets/common/abilities/custom/terracotta_besieger/doublestrike.ron new file mode 100644 index 0000000000..d6d7579f4f --- /dev/null +++ b/assets/common/abilities/custom/terracotta_besieger/doublestrike.ron @@ -0,0 +1,57 @@ +ComboMelee2( + strikes: [ + ( + melee_constructor: ( + kind: Bash( + damage: 18, + poise: 0, + knockback: 4, + energy_regen: 0, + ), + range: 3.5, + angle: 50.0, + damage_effect: Some(Buff(( + kind: Bleeding, + dur_secs: 10.0, + strength: DamageFraction(0.1), + chance: 0.1, + ))), + ), + buildup_duration: 1.2, + swing_duration: 0.12, + hit_timing: 0.5, + recover_duration: 1.2, + movement: ( + swing: Some(Forward(1.5)), + ), + ori_modifier: 0.6, + ), + ( + melee_constructor: ( + kind: Bash( + damage: 26, + poise: 0, + knockback: 16, + energy_regen: 0, + ), + range: 5.5, + angle: 15.0, + damage_effect: Some(Buff(( + kind: Bleeding, + dur_secs: 10.0, + strength: DamageFraction(0.1), + chance: 0.1, + ))), + ), + buildup_duration: 1.0, + swing_duration: 0.15, + hit_timing: 0.5, + recover_duration: 2.4, + movement: ( + swing: Some(Forward(2.5)), + ), + ori_modifier: 0.6, + ), + ], + energy_cost_per_strike: 0, +) diff --git a/assets/common/abilities/custom/terracotta_besieger/multishot.ron b/assets/common/abilities/custom/terracotta_besieger/multishot.ron new file mode 100644 index 0000000000..942cf8a248 --- /dev/null +++ b/assets/common/abilities/custom/terracotta_besieger/multishot.ron @@ -0,0 +1,16 @@ +BasicRanged( + energy_cost: 0, + buildup_duration: 1.0, + recover_duration: 2.5, + projectile: Arrow( + damage: 25.0, + knockback: 12.0, + energy_regen: 4.0, + ), + projectile_body: Object(BoltBesieger), + projectile_light: None, + projectile_speed: 60.0, + num_projectiles: 4, + projectile_spread: 0.05, + move_efficiency: 0.3, +) diff --git a/assets/common/abilities/custom/terracotta_demolisher/drop.ron b/assets/common/abilities/custom/terracotta_demolisher/drop.ron new file mode 100644 index 0000000000..529115d7cd --- /dev/null +++ b/assets/common/abilities/custom/terracotta_demolisher/drop.ron @@ -0,0 +1,18 @@ +BasicRanged( + energy_cost: 0, + buildup_duration: 1.0, + recover_duration: 1.5, + projectile: FireDroplet( + damage: 30.0, + radius: 10.0, + min_falloff: 0.5, + energy_regen: 0, + reagent: Some(Yellow), + ), + projectile_body: Object(TerracottaDemolisherBomb), + projectile_light: None, + projectile_speed: 0.0, + num_projectiles: 1, + projectile_spread: 0.0, + move_efficiency: 0.3, +) diff --git a/assets/common/abilities/custom/terracotta_demolisher/throw.ron b/assets/common/abilities/custom/terracotta_demolisher/throw.ron new file mode 100644 index 0000000000..0764fd126f --- /dev/null +++ b/assets/common/abilities/custom/terracotta_demolisher/throw.ron @@ -0,0 +1,18 @@ +BasicRanged( + energy_cost: 0, + buildup_duration: 1.0, + recover_duration: 1.5, + projectile: FireDroplet( + damage: 30.0, + radius: 10.0, + min_falloff: 0.5, + energy_regen: 0, + reagent: Some(Yellow), + ), + projectile_body: Object(TerracottaDemolisherBomb), + projectile_light: None, + projectile_speed: 20.0, + num_projectiles: 1, + projectile_spread: 0.0, + move_efficiency: 0.3, +) diff --git a/assets/common/abilities/custom/terracotta_punisher/doublestrike.ron b/assets/common/abilities/custom/terracotta_punisher/doublestrike.ron new file mode 100644 index 0000000000..901b9e8ae2 --- /dev/null +++ b/assets/common/abilities/custom/terracotta_punisher/doublestrike.ron @@ -0,0 +1,45 @@ +ComboMelee2( + strikes: [ + ( + melee_constructor: ( + kind: Bash( + damage: 24, + poise: 40, + knockback: 4, + energy_regen: 0, + ), + range: 4.5, + angle: 50.0, + ), + buildup_duration: 1.2, + swing_duration: 0.08, + hit_timing: 0.5, + recover_duration: 0.9, + movement: ( + swing: Some(Forward(3.5)), + ), + ori_modifier: 0.65, + ), + ( + melee_constructor: ( + kind: Bash( + damage: 32, + poise: 40, + knockback: 16, + energy_regen: 0, + ), + range: 2.5, + angle: 30.0, + ), + buildup_duration: 1.5, + swing_duration: 0.25, + hit_timing: 0.5, + recover_duration: 1.2, + movement: ( + swing: Some(Forward(2.0)), + ), + ori_modifier: 0.65, + ), + ], + energy_cost_per_strike: 0, +) diff --git a/assets/common/abilities/custom/terracotta_pursuer/dash.ron b/assets/common/abilities/custom/terracotta_pursuer/dash.ron new file mode 100644 index 0000000000..60367808de --- /dev/null +++ b/assets/common/abilities/custom/terracotta_pursuer/dash.ron @@ -0,0 +1,28 @@ +DashMelee( + energy_cost: 10.0, + melee_constructor: ( + kind: Stab( + damage: 25.0, + poise: 40.0, + knockback: 8.0, + energy_regen: 0.0, + ), + scaled: Some(( + kind: Stab( + damage: 16.0, + poise: 0.0, + knockback: 7.0, + energy_regen: 0.0, + ))), + range: 5.0, + angle: 45.0, + ), + energy_drain: 0, + forward_speed: 4.0, + buildup_duration: 0.6, + charge_duration: 1.2, + swing_duration: 0.1, + recover_duration: 0.9, + ori_modifier: 0.3, + charge_through: false, +) diff --git a/assets/common/abilities/custom/terracotta_pursuer/doublestrike.ron b/assets/common/abilities/custom/terracotta_pursuer/doublestrike.ron new file mode 100644 index 0000000000..40470f72fd --- /dev/null +++ b/assets/common/abilities/custom/terracotta_pursuer/doublestrike.ron @@ -0,0 +1,57 @@ +ComboMelee2( + strikes: [ + ( + melee_constructor: ( + kind: Slash( + damage: 20, + poise: 15, + knockback: 8, + energy_regen: 0, + ), + range: 3.5, + angle: 50.0, + damage_effect: Some(Buff(( + kind: Bleeding, + dur_secs: 10.0, + strength: DamageFraction(0.1), + chance: 0.1, + ))), + ), + buildup_duration: 0.4, + swing_duration: 0.08, + hit_timing: 0.5, + recover_duration: 0.5, + movement: ( + swing: Some(Forward(2.5)), + ), + ori_modifier: 0.7, + ), + ( + melee_constructor: ( + kind: Slash( + damage: 25, + poise: 20, + knockback: 12, + energy_regen: 0, + ), + range: 3.5, + angle: 30.0, + damage_effect: Some(Buff(( + kind: Bleeding, + dur_secs: 10.0, + strength: DamageFraction(0.1), + chance: 0.1, + ))), + ), + buildup_duration: 0.7, + swing_duration: 0.1, + hit_timing: 0.5, + recover_duration: 0.7, + movement: ( + swing: Some(Forward(2.0)), + ), + ori_modifier: 0.7, + ), + ], + energy_cost_per_strike: 0, +) diff --git a/assets/common/abilities/custom/terracotta_statue/blast.ron b/assets/common/abilities/custom/terracotta_statue/blast.ron new file mode 100644 index 0000000000..e0e9da10dd --- /dev/null +++ b/assets/common/abilities/custom/terracotta_statue/blast.ron @@ -0,0 +1,17 @@ +BasicRanged( + energy_cost: 0.0, + buildup_duration: 1.5, + recover_duration: 1.5, + projectile: LaserBeam( + damage: 50.0, + radius: 20.0, + knockback: 50.0, + energy_regen: 0.0, + min_falloff: 0.0, + ), + projectile_body: Object(LaserBeamSmall), + projectile_speed: 45.0, + num_projectiles: 1, + projectile_spread: 0.0, + move_efficiency: 0.3, +) diff --git a/assets/common/abilities/custom/terracotta_statue/trap.ron b/assets/common/abilities/custom/terracotta_statue/trap.ron new file mode 100644 index 0000000000..ab2944a923 --- /dev/null +++ b/assets/common/abilities/custom/terracotta_statue/trap.ron @@ -0,0 +1,10 @@ +SpriteSummon( + buildup_duration: 1.5, + cast_duration: 0.1, + recover_duration: 12.0, + sprite: Empty, + del_timeout: Some((8, 5)), + summon_distance: (2, 15.0), + sparseness: 0.0, + angle: 360, +) \ No newline at end of file diff --git a/assets/common/abilities/music/steeldrum.ron b/assets/common/abilities/music/steeltonguedrum.ron similarity index 100% rename from assets/common/abilities/music/steeldrum.ron rename to assets/common/abilities/music/steeltonguedrum.ron diff --git a/assets/common/entity/dungeon/terracotta/besieger.ron b/assets/common/entity/dungeon/terracotta/besieger.ron new file mode 100644 index 0000000000..e316322740 --- /dev/null +++ b/assets/common/entity/dungeon/terracotta/besieger.ron @@ -0,0 +1,11 @@ +#![enable(implicit_some)] +( + name: Automatic, + body: RandomWith("terracotta_besieger"), + alignment: Alignment(Enemy), + loot: LootTable("common.loot_tables.dungeon.terracotta.enemy"), + inventory: ( + loadout: FromBody, + ), + meta: [], +) \ No newline at end of file diff --git a/assets/common/entity/dungeon/terracotta/cursekeeper.ron b/assets/common/entity/dungeon/terracotta/cursekeeper.ron new file mode 100644 index 0000000000..ca45905f4a --- /dev/null +++ b/assets/common/entity/dungeon/terracotta/cursekeeper.ron @@ -0,0 +1,11 @@ +#![enable(implicit_some)] +( + name: Name("Cursekeeper"), + body: RandomWith("cursekeeper"), + alignment: Alignment(Enemy), + loot: LootTable("common.loot_tables.dungeon.terracotta.cursekeeper"), + inventory: ( + loadout: FromBody, + ), + meta: [], +) \ No newline at end of file diff --git a/assets/common/entity/dungeon/terracotta/cursekeeper_fake.ron b/assets/common/entity/dungeon/terracotta/cursekeeper_fake.ron new file mode 100644 index 0000000000..e7bb8d7fd4 --- /dev/null +++ b/assets/common/entity/dungeon/terracotta/cursekeeper_fake.ron @@ -0,0 +1,12 @@ +#![enable(implicit_some)] +( + name: Name("Cursekeeper"), + body: RandomWith("cursekeeper"), + alignment: Alignment(Enemy), + loot: Item("common.items.keys.terracotta_key_chest"), + inventory: ( + loadout: Inline(( + active_hands: InHands((Item("common.items.npc_weapons.unique.cursekeeper_sceptre_fake"), None)), + )), ), + meta: [], +) \ No newline at end of file diff --git a/assets/common/entity/dungeon/terracotta/demolisher.ron b/assets/common/entity/dungeon/terracotta/demolisher.ron new file mode 100644 index 0000000000..92426ce857 --- /dev/null +++ b/assets/common/entity/dungeon/terracotta/demolisher.ron @@ -0,0 +1,11 @@ +#![enable(implicit_some)] +( + name: Automatic, + body: RandomWith("terracotta_demolisher"), + alignment: Alignment(Enemy), + loot: LootTable("common.loot_tables.dungeon.terracotta.enemy"), + inventory: ( + loadout: FromBody, + ), + meta: [], +) \ No newline at end of file diff --git a/assets/common/entity/dungeon/terracotta/jiangshi.ron b/assets/common/entity/dungeon/terracotta/jiangshi.ron new file mode 100644 index 0000000000..12bf298420 --- /dev/null +++ b/assets/common/entity/dungeon/terracotta/jiangshi.ron @@ -0,0 +1,14 @@ +#![enable(implicit_some)] +( + name: Name("Jiangshi"), + body: RandomWith("jiangshi"), + alignment: Alignment(Enemy), + loot: Nothing, + inventory: ( + loadout: Inline(( + inherit: Asset("common.loadout.dungeon.terracotta.jiangshi"), + active_hands: InHands((Item("common.items.npc_weapons.unique.jiangshi"), None)), + )), + ), + meta: [], +) \ No newline at end of file diff --git a/assets/common/entity/dungeon/terracotta/mogwai.ron b/assets/common/entity/dungeon/terracotta/mogwai.ron new file mode 100644 index 0000000000..24bc35a0c5 --- /dev/null +++ b/assets/common/entity/dungeon/terracotta/mogwai.ron @@ -0,0 +1,11 @@ +#![enable(implicit_some)] +( + name: Name("Mogway"), + body: RandomWith("mogwai"), + alignment: Alignment(Enemy), + loot: LootTable("common.loot_tables.dungeon.terracotta.enemy"), + inventory: ( + loadout: FromBody, + ), + meta: [], +) \ No newline at end of file diff --git a/assets/common/entity/dungeon/terracotta/punisher.ron b/assets/common/entity/dungeon/terracotta/punisher.ron new file mode 100644 index 0000000000..67b0d55433 --- /dev/null +++ b/assets/common/entity/dungeon/terracotta/punisher.ron @@ -0,0 +1,11 @@ +#![enable(implicit_some)] +( + name: Automatic, + body: RandomWith("terracotta_punisher"), + alignment: Alignment(Enemy), + loot: LootTable("common.loot_tables.dungeon.terracotta.enemy"), + inventory: ( + loadout: FromBody, + ), + meta: [], +) \ No newline at end of file diff --git a/assets/common/entity/dungeon/terracotta/pursuer.ron b/assets/common/entity/dungeon/terracotta/pursuer.ron new file mode 100644 index 0000000000..9e9de10f54 --- /dev/null +++ b/assets/common/entity/dungeon/terracotta/pursuer.ron @@ -0,0 +1,11 @@ +#![enable(implicit_some)] +( + name: Automatic, + body: RandomWith("terracotta_pursuer"), + alignment: Alignment(Enemy), + loot: LootTable("common.loot_tables.dungeon.terracotta.enemy"), + inventory: ( + loadout: FromBody, + ), + meta: [], +) \ No newline at end of file diff --git a/assets/common/entity/dungeon/terracotta/shamanic_spirit.ron b/assets/common/entity/dungeon/terracotta/shamanic_spirit.ron new file mode 100644 index 0000000000..409bebdc78 --- /dev/null +++ b/assets/common/entity/dungeon/terracotta/shamanic_spirit.ron @@ -0,0 +1,14 @@ +#![enable(implicit_some)] +( + name: Name("Shamanic Spirit"), + body: RandomWith("shamanic_spirit"), + alignment: Alignment(Enemy), + loot: LootTable("common.loot_tables.dungeon.terracotta.enemy"), + inventory: ( + loadout: Inline(( + inherit: Asset("common.loadout.dungeon.terracotta.shamanic_spirit"), + active_hands: InHands((Item("common.items.npc_weapons.unique.shamanic_spirit"), None)), + )), + ), + meta: [], +) \ No newline at end of file diff --git a/assets/common/entity/dungeon/terracotta/terracotta_statue.ron b/assets/common/entity/dungeon/terracotta/terracotta_statue.ron new file mode 100644 index 0000000000..5cb28ec9b6 --- /dev/null +++ b/assets/common/entity/dungeon/terracotta/terracotta_statue.ron @@ -0,0 +1,11 @@ +#![enable(implicit_some)] +( + name: Name("Terracotta Statue"), + body: Exact(Object(TerracottaStatue)), + alignment: Alignment(Enemy), + loot: Nothing, + inventory: ( + loadout: FromBody + ), + meta: [], +) \ No newline at end of file diff --git a/assets/common/entity/dungeon/terracotta/terracotta_statue_key.ron b/assets/common/entity/dungeon/terracotta/terracotta_statue_key.ron new file mode 100644 index 0000000000..ece00c8b90 --- /dev/null +++ b/assets/common/entity/dungeon/terracotta/terracotta_statue_key.ron @@ -0,0 +1,11 @@ +#![enable(implicit_some)] +( + name: Name("Terracotta Statue"), + body: Exact(Object(TerracottaStatue)), + alignment: Alignment(Enemy), + loot: Item("common.items.keys.terracotta_key_chest"), + inventory: ( + loadout: FromBody + ), + meta: [], +) \ No newline at end of file diff --git a/assets/common/entity/dungeon/terracotta/terracotta_statue_key_chance.ron b/assets/common/entity/dungeon/terracotta/terracotta_statue_key_chance.ron new file mode 100644 index 0000000000..95b82ff188 --- /dev/null +++ b/assets/common/entity/dungeon/terracotta/terracotta_statue_key_chance.ron @@ -0,0 +1,11 @@ +#![enable(implicit_some)] +( + name: Name("Terracotta Statue"), + body: Exact(Object(TerracottaStatue)), + alignment: Alignment(Enemy), + loot: LootTable("common.loot_tables.dungeon.terracotta.terracotta_statue_key_chance"), + inventory: ( + loadout: FromBody + ), + meta: [], +) \ No newline at end of file diff --git a/assets/common/item_i18n_manifest.ron b/assets/common/item_i18n_manifest.ron index e5fde15df2..9d03840cdb 100644 --- a/assets/common/item_i18n_manifest.ron +++ b/assets/common/item_i18n_manifest.ron @@ -57,6 +57,9 @@ Simple( "common.items.npc_armor.golem.gravewarden", ): "common-items-npc_armor-golem-gravewarden", + Simple( + "common.items.npc_armor.golem.mogwai", + ): "common-items-npc_armor-golem-mogwai", Simple( "common.items.npc_armor.biped_small.myrmidon.foot.hoplite", ): "common-items-npc_armor-biped_small-myrmidon-foot-hoplite", @@ -525,6 +528,33 @@ Simple( "common.items.npc_armor.biped_small.gnoll.tail.trapper", ): "common-items-npc_armor-biped_small-gnoll-tail-trapper", + Simple( + "common.items.npc_armor.biped_small.jiangshi.head.jiangshi", + ): "common-items-npc_armor-biped_small-jiangshi-head-jiangshi", + Simple( + "common.items.npc_armor.biped_small.jiangshi.chest.jiangshi", + ): "common-items-npc_armor-biped_small-jiangshi-chest-jiangshi", + Simple( + "common.items.npc_armor.biped_small.jiangshi.pants.jiangshi", + ): "common-items-npc_armor-biped_small-jiangshi-pants-jiangshi", + Simple( + "common.items.npc_armor.biped_small.jiangshi.hand.jiangshi", + ): "common-items-npc_armor-biped_small-jiangshi-hand-jiangshi", + Simple( + "common.items.npc_armor.biped_small.jiangshi.foot.jiangshi", + ): "common-items-npc_armor-biped_small-jiangshi-foot-jiangshi", + Simple( + "common.items.npc_armor.biped_small.shamanic_spirit.head.shamanic_spirit", + ): "common-items-npc_armor-biped_small-shamanic_spirit-head-shamanic_spirit", + Simple( + "common.items.npc_armor.biped_small.shamanic_spirit.chest.shamanic_spirit", + ): "common-items-npc_armor-biped_small-shamanic_spirit-chest-shamanic_spirit", + Simple( + "common.items.npc_armor.biped_small.shamanic_spirit.pants.shamanic_spirit", + ): "common-items-npc_armor-biped_small-shamanic_spirit-pants-shamanic_spirit", + Simple( + "common.items.npc_armor.biped_small.shamanic_spirit.hand.shamanic_spirit", + ): "common-items-npc_armor-biped_small-shamanic_spirit-hand-shamanic_spirit", Simple( "common.items.npc_armor.chest.leather_blue", ): "armor-leather_blue-pants", @@ -630,12 +660,21 @@ Simple( "common.items.npc_armor.biped_large.haniwageneral", ): "common-items-npc_armor-biped_large-haniwageneral", + Simple( + "common.items.npc_armor.biped_large.terracotta", + ): "common-items-npc_armor-biped_large-terracotta", Simple( "common.items.keys.bone_key", ): "object-key-bone", Simple( "common.items.keys.haniwa_key", ): "object-key-haniwa", + Simple( + "common.items.keys.terracotta_key_chest", + ): "object-key-terracotta_chest", + Simple( + "common.items.keys.terracotta_key_door", + ): "object-key-terracotta_door", Simple( "common.items.keys.glass_key", ): "object-key-glass", @@ -2319,8 +2358,8 @@ "common.items.tool.instruments.wildskin_drum", ): "weapon-tool-wildskin_drum", Simple( - "common.items.tool.instruments.steeldrum", - ): "weapon-tool-steeldrum", + "common.items.tool.instruments.steeltonguedrum", + ): "weapon-tool-steeltonguedrum", Simple( "common.items.tool.instruments.shamisen", ): "weapon-tool-shamisen", @@ -2418,6 +2457,9 @@ Simple( "common.items.npc_weapons.bow.saurok_bow", ): "common-items-npc_weapons-bow-saurok_bow", + Simple( + "common.items.npc_weapons.bow.terracotta_besieger_bow", + ): "common-items-npc_weapons-bow-terracotta_besieger_bow", Simple( "common.items.npc_weapons.axe.gigas_frost_axe", ): "common-items-npc_weapons-axe-gigas_frost_axe", @@ -2457,6 +2499,9 @@ Simple( "common.items.npc_weapons.sword.haniwa_general_sword", ): "common-items-npc_weapons-sword-haniwa_general_sword", + Simple( + "common.items.npc_weapons.sword.terracotta_pursuer_sword", + ): "common-items-npc_weapons-sword-terracotta_pursuer_sword", Simple( "common.items.npc_weapons.unique.akhlut", ): "common-items-npc_weapons-unique-akhlut", @@ -2511,6 +2556,27 @@ Simple( "common.items.npc_weapons.unique.flamekeeper_staff", ): "common-items-npc_weapons-unique-flamekeeper_staff", + Simple( + "common.items.npc_weapons.unique.jiangshi", + ): "common-items-npc_weapons-unique-jiangshi", + Simple( + "common.items.npc_weapons.unique.mogwai", + ): "common-items-npc_weapons-unique-mogwai", + Simple( + "common.items.npc_weapons.unique.shamanic_spirit", + ): "common-items-npc_weapons-unique-shamanic_spirit", + Simple( + "common.items.npc_weapons.unique.terracotta_demolisher_fist", + ): "common-items-npc_weapons-unique-terracotta_demolisher_fist", + Simple( + "common.items.npc_weapons.unique.cursekeeper_sceptre", + ): "common-items-npc_weapons-unique-cursekeeper_sceptre", + Simple( + "common.items.npc_weapons.unique.cursekeeper_sceptre_fake", + ): "common-items-npc_weapons-unique-cursekeeper_sceptre_fake", + Simple( + "common.items.npc_weapons.unique.terracotta_statue", + ): "common-items-npc_weapons-unique-terracotta_statue", Simple( "common.items.npc_weapons.unique.flamethrower", ): "common-items-npc_weapons-unique-flamethrower", @@ -2757,6 +2823,9 @@ Simple( "common.items.npc_weapons.hammer.yeti_hammer", ): "common-items-npc_weapons-hammer-yeti_hammer", + Simple( + "common.items.npc_weapons.hammer.terracotta_punisher_club", + ): "common-items-npc_weapons-hammer-terracotta_punisher_club", Simple( "common.items.modular.weapon.primary.bow.bow", ): "common-items-modular-weapon-primary-bow-bow", diff --git a/assets/common/items/keys/terracotta_key_chest.ron b/assets/common/items/keys/terracotta_key_chest.ron new file mode 100644 index 0000000000..bd2df4d416 --- /dev/null +++ b/assets/common/items/keys/terracotta_key_chest.ron @@ -0,0 +1,10 @@ +ItemDef( + legacy_name: "Terracotta Chest Key", + legacy_description: "Used to open chests in Terracotta Ruins. Will break after use.", + kind: Utility( + kind: Key, + ), + quality: Epic, + tags: [Utility], +) + diff --git a/assets/common/items/keys/terracotta_key_door.ron b/assets/common/items/keys/terracotta_key_door.ron new file mode 100644 index 0000000000..1e09626e6e --- /dev/null +++ b/assets/common/items/keys/terracotta_key_door.ron @@ -0,0 +1,10 @@ +ItemDef( + legacy_name: "Terracotta Door Key", + legacy_description: "Used to open doors in Terracotta Ruins. Will break after use.", + kind: Utility( + kind: Key, + ), + quality: Epic, + tags: [Utility], +) + diff --git a/assets/common/items/npc_armor/biped_large/terracotta.ron b/assets/common/items/npc_armor/biped_large/terracotta.ron new file mode 100644 index 0000000000..665b2f0ef5 --- /dev/null +++ b/assets/common/items/npc_armor/biped_large/terracotta.ron @@ -0,0 +1,13 @@ +ItemDef( + legacy_name: "Terracotta Armor", + legacy_description: "Worn by terracotta enemies.", + kind: Armor(( + kind: Chest, + stats: Direct(( + protection: Some(Normal(50.0)), + poise_resilience: Some(Normal(20.0)), + )), + )), + quality: Epic, + tags: [], +) \ No newline at end of file diff --git a/assets/common/items/npc_armor/biped_small/jiangshi/chest/jiangshi.ron b/assets/common/items/npc_armor/biped_small/jiangshi/chest/jiangshi.ron new file mode 100644 index 0000000000..58d0540763 --- /dev/null +++ b/assets/common/items/npc_armor/biped_small/jiangshi/chest/jiangshi.ron @@ -0,0 +1,13 @@ +ItemDef( + legacy_name: "Jiangshi Chest", + legacy_description: "Jiangshi Chest", + kind: Armor(( + kind: Chest, + stats: Direct(( + protection: Some(Normal(10.0)), + precision_power: Some(0.06), + )), + )), + quality: Low, + tags: [], +) diff --git a/assets/common/items/npc_armor/biped_small/jiangshi/foot/jiangshi.ron b/assets/common/items/npc_armor/biped_small/jiangshi/foot/jiangshi.ron new file mode 100644 index 0000000000..d825a7cae7 --- /dev/null +++ b/assets/common/items/npc_armor/biped_small/jiangshi/foot/jiangshi.ron @@ -0,0 +1,15 @@ +ItemDef( + legacy_name: "Jiangshi Foot", + legacy_description: "Jiangshi Foot.", + kind: Armor(( + kind: Foot, + stats: Direct(( + protection: Some(Normal(4.0)), + energy_max: Some(1.8), + energy_reward: Some(0.018), + precision_power: Some(0.016), + )), + )), + quality: Low, + tags: [], +) diff --git a/assets/common/items/npc_armor/biped_small/jiangshi/hand/jiangshi.ron b/assets/common/items/npc_armor/biped_small/jiangshi/hand/jiangshi.ron new file mode 100644 index 0000000000..b946f8017c --- /dev/null +++ b/assets/common/items/npc_armor/biped_small/jiangshi/hand/jiangshi.ron @@ -0,0 +1,13 @@ +ItemDef( + legacy_name: "Jiangshi Hand", + legacy_description: "Jiangshi Hand", + kind: Armor(( + kind: Hand, + stats: Direct(( + protection: Some(Normal(5.0)), + precision_power: Some(0.016), + )), + )), + quality: Low, + tags: [], +) diff --git a/assets/common/items/npc_armor/biped_small/jiangshi/head/jiangshi.ron b/assets/common/items/npc_armor/biped_small/jiangshi/head/jiangshi.ron new file mode 100644 index 0000000000..c45ebf5a9e --- /dev/null +++ b/assets/common/items/npc_armor/biped_small/jiangshi/head/jiangshi.ron @@ -0,0 +1,13 @@ +ItemDef( + legacy_name: "Jiangshi Head", + legacy_description: "Jiangshi Head", + kind: Armor(( + kind: Head, + stats: Direct(( + protection: Some(Normal(8.0)), + precision_power: Some(0.032), + )), + )), + quality: Low, + tags: [], +) diff --git a/assets/common/items/npc_armor/biped_small/jiangshi/pants/jiangshi.ron b/assets/common/items/npc_armor/biped_small/jiangshi/pants/jiangshi.ron new file mode 100644 index 0000000000..f460a0a894 --- /dev/null +++ b/assets/common/items/npc_armor/biped_small/jiangshi/pants/jiangshi.ron @@ -0,0 +1,13 @@ +ItemDef( + legacy_name: "Jiangshi Pants", + legacy_description: "Jiangshi Pants", + kind: Armor(( + kind: Pants, + stats: Direct(( + protection: Some(Normal(6.0)), + precision_power: Some(0.032), + )), + )), + quality: Low, + tags: [], +) diff --git a/assets/common/items/npc_armor/biped_small/shamanic_spirit/chest/shamanic_spirit.ron b/assets/common/items/npc_armor/biped_small/shamanic_spirit/chest/shamanic_spirit.ron new file mode 100644 index 0000000000..012191209d --- /dev/null +++ b/assets/common/items/npc_armor/biped_small/shamanic_spirit/chest/shamanic_spirit.ron @@ -0,0 +1,14 @@ +ItemDef( + legacy_name: "Shamanic Spirit Chest", + legacy_description: "Shamanic Spirit Chest", + kind: Armor(( + kind: Chest, + stats: Direct(( + protection: Some(Normal(16.0)), + poise_resilience: Some(Normal(3.0)), + precision_power: Some(0.06), + )), + )), + quality: Low, + tags: [], +) diff --git a/assets/common/items/npc_armor/biped_small/shamanic_spirit/hand/shamanic_spirit.ron b/assets/common/items/npc_armor/biped_small/shamanic_spirit/hand/shamanic_spirit.ron new file mode 100644 index 0000000000..bbe08c4034 --- /dev/null +++ b/assets/common/items/npc_armor/biped_small/shamanic_spirit/hand/shamanic_spirit.ron @@ -0,0 +1,14 @@ +ItemDef( + legacy_name: "Shamanic Spirit Hand", + legacy_description: "Shamanic Spirit Hand", + kind: Armor(( + kind: Hand, + stats: Direct(( + protection: Some(Normal(6.0)), + poise_resilience: Some(Normal(3.0)), + precision_power: Some(0.016), + )), + )), + quality: Low, + tags: [], +) diff --git a/assets/common/items/npc_armor/biped_small/shamanic_spirit/head/shamanic_spirit.ron b/assets/common/items/npc_armor/biped_small/shamanic_spirit/head/shamanic_spirit.ron new file mode 100644 index 0000000000..7bfd99850d --- /dev/null +++ b/assets/common/items/npc_armor/biped_small/shamanic_spirit/head/shamanic_spirit.ron @@ -0,0 +1,14 @@ +ItemDef( + legacy_name: "Shamanic Spirit Head", + legacy_description: "Shamanic Spirit Head", + kind: Armor(( + kind: Head, + stats: Direct(( + protection: Some(Normal(9.0)), + poise_resilience: Some(Normal(3.0)), + precision_power: Some(0.032), + )), + )), + quality: Low, + tags: [], +) diff --git a/assets/common/items/npc_armor/biped_small/shamanic_spirit/pants/shamanic_spirit.ron b/assets/common/items/npc_armor/biped_small/shamanic_spirit/pants/shamanic_spirit.ron new file mode 100644 index 0000000000..84605d0c54 --- /dev/null +++ b/assets/common/items/npc_armor/biped_small/shamanic_spirit/pants/shamanic_spirit.ron @@ -0,0 +1,14 @@ +ItemDef( + legacy_name: "Shamanic Spirit Pants", + legacy_description: "Shamanic Spirit Pants", + kind: Armor(( + kind: Pants, + stats: Direct(( + protection: Some(Normal(9.0)), + poise_resilience: Some(Normal(3.0)), + precision_power: Some(0.032), + )), + )), + quality: Low, + tags: [], +) diff --git a/assets/common/items/npc_armor/golem/mogwai.ron b/assets/common/items/npc_armor/golem/mogwai.ron new file mode 100644 index 0000000000..64ce6d41e1 --- /dev/null +++ b/assets/common/items/npc_armor/golem/mogwai.ron @@ -0,0 +1,13 @@ +ItemDef( + legacy_name: "Mogwai Armor", + legacy_description: "Worn by mogwai.", + kind: Armor(( + kind: Chest, + stats: Direct(( + protection: Some(Normal(80.0)), + poise_resilience: Some(Normal(5.0)), + )), + )), + quality: Legendary, + tags: [], +) \ No newline at end of file diff --git a/assets/common/items/npc_weapons/bow/terracotta_besieger_bow.ron b/assets/common/items/npc_weapons/bow/terracotta_besieger_bow.ron new file mode 100644 index 0000000000..f5b978cdf2 --- /dev/null +++ b/assets/common/items/npc_weapons/bow/terracotta_besieger_bow.ron @@ -0,0 +1,20 @@ +ItemDef( + legacy_name: "Terracotta Besieger Bow", + legacy_description: "", + kind: Tool(( + kind: Bow, + hands: Two, + stats: ( + equip_time_secs: 0.0, + power: 1.0, + effect_power: 1.0, + speed: 1.0, + range: 1.0, + energy_efficiency: 1.0, + buff_strength: 1.0, + ), + )), + quality: Moderate, + tags: [], + ability_spec: Some(Custom("TerracottaBesieger")), +) \ No newline at end of file diff --git a/assets/common/items/npc_weapons/hammer/terracotta_punisher_club.ron b/assets/common/items/npc_weapons/hammer/terracotta_punisher_club.ron new file mode 100644 index 0000000000..dd429856f5 --- /dev/null +++ b/assets/common/items/npc_weapons/hammer/terracotta_punisher_club.ron @@ -0,0 +1,20 @@ +ItemDef( + legacy_name: "Terracotta Punisher Club", + legacy_description: "", + kind: Tool(( + kind: Hammer, + hands: Two, + stats: ( + equip_time_secs: 0.5, + power: 1.0, + effect_power: 1.0, + speed: 1.0, + range: 1.0, + energy_efficiency: 1.0, + buff_strength: 1.0, + ), + )), + quality: Low, + tags: [], + ability_spec: Some(Custom("Hammer Simple")), +) \ No newline at end of file diff --git a/assets/common/items/npc_weapons/sword/terracotta_pursuer_sword.ron b/assets/common/items/npc_weapons/sword/terracotta_pursuer_sword.ron new file mode 100644 index 0000000000..57cf21e2ed --- /dev/null +++ b/assets/common/items/npc_weapons/sword/terracotta_pursuer_sword.ron @@ -0,0 +1,20 @@ +ItemDef( + legacy_name: "Terracotta Pursuer Sword", + legacy_description: "", + kind: Tool(( + kind: Sword, + hands: One, + stats: ( + equip_time_secs: 0.5, + power: 1.5, + effect_power: 1.0, + speed: 0.75, + range: 1.0, + energy_efficiency: 1.0, + buff_strength: 1.0, + ), + )), + quality: Low, + tags: [], + ability_spec: Some(Custom("TerracottaPursuer")), +) \ No newline at end of file diff --git a/assets/common/items/npc_weapons/unique/cursekeeper_sceptre.ron b/assets/common/items/npc_weapons/unique/cursekeeper_sceptre.ron new file mode 100644 index 0000000000..f35344ad5b --- /dev/null +++ b/assets/common/items/npc_weapons/unique/cursekeeper_sceptre.ron @@ -0,0 +1,20 @@ +ItemDef( + legacy_name: "Cursekeeper Sceptre", + legacy_description: "All kinds of evil.", + kind: Tool(( + kind: Sceptre, + hands: Two, + stats: ( + equip_time_secs: 0.4, + power: 1.0, + effect_power: 0.8, + speed: 1.0, + range: 1.0, + energy_efficiency: 1.0, + buff_strength: 1.0, + ), + )), + quality: Epic, + tags: [], + ability_spec: Some(Custom("Cursekeeper")), +) diff --git a/assets/common/items/npc_weapons/unique/cursekeeper_sceptre_fake.ron b/assets/common/items/npc_weapons/unique/cursekeeper_sceptre_fake.ron new file mode 100644 index 0000000000..02c1b047be --- /dev/null +++ b/assets/common/items/npc_weapons/unique/cursekeeper_sceptre_fake.ron @@ -0,0 +1,20 @@ +ItemDef( + legacy_name: "Cursekeeper Sceptre", + legacy_description: "All kinds of evil.", + kind: Tool(( + kind: Sceptre, + hands: Two, + stats: ( + equip_time_secs: 0.4, + power: 1.0, + effect_power: 0.8, + speed: 1.0, + range: 1.0, + energy_efficiency: 1.0, + buff_strength: 1.0, + ), + )), + quality: Epic, + tags: [], + ability_spec: Some(Custom("CursekeeperFake")), +) diff --git a/assets/common/items/npc_weapons/unique/jiangshi.ron b/assets/common/items/npc_weapons/unique/jiangshi.ron new file mode 100644 index 0000000000..a95a1e40e3 --- /dev/null +++ b/assets/common/items/npc_weapons/unique/jiangshi.ron @@ -0,0 +1,20 @@ +ItemDef( + legacy_name: "Jiangshi", + legacy_description: "testing123", + kind: Tool(( + kind: Natural, + hands: Two, + stats: ( + equip_time_secs: 0.01, + power: 1.0, + effect_power: 1.0, + speed: 1.0, + range: 1.0, + energy_efficiency: 1.0, + buff_strength: 1.0, + ), + )), + quality: Low, + tags: [], + ability_spec: Some(Custom("Jiangshi")), +) diff --git a/assets/common/items/npc_weapons/unique/mogwai.ron b/assets/common/items/npc_weapons/unique/mogwai.ron new file mode 100644 index 0000000000..4d13530946 --- /dev/null +++ b/assets/common/items/npc_weapons/unique/mogwai.ron @@ -0,0 +1,20 @@ +ItemDef( + legacy_name: "Mogwai Eye", + legacy_description: "Yeet.", + kind: Tool(( + kind: Natural, + hands: Two, + stats: ( + equip_time_secs: 0.001, + power: 1.0, + effect_power: 1.0, + speed: 1.0, + range: 1.0, + energy_efficiency: 1.0, + buff_strength: 1.0, + ), + )), + quality: Low, + tags: [], + ability_spec: Some(Custom("Mogwai")), +) \ No newline at end of file diff --git a/assets/common/items/npc_weapons/unique/shamanic_spirit.ron b/assets/common/items/npc_weapons/unique/shamanic_spirit.ron new file mode 100644 index 0000000000..cc1a119c4f --- /dev/null +++ b/assets/common/items/npc_weapons/unique/shamanic_spirit.ron @@ -0,0 +1,20 @@ +ItemDef( + legacy_name: "Shamanic Spirit", + legacy_description: "testing123", + kind: Tool(( + kind: Natural, + hands: Two, + stats: ( + equip_time_secs: 0.01, + power: 1.0, + effect_power: 1.0, + speed: 1.0, + range: 1.0, + energy_efficiency: 1.0, + buff_strength: 1.0, + ), + )), + quality: Low, + tags: [], + ability_spec: Some(Custom("ShamanicSpirit")), +) diff --git a/assets/common/items/npc_weapons/unique/terracotta_demolisher_fist.ron b/assets/common/items/npc_weapons/unique/terracotta_demolisher_fist.ron new file mode 100644 index 0000000000..fea2723bad --- /dev/null +++ b/assets/common/items/npc_weapons/unique/terracotta_demolisher_fist.ron @@ -0,0 +1,20 @@ +ItemDef( + legacy_name: "Terracotta Demolisher Fist", + legacy_description: "", + kind: Tool(( + kind: Natural, + hands: Two, + stats: ( + equip_time_secs: 0.5, + power: 1.0, + effect_power: 1.0, + speed: 1.0, + range: 1.0, + energy_efficiency: 1.0, + buff_strength: 1.0, + ), + )), + quality: Moderate, + tags: [], + ability_spec: Some(Custom("TerracottaDemolisher")), +) \ No newline at end of file diff --git a/assets/common/items/npc_weapons/unique/terracotta_statue.ron b/assets/common/items/npc_weapons/unique/terracotta_statue.ron new file mode 100644 index 0000000000..1c229b6bb2 --- /dev/null +++ b/assets/common/items/npc_weapons/unique/terracotta_statue.ron @@ -0,0 +1,21 @@ +ItemDef( + legacy_name: "Terracotta Statue", + legacy_description: "Terracotta Statue", + kind: Tool(( + kind: Natural, + hands: Two, + stats: ( + equip_time_secs: 0.0, + power: 1.0, + effect_power: 1.0, + speed: 1.0, + crit_chance: 0.0, + range: 1.0, + energy_efficiency: 1.0, + buff_strength: 1.0, + ), + )), + quality: Common, + tags: [], + ability_spec: Some(Custom("TerracottaStatue")), +) \ No newline at end of file diff --git a/assets/common/items/tool/instruments/steeldrum.ron b/assets/common/items/tool/instruments/steeltonguedrum.ron similarity index 89% rename from assets/common/items/tool/instruments/steeldrum.ron rename to assets/common/items/tool/instruments/steeltonguedrum.ron index 1ac5589729..2fd5bfd5c6 100644 --- a/assets/common/items/tool/instruments/steeldrum.ron +++ b/assets/common/items/tool/instruments/steeltonguedrum.ron @@ -16,5 +16,5 @@ ItemDef( )), quality: Legendary, tags: [Utility], - ability_spec: Some(Custom("Steeldrum")), + ability_spec: Some(Custom("Steeltonguedrum")), ) diff --git a/assets/common/loadout/dungeon/terracotta/jiangshi.ron b/assets/common/loadout/dungeon/terracotta/jiangshi.ron new file mode 100644 index 0000000000..054f3e9532 --- /dev/null +++ b/assets/common/loadout/dungeon/terracotta/jiangshi.ron @@ -0,0 +1,8 @@ +#![enable(implicit_some)] +( + head: Item("common.items.npc_armor.biped_small.jiangshi.head.jiangshi"), + chest: Item("common.items.npc_armor.biped_small.jiangshi.chest.jiangshi"), + gloves: Item("common.items.npc_armor.biped_small.jiangshi.hand.jiangshi"), + legs: Item("common.items.npc_armor.biped_small.jiangshi.pants.jiangshi"), + feet: Item("common.items.npc_armor.biped_small.jiangshi.foot.jiangshi"), +) \ No newline at end of file diff --git a/assets/common/loadout/dungeon/terracotta/shamanic_spirit.ron b/assets/common/loadout/dungeon/terracotta/shamanic_spirit.ron new file mode 100644 index 0000000000..9032a11dff --- /dev/null +++ b/assets/common/loadout/dungeon/terracotta/shamanic_spirit.ron @@ -0,0 +1,7 @@ +#![enable(implicit_some)] +( + head: Item("common.items.npc_armor.biped_small.shamanic_spirit.head.shamanic_spirit"), + chest: Item("common.items.npc_armor.biped_small.shamanic_spirit.chest.shamanic_spirit"), + gloves: Item("common.items.npc_armor.biped_small.shamanic_spirit.hand.shamanic_spirit"), + legs: Item("common.items.npc_armor.biped_small.shamanic_spirit.pants.shamanic_spirit"), +) \ No newline at end of file diff --git a/assets/common/loot_tables/dungeon/terracotta/chest_terracotta.ron b/assets/common/loot_tables/dungeon/terracotta/chest_terracotta.ron new file mode 100644 index 0000000000..998979fd85 --- /dev/null +++ b/assets/common/loot_tables/dungeon/terracotta/chest_terracotta.ron @@ -0,0 +1,4 @@ +[ + // Key + (1.0, Item("common.items.keys.terracotta_key_door")), +] \ No newline at end of file diff --git a/assets/common/loot_tables/dungeon/terracotta/cursekeeper.ron b/assets/common/loot_tables/dungeon/terracotta/cursekeeper.ron new file mode 100644 index 0000000000..cfc7ffca14 --- /dev/null +++ b/assets/common/loot_tables/dungeon/terracotta/cursekeeper.ron @@ -0,0 +1,7 @@ +[ + (1, All([ + Item("common.items.keys.terracotta_key_door"), + LootTable("common.loot_tables.dungeon.terracotta.cursekeeper_extra"), + ], + )), +] \ No newline at end of file diff --git a/assets/common/loot_tables/dungeon/terracotta/cursekeeper_extra.ron b/assets/common/loot_tables/dungeon/terracotta/cursekeeper_extra.ron new file mode 100644 index 0000000000..554b4c62b5 --- /dev/null +++ b/assets/common/loot_tables/dungeon/terracotta/cursekeeper_extra.ron @@ -0,0 +1,8 @@ +[ + // Weapons + (3.0, LootTable("common.loot_tables.weapons.tier-5")), + // Armor + (3.0, LootTable("common.loot_tables.armor.tier-5")), + // Misc + (0.25, Item("common.items.tool.instruments.steeltonguedrum")), +] \ No newline at end of file diff --git a/assets/common/loot_tables/dungeon/terracotta/enemy.ron b/assets/common/loot_tables/dungeon/terracotta/enemy.ron new file mode 100644 index 0000000000..7b10ac71b9 --- /dev/null +++ b/assets/common/loot_tables/dungeon/terracotta/enemy.ron @@ -0,0 +1,6 @@ +[ + // Consumables + (1.0, MultiDrop(Item("common.items.consumable.potion_minor"), 2, 5)), + // Nothing + (2.0, Nothing), +] diff --git a/assets/common/loot_tables/dungeon/terracotta/terracotta_statue_key_chance.ron b/assets/common/loot_tables/dungeon/terracotta/terracotta_statue_key_chance.ron new file mode 100644 index 0000000000..6eadb68e98 --- /dev/null +++ b/assets/common/loot_tables/dungeon/terracotta/terracotta_statue_key_chance.ron @@ -0,0 +1,6 @@ +[ + // Key + (1.0, Item("common.items.keys.terracotta_key_chest")), + // Nothing + (5.0, Nothing), +] \ No newline at end of file diff --git a/assets/common/npc_names.ron b/assets/common/npc_names.ron index 8f0d229d7b..11872e8132 100644 --- a/assets/common/npc_names.ron +++ b/assets/common/npc_names.ron @@ -989,6 +989,26 @@ haniwa_general: ( keyword: "haniwa_general", generic: "Haniwa General" + ), + terracotta_besieger: ( + keyword: "terracotta_besieger", + generic: "Terracotta Besieger" + ), + terracotta_demolisher: ( + keyword: "terracotta_demolisher", + generic: "Terracotta Demolisher" + ), + terracotta_punisher: ( + keyword: "terracotta_punisher", + generic: "Terracotta Punisher" + ), + terracotta_pursuer: ( + keyword: "terracotta_pursuer", + generic: "Terracotta Pursuer" + ), + cursekeeper: ( + keyword: "cursekeeper", + generic: "Cursekeeper" ) ) ), @@ -1024,6 +1044,10 @@ keyword: "ancienteffigy", generic: "Ancient Effigy" ), + mogwai: ( + keyword: "mogwai", + generic: "Mogwai" + ), coralgolem: ( keyword: "coralgolem", generic: "Coral Golem" @@ -1189,6 +1213,14 @@ keyword: "irrwurz", generic: "Irrwurz", ), + shamanic_spirit: ( + keyword: "shamanic_spirit", + generic: "Shamanic Spirit", + ), + jiangshi: ( + keyword: "jiangshi", + generic: "Jiangshi", + ), ) ), fish_small: ( diff --git a/assets/server/manifests/kits.ron b/assets/server/manifests/kits.ron index 4a55ebd6d8..ca25cd024a 100644 --- a/assets/server/manifests/kits.ron +++ b/assets/server/manifests/kits.ron @@ -412,7 +412,7 @@ (Item("common.items.tool.instruments.sitar"),1), (Item("common.items.tool.instruments.washboard"),1), (Item("common.items.tool.instruments.wildskin_drum"),1), - (Item("common.items.tool.instruments.steeldrum"),1), + (Item("common.items.tool.instruments.steeltonguedrum"),1), (Item("common.items.tool.instruments.shamisen"),1), ], }) diff --git a/assets/voxygen/audio/sfx.ron b/assets/voxygen/audio/sfx.ron index 997f11c4d7..9e97651176 100644 --- a/assets/voxygen/audio/sfx.ron +++ b/assets/voxygen/audio/sfx.ron @@ -760,26 +760,25 @@ threshold: 0.5, subtitle: "subtitle-instrument_lute", ), - Music(Instrument, Custom("Steeldrum")): ( + Music(Instrument, Custom("Steeltonguedrum")): ( files: [ - "voxygen.audio.sfx.instrument.steeldrum.steeldrum_eg", - "voxygen.audio.sfx.instrument.steeldrum.steeldrum_ec1g", - "voxygen.audio.sfx.instrument.steeldrum.steeldrum_e", - "voxygen.audio.sfx.instrument.steeldrum.steeldrum_d1c1", - "voxygen.audio.sfx.instrument.steeldrum.steeldrum_d1", - "voxygen.audio.sfx.instrument.steeldrum.steeldrum_d", - "voxygen.audio.sfx.instrument.steeldrum.steeldrum_ce", - "voxygen.audio.sfx.instrument.steeldrum.steeldrum_c1ag", - "voxygen.audio.sfx.instrument.steeldrum.steeldrum_c1ae", - "voxygen.audio.sfx.instrument.steeldrum.steeldrum_c1", - "voxygen.audio.sfx.instrument.steeldrum.steeldrum_c", - "voxygen.audio.sfx.instrument.steeldrum.steeldrum_ac1", - "voxygen.audio.sfx.instrument.steeldrum.steeldrum_a", - "voxygen.audio.sfx.instrument.steeldrum.steeldrum_c1c1", - "voxygen.audio.sfx.instrument.steeldrum.steeldrum_g", + "voxygen.audio.sfx.instrument.steeltonguedrum.steeltonguedrum_eg", + "voxygen.audio.sfx.instrument.steeltonguedrum.steeltonguedrum_e", + "voxygen.audio.sfx.instrument.steeltonguedrum.steeltonguedrum_d1c1", + "voxygen.audio.sfx.instrument.steeltonguedrum.steeltonguedrum_d1", + "voxygen.audio.sfx.instrument.steeltonguedrum.steeltonguedrum_d", + "voxygen.audio.sfx.instrument.steeltonguedrum.steeltonguedrum_ce", + "voxygen.audio.sfx.instrument.steeltonguedrum.steeltonguedrum_c1ag", + "voxygen.audio.sfx.instrument.steeltonguedrum.steeltonguedrum_c1ae", + "voxygen.audio.sfx.instrument.steeltonguedrum.steeltonguedrum_c1", + "voxygen.audio.sfx.instrument.steeltonguedrum.steeltonguedrum_c", + "voxygen.audio.sfx.instrument.steeltonguedrum.steeltonguedrum_ac1", + "voxygen.audio.sfx.instrument.steeltonguedrum.steeltonguedrum_a", + "voxygen.audio.sfx.instrument.steeltonguedrum.steeltonguedrum_c1c1", + "voxygen.audio.sfx.instrument.steeltonguedrum.steeltonguedrum_g", ], threshold: 0.5, - subtitle: "subtitle-instrument_steeldrum", + subtitle: "subtitle-instrument_steeltonguedrum", ), Music(Instrument, Custom("Shamisen")): ( files: [ diff --git a/assets/voxygen/audio/sfx/instrument/steeldrum/steeldrum_a.ogg b/assets/voxygen/audio/sfx/instrument/steeldrum/steeldrum_a.ogg deleted file mode 100644 index 1222590236..0000000000 --- a/assets/voxygen/audio/sfx/instrument/steeldrum/steeldrum_a.ogg +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:016d588e10d816a3b7c7ee034ba18716096ecf17fc98aa36c99dca1609581b3e -size 8888 diff --git a/assets/voxygen/audio/sfx/instrument/steeldrum/steeldrum_ac1.ogg b/assets/voxygen/audio/sfx/instrument/steeldrum/steeldrum_ac1.ogg deleted file mode 100644 index 710064fe27..0000000000 --- a/assets/voxygen/audio/sfx/instrument/steeldrum/steeldrum_ac1.ogg +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:59ccdb9a9257ada30609fa314be48421d08f8537021d28e8e0871f980b3fb1b7 -size 8705 diff --git a/assets/voxygen/audio/sfx/instrument/steeldrum/steeldrum_c.ogg b/assets/voxygen/audio/sfx/instrument/steeldrum/steeldrum_c.ogg deleted file mode 100644 index 901cc41730..0000000000 --- a/assets/voxygen/audio/sfx/instrument/steeldrum/steeldrum_c.ogg +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:29d955a2270ad69b065da9c53af968819c61120f88fa4010fa0144ec04bc4653 -size 8807 diff --git a/assets/voxygen/audio/sfx/instrument/steeldrum/steeldrum_c1.ogg b/assets/voxygen/audio/sfx/instrument/steeldrum/steeldrum_c1.ogg deleted file mode 100644 index 2f734d56d0..0000000000 --- a/assets/voxygen/audio/sfx/instrument/steeldrum/steeldrum_c1.ogg +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:01cca498fac35f59542c4bc2b1aa65d5fca2b28282cb59735ffc119fd476de86 -size 9410 diff --git a/assets/voxygen/audio/sfx/instrument/steeldrum/steeldrum_c1ae.ogg b/assets/voxygen/audio/sfx/instrument/steeldrum/steeldrum_c1ae.ogg deleted file mode 100644 index 155b052588..0000000000 --- a/assets/voxygen/audio/sfx/instrument/steeldrum/steeldrum_c1ae.ogg +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:38b8ea6dea72de49af95556022b45f682ba3144d7a906062247d68b3bd7c00cc -size 9422 diff --git a/assets/voxygen/audio/sfx/instrument/steeldrum/steeldrum_c1ag.ogg b/assets/voxygen/audio/sfx/instrument/steeldrum/steeldrum_c1ag.ogg deleted file mode 100644 index 67fa2034c5..0000000000 --- a/assets/voxygen/audio/sfx/instrument/steeldrum/steeldrum_c1ag.ogg +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:9f7c6d4d76d5012c6fe6ca024be97a65c3a776adcb058af84b792fbb7714272c -size 9521 diff --git a/assets/voxygen/audio/sfx/instrument/steeldrum/steeldrum_c1c1.ogg b/assets/voxygen/audio/sfx/instrument/steeldrum/steeldrum_c1c1.ogg deleted file mode 100644 index 289d9531d2..0000000000 --- a/assets/voxygen/audio/sfx/instrument/steeldrum/steeldrum_c1c1.ogg +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:0fda79927b48de1127f4aa166a69d09cdd5d78a7bd56ef6a39e9e9a2b29de4e5 -size 9496 diff --git a/assets/voxygen/audio/sfx/instrument/steeldrum/steeldrum_ce.ogg b/assets/voxygen/audio/sfx/instrument/steeldrum/steeldrum_ce.ogg deleted file mode 100644 index 6ef666dd66..0000000000 --- a/assets/voxygen/audio/sfx/instrument/steeldrum/steeldrum_ce.ogg +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:03a69acba20f0ad6d5e394f298ee8db8d630299da0df633335b5da1bba20e7c3 -size 8677 diff --git a/assets/voxygen/audio/sfx/instrument/steeldrum/steeldrum_d.ogg b/assets/voxygen/audio/sfx/instrument/steeldrum/steeldrum_d.ogg deleted file mode 100644 index fe8c4a729e..0000000000 --- a/assets/voxygen/audio/sfx/instrument/steeldrum/steeldrum_d.ogg +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:d6563b91cf4c4744d6e01b28d84cb01f576e332c950b2395c3f3b9063759806c -size 8830 diff --git a/assets/voxygen/audio/sfx/instrument/steeldrum/steeldrum_d1.ogg b/assets/voxygen/audio/sfx/instrument/steeldrum/steeldrum_d1.ogg deleted file mode 100644 index e5fbc2241c..0000000000 --- a/assets/voxygen/audio/sfx/instrument/steeldrum/steeldrum_d1.ogg +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:9d67c3e439575f295774ce5adbdcaa6662e23457a3987726d2044ca3120e491f -size 9345 diff --git a/assets/voxygen/audio/sfx/instrument/steeldrum/steeldrum_d1c1.ogg b/assets/voxygen/audio/sfx/instrument/steeldrum/steeldrum_d1c1.ogg deleted file mode 100644 index 77da3dbfed..0000000000 --- a/assets/voxygen/audio/sfx/instrument/steeldrum/steeldrum_d1c1.ogg +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:3ec5e04308f6ee823702d49592391ba2ed6f57438494788c284d80fcf43f1889 -size 9486 diff --git a/assets/voxygen/audio/sfx/instrument/steeldrum/steeldrum_e.ogg b/assets/voxygen/audio/sfx/instrument/steeldrum/steeldrum_e.ogg deleted file mode 100644 index 0cb7cec6a4..0000000000 --- a/assets/voxygen/audio/sfx/instrument/steeldrum/steeldrum_e.ogg +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:6d55864c3b007bd290b6a11f5249d9703979841982a9b17f5e04d630d6de4b06 -size 8612 diff --git a/assets/voxygen/audio/sfx/instrument/steeldrum/steeldrum_ec1g.ogg b/assets/voxygen/audio/sfx/instrument/steeldrum/steeldrum_ec1g.ogg deleted file mode 100644 index aa65983c0d..0000000000 --- a/assets/voxygen/audio/sfx/instrument/steeldrum/steeldrum_ec1g.ogg +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:1f789a828d914656bfe1e463231cf6325f2763c25037729635b91fe47fa2a6c9 -size 9173 diff --git a/assets/voxygen/audio/sfx/instrument/steeldrum/steeldrum_eg.ogg b/assets/voxygen/audio/sfx/instrument/steeldrum/steeldrum_eg.ogg deleted file mode 100644 index d62fd61b97..0000000000 --- a/assets/voxygen/audio/sfx/instrument/steeldrum/steeldrum_eg.ogg +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:40abea4d44f2b316bbe20e1bc34d7d9e83d423cf828cf1e21eafb6f11c9efd50 -size 8808 diff --git a/assets/voxygen/audio/sfx/instrument/steeldrum/steeldrum_g.ogg b/assets/voxygen/audio/sfx/instrument/steeldrum/steeldrum_g.ogg deleted file mode 100644 index 713fb407cf..0000000000 --- a/assets/voxygen/audio/sfx/instrument/steeldrum/steeldrum_g.ogg +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:654df76d9b8c0e07186e67fe2adfad1d7127631ee6301d8be42e679f1239f617 -size 8973 diff --git a/assets/voxygen/audio/sfx/instrument/steeltonguedrum/steeltonguedrum_a.ogg b/assets/voxygen/audio/sfx/instrument/steeltonguedrum/steeltonguedrum_a.ogg new file mode 100644 index 0000000000..0e97c3f857 --- /dev/null +++ b/assets/voxygen/audio/sfx/instrument/steeltonguedrum/steeltonguedrum_a.ogg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7c25fc99ff492bb62b0b1266741820080690f5d43701a5e5642a677542e3125b +size 28387 diff --git a/assets/voxygen/audio/sfx/instrument/steeltonguedrum/steeltonguedrum_ac1.ogg b/assets/voxygen/audio/sfx/instrument/steeltonguedrum/steeltonguedrum_ac1.ogg new file mode 100644 index 0000000000..3dc487bbe9 --- /dev/null +++ b/assets/voxygen/audio/sfx/instrument/steeltonguedrum/steeltonguedrum_ac1.ogg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7a6cfbdddc8b4a3ce2aa43cf495d518789fbff380b54dd336b36f21123f88ec9 +size 29753 diff --git a/assets/voxygen/audio/sfx/instrument/steeltonguedrum/steeltonguedrum_c.ogg b/assets/voxygen/audio/sfx/instrument/steeltonguedrum/steeltonguedrum_c.ogg new file mode 100644 index 0000000000..87d1433956 --- /dev/null +++ b/assets/voxygen/audio/sfx/instrument/steeltonguedrum/steeltonguedrum_c.ogg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:eb7a17eda6e79c60544ce75267c7f99905e40bbed6b37470aff14fe0d2c4904e +size 27754 diff --git a/assets/voxygen/audio/sfx/instrument/steeltonguedrum/steeltonguedrum_c1.ogg b/assets/voxygen/audio/sfx/instrument/steeltonguedrum/steeltonguedrum_c1.ogg new file mode 100644 index 0000000000..e7c0373354 --- /dev/null +++ b/assets/voxygen/audio/sfx/instrument/steeltonguedrum/steeltonguedrum_c1.ogg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c391753dbe3b4f2d70b0f7b735e6ed11e139401e87af10a2aeef7dc4e7f963f6 +size 28121 diff --git a/assets/voxygen/audio/sfx/instrument/steeltonguedrum/steeltonguedrum_c1ae.ogg b/assets/voxygen/audio/sfx/instrument/steeltonguedrum/steeltonguedrum_c1ae.ogg new file mode 100644 index 0000000000..8c919d148c --- /dev/null +++ b/assets/voxygen/audio/sfx/instrument/steeltonguedrum/steeltonguedrum_c1ae.ogg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:511114496799ac848ac1d23d2901e87531e17a703a072cc9c2c252b4e85a9afd +size 31012 diff --git a/assets/voxygen/audio/sfx/instrument/steeltonguedrum/steeltonguedrum_c1ag.ogg b/assets/voxygen/audio/sfx/instrument/steeltonguedrum/steeltonguedrum_c1ag.ogg new file mode 100644 index 0000000000..9d92a2a761 --- /dev/null +++ b/assets/voxygen/audio/sfx/instrument/steeltonguedrum/steeltonguedrum_c1ag.ogg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:aaf1b3f7bfb792889f5118c8a070807eca021e0d6ccb6167ec7d71c9844532c6 +size 30338 diff --git a/assets/voxygen/audio/sfx/instrument/steeltonguedrum/steeltonguedrum_c1c1.ogg b/assets/voxygen/audio/sfx/instrument/steeltonguedrum/steeltonguedrum_c1c1.ogg new file mode 100644 index 0000000000..32fcc11fa6 --- /dev/null +++ b/assets/voxygen/audio/sfx/instrument/steeltonguedrum/steeltonguedrum_c1c1.ogg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c04108d9ebbe0efb401cf04e560d5ca1105be3215c666527397947d9caf32c7a +size 28856 diff --git a/assets/voxygen/audio/sfx/instrument/steeltonguedrum/steeltonguedrum_ce.ogg b/assets/voxygen/audio/sfx/instrument/steeltonguedrum/steeltonguedrum_ce.ogg new file mode 100644 index 0000000000..374dd0bc4f --- /dev/null +++ b/assets/voxygen/audio/sfx/instrument/steeltonguedrum/steeltonguedrum_ce.ogg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:32c3dafa6286bf8a6859992a5b05b8d4433ce6b697914c54c9c44fca733c6030 +size 28874 diff --git a/assets/voxygen/audio/sfx/instrument/steeltonguedrum/steeltonguedrum_d.ogg b/assets/voxygen/audio/sfx/instrument/steeltonguedrum/steeltonguedrum_d.ogg new file mode 100644 index 0000000000..6c8f87e9e8 --- /dev/null +++ b/assets/voxygen/audio/sfx/instrument/steeltonguedrum/steeltonguedrum_d.ogg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4579dd7b36cdf64e64d2cd19f50499990029b29a2291c279fab8d10c37d73d7c +size 27851 diff --git a/assets/voxygen/audio/sfx/instrument/steeltonguedrum/steeltonguedrum_d1.ogg b/assets/voxygen/audio/sfx/instrument/steeltonguedrum/steeltonguedrum_d1.ogg new file mode 100644 index 0000000000..125ff093c9 --- /dev/null +++ b/assets/voxygen/audio/sfx/instrument/steeltonguedrum/steeltonguedrum_d1.ogg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7412585a952efd3cc85bd792ea58b71cd06bedb3c755e68700e2cf6bb04c2b81 +size 27373 diff --git a/assets/voxygen/audio/sfx/instrument/steeltonguedrum/steeltonguedrum_d1c1.ogg b/assets/voxygen/audio/sfx/instrument/steeltonguedrum/steeltonguedrum_d1c1.ogg new file mode 100644 index 0000000000..710e526985 --- /dev/null +++ b/assets/voxygen/audio/sfx/instrument/steeltonguedrum/steeltonguedrum_d1c1.ogg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5b84896bce620fb8c47cca0f34eb0dc055b106fbe59841fb1191f7471f9f6982 +size 29156 diff --git a/assets/voxygen/audio/sfx/instrument/steeltonguedrum/steeltonguedrum_e.ogg b/assets/voxygen/audio/sfx/instrument/steeltonguedrum/steeltonguedrum_e.ogg new file mode 100644 index 0000000000..ca3ed3626b --- /dev/null +++ b/assets/voxygen/audio/sfx/instrument/steeltonguedrum/steeltonguedrum_e.ogg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8f26596d20198e854f1337d317f8763a63c1e8ebc571c2875cc77cb480b4d03e +size 28183 diff --git a/assets/voxygen/audio/sfx/instrument/steeltonguedrum/steeltonguedrum_eg.ogg b/assets/voxygen/audio/sfx/instrument/steeltonguedrum/steeltonguedrum_eg.ogg new file mode 100644 index 0000000000..7a9d102298 --- /dev/null +++ b/assets/voxygen/audio/sfx/instrument/steeltonguedrum/steeltonguedrum_eg.ogg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c96aba4e3ebc6bf048d7ef55501caf0387cf018dc6bab9bfd222367bb492c3e6 +size 29415 diff --git a/assets/voxygen/audio/sfx/instrument/steeltonguedrum/steeltonguedrum_g.ogg b/assets/voxygen/audio/sfx/instrument/steeltonguedrum/steeltonguedrum_g.ogg new file mode 100644 index 0000000000..99d4db92d4 --- /dev/null +++ b/assets/voxygen/audio/sfx/instrument/steeltonguedrum/steeltonguedrum_g.ogg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5e3363daaa8ca3db7a7e5a63fe6ff46551765130a5afc6d1f06324429c9d700a +size 28631 diff --git a/assets/voxygen/element/ui/map/buttons/terracotta.png b/assets/voxygen/element/ui/map/buttons/terracotta.png new file mode 100644 index 0000000000..30cb1f7a44 --- /dev/null +++ b/assets/voxygen/element/ui/map/buttons/terracotta.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7ba6e93178c28a2b9a3e1d43b28bfc34d77ac86c4dddc4022ac02c28fbcacfc1 +size 528 diff --git a/assets/voxygen/element/ui/map/buttons/terracotta_bg.png b/assets/voxygen/element/ui/map/buttons/terracotta_bg.png new file mode 100644 index 0000000000..ffc29d5e8f --- /dev/null +++ b/assets/voxygen/element/ui/map/buttons/terracotta_bg.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f151945032364464d1df9bdecebf7e511be695b61f0390cc7496322adc2f5585 +size 154 diff --git a/assets/voxygen/element/ui/map/buttons/terracotta_hover.png b/assets/voxygen/element/ui/map/buttons/terracotta_hover.png new file mode 100644 index 0000000000..e79ee66cf3 --- /dev/null +++ b/assets/voxygen/element/ui/map/buttons/terracotta_hover.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e91187dbb38f7aeb9e09fbc792d3b4d8844fbb91051e09291ac39779d6bd9515 +size 537 diff --git a/assets/voxygen/i18n/en/body.ftl b/assets/voxygen/i18n/en/body.ftl index e25f268f48..f1ad801bac 100644 --- a/assets/voxygen/i18n/en/body.ftl +++ b/assets/voxygen/i18n/en/body.ftl @@ -12,3 +12,24 @@ body-npc-speech-biped_large-swamp_troll = a swamp troll body-npc-speech-biped_large-blue_oni = a blue oni body-npc-speech-biped_large-red_oni = a red oni body-npc-speech-biped_large-tursus = a tursus +body-npc-speech-biped_large-dullahan = a dullahan +body-npc-speech-biped_large-occult_saurok = an occult saurok +body-npc-speech-biped_large-mighty_saurok = a mighty saurok +body-npc-speech-biped_large-sly_saurok = a sly saurok +body-npc-speech-biped_large-mindflayer = a mindflayer +body-npc-speech-biped_large-minotaur = a minotaur +body-npc-speech-biped_large-tidal_warrior = a tidal warrior +body-npc-speech-biped_large-yeti = a yeti +body-npc-speech-biped_large-harvester = a harvester +body-npc-speech-biped_large-cultist_warlord = a cultist warlord +body-npc-speech-biped_large-cultist_warlock = a cultist warlock +body-npc-speech-biped_large-husk_brute = a husk brute +body-npc-speech-biped_large-gigas_frost = a gigas frost +body-npc-speech-biped_large-adlet_elder = an adlet elder +body-npc-speech-biped_large-sea_bishop = a sea bishop +body-npc-speech-biped_large-haniwa_general = a haniwa general +body-npc-speech-biped_large-terracotta_besieger = a terracotta besieger +body-npc-speech-biped_large-terracotta_demolisher = a terracotta demolisher +body-npc-speech-biped_large-terracotta_punisher = a terracotta punisher +body-npc-speech-biped_large-terracotta_pursuer = a terracotta pursuer +body-npc-speech-biped_large-cursekeeper = a terracotta pursuer diff --git a/assets/voxygen/i18n/en/hud/map.ftl b/assets/voxygen/i18n/en/hud/map.ftl index e763c8a020..59e1db0a5b 100644 --- a/assets/voxygen/i18n/en/hud/map.ftl +++ b/assets/voxygen/i18n/en/hud/map.ftl @@ -36,4 +36,5 @@ hud-map-gnarling = Gnarling Fortification hud-map-chapel_site = Sea Chapel hud-map-adlet = Adlet Stronghold hud-map-haniwa = Haniwa Catacomb +hud-map-terracotta = Terracotta Ruins hud-map-placed_by = Placed by { $name } \ No newline at end of file diff --git a/assets/voxygen/i18n/en/item/armor/npc.ftl b/assets/voxygen/i18n/en/item/armor/npc.ftl index f2cc8e585a..87ddf8e272 100644 --- a/assets/voxygen/i18n/en/item/armor/npc.ftl +++ b/assets/voxygen/i18n/en/item/armor/npc.ftl @@ -25,6 +25,9 @@ common-items-npc_armor-golem-ancienteffigy = Ancient Effigy Armor common-items-npc_armor-golem-gravewarden = Grave Warden Armor .desc = Worn by grave warden. +common-items-npc_armor-golem-mogwai = Mogwai Armor + .desc = Worn by mogwai. + common-items-npc_armor-biped_small-myrmidon-foot-hoplite = Myrmidon Hoplite .desc = Ceremonial attire used by members. @@ -493,6 +496,33 @@ common-items-npc_armor-biped_small-gnoll-tail-shaman = Gnoll Shaman common-items-npc_armor-biped_small-gnoll-tail-trapper = Gnoll Trapper .desc = Ceremonial attire used by members. +common-items-npc_armor-biped_small-jiangshi-head-jiangshi = Jiangshi + .desc = Ceremonial attire used by members. + +common-items-npc_armor-biped_small-jiangshi-chest-jiangshi = Jiangshi + .desc = Ceremonial attire used by members. + +common-items-npc_armor-biped_small-jiangshi-pants-jiangshi = Jiangshi + .desc = Ceremonial attire used by members. + +common-items-npc_armor-biped_small-jiangshi-hand-jiangshi = Jiangshi + .desc = Ceremonial attire used by members. + +common-items-npc_armor-biped_small-jiangshi-foot-jiangshi = Jiangshi + .desc = Ceremonial attire used by members. + +common-items-npc_armor-biped_small-shamanic_spirit-head-shamanic_spirit = Shamanic Spirit + .desc = Ceremonial attire used by members. + +common-items-npc_armor-biped_small-shamanic_spirit-chest-shamanic_spirit = Shamanic Spirit + .desc = Ceremonial attire used by members. + +common-items-npc_armor-biped_small-shamanic_spirit-pants-shamanic_spirit = Shamanic Spirit + .desc = Ceremonial attire used by members. + +common-items-npc_armor-biped_small-shamanic_spirit-hand-shamanic_spirit = Shamanic Spirit + .desc = Ceremonial attire used by members. + common-items-npc_armor-chest-plate_red = Iron Chestplate .desc = A chestplate forged from iron. @@ -613,6 +643,9 @@ common-items-npc_armor-biped_large-yeti = Yeti Hide common-items-npc_armor-biped_large-haniwageneral = Haniwa General Uniform .desc = Has seen combat. +common-items-npc_armor-biped_large-terracotta = Terracotta Armor + .desc = A little dusty, that's all. + armor-leather_blue-pants = Blue Leather Cuirass .desc = {""} diff --git a/assets/voxygen/i18n/en/item/items/key.ftl b/assets/voxygen/i18n/en/item/items/key.ftl index f7845fa700..7129886e9b 100644 --- a/assets/voxygen/i18n/en/item/items/key.ftl +++ b/assets/voxygen/i18n/en/item/items/key.ftl @@ -33,3 +33,9 @@ object-key-cyclops_eyeball = Cyclops Eye object-key-haniwa = Haniwa Keystone .desc = Used to open doors. Will break after use. + +object-key-terracotta_chest = Terracotta Chest Key + .desc = Used to open chests. Will break after use. + +object-key-terracotta_door = Terracotta Door Key + .desc = Used to open doors. Will break after use. \ No newline at end of file diff --git a/assets/voxygen/i18n/en/item/weapon/musical_instrument.ftl b/assets/voxygen/i18n/en/item/weapon/musical_instrument.ftl index 3df8d23644..dc2deccc3b 100644 --- a/assets/voxygen/i18n/en/item/weapon/musical_instrument.ftl +++ b/assets/voxygen/i18n/en/item/weapon/musical_instrument.ftl @@ -37,8 +37,8 @@ weapon-tool-washboard = Washboard weapon-tool-wildskin_drum = Wildskin Drum .desc = one, two, you know what to do! -weapon-tool-steeldrum = Steeldrum - .desc = Steeldrum. +weapon-tool-steeltonguedrum = Steeltongue Drum + .desc = Steeltongue Drum. weapon-tool-shamisen = Shamisen .desc = Shamisen. diff --git a/assets/voxygen/i18n/en/item/weapon/npc.ftl b/assets/voxygen/i18n/en/item/weapon/npc.ftl index fe8b26ea4e..3f3c012b77 100644 --- a/assets/voxygen/i18n/en/item/weapon/npc.ftl +++ b/assets/voxygen/i18n/en/item/weapon/npc.ftl @@ -73,6 +73,9 @@ common-items-npc_weapons-bow-bipedlarge-velorite = Giant Velorite Bow common-items-npc_weapons-bow-saurok_bow = Saurok bow .desc = Placeholder +common-items-npc_weapons-bow-terracotta_besieger_bow = Terracotta Besieger Bow + .desc = Placeholder + common-items-npc_weapons-axe-gigas_frost_axe = Frost Gigas Axe .desc = Placeholder @@ -112,6 +115,9 @@ common-items-npc_weapons-sword-saurok_sword = Saurok Sword common-items-npc_weapons-sword-haniwa_general_sword = Haniwa General Sword .desc = Placeholder +common-items-npc_weapons-sword-terracotta_pursuer_sword = Terracotta Pursuer Sword + .desc = Placeholder + common-items-npc_weapons-unique-akhlut = Quad Med Basic .desc = testing123 @@ -169,6 +175,27 @@ common-items-npc_weapons-unique-fiery_tornado = FieryTornado common-items-npc_weapons-unique-flamekeeper_staff = Flamekeeper Staff .desc = Flamekeeper Staff +common-items-npc_weapons-unique-cursekeeper_sceptre = Cursekeeper Sceptre + .desc = Cursekeeper Sceptre + +common-items-npc_weapons-unique-cursekeeper_sceptre_fake = Cursekeeper Sceptre + .desc = Cursekeeper Sceptre + +common-items-npc_weapons-unique-jiangshi = Jiangshi Magic + .desc = Jiangshi Magic + +common-items-npc_weapons-unique-mogwai = Mogwai Magic + .desc = Mogwai Magic + +common-items-npc_weapons-unique-shamanic_spirit = Shamanic Spirit + .desc = Shamanic Spirit + +common-items-npc_weapons-unique-terracotta_demolisher_fist = Terracotta Demolisher Fist + .desc = Terracotta Demolisher Fist + +common-items-npc_weapons-unique-terracotta_statue = Terracotta Statue + .desc = Terracotta Statue + common-items-npc_weapons-unique-flamethrower = Flamethrower .desc = Throwing Flames @@ -417,3 +444,6 @@ common-items-npc_weapons-hammer-wendigo_hammer = Wendigo Hammer common-items-npc_weapons-hammer-yeti_hammer = Yeti Hammer .desc = Placeholder + +common-items-npc_weapons-hammer-terracotta_punisher_club = Terracotta Punisher Club + .desc = Placeholder diff --git a/assets/voxygen/item_image_manifest.ron b/assets/voxygen/item_image_manifest.ron index 94a5ef00d3..aa31dcece6 100644 --- a/assets/voxygen/item_image_manifest.ron +++ b/assets/voxygen/item_image_manifest.ron @@ -1662,8 +1662,8 @@ "voxel.weapon.tool.wooden_lute", (0.0, 0.0, 0.0), (45.0, 90.0, 0.0), 1.0, ), - Simple("common.items.tool.instruments.steeldrum"): VoxTrans( - "voxel.weapon.tool.steeldrum", + Simple("common.items.tool.instruments.steeltonguedrum"): VoxTrans( + "voxel.weapon.tool.steeltonguedrum", (0.0, 0.0, 0.0), (45.0, 90.0, 0.0), 1.0, ), Simple("common.items.tool.instruments.shamisen"): VoxTrans( @@ -4974,6 +4974,14 @@ "voxel.object.key_rusty-0", (0.0, 0.0, 0.0), (-100.0, 250.0, 15.0), 1.0, ), + Simple("common.items.keys.terracotta_key_chest"): VoxTrans( + "voxel.object.key_terracotta_chest", + (0.0, 0.0, 0.0), (-100.0, 250.0, 15.0), 1.0, + ), + Simple("common.items.keys.terracotta_key_door"): VoxTrans( + "voxel.object.key_terracotta_door", + (0.0, 0.0, 0.0), (-100.0, 250.0, 15.0), 1.0, + ), // Lockpicks Simple("common.items.utility.lockpick_0"): VoxTrans( "voxel.object.lockpick", diff --git a/assets/voxygen/voxel/biped_large_central_manifest.ron b/assets/voxygen/voxel/biped_large_central_manifest.ron index 0c1ed53af7..5392541fd7 100644 --- a/assets/voxygen/voxel/biped_large_central_manifest.ron +++ b/assets/voxygen/voxel/biped_large_central_manifest.ron @@ -1302,7 +1302,7 @@ ), (HaniwaGeneral, Male): ( head: ( - offset: (-7.5, 0.0, -6.5), + offset: (-7.5, -6.5, -6.5), central: ("npc.haniwa.general.haniwa_general"), ), torso_upper: ( @@ -1330,7 +1330,7 @@ ), (HaniwaGeneral, Female): ( head: ( - offset: (-7.5, 0.0, -6.5), + offset: (-7.5, -6.5, -6.5), central: ("npc.haniwa.general.haniwa_general"), ), torso_upper: ( @@ -1356,4 +1356,284 @@ central: ("armor.empty"), ) ), + (TerracottaBesieger, Male): ( + head: ( + offset: (-7.5, -8.5, -10.5), + central: ("npc.terracotta.terracotta_besieger"), + ), + torso_upper: ( + offset: (-9.5, -6.0, -6.0), + central: ("npc.terracotta.terracotta_besieger"), + model_index: 1, + ), + torso_lower: ( + offset: (-9.5, -6.0, -8.0), + central: ("npc.terracotta.terracotta_besieger"), + model_index: 2, + ), + jaw: ( + offset: (-5.0, 0.0, -3.5), + central: ("armor.empty"), + ), + tail: ( + offset: (-2.0, -17.0, -1.0), + central: ("armor.empty"), + ), + second: ( + offset: (0.0, 0.0, 0.0), + central: ("armor.empty"), + ) + ), + (TerracottaBesieger, Female): ( + head: ( + offset: (-7.5, -8.5, -10.5), + central: ("npc.terracotta.terracotta_besieger"), + ), + torso_upper: ( + offset: (-9.5, -6.0, -6.0), + central: ("npc.terracotta.terracotta_besieger"), + model_index: 1, + ), + torso_lower: ( + offset: (-9.5, -6.0, -8.0), + central: ("npc.terracotta.terracotta_besieger"), + model_index: 2, + ), + jaw: ( + offset: (-5.0, 0.0, -3.5), + central: ("armor.empty"), + ), + tail: ( + offset: (-2.0, -17.0, -1.0), + central: ("armor.empty"), + ), + second: ( + offset: (0.0, 0.0, 0.0), + central: ("armor.empty"), + ) + ), + (TerracottaDemolisher, Male): ( + head: ( + offset: (-6.5, -5.5, -7.5), + central: ("npc.terracotta.terracotta_demolisher"), + ), + torso_upper: ( + offset: (-6.5, -4.5, -5.0), + central: ("npc.terracotta.terracotta_demolisher"), + model_index: 1, + ), + torso_lower: ( + offset: (-7.5, -5.5, -6.0), + central: ("npc.terracotta.terracotta_demolisher"), + model_index: 2, + ), + jaw: ( + offset: (-5.0, 0.0, -3.5), + central: ("armor.empty"), + ), + tail: ( + offset: (-2.0, -17.0, -1.0), + central: ("armor.empty"), + ), + second: ( + offset: (0.0, 0.0, 0.0), + central: ("armor.empty"), + ) + ), + (TerracottaDemolisher, Female): ( + head: ( + offset: (-6.5, -5.5, -7.5), + central: ("npc.terracotta.terracotta_demolisher"), + ), + torso_upper: ( + offset: (-6.5, -4.5, -5.0), + central: ("npc.terracotta.terracotta_demolisher"), + model_index: 1, + ), + torso_lower: ( + offset: (-7.5, -5.5, -6.0), + central: ("npc.terracotta.terracotta_demolisher"), + model_index: 2, + ), + jaw: ( + offset: (-5.0, 0.0, -3.5), + central: ("armor.empty"), + ), + tail: ( + offset: (-2.0, -17.0, -1.0), + central: ("armor.empty"), + ), + second: ( + offset: (0.0, 0.0, 0.0), + central: ("armor.empty"), + ) + ), + (TerracottaPunisher, Male): ( + head: ( + offset: (-5.5, -5.5, -5.5), + central: ("npc.terracotta.terracotta_punisher"), + ), + torso_upper: ( + offset: (-6.5, -4.5, -5.0), + central: ("npc.terracotta.terracotta_punisher"), + model_index: 1, + ), + torso_lower: ( + offset: (-7.5, -6.0, -6.0), + central: ("npc.terracotta.terracotta_punisher"), + model_index: 2, + ), + jaw: ( + offset: (-5.0, 0.0, -3.5), + central: ("armor.empty"), + ), + tail: ( + offset: (-2.0, -17.0, -1.0), + central: ("armor.empty"), + ), + second: ( + offset: (0.0, 0.0, 0.0), + central: ("armor.empty"), + ) + ), + (TerracottaPunisher, Female): ( + head: ( + offset: (-5.5, -5.5, -5.5), + central: ("npc.terracotta.terracotta_punisher"), + ), + torso_upper: ( + offset: (-6.5, -4.5, -5.0), + central: ("npc.terracotta.terracotta_punisher"), + model_index: 1, + ), + torso_lower: ( + offset: (-7.5, -6.0, -6.0), + central: ("npc.terracotta.terracotta_punisher"), + model_index: 2, + ), + jaw: ( + offset: (-5.0, 0.0, -3.5), + central: ("armor.empty"), + ), + tail: ( + offset: (-2.0, -17.0, -1.0), + central: ("armor.empty"), + ), + second: ( + offset: (0.0, 0.0, 0.0), + central: ("armor.empty"), + ) + ), + (TerracottaPursuer, Male): ( + head: ( + offset: (-5.5, -8.5, -9.0), + central: ("npc.terracotta.terracotta_pursuer"), + ), + torso_upper: ( + offset: (-6.5, -4.5, -5.0), + central: ("npc.terracotta.terracotta_pursuer"), + model_index: 1, + ), + torso_lower: ( + offset: (-7.5, -6.0, -6.0), + central: ("npc.terracotta.terracotta_pursuer"), + model_index: 2, + ), + jaw: ( + offset: (-5.0, 0.0, -3.5), + central: ("armor.empty"), + ), + tail: ( + offset: (-2.0, -17.0, -1.0), + central: ("armor.empty"), + ), + second: ( + offset: (0.0, 0.0, 0.0), + central: ("armor.empty"), + ) + ), + (TerracottaPursuer, Female): ( + head: ( + offset: (-5.5, -8.5, -9.0), + central: ("npc.terracotta.terracotta_pursuer"), + ), + torso_upper: ( + offset: (-6.5, -4.5, -5.0), + central: ("npc.terracotta.terracotta_pursuer"), + model_index: 1, + ), + torso_lower: ( + offset: (-7.5, -6.0, -6.0), + central: ("npc.terracotta.terracotta_pursuer"), + model_index: 2, + ), + jaw: ( + offset: (-5.0, 0.0, -3.5), + central: ("armor.empty"), + ), + tail: ( + offset: (-2.0, -17.0, -1.0), + central: ("armor.empty"), + ), + second: ( + offset: (0.0, 0.0, 0.0), + central: ("armor.empty"), + ) + ), + (Cursekeeper, Male): ( + head: ( + offset: (-11.0, -11.0, -8.0), + central: ("npc.terracotta.cursekeeper"), + ), + torso_upper: ( + offset: (-7.0, -6.5, -5.5), + central: ("npc.terracotta.cursekeeper"), + model_index: 1, + ), + torso_lower: ( + offset: (-7.0, -7.0, -18.0), + central: ("npc.terracotta.cursekeeper"), + model_index: 2, + ), + jaw: ( + offset: (-5.0, 0.0, -3.5), + central: ("armor.empty"), + ), + tail: ( + offset: (-2.0, -17.0, -1.0), + central: ("armor.empty"), + ), + second: ( + offset: (0.0, 0.0, 0.0), + central: ("armor.empty"), + ) + ), + (Cursekeeper, Female): ( + head: ( + offset: (-11.0, -11.0, -8.0), + central: ("npc.terracotta.cursekeeper"), + ), + torso_upper: ( + offset: (-7.0, -6.5, -5.5), + central: ("npc.terracotta.cursekeeper"), + model_index: 1, + ), + torso_lower: ( + offset: (-7.0, -7.0, -18.0), + central: ("npc.terracotta.cursekeeper"), + model_index: 2, + ), + jaw: ( + offset: (-5.0, 0.0, -3.5), + central: ("armor.empty"), + ), + tail: ( + offset: (-2.0, -17.0, -1.0), + central: ("armor.empty"), + ), + second: ( + offset: (0.0, 0.0, 0.0), + central: ("armor.empty"), + ) + ), }) diff --git a/assets/voxygen/voxel/biped_large_lateral_manifest.ron b/assets/voxygen/voxel/biped_large_lateral_manifest.ron index 835c820eb0..9aa701a6a9 100644 --- a/assets/voxygen/voxel/biped_large_lateral_manifest.ron +++ b/assets/voxygen/voxel/biped_large_lateral_manifest.ron @@ -1783,4 +1783,416 @@ model_index: 10, ), ), + (TerracottaBesieger, Male): ( + shoulder_l: ( + offset: (-4.0, -5.0, -7.0), + lateral: ("npc.terracotta.terracotta_besieger"), + model_index: 3, + ), + shoulder_r: ( + offset: (-4.0, -5.0, -7.0), + lateral: ("npc.terracotta.terracotta_besieger"), + model_index: 4, + ), + hand_l: ( + offset: (-3.5, -4.0, -11.0), + lateral: ("npc.terracotta.terracotta_besieger"), + model_index: 5, + ), + hand_r: ( + offset: (-3.5, -4.0, -11.0), + lateral: ("npc.terracotta.terracotta_besieger"), + model_index: 6, + ), + leg_l: ( + offset: (-4.0, -3.5, -4.5), + lateral: ("npc.terracotta.terracotta_besieger"), + model_index: 7, + ), + leg_r: ( + offset: (-4.0, -3.5, -4.5), + lateral: ("npc.terracotta.terracotta_besieger"), + model_index: 8, + ), + foot_l: ( + offset: (-2.5, -4.5, -4.0), + lateral: ("npc.terracotta.terracotta_besieger"), + model_index: 9, + ), + foot_r: ( + offset: (-2.5, -4.5, -4.0), + lateral: ("npc.terracotta.terracotta_besieger"), + model_index: 10, + ), + ), + (TerracottaBesieger, Female): ( + shoulder_l: ( + offset: (-4.0, -5.0, -7.0), + lateral: ("npc.terracotta.terracotta_besieger"), + model_index: 3, + ), + shoulder_r: ( + offset: (-4.0, -5.0, -7.0), + lateral: ("npc.terracotta.terracotta_besieger"), + model_index: 4, + ), + hand_l: ( + offset: (-3.5, -4.0, -11.0), + lateral: ("npc.terracotta.terracotta_besieger"), + model_index: 5, + ), + hand_r: ( + offset: (-3.5, -4.0, -11.0), + lateral: ("npc.terracotta.terracotta_besieger"), + model_index: 6, + ), + leg_l: ( + offset: (-4.0, -3.5, -4.5), + lateral: ("npc.terracotta.terracotta_besieger"), + model_index: 7, + ), + leg_r: ( + offset: (-4.0, -3.5, -4.5), + lateral: ("npc.terracotta.terracotta_besieger"), + model_index: 8, + ), + foot_l: ( + offset: (-2.5, -4.5, -4.0), + lateral: ("npc.terracotta.terracotta_besieger"), + model_index: 9, + ), + foot_r: ( + offset: (-2.5, -4.5, -4.0), + lateral: ("npc.terracotta.terracotta_besieger"), + model_index: 10, + ), + ), + (TerracottaDemolisher, Male): ( + shoulder_l: ( + offset: (-3.0, -4.0, -7.0), + lateral: ("npc.terracotta.terracotta_demolisher"), + model_index: 3, + ), + shoulder_r: ( + offset: (-3.0, -4.0, -7.0), + lateral: ("npc.terracotta.terracotta_demolisher"), + model_index: 4, + ), + hand_l: ( + offset: (-3.0, -2.0, -9.0), + lateral: ("npc.terracotta.terracotta_demolisher"), + model_index: 5, + ), + hand_r: ( + offset: (-3.0, -2.0, -9.0), + lateral: ("npc.terracotta.terracotta_demolisher"), + model_index: 6, + ), + leg_l: ( + offset: (-3.0, -3.0, -3.5), + lateral: ("npc.terracotta.terracotta_demolisher"), + model_index: 7, + ), + leg_r: ( + offset: (-3.0, -3.0, -3.5), + lateral: ("npc.terracotta.terracotta_demolisher"), + model_index: 8, + ), + foot_l: ( + offset: (-2.0, -3.5, -2.5), + lateral: ("npc.terracotta.terracotta_demolisher"), + model_index: 9, + ), + foot_r: ( + offset: (-2.0, -3.5, -2.5), + lateral: ("npc.terracotta.terracotta_demolisher"), + model_index: 10, + ), + ), + (TerracottaDemolisher, Female): ( + shoulder_l: ( + offset: (-3.0, -4.0, -7.0), + lateral: ("npc.terracotta.terracotta_demolisher"), + model_index: 3, + ), + shoulder_r: ( + offset: (-3.0, -4.0, -7.0), + lateral: ("npc.terracotta.terracotta_demolisher"), + model_index: 4, + ), + hand_l: ( + offset: (-3.0, -2.0, -9.0), + lateral: ("npc.terracotta.terracotta_demolisher"), + model_index: 5, + ), + hand_r: ( + offset: (-3.0, -2.0, -9.0), + lateral: ("npc.terracotta.terracotta_demolisher"), + model_index: 6, + ), + leg_l: ( + offset: (-3.0, -3.0, -3.5), + lateral: ("npc.terracotta.terracotta_demolisher"), + model_index: 7, + ), + leg_r: ( + offset: (-3.0, -3.0, -3.5), + lateral: ("npc.terracotta.terracotta_demolisher"), + model_index: 8, + ), + foot_l: ( + offset: (-2.0, -3.5, -2.5), + lateral: ("npc.terracotta.terracotta_demolisher"), + model_index: 9, + ), + foot_r: ( + offset: (-2.0, -3.5, -2.5), + lateral: ("npc.terracotta.terracotta_demolisher"), + model_index: 10, + ), + ), + (TerracottaPunisher, Male): ( + shoulder_l: ( + offset: (-3.0, -4.0, -7.0), + lateral: ("npc.terracotta.terracotta_punisher"), + model_index: 3, + ), + shoulder_r: ( + offset: (-3.0, -4.0, -7.0), + lateral: ("npc.terracotta.terracotta_punisher"), + model_index: 4, + ), + hand_l: ( + offset: (-3.0, -2.0, -9.0), + lateral: ("npc.terracotta.terracotta_punisher"), + model_index: 5, + ), + hand_r: ( + offset: (-3.0, -2.0, -9.0), + lateral: ("npc.terracotta.terracotta_punisher"), + model_index: 6, + ), + leg_l: ( + offset: (-3.0, -3.0, -3.5), + lateral: ("npc.terracotta.terracotta_punisher"), + model_index: 7, + ), + leg_r: ( + offset: (-3.0, -3.0, -3.5), + lateral: ("npc.terracotta.terracotta_punisher"), + model_index: 8, + ), + foot_l: ( + offset: (-2.0, -3.5, -2.5), + lateral: ("npc.terracotta.terracotta_punisher"), + model_index: 9, + ), + foot_r: ( + offset: (-2.0, -3.5, -2.5), + lateral: ("npc.terracotta.terracotta_punisher"), + model_index: 10, + ), + ), + (TerracottaPunisher, Female): ( + shoulder_l: ( + offset: (-3.0, -4.0, -7.0), + lateral: ("npc.terracotta.terracotta_punisher"), + model_index: 3, + ), + shoulder_r: ( + offset: (-3.0, -4.0, -7.0), + lateral: ("npc.terracotta.terracotta_punisher"), + model_index: 4, + ), + hand_l: ( + offset: (-3.0, -2.0, -9.0), + lateral: ("npc.terracotta.terracotta_punisher"), + model_index: 5, + ), + hand_r: ( + offset: (-3.0, -2.0, -9.0), + lateral: ("npc.terracotta.terracotta_punisher"), + model_index: 6, + ), + leg_l: ( + offset: (-3.0, -3.0, -3.5), + lateral: ("npc.terracotta.terracotta_punisher"), + model_index: 7, + ), + leg_r: ( + offset: (-3.0, -3.0, -3.5), + lateral: ("npc.terracotta.terracotta_punisher"), + model_index: 8, + ), + foot_l: ( + offset: (-2.0, -3.5, -2.5), + lateral: ("npc.terracotta.terracotta_punisher"), + model_index: 9, + ), + foot_r: ( + offset: (-2.0, -3.5, -2.5), + lateral: ("npc.terracotta.terracotta_punisher"), + model_index: 10, + ), + ), + (TerracottaPursuer, Male): ( + shoulder_l: ( + offset: (-3.0, -4.0, -7.0), + lateral: ("npc.terracotta.terracotta_pursuer"), + model_index: 3, + ), + shoulder_r: ( + offset: (-3.0, -4.0, -7.0), + lateral: ("npc.terracotta.terracotta_pursuer"), + model_index: 4, + ), + hand_l: ( + offset: (-3.0, -2.0, -9.0), + lateral: ("npc.terracotta.terracotta_pursuer"), + model_index: 5, + ), + hand_r: ( + offset: (-3.0, -2.0, -9.0), + lateral: ("npc.terracotta.terracotta_pursuer"), + model_index: 6, + ), + leg_l: ( + offset: (-3.0, -3.0, -3.5), + lateral: ("npc.terracotta.terracotta_pursuer"), + model_index: 7, + ), + leg_r: ( + offset: (-3.0, -3.0, -3.5), + lateral: ("npc.terracotta.terracotta_pursuer"), + model_index: 8, + ), + foot_l: ( + offset: (-2.0, -3.5, -2.5), + lateral: ("npc.terracotta.terracotta_pursuer"), + model_index: 9, + ), + foot_r: ( + offset: (-2.0, -3.5, -2.5), + lateral: ("npc.terracotta.terracotta_pursuer"), + model_index: 10, + ), + ), + (TerracottaPursuer, Female): ( + shoulder_l: ( + offset: (-3.0, -4.0, -7.0), + lateral: ("npc.terracotta.terracotta_pursuer"), + model_index: 3, + ), + shoulder_r: ( + offset: (-3.0, -4.0, -7.0), + lateral: ("npc.terracotta.terracotta_pursuer"), + model_index: 4, + ), + hand_l: ( + offset: (-3.0, -2.0, -9.0), + lateral: ("npc.terracotta.terracotta_pursuer"), + model_index: 5, + ), + hand_r: ( + offset: (-3.0, -2.0, -9.0), + lateral: ("npc.terracotta.terracotta_pursuer"), + model_index: 6, + ), + leg_l: ( + offset: (-3.0, -3.0, -3.5), + lateral: ("npc.terracotta.terracotta_pursuer"), + model_index: 7, + ), + leg_r: ( + offset: (-3.0, -3.0, -3.5), + lateral: ("npc.terracotta.terracotta_pursuer"), + model_index: 8, + ), + foot_l: ( + offset: (-2.0, -3.5, -2.5), + lateral: ("npc.terracotta.terracotta_pursuer"), + model_index: 9, + ), + foot_r: ( + offset: (-2.0, -3.5, -2.5), + lateral: ("npc.terracotta.terracotta_pursuer"), + model_index: 10, + ), + ), + (Cursekeeper, Male): ( + shoulder_l: ( + offset: (-3.0, -2.0, -7.0), + lateral: ("npc.terracotta.cursekeeper"), + model_index: 3, + ), + shoulder_r: ( + offset: (-3.0, -2.0, -7.0), + lateral: ("npc.terracotta.cursekeeper"), + model_index: 4, + ), + hand_l: ( + offset: (-3.5, -3.5, -14.0), + lateral: ("npc.terracotta.cursekeeper"), + model_index: 5, + ), + hand_r: ( + offset: (-3.5, -3.5, -14.0), + lateral: ("npc.terracotta.cursekeeper"), + model_index: 6, + ), + leg_l: ( + offset: (-4.0, -3.5, -4.5), + lateral: ("armor.empty"), + ), + leg_r: ( + offset: (-4.0, -3.5, -4.5), + lateral: ("armor.empty"), + ), + foot_l: ( + offset: (-2.5, -4.5, -4.0), + lateral: ("armor.empty"), + ), + foot_r: ( + offset: (-2.5, -4.5, -4.0), + lateral: ("armor.empty"), + ), + ), + (Cursekeeper, Female): ( + shoulder_l: ( + offset: (-3.0, -2.0, -7.0), + lateral: ("npc.terracotta.cursekeeper"), + model_index: 3, + ), + shoulder_r: ( + offset: (-3.0, -2.0, -7.0), + lateral: ("npc.terracotta.cursekeeper"), + model_index: 4, + ), + hand_l: ( + offset: (-3.5, -3.5, -14.0), + lateral: ("npc.terracotta.cursekeeper"), + model_index: 5, + ), + hand_r: ( + offset: (-3.5, -3.5, -14.0), + lateral: ("npc.terracotta.cursekeeper"), + model_index: 6, + ), + leg_l: ( + offset: (-4.0, -3.5, -4.5), + lateral: ("armor.empty"), + ), + leg_r: ( + offset: (-4.0, -3.5, -4.5), + lateral: ("armor.empty"), + ), + foot_l: ( + offset: (-2.5, -4.5, -4.0), + lateral: ("armor.empty"), + ), + foot_r: ( + offset: (-2.5, -4.5, -4.0), + lateral: ("armor.empty"), + ), + ), }) \ No newline at end of file diff --git a/assets/voxygen/voxel/biped_small_armor_chest_manifest.ron b/assets/voxygen/voxel/biped_small_armor_chest_manifest.ron index ffd3b6c2df..1002f95bc4 100644 --- a/assets/voxygen/voxel/biped_small_armor_chest_manifest.ron +++ b/assets/voxygen/voxel/biped_small_armor_chest_manifest.ron @@ -90,5 +90,11 @@ "common.items.npc_armor.biped_small.flamekeeper.chest.flamekeeper": ( vox_spec: ("npc.flamekeeper.chest", (-6.0, -11.0, -5.5)), ), + "common.items.npc_armor.biped_small.shamanic_spirit.chest.shamanic_spirit": ( + vox_spec: ("npc.shamanic_spirit.chest", (-7.0, -4.0, -4.0)), + ), + "common.items.npc_armor.biped_small.jiangshi.chest.jiangshi": ( + vox_spec: ("npc.jiangshi.chest", (-7.0, -4.0, -4.0)), + ), }, )) diff --git a/assets/voxygen/voxel/biped_small_armor_foot_manifest.ron b/assets/voxygen/voxel/biped_small_armor_foot_manifest.ron index 58c559dbea..59a1927218 100644 --- a/assets/voxygen/voxel/biped_small_armor_foot_manifest.ron +++ b/assets/voxygen/voxel/biped_small_armor_foot_manifest.ron @@ -240,5 +240,13 @@ vox_spec: ("npc.flamekeeper.foot_r", (-2.5, -4.5, -7.0)), ) ), + "common.items.npc_armor.biped_small.jiangshi.foot.jiangshi": ( + left: ( + vox_spec: ("npc.jiangshi.foot_r", (-2.0, -3.0, -8.0)), + ), + right: ( + vox_spec: ("npc.jiangshi.foot_r", (-2.0, -3.0, -8.0)), + ) + ), }, )) diff --git a/assets/voxygen/voxel/biped_small_armor_hand_manifest.ron b/assets/voxygen/voxel/biped_small_armor_hand_manifest.ron index 50fd859a58..6abbe374fc 100644 --- a/assets/voxygen/voxel/biped_small_armor_hand_manifest.ron +++ b/assets/voxygen/voxel/biped_small_armor_hand_manifest.ron @@ -240,5 +240,21 @@ vox_spec: ("npc.flamekeeper.hand_r", (0.0, -2.5, -6.5)), ) ), + "common.items.npc_armor.biped_small.shamanic_spirit.hand.shamanic_spirit": ( + left: ( + vox_spec: ("npc.shamanic_spirit.hand_r", (-4.0, -2.0, -9.0)), + ), + right: ( + vox_spec: ("npc.shamanic_spirit.hand_r", (0.0, -2.0, -9.0)), + ) + ), + "common.items.npc_armor.biped_small.jiangshi.hand.jiangshi": ( + left: ( + vox_spec: ("npc.jiangshi.hand_r", (-5.0, -2.0, -11.0)), + ), + right: ( + vox_spec: ("npc.jiangshi.hand_r", (0.0, -2.0, -11.0)), + ) + ), } )) \ No newline at end of file diff --git a/assets/voxygen/voxel/biped_small_armor_head_manifest.ron b/assets/voxygen/voxel/biped_small_armor_head_manifest.ron index bc8bc6563a..d65c4f5fc8 100644 --- a/assets/voxygen/voxel/biped_small_armor_head_manifest.ron +++ b/assets/voxygen/voxel/biped_small_armor_head_manifest.ron @@ -85,5 +85,11 @@ "common.items.npc_armor.biped_small.flamekeeper.head.flamekeeper": ( vox_spec: ("npc.flamekeeper.head", (-8.0, -7.0, -10.0)), ), + "common.items.npc_armor.biped_small.shamanic_spirit.head.shamanic_spirit": ( + vox_spec: ("npc.shamanic_spirit.head", (-8.0, -6.5, -8.5)), + ), + "common.items.npc_armor.biped_small.jiangshi.head.jiangshi": ( + vox_spec: ("npc.jiangshi.head", (-8.0, -9.0, -8.5)), + ), }, )) \ No newline at end of file diff --git a/assets/voxygen/voxel/biped_small_armor_pants_manifest.ron b/assets/voxygen/voxel/biped_small_armor_pants_manifest.ron index d69f494abb..c78a269863 100644 --- a/assets/voxygen/voxel/biped_small_armor_pants_manifest.ron +++ b/assets/voxygen/voxel/biped_small_armor_pants_manifest.ron @@ -90,5 +90,11 @@ "common.items.npc_armor.biped_small.flamekeeper.pants.flamekeeper": ( vox_spec: ("npc.flamekeeper.pants", (-6.0, -2.5, 0.0)), ), + "common.items.npc_armor.biped_small.shamanic_spirit.pants.shamanic_spirit": ( + vox_spec: ("npc.shamanic_spirit.pants", (-5.0, -4.0, -5.5)), + ), + "common.items.npc_armor.biped_small.jiangshi.pants.jiangshi": ( + vox_spec: ("npc.jiangshi.pants", (-5.0, -4.5, -3.5)), + ), }, )) \ No newline at end of file diff --git a/assets/voxygen/voxel/biped_weapon_manifest.ron b/assets/voxygen/voxel/biped_weapon_manifest.ron index c20465424b..d5a69c5045 100644 --- a/assets/voxygen/voxel/biped_weapon_manifest.ron +++ b/assets/voxygen/voxel/biped_weapon_manifest.ron @@ -1160,8 +1160,8 @@ vox_spec: ("weapon.tool.wooden_lute", (-2.5, -6.0, 4.0)), color: None ), - Tool("common.items.tool.instruments.steeldrum"): ( - vox_spec: ("weapon.tool.steeldrum", (-4.5, -8.0, 8.0)), + Tool("common.items.tool.instruments.steeltonguedrum"): ( + vox_spec: ("weapon.tool.steeltonguedrum", (-4.5, -8.0, 8.0)), color: None ), Tool("common.items.tool.instruments.shamisen"): ( @@ -1618,6 +1618,14 @@ vox_spec: ("armor.empty", (-3.0, -3.5, 1.0)), color: None ), + Tool("common.items.npc_weapons.unique.shamanic_spirit"): ( + vox_spec: ("weapon.biped_small.misc.magic_shamanic_spirit", (-2.5, -4.5, -6.0)), + color: None + ), + Tool("common.items.npc_weapons.unique.jiangshi"): ( + vox_spec: ("armor.empty", (-3.0, -3.5, 1.0)), + color: None + ), //BIPEDLARGE Tool("common.items.npc_weapons.hammer.ogre_hammer"): ( vox_spec: ("weapon.hammer.2hhammer_ogre", (-5.0, -5.5, -7.0)), @@ -1813,7 +1821,31 @@ color: None ), Tool("common.items.npc_weapons.unique.sea_bishop_sceptre"): ( - vox_spec: ("weapon.sceptre.scepter_sea_bishop", (-3.5, -4.0, 3.0)), + vox_spec: ("weapon.sceptre.sceptre_sea_bishop", (-3.5, -4.0, 3.0)), + color: None + ), + Tool("common.items.npc_weapons.bow.terracotta_besieger_bow"): ( + vox_spec: ("weapon.bow.terracotta_besieger_bow", (-8.0, -13.5, -12.5)), + color: None + ), + Tool("common.items.npc_weapons.unique.terracotta_demolisher_fist"): ( + vox_spec: ("armor.empty", (-3.0, -3.5, 1.0)), + color: None + ), + Tool("common.items.npc_weapons.hammer.terracotta_punisher_club"): ( + vox_spec: ("weapon.hammer.terracotta_punisher_club", (-5.0, -6.5, -10.0)), + color: None + ), + Tool("common.items.npc_weapons.sword.terracotta_pursuer_sword"): ( + vox_spec: ("weapon.sword.terracotta_pursuer_sword", (-2.5, -5.0, -10.0)), + color: None + ), + Tool("common.items.npc_weapons.unique.cursekeeper_sceptre"): ( + vox_spec: ("weapon.sceptre.sceptre_cursekeeper", (-5.5, -4.5, -3.0)), + color: None + ), + Tool("common.items.npc_weapons.unique.cursekeeper_sceptre_fake"): ( + vox_spec: ("weapon.sceptre.sceptre_cursekeeper", (-5.5, -4.5, -3.0)), color: None ), }) diff --git a/assets/voxygen/voxel/golem_central_manifest.ron b/assets/voxygen/voxel/golem_central_manifest.ron index b16aaf2b4a..4ba394ab75 100644 --- a/assets/voxygen/voxel/golem_central_manifest.ron +++ b/assets/voxygen/voxel/golem_central_manifest.ron @@ -263,4 +263,46 @@ central: ("npc.coralgolem.male.chest_lower"), ), ), + (Mogwai, Male): ( + head: ( + offset: (-14.0, -9.5, -10.5), + central: ("npc.mogwai.male.mogwai"), + model_index: 0, + ), + jaw: ( + offset: (-8.0, 8.0, -3.5), + central: ("npc.mogwai.male.mogwai"), + model_index: 1, + ), + torso_upper: ( + offset: (-11.5, -5.0, -5.5), + central: ("armor.empty"), + + ), + torso_lower: ( + offset: (-7.5, -5.5, -5.5), + central: ("armor.empty"), + ), + ), + (Mogwai, Female): ( + head: ( + offset: (-14.0, -9.5, -10.5), + central: ("npc.mogwai.male.mogwai"), + model_index: 0, + ), + jaw: ( + offset: (-8.0, 8.0, -3.5), + central: ("npc.mogwai.male.mogwai"), + model_index: 1, + ), + torso_upper: ( + offset: (-11.5, -5.0, -5.5), + central: ("armor.empty"), + + ), + torso_lower: ( + offset: (-7.5, -5.5, -5.5), + central: ("armor.empty"), + ), + ), }) diff --git a/assets/voxygen/voxel/golem_lateral_manifest.ron b/assets/voxygen/voxel/golem_lateral_manifest.ron index 8594afef82..f22c35d9f7 100644 --- a/assets/voxygen/voxel/golem_lateral_manifest.ron +++ b/assets/voxygen/voxel/golem_lateral_manifest.ron @@ -493,4 +493,74 @@ lateral: ("npc.coralgolem.male.foot_r"), ) ), + (Mogwai, Male): ( + shoulder_l: ( + offset: (-9.0, -2.5, -4.0), + lateral: ("armor.empty"), + + ), + shoulder_r: ( + offset: (0.0, -2.5, -4.0), + lateral: ("armor.empty"), + ), + hand_l: ( + offset: (-5.5, -5.0, -18.0), + lateral: ("armor.empty"), + ), + hand_r: ( + offset: (-5.5, -5.0, -18.0), + lateral: ("armor.empty"), + ), + leg_l: ( + offset: (-7.0, -4.0, -7.0), + lateral: ("armor.empty"), + ), + leg_r: ( + offset: (0.0, -4.0, -7.0), + lateral: ("armor.empty"), + ), + foot_l: ( + offset: (-4.0, -5.0, -7.0), + lateral: ("armor.empty"), + ), + foot_r: ( + offset: (-4.0, -5.0, -7.0), + lateral: ("armor.empty"), + ), + ), + (Mogwai, Female): ( + shoulder_l: ( + offset: (-9.0, -2.5, -4.0), + lateral: ("armor.empty"), + + ), + shoulder_r: ( + offset: (0.0, -2.5, -4.0), + lateral: ("armor.empty"), + ), + hand_l: ( + offset: (-5.5, -5.0, -18.0), + lateral: ("armor.empty"), + ), + hand_r: ( + offset: (-5.5, -5.0, -18.0), + lateral: ("armor.empty"), + ), + leg_l: ( + offset: (-7.0, -4.0, -7.0), + lateral: ("armor.empty"), + ), + leg_r: ( + offset: (0.0, -4.0, -7.0), + lateral: ("armor.empty"), + ), + foot_l: ( + offset: (-4.0, -5.0, -7.0), + lateral: ("armor.empty"), + ), + foot_r: ( + offset: (-4.0, -5.0, -7.0), + lateral: ("armor.empty"), + ), + ), }) diff --git a/assets/voxygen/voxel/item_drop_manifest.ron b/assets/voxygen/voxel/item_drop_manifest.ron index 54518d661b..50a619428d 100644 --- a/assets/voxygen/voxel/item_drop_manifest.ron +++ b/assets/voxygen/voxel/item_drop_manifest.ron @@ -408,7 +408,7 @@ Simple("common.items.tool.instruments.kalimba"): "voxel.weapon.tool.wooden_kalimba", Simple("common.items.tool.instruments.melodica"): "voxel.weapon.tool.melodica", Simple("common.items.tool.instruments.lute"): "voxel.weapon.tool.wooden_lute", - Simple("common.items.tool.instruments.steeldrum"): "voxel.weapon.tool.steeldrum", + Simple("common.items.tool.instruments.steeltonguedrum"): "voxel.weapon.tool.steeltonguedrum", Simple("common.items.tool.instruments.shamisen"): "voxel.weapon.tool.shamisen", Simple("common.items.tool.instruments.sitar"): "voxel.weapon.tool.wooden_sitar", Simple("common.items.tool.instruments.guitar"): "voxel.weapon.tool.wooden_guitar", @@ -959,6 +959,8 @@ Simple("common.items.keys.quarry_keys.smelting"): "voxel.object.key_rusty-0", Simple("common.items.keys.quarry_keys.flamekeeper_left"): "element.items.keeper_goggle", Simple("common.items.keys.quarry_keys.flamekeeper_right"): "element.items.keeper_goggle", + Simple("common.items.keys.terracotta_key_chest"): "voxel.object.key_terracotta_chest", + Simple("common.items.keys.terracotta_key_door"): "voxel.object.key_terracotta_door", // Gliders Simple("common.items.glider.cloverleaf"): "voxel.glider.cloverleaf", Simple("common.items.glider.basic_white"): "voxel.glider.basic_white", diff --git a/assets/voxygen/voxel/npc/jiangshi/chest.vox b/assets/voxygen/voxel/npc/jiangshi/chest.vox new file mode 100644 index 0000000000..7b6c58f2d7 --- /dev/null +++ b/assets/voxygen/voxel/npc/jiangshi/chest.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f5dac4c35c82c26f61a208a3b578902becedffdca27d1bfa0710a0f20366eb1a +size 2592 diff --git a/assets/voxygen/voxel/npc/jiangshi/foot_r.vox b/assets/voxygen/voxel/npc/jiangshi/foot_r.vox new file mode 100644 index 0000000000..4c5dcfad4a --- /dev/null +++ b/assets/voxygen/voxel/npc/jiangshi/foot_r.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7d3e021f2a94590e0bf9e498807ab9b9288cfb61fca07aaba2b3cbdaf8e6f9d9 +size 1424 diff --git a/assets/voxygen/voxel/npc/jiangshi/hand_r.vox b/assets/voxygen/voxel/npc/jiangshi/hand_r.vox new file mode 100644 index 0000000000..8babab9dbc --- /dev/null +++ b/assets/voxygen/voxel/npc/jiangshi/hand_r.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ab9a24794ab3e0b7519a81b7d87ec75a764b5e0dd70d527a1930a81f6ffc4462 +size 1556 diff --git a/assets/voxygen/voxel/npc/jiangshi/head.vox b/assets/voxygen/voxel/npc/jiangshi/head.vox new file mode 100644 index 0000000000..2ec19769b2 --- /dev/null +++ b/assets/voxygen/voxel/npc/jiangshi/head.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e93123b4bfbadddcf20d9d8440ed6c6ce51d73dad973f7b6b2996703904dd9c4 +size 6268 diff --git a/assets/voxygen/voxel/npc/jiangshi/pants.vox b/assets/voxygen/voxel/npc/jiangshi/pants.vox new file mode 100644 index 0000000000..f804a80031 --- /dev/null +++ b/assets/voxygen/voxel/npc/jiangshi/pants.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:87abbaa267de3bbf7a1d853166a8b90ee3349d7616673e68ff83dfab03a6254d +size 2056 diff --git a/assets/voxygen/voxel/npc/mogwai/male/mogwai.vox b/assets/voxygen/voxel/npc/mogwai/male/mogwai.vox new file mode 100644 index 0000000000..5575a9884d --- /dev/null +++ b/assets/voxygen/voxel/npc/mogwai/male/mogwai.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7bf6d09c25c21b117c1110f8040feeaec7dffa5b678cd9025d76c435ce04d56b +size 23455 diff --git a/assets/voxygen/voxel/npc/shamanic_spirit/chest.vox b/assets/voxygen/voxel/npc/shamanic_spirit/chest.vox new file mode 100644 index 0000000000..7a65a9f1a8 --- /dev/null +++ b/assets/voxygen/voxel/npc/shamanic_spirit/chest.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7cb8d34c0fb5507b75945c2a60e945e0a5d2c3da6fe27efa8dd53986d83f3856 +size 2616 diff --git a/assets/voxygen/voxel/npc/shamanic_spirit/hand_r.vox b/assets/voxygen/voxel/npc/shamanic_spirit/hand_r.vox new file mode 100644 index 0000000000..05657b74db --- /dev/null +++ b/assets/voxygen/voxel/npc/shamanic_spirit/hand_r.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d0417677ba79304019a75d4ef663a37f6a1f093e0ae0f4f46b2ce7779a97dbcf +size 1472 diff --git a/assets/voxygen/voxel/npc/shamanic_spirit/head.vox b/assets/voxygen/voxel/npc/shamanic_spirit/head.vox new file mode 100644 index 0000000000..a69f763185 --- /dev/null +++ b/assets/voxygen/voxel/npc/shamanic_spirit/head.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:892d50d0f1af73aeb3056f81e6e4af4eb407d0994ae1d7cb1898194640414b75 +size 5220 diff --git a/assets/voxygen/voxel/npc/shamanic_spirit/pants.vox b/assets/voxygen/voxel/npc/shamanic_spirit/pants.vox new file mode 100644 index 0000000000..9f5d5cc0fb --- /dev/null +++ b/assets/voxygen/voxel/npc/shamanic_spirit/pants.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:683e36c900178b2b84e19ff09ea67ffefd248673649c67cc064ce5d58808db15 +size 3188 diff --git a/assets/voxygen/voxel/npc/terracotta/cursekeeper.vox b/assets/voxygen/voxel/npc/terracotta/cursekeeper.vox new file mode 100644 index 0000000000..d4ba3c43f0 --- /dev/null +++ b/assets/voxygen/voxel/npc/terracotta/cursekeeper.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9a9301c837547927de207f3797ae02184991faca832135c6936294d6ce75a9c1 +size 24044 diff --git a/assets/voxygen/voxel/npc/terracotta/terracotta_besieger.vox b/assets/voxygen/voxel/npc/terracotta/terracotta_besieger.vox new file mode 100644 index 0000000000..40cd0e15a8 --- /dev/null +++ b/assets/voxygen/voxel/npc/terracotta/terracotta_besieger.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1cba518581d22036ec4125b944dc7d2fc1c8eb4535ac77bb11d2a7e2f0393012 +size 27369 diff --git a/assets/voxygen/voxel/npc/terracotta/terracotta_demolisher.vox b/assets/voxygen/voxel/npc/terracotta/terracotta_demolisher.vox new file mode 100644 index 0000000000..10780c5d32 --- /dev/null +++ b/assets/voxygen/voxel/npc/terracotta/terracotta_demolisher.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3db94fcfd962cdccddbec09ebf595bf161437e4999785333a464fcdbb6488867 +size 14813 diff --git a/assets/voxygen/voxel/npc/terracotta/terracotta_punisher.vox b/assets/voxygen/voxel/npc/terracotta/terracotta_punisher.vox new file mode 100644 index 0000000000..95cf07280e --- /dev/null +++ b/assets/voxygen/voxel/npc/terracotta/terracotta_punisher.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bfdb002436277755993504d719892705c59e304c8b1f273bfbdd5b637e569657 +size 14629 diff --git a/assets/voxygen/voxel/npc/terracotta/terracotta_pursuer.vox b/assets/voxygen/voxel/npc/terracotta/terracotta_pursuer.vox new file mode 100644 index 0000000000..917c74acc3 --- /dev/null +++ b/assets/voxygen/voxel/npc/terracotta/terracotta_pursuer.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f0b9eb1b661b6306c24cc93fa356eb72537079d3e1659fb14ffb1629125ec7c4 +size 15086 diff --git a/assets/voxygen/voxel/object/key_terracotta_chest.vox b/assets/voxygen/voxel/object/key_terracotta_chest.vox new file mode 100644 index 0000000000..2b5c506df4 --- /dev/null +++ b/assets/voxygen/voxel/object/key_terracotta_chest.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1d26afd25a22101fb1345874ea1caaa3381d793b2dca548eab8f56e246dac2bd +size 1164 diff --git a/assets/voxygen/voxel/object/key_terracotta_door.vox b/assets/voxygen/voxel/object/key_terracotta_door.vox new file mode 100644 index 0000000000..a7cf6d28b2 --- /dev/null +++ b/assets/voxygen/voxel/object/key_terracotta_door.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ae3ac36e7691ec8581b2bef4ab16edfa7eb6be7dee95d39d38455de6a29a040c +size 1296 diff --git a/assets/voxygen/voxel/object/terracotta_demolisher_bomb.vox b/assets/voxygen/voxel/object/terracotta_demolisher_bomb.vox new file mode 100644 index 0000000000..9d0301b944 --- /dev/null +++ b/assets/voxygen/voxel/object/terracotta_demolisher_bomb.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8be161d17ad449860b347523b6ce00ad9988b3cd8c1a9c43bf599469ff816812 +size 2720 diff --git a/assets/voxygen/voxel/object_manifest.ron b/assets/voxygen/voxel/object_manifest.ron index ac62ed2148..51c01667fd 100644 --- a/assets/voxygen/voxel/object_manifest.ron +++ b/assets/voxygen/voxel/object_manifest.ron @@ -39,6 +39,16 @@ central: ("armor.empty"), ) ), + TerracottaDemolisherBomb: ( + bone0: ( + offset: (-5.5, -5.5, 0.0), + central: ("object.terracotta_demolisher_bomb"), + ), + bone1: ( + offset: (0.0, 0.0, 0.0), + central: ("armor.empty"), + ) + ), FireworkBlue: ( bone0: ( offset: (0.0, 0.0, 0.0), @@ -729,6 +739,16 @@ central: ("armor.empty"), ) ), + BoltBesieger: ( + bone0: ( + offset: (-2.5, -10.0, -2.5), + central: ("weapon.projectile.besieger_bolt"), + ), + bone1: ( + offset: (0.0, 0.0, 0.0), + central: ("armor.empty"), + ) + ), SilverOre: ( bone0: ( offset: (-4.5, -5.0, 0.0), @@ -981,6 +1001,16 @@ central: ("armor.empty"), ) ), + LaserBeamSmall: ( + bone0: ( + offset: (-1.0, -9.0, -3.0), + central: ("weapon.projectile.laser_beam_small"), + ), + bone1: ( + offset: (0.0, 0.0, 0.0), + central: ("armor.empty"), + ) + ), LightningBolt: ( bone0: ( offset: (-4.5, -80.0, -3.0), @@ -1021,6 +1051,16 @@ central: ("armor.empty"), ) ), + TerracottaStatue: ( + bone0: ( + offset: (-28.0, -28.0, -0.0), + central: ("sprite.furniture.terracotta_statue_4"), + ), + bone1: ( + offset: (0.0, 0.0, 0.0), + central: ("armor.empty"), + ) + ), Portal: ( bone0: ( offset: (-33.0, -33.0, 0.0), diff --git a/assets/voxygen/voxel/sprite/chests/chest_terracotta.vox b/assets/voxygen/voxel/sprite/chests/chest_terracotta.vox new file mode 100644 index 0000000000..66cb1832e9 --- /dev/null +++ b/assets/voxygen/voxel/sprite/chests/chest_terracotta.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6e699986923b9f41c18cb013205e86f2087092aef492dca6b5d338c2d21305ae +size 7360 diff --git a/assets/voxygen/voxel/sprite/furniture/terracotta_keydoor.vox b/assets/voxygen/voxel/sprite/furniture/terracotta_keydoor.vox new file mode 100644 index 0000000000..d7c9fbe832 --- /dev/null +++ b/assets/voxygen/voxel/sprite/furniture/terracotta_keydoor.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ba71fbb11749677b9f14635689e81a92c2ce1504375641039f25f5c44caf9539 +size 6420 diff --git a/assets/voxygen/voxel/sprite/furniture/terracotta_keyhole.vox b/assets/voxygen/voxel/sprite/furniture/terracotta_keyhole.vox new file mode 100644 index 0000000000..f8eb8648b2 --- /dev/null +++ b/assets/voxygen/voxel/sprite/furniture/terracotta_keyhole.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7b789b0e1fc60b7cc26b334c69489572c0c46566850ac85286961f64643b7728 +size 6108 diff --git a/assets/voxygen/voxel/sprite/furniture/terracotta_statue_0.vox b/assets/voxygen/voxel/sprite/furniture/terracotta_statue_0.vox new file mode 100644 index 0000000000..d4d6231fb2 --- /dev/null +++ b/assets/voxygen/voxel/sprite/furniture/terracotta_statue_0.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8c07fcd15994d984000bc485c2a92b66475844855fa108995e74648f349823d2 +size 29096 diff --git a/assets/voxygen/voxel/sprite/furniture/terracotta_statue_1.vox b/assets/voxygen/voxel/sprite/furniture/terracotta_statue_1.vox new file mode 100644 index 0000000000..02b568d577 --- /dev/null +++ b/assets/voxygen/voxel/sprite/furniture/terracotta_statue_1.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:392905668c46428d25d0e2f73619952e46d355a5d933a3e4b8c2c2b2c3760554 +size 16908 diff --git a/assets/voxygen/voxel/sprite/furniture/terracotta_statue_2.vox b/assets/voxygen/voxel/sprite/furniture/terracotta_statue_2.vox new file mode 100644 index 0000000000..4bffcd4f55 --- /dev/null +++ b/assets/voxygen/voxel/sprite/furniture/terracotta_statue_2.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0bc2758db1c9136392891cfc468643ec011e2e265483e446a2089315227d616a +size 16704 diff --git a/assets/voxygen/voxel/sprite/furniture/terracotta_statue_3.vox b/assets/voxygen/voxel/sprite/furniture/terracotta_statue_3.vox new file mode 100644 index 0000000000..6fe3e47ffd --- /dev/null +++ b/assets/voxygen/voxel/sprite/furniture/terracotta_statue_3.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:69165557fc6e7739fd82455fb8a829221f4aeea42a3a46fcd9c782ea46272b87 +size 17180 diff --git a/assets/voxygen/voxel/sprite/furniture/terracotta_statue_4.vox b/assets/voxygen/voxel/sprite/furniture/terracotta_statue_4.vox new file mode 100644 index 0000000000..e9fcf716b7 --- /dev/null +++ b/assets/voxygen/voxel/sprite/furniture/terracotta_statue_4.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5f744f68a189601591021384cc3aca8096d2ddbcf3772fafc724d2ccec1c13d3 +size 166120 diff --git a/assets/voxygen/voxel/sprite/misc/terracotta_block-0.vox b/assets/voxygen/voxel/sprite/misc/terracotta_block-0.vox new file mode 100644 index 0000000000..b676ae3678 --- /dev/null +++ b/assets/voxygen/voxel/sprite/misc/terracotta_block-0.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6b69e070d439081e96b7789f11dab1c2e3757d9618e4599aaf49845686e775c5 +size 6420 diff --git a/assets/voxygen/voxel/sprite/misc/terracotta_block-1.vox b/assets/voxygen/voxel/sprite/misc/terracotta_block-1.vox new file mode 100644 index 0000000000..860f29aa5a --- /dev/null +++ b/assets/voxygen/voxel/sprite/misc/terracotta_block-1.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e223634a382bed2355801335bdc6f751b900651ab83d1b210376d1c51165b8a1 +size 6420 diff --git a/assets/voxygen/voxel/sprite/misc/terracotta_block-2.vox b/assets/voxygen/voxel/sprite/misc/terracotta_block-2.vox new file mode 100644 index 0000000000..809bdac3b6 --- /dev/null +++ b/assets/voxygen/voxel/sprite/misc/terracotta_block-2.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d92b6a59957b8e22e6a044f4555cb330ec6aee7db6ee52348c3dd15f0fa0949f +size 6420 diff --git a/assets/voxygen/voxel/sprite/misc/terracotta_block-3.vox b/assets/voxygen/voxel/sprite/misc/terracotta_block-3.vox new file mode 100644 index 0000000000..c0e68b2412 --- /dev/null +++ b/assets/voxygen/voxel/sprite/misc/terracotta_block-3.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:63226168a51ca22ea92eb29fd5b96211a15120a98b9964b376d5661841d93d1f +size 6420 diff --git a/assets/voxygen/voxel/sprite/misc/terracotta_block-4.vox b/assets/voxygen/voxel/sprite/misc/terracotta_block-4.vox new file mode 100644 index 0000000000..7d64b2fcb1 --- /dev/null +++ b/assets/voxygen/voxel/sprite/misc/terracotta_block-4.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:224b8f9e959f4895151b4e4b2494bf605c40735b6450035452eaae7c5c42f977 +size 6420 diff --git a/assets/voxygen/voxel/sprite/misc/terracotta_block-5.vox b/assets/voxygen/voxel/sprite/misc/terracotta_block-5.vox new file mode 100644 index 0000000000..9757311041 --- /dev/null +++ b/assets/voxygen/voxel/sprite/misc/terracotta_block-5.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cadc7fe3e041be83c77f12b3cbfa78ce91a32cb4bc9cba9e9375d3bebfdd7ac7 +size 6420 diff --git a/assets/voxygen/voxel/sprite/misc/terracotta_block-6.vox b/assets/voxygen/voxel/sprite/misc/terracotta_block-6.vox new file mode 100644 index 0000000000..9757311041 --- /dev/null +++ b/assets/voxygen/voxel/sprite/misc/terracotta_block-6.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cadc7fe3e041be83c77f12b3cbfa78ce91a32cb4bc9cba9e9375d3bebfdd7ac7 +size 6420 diff --git a/assets/voxygen/voxel/sprite_manifest.ron b/assets/voxygen/voxel/sprite_manifest.ron index 7d55c934d0..f96cfae70f 100644 --- a/assets/voxygen/voxel/sprite_manifest.ron +++ b/assets/voxygen/voxel/sprite_manifest.ron @@ -1086,6 +1086,92 @@ HaniwaTrapTriggered: Some(( ], wind_sway: 0.0, )), +// Terracotta Door, Keyhole, Chest, Statue +TerracottaKeyDoor: Some(( + variations: [ + ( + model: "voxygen.voxel.sprite.furniture.terracotta_keydoor", + offset: (-5.5, -5.5, 0.0), + lod_axes: (0.0, 0.0, 0.0), + ), + ], + wind_sway: 0.0, +)), +TerracottaKeyhole: Some(( + variations: [ + ( + model: "voxygen.voxel.sprite.furniture.terracotta_keyhole", + offset: (-5.5, -5.5, 0.0), + lod_axes: (0.0, 0.0, 0.0), + ), + ], + wind_sway: 0.0, +)), +TerracottaChest: Some(( + variations: [ + ( + model: "voxygen.voxel.sprite.chests.chest_terracotta", + offset: (-7.0, -5.0, -0.0), + lod_axes: (1.0, 1.0, 1.0), + ), + ], + wind_sway: 0.0, +)), +TerracottaStatue: Some(( + variations: [ + ( + model: "voxygen.voxel.sprite.furniture.terracotta_statue_0", + offset: (-22.0, -18.0, -0.0), + lod_axes: (1.0, 1.0, 1.0), + ), + ( + model: "voxygen.voxel.sprite.furniture.terracotta_statue_1", + offset: (-22.0, -18.0, -0.0), + lod_axes: (1.0, 1.0, 1.0), + ), + ( + model: "voxygen.voxel.sprite.furniture.terracotta_statue_2", + offset: (-22.0, -18.0, -0.0), + lod_axes: (1.0, 1.0, 1.0), + ), + ], + wind_sway: 0.0, +)), +TerracottaBlock: Some(( + variations: [ + ( + model: "voxygen.voxel.sprite.misc.terracotta_block-0", + offset: (-5.5, -5.5, 0.0), + lod_axes: (0.0, 0.0, 0.0), + ), + ( + model: "voxygen.voxel.sprite.misc.terracotta_block-1", + offset: (-5.5, -5.5, 0.0), + lod_axes: (0.0, 0.0, 0.0), + ), + ( + model: "voxygen.voxel.sprite.misc.terracotta_block-2", + offset: (-5.5, -5.5, 0.0), + lod_axes: (0.0, 0.0, 0.0), + ), + ( + model: "voxygen.voxel.sprite.misc.terracotta_block-3", + offset: (-5.5, -5.5, 0.0), + lod_axes: (0.0, 0.0, 0.0), + ), + ( + model: "voxygen.voxel.sprite.misc.terracotta_block-5", + offset: (-5.5, -5.5, 0.0), + lod_axes: (0.0, 0.0, 0.0), + ), + ( + model: "voxygen.voxel.sprite.misc.terracotta_block-6", + offset: (-5.5, -5.5, 0.0), + lod_axes: (0.0, 0.0, 0.0), + ), + ], + wind_sway: 0.0, +)), // Welwitch Welwitch: Some(( variations: [ diff --git a/assets/voxygen/voxel/weapon/biped_small/misc/magic_shamanic_spirit.vox b/assets/voxygen/voxel/weapon/biped_small/misc/magic_shamanic_spirit.vox new file mode 100644 index 0000000000..04b6f71695 --- /dev/null +++ b/assets/voxygen/voxel/weapon/biped_small/misc/magic_shamanic_spirit.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:625c0a1606ec544f229be129abd9023c74585604879a121fbdfe7ab7d7f5273a +size 1224 diff --git a/assets/voxygen/voxel/weapon/bow/terracotta_besieger_bow.vox b/assets/voxygen/voxel/weapon/bow/terracotta_besieger_bow.vox new file mode 100644 index 0000000000..2c4ceb48c6 --- /dev/null +++ b/assets/voxygen/voxel/weapon/bow/terracotta_besieger_bow.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a82d61480975293ea302e57e41bf88ee61a8518cbc46c5c52bc7dec133729c86 +size 5064 diff --git a/assets/voxygen/voxel/weapon/hammer/terracotta_punisher_club.vox b/assets/voxygen/voxel/weapon/hammer/terracotta_punisher_club.vox new file mode 100644 index 0000000000..53cd544cbc --- /dev/null +++ b/assets/voxygen/voxel/weapon/hammer/terracotta_punisher_club.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:284739ccadb6cf88fe256787c59ca5ab3ea54321877fea93f5b6743fd3f4331c +size 3776 diff --git a/assets/voxygen/voxel/weapon/projectile/besieger_bolt.vox b/assets/voxygen/voxel/weapon/projectile/besieger_bolt.vox new file mode 100644 index 0000000000..cf524a3c63 --- /dev/null +++ b/assets/voxygen/voxel/weapon/projectile/besieger_bolt.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c16836e73c6d58c1b83e6e297de83fc1ffc1ca4c6dfc2374458b172e0e15ddf6 +size 1300 diff --git a/assets/voxygen/voxel/weapon/projectile/laser_beam_small.vox b/assets/voxygen/voxel/weapon/projectile/laser_beam_small.vox new file mode 100644 index 0000000000..2702fe8f6b --- /dev/null +++ b/assets/voxygen/voxel/weapon/projectile/laser_beam_small.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:345279ec9045bb73f360d044a77d5863918e11ae3db646d84f557e22a0d2efa6 +size 1152 diff --git a/assets/voxygen/voxel/weapon/sceptre/sceptre_cursekeeper.vox b/assets/voxygen/voxel/weapon/sceptre/sceptre_cursekeeper.vox new file mode 100644 index 0000000000..232566598b --- /dev/null +++ b/assets/voxygen/voxel/weapon/sceptre/sceptre_cursekeeper.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:71483d224c501f86a588373abf3a8e957a46f87bb3ad0e2840d74266ec6460d5 +size 1800 diff --git a/assets/voxygen/voxel/weapon/sceptre/scepter_sea_bishop.vox b/assets/voxygen/voxel/weapon/sceptre/sceptre_sea_bishop.vox similarity index 100% rename from assets/voxygen/voxel/weapon/sceptre/scepter_sea_bishop.vox rename to assets/voxygen/voxel/weapon/sceptre/sceptre_sea_bishop.vox diff --git a/assets/voxygen/voxel/weapon/sword/terracotta_pursuer_sword.vox b/assets/voxygen/voxel/weapon/sword/terracotta_pursuer_sword.vox new file mode 100644 index 0000000000..7231cbd3b8 --- /dev/null +++ b/assets/voxygen/voxel/weapon/sword/terracotta_pursuer_sword.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6b62de68341b95099f5bb09a75d2281fac5dab4fc12fa66a9e14fa8f4f832f7f +size 1648 diff --git a/assets/voxygen/voxel/weapon/tool/steeldrum.vox b/assets/voxygen/voxel/weapon/tool/steeldrum.vox deleted file mode 100644 index 42b71acf45..0000000000 --- a/assets/voxygen/voxel/weapon/tool/steeldrum.vox +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:5689fcd5718343af48d9a5d9316654c9a450b9afd16dca59d8a81577cfc94852 -size 1608 diff --git a/assets/voxygen/voxel/weapon/tool/steeltonguedrum.vox b/assets/voxygen/voxel/weapon/tool/steeltonguedrum.vox new file mode 100644 index 0000000000..0cd99d83d9 --- /dev/null +++ b/assets/voxygen/voxel/weapon/tool/steeltonguedrum.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:41ee41ecb0850cc0ef5b914b4679ddd59a13fc98cfeffe4af61dc04aceb80b4b +size 1568 diff --git a/assets/world/manifests/site_structures/terracotta/terracotta_decor_large.ron b/assets/world/manifests/site_structures/terracotta/terracotta_decor_large.ron new file mode 100644 index 0000000000..1811075e2b --- /dev/null +++ b/assets/world/manifests/site_structures/terracotta/terracotta_decor_large.ron @@ -0,0 +1,20 @@ +#![enable(unwrap_newtypes)] + +[ + ( + specifier: "world.structure.terracotta.decor.terracotta_decor-4", + center: (17, 17, 0), + custom_indices: { + 129: Filled(Water, (r: 53, g: 112, b: 137)), + }, + ), + ( + specifier: "world.structure.terracotta.decor.terracotta_decor-5", + center: (17, 17, 0), + custom_indices: { + 130: Sprite(JungleRedGrass), + 131: Sprite(JungleLeafyPlant), + 132: Sprite(JungleFern), + }, + ), +] diff --git a/assets/world/manifests/site_structures/terracotta/terracotta_decor_small.ron b/assets/world/manifests/site_structures/terracotta/terracotta_decor_small.ron new file mode 100644 index 0000000000..b07207f37e --- /dev/null +++ b/assets/world/manifests/site_structures/terracotta/terracotta_decor_small.ron @@ -0,0 +1,36 @@ +#![enable(unwrap_newtypes)] + +[ + ( + specifier: "world.structure.terracotta.decor.terracotta_decor-0", + center: (6, 6, 0), + custom_indices: { + 130: Sprite(JungleRedGrass), + 131: Sprite(JungleLeafyPlant), + 132: Sprite(JungleFern), + }, + ), + ( + specifier: "world.structure.terracotta.decor.terracotta_decor-1", + center: (6, 6, 1), + custom_indices: { + 129: Filled(Water, (r: 53, g: 112, b: 137)), + }, + ), + ( + specifier: "world.structure.terracotta.decor.terracotta_decor-2", + center: (6, 6, 0), + custom_indices: { + 129: Filled(Water, (r: 53, g: 112, b: 137)), + }, + ), + ( + specifier: "world.structure.terracotta.decor.terracotta_decor-3", + center: (6, 6, 0), + custom_indices: { + 130: Sprite(JungleRedGrass), + 131: Sprite(JungleLeafyPlant), + 132: Sprite(JungleFern), + }, + ), +] diff --git a/assets/world/structure/terracotta/decor/terracotta_decor-0.vox b/assets/world/structure/terracotta/decor/terracotta_decor-0.vox new file mode 100644 index 0000000000..64643eb82e --- /dev/null +++ b/assets/world/structure/terracotta/decor/terracotta_decor-0.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:23a0d67dd49453520438137656efd14fe5dcf10ebe7fc4b7586d6fc17a64178b +size 2296 diff --git a/assets/world/structure/terracotta/decor/terracotta_decor-1.vox b/assets/world/structure/terracotta/decor/terracotta_decor-1.vox new file mode 100644 index 0000000000..f0e1034555 --- /dev/null +++ b/assets/world/structure/terracotta/decor/terracotta_decor-1.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9a458da3b1cbfc5ad1105bff9ce2031d6d9fbfdcdd6962bcba834d4adbb770e1 +size 2404 diff --git a/assets/world/structure/terracotta/decor/terracotta_decor-2.vox b/assets/world/structure/terracotta/decor/terracotta_decor-2.vox new file mode 100644 index 0000000000..0fc791e5bb --- /dev/null +++ b/assets/world/structure/terracotta/decor/terracotta_decor-2.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2ce4fcef1864d71dd988445bcc58a08a63cab098cea1a5197a52ae013e44f8f9 +size 2648 diff --git a/assets/world/structure/terracotta/decor/terracotta_decor-3.vox b/assets/world/structure/terracotta/decor/terracotta_decor-3.vox new file mode 100644 index 0000000000..7b717dff17 --- /dev/null +++ b/assets/world/structure/terracotta/decor/terracotta_decor-3.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e224e6622fd1159303cb2edaf2bd88669e045679c681ebc3041b8b2b205fe6af +size 2444 diff --git a/assets/world/structure/terracotta/decor/terracotta_decor-4.vox b/assets/world/structure/terracotta/decor/terracotta_decor-4.vox new file mode 100644 index 0000000000..65d68a8a1b --- /dev/null +++ b/assets/world/structure/terracotta/decor/terracotta_decor-4.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8a1ca24a445865d3617316a0e976a5173513943e97e21620a3f93fd6c7177185 +size 5544 diff --git a/assets/world/structure/terracotta/decor/terracotta_decor-5.vox b/assets/world/structure/terracotta/decor/terracotta_decor-5.vox new file mode 100644 index 0000000000..f38385c8ff --- /dev/null +++ b/assets/world/structure/terracotta/decor/terracotta_decor-5.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4f3cb32ac353cba8063aaff8d4023926094531fc04a8cc72e9e205b54f3475d1 +size 5032 diff --git a/common/net/src/msg/world_msg.rs b/common/net/src/msg/world_msg.rs index ed1ad32933..77985ddc76 100644 --- a/common/net/src/msg/world_msg.rs +++ b/common/net/src/msg/world_msg.rs @@ -149,6 +149,7 @@ pub enum SiteKind { Tree, Gnarling, ChapelSite, + Terracotta, Bridge, Adlet, Haniwa, diff --git a/common/src/comp/agent.rs b/common/src/comp/agent.rs index d7041483e1..880d06a42f 100644 --- a/common/src/comp/agent.rs +++ b/common/src/comp/agent.rs @@ -359,7 +359,9 @@ impl<'a> From<&'a Body> for Psyche { | biped_small::Species::Boreal | biped_small::Species::Clockwork | biped_small::Species::Flamekeeper - | biped_small::Species::Irrwurz => 0.0, + | biped_small::Species::Irrwurz + | biped_small::Species::ShamanicSpirit + | biped_small::Species::Jiangshi => 0.0, _ => 0.5, }, diff --git a/common/src/comp/body.rs b/common/src/comp/body.rs index 50403d7855..21caa90e22 100644 --- a/common/src/comp/body.rs +++ b/common/src/comp/body.rs @@ -359,6 +359,11 @@ impl Body { biped_large::Species::Gigasfrost => 400.0, biped_large::Species::AdletElder => 350.0, biped_large::Species::HaniwaGeneral => 360.0, + biped_large::Species::TerracottaBesieger + | biped_large::Species::TerracottaDemolisher + | biped_large::Species::TerracottaPunisher + | biped_large::Species::TerracottaPursuer + | biped_large::Species::Cursekeeper => 380.0, _ => 400.0, }, Body::BipedSmall(body) => match body.species { @@ -523,6 +528,11 @@ impl Body { biped_large::Species::AdletElder => Vec3::new(3.5, 3.0, 5.0), biped_large::Species::SeaBishop => Vec3::new(3.7, 2.5, 4.2), biped_large::Species::HaniwaGeneral => Vec3::new(3.3, 2.3, 3.8), + biped_large::Species::TerracottaBesieger => Vec3::new(3.8, 3.0, 5.0), + biped_large::Species::TerracottaDemolisher => Vec3::new(3.3, 2.5, 3.8), + biped_large::Species::TerracottaPunisher => Vec3::new(3.3, 2.5, 3.8), + biped_large::Species::TerracottaPursuer => Vec3::new(3.3, 2.5, 3.8), + biped_large::Species::Cursekeeper => Vec3::new(3.8, 3.0, 5.0), _ => Vec3::new(4.6, 3.0, 6.0), }, Body::BipedSmall(body) => match body.species { @@ -537,6 +547,8 @@ impl Body { biped_small::Species::Irrwurz => Vec3::new(1.5, 1.5, 2.0), biped_small::Species::Clockwork => Vec3::new(1.3, 2.0, 2.5), biped_small::Species::Flamekeeper => Vec3::new(5.0, 5.0, 10.0), + biped_small::Species::ShamanicSpirit => Vec3::new(1.3, 2.0, 2.3), + biped_small::Species::Jiangshi => Vec3::new(1.3, 1.8, 2.5), _ => Vec3::new(1.0, 0.75, 1.4), }, Body::BirdLarge(body) => match body.species { @@ -556,6 +568,7 @@ impl Body { golem::Species::CoralGolem => Vec3::new(3.0, 5.0, 4.0), golem::Species::ClayGolem => Vec3::new(6.8, 3.5, 7.5), golem::Species::AncientEffigy => Vec3::new(2.5, 2.5, 3.8), + golem::Species::Mogwai => Vec3::new(2.5, 2.5, 3.8), _ => Vec3::new(5.0, 4.5, 7.5), }, Body::Humanoid(humanoid) => { @@ -921,6 +934,11 @@ impl Body { biped_large::Species::Tursus => 300, biped_large::Species::SeaBishop => 550, biped_large::Species::HaniwaGeneral => 600, + biped_large::Species::TerracottaBesieger + | biped_large::Species::TerracottaDemolisher + | biped_large::Species::TerracottaPunisher + | biped_large::Species::TerracottaPursuer => 300, + biped_large::Species::Cursekeeper => 3000, _ => 120, }, Body::BipedSmall(biped_small) => match biped_small.species { @@ -934,6 +952,8 @@ impl Body { biped_small::Species::Clockwork => 250, biped_small::Species::Flamekeeper => 10000, biped_small::Species::Irrwurz => 100, + biped_small::Species::ShamanicSpirit => 240, + biped_small::Species::Jiangshi => 250, _ => 60, }, Body::Object(object) => match object { @@ -944,6 +964,7 @@ impl Body { object::Body::HaniwaSentry => 60, object::Body::SeaLantern => 100, object::Body::GnarlingTotemGreen => 25, + object::Body::TerracottaStatue => 600, object::Body::GnarlingTotemRed | object::Body::GnarlingTotemWhite => 35, _ => 1000, }, @@ -954,6 +975,7 @@ impl Body { golem::Species::Gravewarden => 1000, golem::Species::CoralGolem => 550, golem::Species::AncientEffigy => 250, + golem::Species::Mogwai => 500, _ => 1000, }, Body::Theropod(theropod) => match theropod.species { @@ -1044,6 +1066,8 @@ impl Body { | biped_small::Species::Boreal | biped_small::Species::Clockwork | biped_small::Species::Haniwa + | biped_small::Species::ShamanicSpirit + | biped_small::Species::Jiangshi ), Body::BipedLarge(b) => matches!( b.species, @@ -1051,6 +1075,11 @@ impl Body { | biped_large::Species::Gigasfrost | biped_large::Species::Dullahan | biped_large::Species::HaniwaGeneral + | biped_large::Species::TerracottaBesieger + | biped_large::Species::TerracottaDemolisher + | biped_large::Species::TerracottaPunisher + | biped_large::Species::TerracottaPursuer + | biped_large::Species::Cursekeeper ), Body::QuadrupedMedium(b) => { matches!(b.species, quadruped_medium::Species::ClaySteed) @@ -1061,7 +1090,7 @@ impl Body { Body::Object(_) | Body::Golem(_) | Body::Ship(_) => true, Body::BipedLarge(b) => matches!( b.species, - biped_large::Species::Dullahan | biped_large::Species::HaniwaGeneral {} + biped_large::Species::Dullahan | biped_large::Species::HaniwaGeneral ), Body::BipedSmall(b) => matches!(b.species, biped_small::Species::Haniwa), Body::QuadrupedMedium(b) => { @@ -1082,7 +1111,9 @@ impl Body { ), Body::Object(object) => matches!( object, - object::Body::HaniwaSentry | object::Body::Flamethrower + object::Body::HaniwaSentry + | object::Body::Flamethrower + | object::Body::TerracottaStatue ), Body::QuadrupedLow(q) => matches!(q.species, quadruped_low::Species::Lavadrake), Body::BirdLarge(b) => matches!( @@ -1145,6 +1176,7 @@ impl Body { match self { Body::Object(object) => match object { object::Body::BarrelOrgan | object::Body::ArrowTurret => 0.05, + object::Body::TerracottaStatue => 1.5, _ => 0.0, }, Body::Ship(_) => 0.0, diff --git a/common/src/comp/body/biped_large.rs b/common/src/comp/body/biped_large.rs index 513426f589..2a87d3dc95 100644 --- a/common/src/comp/body/biped_large.rs +++ b/common/src/comp/body/biped_large.rs @@ -44,7 +44,27 @@ impl Body { Species::Blueoni => "body-npc-speech-biped_large-blue_oni", Species::Redoni => "body-npc-speech-biped_large-red_oni", Species::Tursus => "body-npc-speech-biped_large-tursus", - _ => return None, + Species::Dullahan => "body-npc-speech-biped_large-dullahan", + Species::Occultsaurok => "body-npc-speech-biped_large-occult_saurok", + Species::Mightysaurok => "body-npc-speech-biped_large-mighty_saurok", + Species::Slysaurok => "body-npc-speech-biped_large-sly_saurok", + Species::Mindflayer => "body-npc-speech-biped_large-mindflayer", + Species::Minotaur => "body-npc-speech-biped_large-minotaur", + Species::Tidalwarrior => "body-npc-speech-biped_large-tidal_warrior", + Species::Yeti => "body-npc-speech-biped_large-yeti", + Species::Harvester => "body-npc-speech-biped_large-harvester", + Species::Cultistwarlord => "body-npc-speech-biped_large-cultist_warlord", + Species::Cultistwarlock => "body-npc-speech-biped_large-cultist_warlock", + Species::Huskbrute => "body-npc-speech-biped_large-husk_brute", + Species::Gigasfrost => "body-npc-speech-biped_large-gigas_frost", + Species::AdletElder => "body-npc-speech-biped_large-adlet_elder", + Species::SeaBishop => "body-npc-speech-biped_large-sea_bishop", + Species::HaniwaGeneral => "body-npc-speech-biped_large-haniwa_general", + Species::TerracottaBesieger => "body-npc-speech-biped_large-terracotta_besieger", + Species::TerracottaDemolisher => "body-npc-speech-biped_large-terracotta_demolisher", + Species::TerracottaPunisher => "body-npc-speech-biped_large-terracotta_punisher", + Species::TerracottaPursuer => "body-npc-speech-biped_large-terracotta_pursuer", + Species::Cursekeeper => "body-npc-speech-biped_large-cursekeeper", }; Some(Content::localized(key)) @@ -86,6 +106,11 @@ make_case_elim!( AdletElder = 23, SeaBishop = 24, HaniwaGeneral = 25, + TerracottaBesieger = 26, + TerracottaDemolisher = 27, + TerracottaPunisher = 28, + TerracottaPursuer = 29, + Cursekeeper = 30, } ); @@ -120,6 +145,11 @@ pub struct AllSpecies { pub adlet_elder: SpeciesMeta, pub sea_bishop: SpeciesMeta, pub haniwa_general: SpeciesMeta, + pub terracotta_besieger: SpeciesMeta, + pub terracotta_demolisher: SpeciesMeta, + pub terracotta_punisher: SpeciesMeta, + pub terracotta_pursuer: SpeciesMeta, + pub cursekeeper: SpeciesMeta, } impl<'a, SpeciesMeta> core::ops::Index<&'a Species> for AllSpecies { @@ -154,11 +184,16 @@ impl<'a, SpeciesMeta> core::ops::Index<&'a Species> for AllSpecies Species::AdletElder => &self.adlet_elder, Species::SeaBishop => &self.sea_bishop, Species::HaniwaGeneral => &self.haniwa_general, + Species::TerracottaBesieger => &self.terracotta_besieger, + Species::TerracottaDemolisher => &self.terracotta_demolisher, + Species::TerracottaPunisher => &self.terracotta_punisher, + Species::TerracottaPursuer => &self.terracotta_pursuer, + Species::Cursekeeper => &self.cursekeeper, } } } -pub const ALL_SPECIES: [Species; 26] = [ +pub const ALL_SPECIES: [Species; 31] = [ Species::Ogre, Species::Cyclops, Species::Wendigo, @@ -185,6 +220,11 @@ pub const ALL_SPECIES: [Species; 26] = [ Species::AdletElder, Species::SeaBishop, Species::HaniwaGeneral, + Species::TerracottaBesieger, + Species::TerracottaDemolisher, + Species::TerracottaPunisher, + Species::TerracottaPursuer, + Species::Cursekeeper, ]; impl<'a, SpeciesMeta: 'a> IntoIterator for &'a AllSpecies { diff --git a/common/src/comp/body/biped_small.rs b/common/src/comp/body/biped_small.rs index 731efb4b2d..314a55781c 100644 --- a/common/src/comp/body/biped_small.rs +++ b/common/src/comp/body/biped_small.rs @@ -50,6 +50,8 @@ make_case_elim!( Irrwurz = 13, Clockwork = 14, Flamekeeper = 15, + ShamanicSpirit = 16, + Jiangshi = 17, } ); @@ -74,6 +76,8 @@ pub struct AllSpecies { pub irrwurz: SpeciesMeta, pub clockwork: SpeciesMeta, pub flamekeeper: SpeciesMeta, + pub shamanic_spirit: SpeciesMeta, + pub jiangshi: SpeciesMeta, } impl<'a, SpeciesMeta> core::ops::Index<&'a Species> for AllSpecies { @@ -98,11 +102,13 @@ impl<'a, SpeciesMeta> core::ops::Index<&'a Species> for AllSpecies Species::Irrwurz => &self.irrwurz, Species::Clockwork => &self.clockwork, Species::Flamekeeper => &self.flamekeeper, + Species::ShamanicSpirit => &self.shamanic_spirit, + Species::Jiangshi => &self.jiangshi, } } } -pub const ALL_SPECIES: [Species; 16] = [ +pub const ALL_SPECIES: [Species; 18] = [ Species::Gnome, Species::Sahagin, Species::Adlet, @@ -119,6 +125,8 @@ pub const ALL_SPECIES: [Species; 16] = [ Species::Irrwurz, Species::Clockwork, Species::Flamekeeper, + Species::ShamanicSpirit, + Species::Jiangshi, ]; impl<'a, SpeciesMeta: 'a> IntoIterator for &'a AllSpecies { diff --git a/common/src/comp/body/golem.rs b/common/src/comp/body/golem.rs index c3017af472..3554584ed0 100644 --- a/common/src/comp/body/golem.rs +++ b/common/src/comp/body/golem.rs @@ -41,6 +41,7 @@ make_case_elim!( CoralGolem = 4, Gravewarden = 5, AncientEffigy = 6, + Mogwai = 7, } ); @@ -56,6 +57,7 @@ pub struct AllSpecies { pub coralgolem: SpeciesMeta, pub gravewarden: SpeciesMeta, pub ancienteffigy: SpeciesMeta, + pub mogwai: SpeciesMeta, } impl<'a, SpeciesMeta> core::ops::Index<&'a Species> for AllSpecies { @@ -71,11 +73,12 @@ impl<'a, SpeciesMeta> core::ops::Index<&'a Species> for AllSpecies Species::CoralGolem => &self.coralgolem, Species::Gravewarden => &self.gravewarden, Species::AncientEffigy => &self.ancienteffigy, + Species::Mogwai => &self.mogwai, } } } -pub const ALL_SPECIES: [Species; 7] = [ +pub const ALL_SPECIES: [Species; 8] = [ Species::StoneGolem, Species::Treant, Species::ClayGolem, @@ -83,6 +86,7 @@ pub const ALL_SPECIES: [Species; 7] = [ Species::CoralGolem, Species::Gravewarden, Species::AncientEffigy, + Species::Mogwai, ]; impl<'a, SpeciesMeta: 'a> IntoIterator for &'a AllSpecies { diff --git a/common/src/comp/body/object.rs b/common/src/comp/body/object.rs index 0cd5ac243e..cb620fd921 100644 --- a/common/src/comp/body/object.rs +++ b/common/src/comp/body/object.rs @@ -117,6 +117,10 @@ make_case_elim!( ArrowClay = 102, GrenadeClay = 103, Pebble = 104, + LaserBeamSmall = 105, + TerracottaStatue = 106, + TerracottaDemolisherBomb = 107, + BoltBesieger = 108, } ); @@ -127,7 +131,7 @@ impl Body { } } -pub const ALL_OBJECTS: [Body; 105] = [ +pub const ALL_OBJECTS: [Body; 109] = [ Body::Arrow, Body::Bomb, Body::Scarecrow, @@ -217,9 +221,11 @@ pub const ALL_OBJECTS: [Body; 105] = [ Body::GnarlingTotemWhite, Body::GnarlingTotemGreen, Body::DagonBomb, + Body::TerracottaDemolisherBomb, Body::BarrelOrgan, Body::IceBomb, Body::LaserBeam, + Body::LaserBeamSmall, Body::AdletSpear, Body::AdletTrap, Body::Flamethrower, @@ -233,6 +239,8 @@ pub const ALL_OBJECTS: [Body; 105] = [ Body::ArrowClay, Body::GrenadeClay, Body::Pebble, + Body::TerracottaStatue, + Body::BoltBesieger, ]; impl From for super::Body { @@ -329,11 +337,13 @@ impl Body { Body::GnarlingTotemGreen => "gnarling_totem_green", Body::GnarlingTotemWhite => "gnarling_totem_white", Body::DagonBomb => "dagon_bomb", + Body::TerracottaDemolisherBomb => "terracotta_demolisher_bomb", Body::BarrelOrgan => "barrel_organ", Body::IceBomb => "ice_bomb", Body::SpectralSwordSmall => "spectral_sword_small", Body::SpectralSwordLarge => "spectral_sword_large", Body::LaserBeam => "laser_beam", + Body::LaserBeamSmall => "laser_beam_small", Body::AdletSpear => "adlet_spear", Body::AdletTrap => "adlet_trap", Body::Flamethrower => "flamethrower", @@ -347,6 +357,8 @@ impl Body { Body::ArrowClay => "arrow_clay", Body::GrenadeClay => "grenade_clay", Body::Pebble => "pebble", + Body::TerracottaStatue => "terracotta_statue", + Body::BoltBesieger => "besieger_bolt", } } @@ -370,8 +382,10 @@ impl Body { | Body::ArrowTurret | Body::MultiArrow | Body::ArrowClay + | Body::BoltBesieger | Body::Dart | Body::DagonBomb + | Body::TerracottaDemolisherBomb | Body::SpectralSwordSmall | Body::SpectralSwordLarge | Body::AdletSpear @@ -397,7 +411,6 @@ impl Body { Body::Arrow | Body::ArrowSnake | Body::ArrowTurret | Body::MultiArrow | Body::Dart => { 0.003 }, - Body::ArrowClay | Body::Pebble => 1.0, Body::SpectralSwordSmall => 0.5, Body::SpectralSwordLarge => 50.0, Body::BedBlue => 50.0, @@ -407,12 +420,17 @@ impl Body { | Body::BoltFireBig | Body::BoltNature | Body::BoltIcicle - | Body::FireRainDrop => 1.0, + | Body::FireRainDrop + | Body::ArrowClay + | Body::Pebble + | Body::BoltBesieger => 1.0, Body::SpitPoison => 100.0, - Body::Bomb | Body::DagonBomb => { + Body::Bomb | Body::DagonBomb | Body::TerracottaDemolisherBomb => { 0.5 * IRON_DENSITY * std::f32::consts::PI / 6.0 * self.dimensions().x.powi(3) }, - Body::Campfire | Body::CampfireLit | Body::BarrelOrgan => 300.0, + Body::Campfire | Body::CampfireLit | Body::BarrelOrgan | Body::TerracottaStatue => { + 300.0 + }, Body::Carpet | Body::CarpetHumanRound | Body::CarpetHumanSquare @@ -474,7 +492,7 @@ impl Body { Body::Coconut => 2.0, Body::GnarlingTotemRed | Body::GnarlingTotemGreen | Body::GnarlingTotemWhite => 100.0, Body::IceBomb => 12298.0, // 2.5 m diamter but ice - Body::LaserBeam => 80000.0, + Body::LaserBeam | Body::LaserBeamSmall => 80000.0, Body::AdletSpear => 1.5, Body::AdletTrap => 10.0, Body::Mine => 100.0, @@ -492,6 +510,7 @@ impl Body { | Body::MultiArrow | Body::ArrowTurret | Body::ArrowClay + | Body::BoltBesieger | Body::Dart | Body::AdletSpear => Vec3::new(0.01, 0.8, 0.01), Body::AdletTrap => Vec3::new(1.0, 0.6, 0.3), @@ -509,8 +528,10 @@ impl Body { Vec3::new(0.8, 0.8, 1.4) }, Body::BarrelOrgan => Vec3::new(4.0, 2.0, 3.0), + Body::TerracottaStatue => Vec3::new(5.0, 5.0, 5.0), Body::IceBomb => Vec3::broadcast(2.5), Body::LaserBeam => Vec3::new(8.0, 8.0, 8.0), + Body::LaserBeamSmall => Vec3::new(1.0, 1.0, 1.0), Body::Mine => Vec3::new(0.8, 0.8, 0.5), Body::LightningBolt | Body::SpearIcicle => Vec3::new(1.0, 1.0, 1.0), Body::FireRainDrop => Vec3::new(0.01, 0.01, 0.02), diff --git a/common/src/comp/fluid_dynamics.rs b/common/src/comp/fluid_dynamics.rs index 7d222a5c72..4f88545919 100644 --- a/common/src/comp/fluid_dynamics.rs +++ b/common/src/comp/fluid_dynamics.rs @@ -284,6 +284,7 @@ impl Body { | object::Body::FireworkWhite | object::Body::FireworkYellow | object::Body::MultiArrow + | object::Body::BoltBesieger | object::Body::Dart => { let dim = self.dimensions().map(|a| a * 0.5 * scale); const CD: f32 = 0.02; diff --git a/common/src/comp/inventory/loadout_builder.rs b/common/src/comp/inventory/loadout_builder.rs index 5213863c22..3940c31a57 100644 --- a/common/src/comp/inventory/loadout_builder.rs +++ b/common/src/comp/inventory/loadout_builder.rs @@ -560,6 +560,9 @@ fn default_main_tool(body: &Body) -> Item { golem::Species::AncientEffigy => Some(Item::new_from_asset_expect( "common.items.npc_weapons.unique.ancient_effigy_eyes", )), + golem::Species::Mogwai => Some(Item::new_from_asset_expect( + "common.items.npc_weapons.unique.mogwai", + )), _ => None, }, Body::QuadrupedMedium(quadruped_medium) => match quadruped_medium.species { @@ -843,6 +846,21 @@ fn default_main_tool(body: &Body) -> Item { (biped_large::Species::HaniwaGeneral, _) => Some(Item::new_from_asset_expect( "common.items.npc_weapons.sword.haniwa_general_sword", )), + (biped_large::Species::TerracottaBesieger, _) => Some(Item::new_from_asset_expect( + "common.items.npc_weapons.bow.terracotta_besieger_bow", + )), + (biped_large::Species::TerracottaDemolisher, _) => Some(Item::new_from_asset_expect( + "common.items.npc_weapons.unique.terracotta_demolisher_fist", + )), + (biped_large::Species::TerracottaPunisher, _) => Some(Item::new_from_asset_expect( + "common.items.npc_weapons.hammer.terracotta_punisher_club", + )), + (biped_large::Species::TerracottaPursuer, _) => Some(Item::new_from_asset_expect( + "common.items.npc_weapons.sword.terracotta_pursuer_sword", + )), + (biped_large::Species::Cursekeeper, _) => Some(Item::new_from_asset_expect( + "common.items.npc_weapons.unique.cursekeeper_sceptre", + )), }, Body::Object(body) => match body { object::Body::Crossbow => Some(Item::new_from_asset_expect( @@ -854,6 +872,9 @@ fn default_main_tool(body: &Body) -> Item { object::Body::BarrelOrgan => Some(Item::new_from_asset_expect( "common.items.npc_weapons.unique.organ", )), + object::Body::TerracottaStatue => Some(Item::new_from_asset_expect( + "common.items.npc_weapons.unique.terracotta_statue", + )), object::Body::HaniwaSentry => Some(Item::new_from_asset_expect( "common.items.npc_weapons.unique.haniwa_sentry", )), @@ -896,6 +917,12 @@ fn default_main_tool(body: &Body) -> Item { (biped_small::Species::Clockwork, _) => Some(Item::new_from_asset_expect( "common.items.npc_weapons.unique.clockwork", )), + (biped_small::Species::ShamanicSpirit, _) => Some(Item::new_from_asset_expect( + "common.items.npc_weapons.unique.shamanic_spirit", + )), + (biped_small::Species::Jiangshi, _) => Some(Item::new_from_asset_expect( + "common.items.npc_weapons.unique.jiangshi", + )), _ => Some(Item::new_from_asset_expect( "common.items.npc_weapons.biped_small.adlet.hunter", )), @@ -971,6 +998,8 @@ pub enum Preset { HuskSummon, BorealSummon, ClockworkSummon, + ShamanicSpiritSummon, + JiangshiSummon, } impl LoadoutBuilder { @@ -1080,6 +1109,13 @@ impl LoadoutBuilder { biped_large::Species::HaniwaGeneral => { Some("common.items.npc_armor.biped_large.haniwageneral") }, + biped_large::Species::TerracottaBesieger + | biped_large::Species::TerracottaDemolisher + | biped_large::Species::TerracottaPunisher + | biped_large::Species::TerracottaPursuer + | biped_large::Species::Cursekeeper => { + Some("common.items.npc_armor.biped_large.terracotta") + }, _ => None, }, Body::BirdLarge(body) => match body.species { @@ -1098,6 +1134,7 @@ impl LoadoutBuilder { golem::Species::Gravewarden => Some("common.items.npc_armor.golem.gravewarden"), golem::Species::WoodGolem => Some("common.items.npc_armor.golem.woodgolem"), golem::Species::AncientEffigy => Some("common.items.npc_armor.golem.ancienteffigy"), + golem::Species::Mogwai => Some("common.items.npc_armor.golem.mogwai"), _ => None, }, Body::QuadrupedLow(body) => match body.species { @@ -1218,6 +1255,17 @@ impl LoadoutBuilder { None, ); }, + Preset::ShamanicSpiritSummon => { + self = self.with_asset_expect( + "common.loadout.dungeon.terracotta.shamanic_spirit", + rng, + None, + ); + }, + Preset::JiangshiSummon => { + self = + self.with_asset_expect("common.loadout.dungeon.terracotta.jiangshi", rng, None); + }, } self diff --git a/common/src/outcome.rs b/common/src/outcome.rs index 42cd251f10..9dd0779486 100644 --- a/common/src/outcome.rs +++ b/common/src/outcome.rs @@ -112,6 +112,9 @@ pub enum Outcome { FuseCharge { pos: Vec3, }, + TerracottaStatueCharge { + pos: Vec3, + }, Utterance { pos: Vec3, body: comp::Body, @@ -187,6 +190,7 @@ impl Outcome { | Outcome::CyclopsCharge { pos } | Outcome::FlamethrowerCharge { pos } | Outcome::FuseCharge { pos } + | Outcome::TerracottaStatueCharge { pos } | Outcome::LaserBeam { pos } | Outcome::GroundDig { pos } | Outcome::PortalActivated { pos } diff --git a/common/src/states/basic_beam.rs b/common/src/states/basic_beam.rs index f90819cb63..a2276a1ef9 100644 --- a/common/src/states/basic_beam.rs +++ b/common/src/states/basic_beam.rs @@ -5,7 +5,7 @@ use crate::{ }, comp::{ beam, - body::{biped_large, bird_large}, + body::{biped_large, bird_large, golem}, character_state::OutputEvents, object::Body::Flamethrower, Body, CharacterState, Ori, StateUpdate, @@ -260,13 +260,18 @@ fn height_offset(body: &Body, look_dir: Dir, velocity: Vec3, on_ground: Opt 0.0 } }, - Body::Golem(_) => { + Body::Golem(b) => { + let height_factor = match b.species { + golem::Species::Mogwai => 0.4, + _ => 0.9, + }; const DIR_COEFF: f32 = 2.0; - body.height() * 0.9 + look_dir.z * DIR_COEFF + body.height() * height_factor + look_dir.z * DIR_COEFF }, Body::BipedLarge(b) => match b.species { biped_large::Species::Mindflayer => body.height() * 0.6, biped_large::Species::SeaBishop => body.height() * 0.4, + biped_large::Species::Cursekeeper => body.height() * 0.8, _ => body.height() * 0.5, }, _ => body.height() * 0.5, diff --git a/common/src/states/basic_ranged.rs b/common/src/states/basic_ranged.rs index f717f752e2..879e06fad6 100644 --- a/common/src/states/basic_ranged.rs +++ b/common/src/states/basic_ranged.rs @@ -2,7 +2,7 @@ use crate::{ combat::{self, CombatEffect}, comp::{ character_state::OutputEvents, - object::Body::{GrenadeClay, LaserBeam}, + object::Body::{GrenadeClay, LaserBeam, LaserBeamSmall}, Body, CharacterState, LightEmitter, Pos, ProjectileConstructor, StateUpdate, }, event::{LocalEvent, ShootEvent}, @@ -87,6 +87,14 @@ impl CharacterBehavior for Data { }, )); }, + Body::Object(LaserBeamSmall) => { + output_events.emit_local(LocalEvent::CreateOutcome( + Outcome::TerracottaStatueCharge { + pos: data.pos.0 + + *data.ori.look_dir() * (data.body.max_radius()), + }, + )); + }, _ => {}, } } else { diff --git a/common/src/states/sprite_interact.rs b/common/src/states/sprite_interact.rs index 1e2ae1a923..63269afb44 100644 --- a/common/src/states/sprite_interact.rs +++ b/common/src/states/sprite_interact.rs @@ -203,7 +203,8 @@ impl From for Option { | SpriteKind::BoneKeyhole | SpriteKind::HaniwaKeyhole | SpriteKind::GlassKeyhole - | SpriteKind::KeyholeBars => Some(SpriteInteractKind::Unlock), + | SpriteKind::KeyholeBars + | SpriteKind::TerracottaKeyhole => 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() => { diff --git a/common/src/states/sprite_summon.rs b/common/src/states/sprite_summon.rs index 68e52ca713..bd333dbf35 100644 --- a/common/src/states/sprite_summon.rs +++ b/common/src/states/sprite_summon.rs @@ -86,6 +86,14 @@ impl CharacterBehavior for Data { timer: tick_attack_or_default(data, self.timer, None), ..*self }); + // Send local event used for frontend shenanigans + if self.static_data.sprite == SpriteKind::Empty { + output_events.emit_local(LocalEvent::CreateOutcome( + Outcome::TerracottaStatueCharge { + pos: data.pos.0 + *data.ori.look_dir() * (data.body.max_radius()), + }, + )); + } } else { // Transitions to recover section of stage update.character = CharacterState::SpriteSummon(Data { @@ -154,15 +162,22 @@ impl CharacterBehavior for Data { }) .cast(); - // z height relative to caster - let z = sprite_pos.z - + if let (SpriteSummonAnchor::Target, Ok(None)) = - (&self.static_data.anchor, obstale_z_result) - { - 0 - } else { - (10.5 - obstacle_z).ceil() as i32 - }; + let z = match self.static_data.sprite { + // z height - 1 to delete sprite layer below caster + SpriteKind::Empty => { + sprite_pos.z + (10.5 - obstacle_z).ceil() as i32 - 1 + }, + _ => { + sprite_pos.z + + if let (SpriteSummonAnchor::Target, Ok(None)) = + (&self.static_data.anchor, obstale_z_result) + { + 0 + } else { + (10.5 - obstacle_z).ceil() as i32 + } + }, + }; // Location sprite will be created let sprite_pos = Vec3::new(sprite_pos.x, sprite_pos.y, z); @@ -189,15 +204,27 @@ impl CharacterBehavior for Data { ..*self }); // Send local event used for frontend shenanigans - if self.static_data.sprite == SpriteKind::IceSpike { - let summoner_pos = - data.pos.0 + *data.ori.look_dir() * data.body.max_radius(); - output_events.emit_local(LocalEvent::CreateOutcome(Outcome::IceCrack { - pos: match self.static_data.anchor { - SpriteSummonAnchor::Summoner => summoner_pos, - SpriteSummonAnchor::Target => target_pos().unwrap_or(summoner_pos), - }, - })); + match self.static_data.sprite { + SpriteKind::IceSpike => { + let summoner_pos = + data.pos.0 + *data.ori.look_dir() * data.body.max_radius(); + output_events.emit_local(LocalEvent::CreateOutcome( + Outcome::IceCrack { + pos: match self.static_data.anchor { + SpriteSummonAnchor::Summoner => summoner_pos, + SpriteSummonAnchor::Target => { + target_pos().unwrap_or(summoner_pos) + }, + }, + }, + )); + }, + SpriteKind::IronSpike => { + output_events.emit_local(LocalEvent::CreateOutcome(Outcome::Whoosh { + pos: data.pos.0, + })); + }, + _ => {}, } } else { // Transitions to recover section of stage diff --git a/common/src/terrain/block.rs b/common/src/terrain/block.rs index 99423ebf71..bd2a4bc06a 100644 --- a/common/src/terrain/block.rs +++ b/common/src/terrain/block.rs @@ -367,6 +367,7 @@ impl Block { | SpriteKind::DungeonChest5 | SpriteKind::CoralChest | SpriteKind::HaniwaUrn + | SpriteKind::TerracottaChest | SpriteKind::Crate => Some(rtsim::ChunkResource::Loot), _ => None, } @@ -416,6 +417,7 @@ impl Block { | SpriteKind::EmeraldSmall | SpriteKind::SapphireSmall => 3, SpriteKind::Lantern => 24, + SpriteKind::TerracottaStatue => 8, SpriteKind::SeashellLantern | SpriteKind::GlowIceCrystal => 16, SpriteKind::SeaDecorEmblem => 12, SpriteKind::SeaDecorBlock | SpriteKind::HaniwaKeyDoor => 10, @@ -516,6 +518,7 @@ impl Block { | SpriteKind::HaniwaTrap | SpriteKind::HaniwaTrapTriggered | SpriteKind::ChestBuried + | SpriteKind::TerracottaChest | SpriteKind::SeaDecorBlock | SpriteKind::SeaDecorChain | SpriteKind::SeaDecorWindowHor @@ -525,7 +528,11 @@ impl Block { | SpriteKind::HotSurface | SpriteKind::FireBlock | SpriteKind::GlassBarrier - | SpriteKind::GlassKeyhole => None, + | SpriteKind::GlassKeyhole + | SpriteKind::TerracottaKeyDoor + | SpriteKind::TerracottaKeyhole + | SpriteKind::TerracottaStatue + | SpriteKind::TerracottaBlock => None, SpriteKind::EnsnaringVines | SpriteKind::EnsnaringWeb | SpriteKind::SeaUrchin diff --git a/common/src/terrain/site.rs b/common/src/terrain/site.rs index 4734f18e5e..dbcbe999d2 100644 --- a/common/src/terrain/site.rs +++ b/common/src/terrain/site.rs @@ -15,6 +15,9 @@ pub enum DungeonKindMeta { Old, Gnarling, Adlet, + Haniwa, + SeaChapel, + Terracotta, } #[derive(Debug, Copy, Clone, Serialize, Deserialize, PartialEq, Eq)] diff --git a/common/src/terrain/sprite.rs b/common/src/terrain/sprite.rs index ac8576b816..a5773b7da8 100644 --- a/common/src/terrain/sprite.rs +++ b/common/src/terrain/sprite.rs @@ -121,11 +121,12 @@ sprites! { DungeonChest5 = 0x36, CoralChest = 0x37, HaniwaUrn = 0x38, - CommonLockedChest = 0x39, - ChestBuried = 0x3A, - Crate = 0x3B, - Barrel = 0x3C, - CrateBlock = 0x3D, + TerracottaChest = 0x39, + CommonLockedChest = 0x3A, + ChestBuried = 0x3B, + Crate = 0x3C, + Barrel = 0x3D, + CrateBlock = 0x3E, // Wall HangingBasket = 0x50, HangingSign = 0x51, @@ -289,6 +290,8 @@ sprites! { KeyholeBars = 0x08, HaniwaKeyDoor = 0x09, HaniwaKeyhole = 0x0A, + TerracottaKeyDoor = 0x0B, + TerracottaKeyhole = 0x0C, // Windows Window1 = 0x10, Window2 = 0x11, @@ -315,6 +318,8 @@ sprites! { DoorBars = 0x43, HaniwaTrap = 0x44, HaniwaTrapTriggered = 0x45, + TerracottaStatue = 0x46, + TerracottaBlock = 0x47, }, // Decorative items, both natural and artificial Decor = 6 has Ori { @@ -412,6 +417,9 @@ impl SpriteKind { SpriteKind::DungeonChest5 => 1.09, SpriteKind::CoralChest => 1.09, SpriteKind::HaniwaUrn => 1.09, + SpriteKind::TerracottaChest => 1.09, + SpriteKind::TerracottaStatue => 5.29, + SpriteKind::TerracottaBlock => 1.09, SpriteKind::SeaDecorChain => 1.09, SpriteKind::SeaDecorBlock => 1.00, SpriteKind::SeaDecorWindowHor => 0.55, @@ -483,6 +491,8 @@ impl SpriteKind { | SpriteKind::HaniwaKeyDoor | SpriteKind::HaniwaTrap | SpriteKind::HaniwaTrapTriggered + | SpriteKind::TerracottaKeyDoor + | SpriteKind::TerracottaKeyhole | SpriteKind::Bomb | SpriteKind::OneWayWall | SpriteKind::DoorBars @@ -652,6 +662,9 @@ impl SpriteKind { SpriteKind::ChestBuried => table("common.loot_tables.sprite.chest-buried"), SpriteKind::CoralChest => table("common.loot_tables.dungeon.sea_chapel.chest_coral"), SpriteKind::HaniwaUrn => table("common.loot_tables.dungeon.haniwa.key"), + SpriteKind::TerracottaChest => { + table("common.loot_tables.dungeon.terracotta.chest_terracotta") + }, SpriteKind::Mud => table("common.loot_tables.sprite.mud"), SpriteKind::Grave => table("common.loot_tables.sprite.mud"), SpriteKind::Crate => table("common.loot_tables.sprite.crate"), @@ -666,7 +679,8 @@ impl SpriteKind { | SpriteKind::BoneKeyhole | SpriteKind::HaniwaKeyhole | SpriteKind::GlassKeyhole - | SpriteKind::KeyholeBars => { + | SpriteKind::KeyholeBars + | SpriteKind::TerracottaKeyhole => { return Some(None); }, _ => return None, @@ -769,6 +783,12 @@ impl SpriteKind { SpriteKind::GlassKeyhole => UnlockKind::Consumes( ItemDefinitionId::Simple("common.items.keys.glass_key").to_owned(), ), + SpriteKind::TerracottaChest => UnlockKind::Consumes( + ItemDefinitionId::Simple("common.items.keys.terracotta_key_chest").to_owned(), + ), + SpriteKind::TerracottaKeyhole => UnlockKind::Consumes( + ItemDefinitionId::Simple("common.items.keys.terracotta_key_door").to_owned(), + ), _ => UnlockKind::Free, }) } diff --git a/common/src/terrain/structure.rs b/common/src/terrain/structure.rs index d693e7a334..91f085b14e 100644 --- a/common/src/terrain/structure.rs +++ b/common/src/terrain/structure.rs @@ -48,9 +48,10 @@ make_case_elim!( Sign(content: Content, ori: u8) = 28, KeyholeBars(consumes: String) = 29, HaniwaKeyhole(consumes: String) = 30, - MapleLeaves = 31, - CherryLeaves = 32, - AutumnLeaves = 33, + TerracottaKeyhole(consumes: String) = 31, + MapleLeaves = 32, + CherryLeaves = 33, + AutumnLeaves = 34, } ); diff --git a/common/systems/src/buff.rs b/common/systems/src/buff.rs index c35f399136..f78a1fad74 100644 --- a/common/systems/src/buff.rs +++ b/common/systems/src/buff.rs @@ -228,7 +228,7 @@ impl<'a> System<'a> for Sys { entity, buff_change: BuffChange::Add(Buff::new( BuffKind::Bleeding, - BuffData::new(5.0, Some(Secs(3.0))), + BuffData::new(8.0, Some(Secs(4.0))), Vec::new(), BuffSource::World, *read_data.time, diff --git a/rtsim/src/gen/site.rs b/rtsim/src/gen/site.rs index d53e82ddf8..1e06d0e82f 100644 --- a/rtsim/src/gen/site.rs +++ b/rtsim/src/gen/site.rs @@ -30,6 +30,7 @@ impl Site { // Evil SiteKind::Dungeon(_) | SiteKind::ChapelSite(_) + | SiteKind::Terracotta(_) | SiteKind::Gnarling(_) | SiteKind::PirateHideout(_) | SiteKind::JungleRuin(_) diff --git a/server/agent/src/action_nodes.rs b/server/agent/src/action_nodes.rs index 70c7987419..02819ead16 100644 --- a/server/agent/src/action_nodes.rs +++ b/server/agent/src/action_nodes.rs @@ -1086,6 +1086,15 @@ impl<'a> AgentData<'a> { }, "Clay Golem" => Tactic::ClayGolem, "Ancient Effigy" => Tactic::AncientEffigy, + "TerracottaStatue" | "Mogwai" => Tactic::TerracottaStatue, + "TerracottaBesieger" => Tactic::Bow, + "TerracottaDemolisher" => Tactic::SimpleDouble, + "TerracottaPunisher" => Tactic::SimpleMelee, + "TerracottaPursuer" => Tactic::SwordSimple, + "Cursekeeper" => Tactic::Cursekeeper, + "CursekeeperFake" => Tactic::CursekeeperFake, + "ShamanicSpirit" => Tactic::ShamanicSpirit, + "Jiangshi" => Tactic::Jiangshi, "Mindflayer" => Tactic::Mindflayer, "Flamekeeper" => Tactic::Flamekeeper, "Minotaur" => Tactic::Minotaur, @@ -1507,6 +1516,9 @@ impl<'a> AgentData<'a> { tgt_data, read_data, ), + Tactic::Jiangshi => { + self.handle_jiangshi_attack(agent, controller, &attack_data, tgt_data, read_data) + }, Tactic::ClayGolem => { self.handle_clay_golem_attack(agent, controller, &attack_data, tgt_data, read_data) }, @@ -1520,6 +1532,9 @@ impl<'a> AgentData<'a> { tgt_data, read_data, ), + Tactic::TerracottaStatue => { + self.handle_terracotta_statue_attack(agent, controller, &attack_data) + }, Tactic::Minotaur => { self.handle_minotaur_attack(agent, controller, &attack_data, tgt_data, read_data) }, @@ -1567,6 +1582,19 @@ impl<'a> AgentData<'a> { read_data, rng, ), + Tactic::Cursekeeper => { + self.handle_cursekeeper_attack(agent, controller, tgt_data, read_data, rng) + }, + Tactic::CursekeeperFake => { + self.handle_cursekeeper_fake_attack(agent, controller, &attack_data) + }, + Tactic::ShamanicSpirit => self.handle_shamanic_spirit_attack( + agent, + controller, + &attack_data, + tgt_data, + read_data, + ), Tactic::Dagon => { self.handle_dagon_attack(agent, controller, &attack_data, tgt_data, read_data) }, diff --git a/server/agent/src/attack.rs b/server/agent/src/attack.rs index 3d7f66cd11..e68fad1ce8 100644 --- a/server/agent/src/attack.rs +++ b/server/agent/src/attack.rs @@ -4795,6 +4795,136 @@ impl<'a> AgentData<'a> { } } + pub fn handle_cursekeeper_attack( + &self, + agent: &mut Agent, + controller: &mut Controller, + tgt_data: &TargetData, + read_data: &ReadData, + rng: &mut impl Rng, + ) { + let line_of_sight_with_target = || { + entities_have_line_of_sight( + self.pos, + self.body, + self.scale, + tgt_data.pos, + tgt_data.body, + tgt_data.scale, + read_data, + ) + }; + + enum ActionStateTimers { + TimerBeam, + TimerSummon, + SelectSummon, + } + if tgt_data.pos.0.z - self.pos.0.z > 5.0 { + controller.push_action(ControlAction::StartInput { + input: InputKind::Ability(5), + target_entity: agent + .target + .as_ref() + .and_then(|t| read_data.uids.get(t.target)) + .copied(), + select_pos: None, + }); + } else if agent.combat_state.timers[ActionStateTimers::TimerBeam as usize] > 10.0 { + agent.combat_state.timers[ActionStateTimers::TimerBeam as usize] = 0.0; + } else { + agent.combat_state.timers[ActionStateTimers::TimerBeam as usize] += read_data.dt.0; + } + + if matches!(self.char_state, CharacterState::BasicSummon(c) if !matches!(c.stage_section, StageSection::Recover)) + { + agent.combat_state.timers[ActionStateTimers::TimerSummon as usize] = 0.0; + agent.combat_state.timers[ActionStateTimers::SelectSummon as usize] = + rng.gen_range(0..=4) as f32; + } else { + agent.combat_state.timers[ActionStateTimers::TimerSummon as usize] += read_data.dt.0; + } + + if line_of_sight_with_target() { + if agent.combat_state.timers[ActionStateTimers::TimerSummon as usize] > 45.0 { + match agent.combat_state.timers[ActionStateTimers::SelectSummon as usize] as i32 { + 0 => controller.push_basic_input(InputKind::Ability(0)), + 1 => controller.push_basic_input(InputKind::Ability(1)), + 2 => controller.push_basic_input(InputKind::Ability(2)), + 3 => controller.push_basic_input(InputKind::Ability(3)), + _ => controller.push_basic_input(InputKind::Ability(4)), + } + } else if agent.combat_state.timers[ActionStateTimers::TimerBeam as usize] < 6.0 { + controller.push_basic_input(InputKind::Primary); + } else { + controller.push_basic_input(InputKind::Secondary); + } + } + self.path_toward_target( + agent, + controller, + tgt_data.pos.0, + read_data, + Path::Partial, + None, + ); + } + + pub fn handle_shamanic_spirit_attack( + &self, + agent: &mut Agent, + controller: &mut Controller, + attack_data: &AttackData, + tgt_data: &TargetData, + read_data: &ReadData, + ) { + if tgt_data.pos.0.z - self.pos.0.z > 5.0 { + controller.push_action(ControlAction::StartInput { + input: InputKind::Secondary, + target_entity: agent + .target + .as_ref() + .and_then(|t| read_data.uids.get(t.target)) + .copied(), + select_pos: None, + }); + } else if attack_data.in_min_range() && attack_data.angle < 30.0 { + controller.push_basic_input(InputKind::Primary); + controller.inputs.move_dir = Vec2::zero(); + } else { + self.path_toward_target( + agent, + controller, + tgt_data.pos.0, + read_data, + Path::Full, + None, + ); + } + } + + pub fn handle_cursekeeper_fake_attack( + &self, + agent: &mut Agent, + controller: &mut Controller, + attack_data: &AttackData, + ) { + enum Conditions { + AttackToggle = 0, + } + if attack_data.dist_sqrd < 15_f32.powi(2) { + if !agent.combat_state.conditions[Conditions::AttackToggle as usize] { + controller.push_basic_input(InputKind::Primary); + if matches!(self.char_state, CharacterState::BasicSummon(c) if matches!(c.stage_section, StageSection::Recover)) + { + agent.combat_state.conditions[Conditions::AttackToggle as usize] = true; + } + } else { + controller.push_basic_input(InputKind::Secondary); + } + } + } + pub fn handle_dagon_attack( &self, agent: &mut Agent, @@ -6232,4 +6362,56 @@ impl<'a> AgentData<'a> { ); } } + + pub fn handle_terracotta_statue_attack( + &self, + agent: &mut Agent, + controller: &mut Controller, + attack_data: &AttackData, + ) { + enum Conditions { + AttackToggle = 0, + } + // always begin with sprite summon + if !agent.combat_state.conditions[Conditions::AttackToggle as usize] { + controller.push_basic_input(InputKind::Primary); + } else { + controller.inputs.move_dir = Vec2::zero(); + if attack_data.dist_sqrd < 8.5f32.powi(2) { + // sprite summon + controller.push_basic_input(InputKind::Primary); + } else { + // projectile + controller.push_basic_input(InputKind::Secondary); + } + } + if matches!(self.char_state, CharacterState::SpriteSummon(c) if matches!(c.stage_section, StageSection::Recover)) + { + agent.combat_state.conditions[Conditions::AttackToggle as usize] = true; + } + } + + pub fn handle_jiangshi_attack( + &self, + agent: &mut Agent, + controller: &mut Controller, + attack_data: &AttackData, + tgt_data: &TargetData, + read_data: &ReadData, + ) { + if tgt_data.pos.0.z - self.pos.0.z > 5.0 { + controller.push_basic_input(InputKind::Secondary); + } else if attack_data.dist_sqrd < 12.0f32.powi(2) { + controller.push_basic_input(InputKind::Primary); + } + + self.path_toward_target( + agent, + controller, + tgt_data.pos.0, + read_data, + Path::Full, + None, + ); + } } diff --git a/server/agent/src/data.rs b/server/agent/src/data.rs index c39cbc06b1..f941e144c7 100755 --- a/server/agent/src/data.rs +++ b/server/agent/src/data.rs @@ -262,6 +262,12 @@ pub enum Tactic { HaniwaSoldier, HaniwaGuard, HaniwaArcher, + // Terracotta + TerracottaStatue, + Cursekeeper, + CursekeeperFake, + ShamanicSpirit, + Jiangshi, } #[derive(Copy, Clone, Debug)] diff --git a/server/src/events/inventory_manip.rs b/server/src/events/inventory_manip.rs index 63cc8bb014..3ef42a5709 100644 --- a/server/src/events/inventory_manip.rs +++ b/server/src/events/inventory_manip.rs @@ -349,6 +349,9 @@ impl ServerEvent for InventoryManipEvent { Some(SpriteKind::HaniwaKeyhole) => Some(SpriteKind::HaniwaKeyDoor), Some(SpriteKind::GlassKeyhole) => Some(SpriteKind::GlassBarrier), Some(SpriteKind::KeyholeBars) => Some(SpriteKind::DoorBars), + Some(SpriteKind::TerracottaKeyhole) => { + Some(SpriteKind::TerracottaKeyDoor) + }, _ => None, } { let dirs = [ diff --git a/server/src/migrations/V55__steeltonguedrum.sql b/server/src/migrations/V55__steeltonguedrum.sql new file mode 100644 index 0000000000..4b8f9c1754 --- /dev/null +++ b/server/src/migrations/V55__steeltonguedrum.sql @@ -0,0 +1,3 @@ +UPDATE item + SET item_definition_id = 'common.items.tool.instruments.steeltonguedrum' + WHERE item_definition_id = 'common.items.tool.instruments.steeldrum'; diff --git a/voxygen/anim/src/biped_large/combomelee.rs b/voxygen/anim/src/biped_large/combomelee.rs index 2629238eab..32e0907075 100644 --- a/voxygen/anim/src/biped_large/combomelee.rs +++ b/voxygen/anim/src/biped_large/combomelee.rs @@ -151,7 +151,9 @@ impl Animation for ComboAnimation { }, Some( "common.abilities.custom.dullahan.melee" - | "common.abilities.swordsimple.doublestrike", + | "common.abilities.swordsimple.doublestrike" + | "common.abilities.custom.terracotta_pursuer.doublestrike" + | "common.abilities.custom.terracotta_demolisher.triplestrike", ) => { let speed = Vec2::::from(velocity).magnitude(); match strike { @@ -220,6 +222,21 @@ impl Animation for ComboAnimation { _ => {}, } }, + Some("common.abilities.custom.terracotta_besieger.doublestrike") => { + let speed = Vec2::::from(velocity).magnitude(); + let (move1base, move2base, move3) = match stage_section { + Some(StageSection::Buildup) => (anim_time.powf(0.25), 0.0, 0.0), + Some(StageSection::Action) => (1.0, anim_time, 0.0), + Some(StageSection::Recover) => (1.0, 1.0, anim_time.powi(6)), + _ => (0.0, 0.0, 0.0), + }; + let pullback = 1.0 - move3; + let move1 = move1base * pullback; + let move2 = move2base * pullback; + + init_biped_large_beta(&mut next, s_a, speed, acc_vel, move1); + biped_large_beta_axe(&mut next, s_a, move1, move2); + }, _ => {}, } } diff --git a/voxygen/anim/src/biped_large/mod.rs b/voxygen/anim/src/biped_large/mod.rs index 13e6c72447..d72063c235 100644 --- a/voxygen/anim/src/biped_large/mod.rs +++ b/voxygen/anim/src/biped_large/mod.rs @@ -266,7 +266,12 @@ impl<'a> From<&'a Body> for SkeletonAttr { (Gigasfrost, _) => (-1.5, 5.0), (AdletElder, _) => (-8.0, 10.0), (SeaBishop, _) => (0.0, 9.5), - (HaniwaGeneral, _) => (-8.0, 10.0), + (HaniwaGeneral, _) => (-1.5, 10.0), + (TerracottaBesieger, _) => (-2.5, 16.0), + (TerracottaDemolisher, _) => (-2.5, 10.0), + (TerracottaPunisher, _) => (-2.5, 10.0), + (TerracottaPursuer, _) => (-2.0, 13.5), + (Cursekeeper, _) => (2.0, 6.5), }, jaw: match (body.species, body.body_type) { (Ogre, _) => (0.0, 0.0), @@ -295,6 +300,11 @@ impl<'a> From<&'a Body> for SkeletonAttr { (AdletElder, _) => (10.5, -7.0), (SeaBishop, _) => (5.0, -4.5), (HaniwaGeneral, _) => (10.5, -7.0), + (TerracottaBesieger, _) => (10.5, -7.0), + (TerracottaDemolisher, _) => (10.5, -7.0), + (TerracottaPunisher, _) => (10.5, -7.0), + (TerracottaPursuer, _) => (10.5, -7.0), + (Cursekeeper, _) => (10.5, -7.0), }, upper_torso: match (body.species, body.body_type) { (Ogre, Male) => (0.0, 27.5), @@ -324,6 +334,11 @@ impl<'a> From<&'a Body> for SkeletonAttr { (AdletElder, _) => (3.0, 19.0), (SeaBishop, _) => (0.0, 15.0), (HaniwaGeneral, _) => (3.0, 16.0), + (TerracottaBesieger, _) => (3.0, 21.5), + (TerracottaDemolisher, _) => (3.0, 16.5), + (TerracottaPunisher, _) => (3.0, 15.5), + (TerracottaPursuer, _) => (3.0, 15.5), + (Cursekeeper, _) => (-4.0, 20.0), }, lower_torso: match (body.species, body.body_type) { (Ogre, Male) => (1.0, -7.0), @@ -353,6 +368,11 @@ impl<'a> From<&'a Body> for SkeletonAttr { (AdletElder, _) => (0.0, -4.0), (SeaBishop, _) => (0.0, -1.0), (HaniwaGeneral, _) => (-1.0, -3.5), + (TerracottaBesieger, _) => (-1.0, -4.5), + (TerracottaDemolisher, _) => (-2.0, -3.5), + (TerracottaPunisher, _) => (-1.5, -2.5), + (TerracottaPursuer, _) => (-1.5, -2.5), + (Cursekeeper, _) => (-1.5, -4.5), }, tail: match (body.species, body.body_type) { (Werewolf, _) => (-5.5, -2.0), @@ -391,6 +411,11 @@ impl<'a> From<&'a Body> for SkeletonAttr { (AdletElder, _) => (8.5, 1.0, 2.5), (SeaBishop, _) => (7.0, 0.0, 1.0), (HaniwaGeneral, _) => (9.0, -1.0, 4.5), + (TerracottaBesieger, _) => (13.0, -1.0, 2.0), + (TerracottaDemolisher, _) => (9.0, -1.0, 3.0), + (TerracottaPunisher, _) => (9.0, -1.0, 4.0), + (TerracottaPursuer, _) => (9.0, -1.0, 4.0), + (Cursekeeper, _) => (9.5, -0.5, 2.5), }, hand: match (body.species, body.body_type) { (Ogre, Male) => (14.5, 0.0, -4.0), @@ -420,6 +445,11 @@ impl<'a> From<&'a Body> for SkeletonAttr { (AdletElder, _) => (8.0, 1.5, -2.5), (SeaBishop, _) => (10.0, 0.0, -3.0), (HaniwaGeneral, _) => (10.0, -1.0, -3.0), + (TerracottaBesieger, _) => (13.5, -1.0, -3.5), + (TerracottaDemolisher, _) => (10.0, -1.0, -1.5), + (TerracottaPunisher, _) => (10.0, -1.0, -1.5), + (TerracottaPursuer, _) => (10.0, -1.0, -1.5), + (Cursekeeper, _) => (11.0, -1.0, -4.0), }, leg: match (body.species, body.body_type) { (Ogre, Male) => (0.0, 0.0, -4.0), @@ -449,6 +479,11 @@ impl<'a> From<&'a Body> for SkeletonAttr { (AdletElder, _) => (3.0, -1.5, -4.0), (SeaBishop, _) => (3.0, 1.0, -14.0), (HaniwaGeneral, _) => (3.0, 0.0, -5.0), + (TerracottaBesieger, _) => (5.0, 0.5, -6.0), + (TerracottaDemolisher, _) => (3.5, 1.5, -5.0), + (TerracottaPunisher, _) => (3.5, 1.0, -5.0), + (TerracottaPursuer, _) => (3.5, 1.0, -5.0), + (Cursekeeper, _) => (5.0, 0.5, -6.0), }, foot: match (body.species, body.body_type) { (Ogre, Male) => (4.0, 1.0, -12.0), @@ -478,6 +513,11 @@ impl<'a> From<&'a Body> for SkeletonAttr { (AdletElder, _) => (4.0, 3.5, -10.0), (SeaBishop, _) => (5.5, 3.0, -6.5), (HaniwaGeneral, _) => (3.0, 1.0, -10.0), + (TerracottaBesieger, _) => (5.5, 2.5, -13.0), + (TerracottaDemolisher, _) => (3.5, 3.0, -10.5), + (TerracottaPunisher, _) => (3.5, 2.0, -10.5), + (TerracottaPursuer, _) => (3.5, 2.5, -10.5), + (Cursekeeper, _) => (5.5, 2.5, -13.0), }, scaler: match (body.species, body.body_type) { (Ogre, Male) => 1.12, @@ -507,6 +547,11 @@ impl<'a> From<&'a Body> for SkeletonAttr { (AdletElder, _) => 1.0, (SeaBishop, _) => 1.0, (HaniwaGeneral, _) => 1.0, + (TerracottaBesieger, _) => 1.0, + (TerracottaDemolisher, _) => 1.0, + (TerracottaPunisher, _) => 1.0, + (TerracottaPursuer, _) => 1.0, + (Cursekeeper, _) => 1.0, }, tempo: match (body.species, body.body_type) { (Ogre, Male) => 0.9, @@ -517,6 +562,11 @@ impl<'a> From<&'a Body> for SkeletonAttr { (Swamptroll, _) => 0.9, (Dullahan, _) => 0.8, (Minotaur, _) => 0.8, + (TerracottaBesieger, _) => 0.7, + (TerracottaDemolisher, _) => 0.8, + (TerracottaPunisher, _) => 0.8, + (TerracottaPursuer, _) => 0.7, + (Cursekeeper, _) => 0.8, _ => 1.0, }, grip: match (body.species, body.body_type) { @@ -547,6 +597,11 @@ impl<'a> From<&'a Body> for SkeletonAttr { (AdletElder, _) => (10.0, 0.0), (SeaBishop, _) => (6.0, 0.0), (HaniwaGeneral, _) => (10.0, 0.0), + (TerracottaBesieger, _) => (5.0, 0.0), + (TerracottaDemolisher, _) => (6.0, 0.0), + (TerracottaPunisher, _) => (6.0, 0.0), + (TerracottaPursuer, _) => (6.0, 0.0), + (Cursekeeper, _) => (14.0, 0.0), }, shl: match (body.species, body.body_type) { (Dullahan, _) => (-4.75, -11.0, 8.5, 1.47, -0.2, 0.0), @@ -606,7 +661,10 @@ impl<'a> From<&'a Body> for SkeletonAttr { _ => (-7.0, 3.0, -8.0, 0.0, 0.0, 0.0), }, beast: matches!((body.species, body.body_type), (Werewolf, _)), - float: matches!((body.species, body.body_type), (Mindflayer, _)), + float: matches!( + (body.species, body.body_type), + (Mindflayer, _) | (Cursekeeper, _) + ), height: comp::Body::BipedLarge(*body).dimensions().z, } } @@ -641,6 +699,11 @@ fn mount_point(body: &Body) -> Vec3 { (AdletElder, _) => (0.0, 0.0, -1.0), (SeaBishop, _) => (0.0, 0.0, -1.0), (HaniwaGeneral, _) => (0.0, 0.0, -1.0), + (TerracottaBesieger, _) => (0.0, 0.0, -1.0), + (TerracottaDemolisher, _) => (0.0, 0.0, -1.0), + (TerracottaPunisher, _) => (0.0, 0.0, -1.0), + (TerracottaPursuer, _) => (0.0, 0.0, -1.0), + (Cursekeeper, _) => (0.0, 0.0, -1.0), } .into() } diff --git a/voxygen/anim/src/biped_large/shoot.rs b/voxygen/anim/src/biped_large/shoot.rs index ed4e889357..7f259097da 100644 --- a/voxygen/anim/src/biped_large/shoot.rs +++ b/voxygen/anim/src/biped_large/shoot.rs @@ -92,8 +92,10 @@ impl Animation for ShootAnimation { match active_tool_kind { Some(ToolKind::Sword) => match ability_id { - Some("common.abilities.custom.dullahan.knife_rain") - | Some("common.abilities.custom.dullahan.fierce_darts") => { + Some( + "common.abilities.custom.dullahan.knife_rain" + | "common.abilities.custom.dullahan.fierce_darts", + ) => { let (move1base, move2base, move3) = match stage_section { Some(StageSection::Buildup) => (anim_time.powf(0.25), 0.0, 0.0), Some(StageSection::Action) => (1.0, anim_time, 0.0), @@ -283,51 +285,99 @@ impl Animation for ShootAnimation { next.shoulder_r.orientation = Quaternion::rotation_x(move1 * 0.8 + 0.6 * speednorm + (footrotl * -0.2)); }, - Some(ToolKind::Bow) => { - let (move1base, move2base, move3) = match stage_section { - Some(StageSection::Buildup) => (anim_time.powf(0.25), 0.0, 0.0), - Some(StageSection::Action) => (1.0, anim_time, 0.0), - Some(StageSection::Recover) => (1.0, 1.0, anim_time.powi(4)), - _ => (0.0, 0.0, 0.0), - }; - let pullback = 1.0 - move3; - let move1 = move1base * pullback; - let move2 = move2base * pullback; - next.control_l.position = Vec3::new(-1.0, -2.0 + move2 * -7.0, -3.0); - next.control_r.position = Vec3::new(0.0, 4.0, 1.0); + Some(ToolKind::Bow) => match ability_id { + Some("common.abilities.custom.terracotta_besieger.multishot") => { + let (move1base, move2base, move3) = match stage_section { + Some(StageSection::Buildup) => (anim_time.powf(0.25), 0.0, 0.0), + Some(StageSection::Action) => (1.0, anim_time, 0.0), + Some(StageSection::Recover) => (1.0, 1.0, anim_time.powi(4)), + _ => (0.0, 0.0, 0.0), + }; + let pullback = 1.0 - move3; + let move1 = move1base * pullback; + let move2 = move2base * pullback; + next.control_l.position = Vec3::new(-5.0, -2.0 + move2 * -7.0, -3.0); + next.control_r.position = Vec3::new(4.0, 4.0, 1.0); - next.control.position = Vec3::new( - -1.0 + move1 * 2.0, - 6.0 + s_a.grip.0 / 1.2 + move1 * 7.0, - -5.0 + -s_a.grip.0 / 2.0 + move1 * s_a.height * 3.4, - ); + next.control.position = Vec3::new( + -1.0 + move1 * 2.0, + 6.0 + s_a.grip.0 / 1.2 + move1 * 7.0, + -5.0 + -s_a.grip.0 / 2.0 + move1 * s_a.height * 1.5, + ); - next.control_l.orientation = - Quaternion::rotation_x(move1 * 0.2 + PI / 2.0 + move2 * 0.4) - * Quaternion::rotation_y(-0.2); - next.control_r.orientation = Quaternion::rotation_x(PI / 2.2 + move1 * 0.4) - * Quaternion::rotation_y(0.4) - * Quaternion::rotation_z(0.0); + next.control_l.orientation = + Quaternion::rotation_x(move1 * 0.2 + PI / 2.0 + move2 * 0.4) + * Quaternion::rotation_y(-0.2); + next.control_r.orientation = Quaternion::rotation_x(PI / 2.2 + move1 * 0.4) + * Quaternion::rotation_y(0.4) + * Quaternion::rotation_z(0.0); - next.control.orientation = Quaternion::rotation_x(-0.2) - * Quaternion::rotation_y(1.0 + move1 * -0.4) - * Quaternion::rotation_z(-0.1); - next.head.orientation = Quaternion::rotation_z(move1 * 0.25); - next.shoulder_l.position = Vec3::new( - -s_a.shoulder.0, - s_a.shoulder.1, - s_a.shoulder.2 - foothorir * 1.0, - ); - next.shoulder_l.orientation = - Quaternion::rotation_x(move1 * 1.2 + 1.2 * speednorm + (footrotr * -0.2)); + next.control.orientation = Quaternion::rotation_x(-0.2) + * Quaternion::rotation_y(2.0 + move1 * -0.4) + * Quaternion::rotation_z(0.1); + next.head.orientation = Quaternion::rotation_z(move1 * 0.25); + next.shoulder_l.position = Vec3::new( + -s_a.shoulder.0, + s_a.shoulder.1, + s_a.shoulder.2 - foothorir * 1.0, + ); + next.shoulder_l.orientation = + Quaternion::rotation_x(move1 * 1.2 + 1.2 * speednorm + (footrotr * -0.2)); - next.shoulder_r.position = Vec3::new( - s_a.shoulder.0, - s_a.shoulder.1, - s_a.shoulder.2 - foothoril * 1.0, - ); - next.shoulder_r.orientation = - Quaternion::rotation_x(move1 * 0.8 + 1.2 * speednorm + (footrotl * -0.2)); + next.shoulder_r.position = Vec3::new( + s_a.shoulder.0, + s_a.shoulder.1, + s_a.shoulder.2 - foothoril * 1.0, + ); + next.shoulder_r.orientation = + Quaternion::rotation_x(move1 * 0.8 + 1.2 * speednorm + (footrotl * -0.2)); + }, + _ => { + let (move1base, move2base, move3) = match stage_section { + Some(StageSection::Buildup) => (anim_time.powf(0.25), 0.0, 0.0), + Some(StageSection::Action) => (1.0, anim_time, 0.0), + Some(StageSection::Recover) => (1.0, 1.0, anim_time.powi(4)), + _ => (0.0, 0.0, 0.0), + }; + let pullback = 1.0 - move3; + let move1 = move1base * pullback; + let move2 = move2base * pullback; + next.control_l.position = Vec3::new(-1.0, -2.0 + move2 * -7.0, -3.0); + next.control_r.position = Vec3::new(0.0, 4.0, 1.0); + + next.control.position = Vec3::new( + -1.0 + move1 * 2.0, + 6.0 + s_a.grip.0 / 1.2 + move1 * 7.0, + -5.0 + -s_a.grip.0 / 2.0 + move1 * s_a.height * 3.4, + ); + + next.control_l.orientation = + Quaternion::rotation_x(move1 * 0.2 + PI / 2.0 + move2 * 0.4) + * Quaternion::rotation_y(-0.2); + next.control_r.orientation = Quaternion::rotation_x(PI / 2.2 + move1 * 0.4) + * Quaternion::rotation_y(0.4) + * Quaternion::rotation_z(0.0); + + next.control.orientation = Quaternion::rotation_x(-0.2) + * Quaternion::rotation_y(1.0 + move1 * -0.4) + * Quaternion::rotation_z(-0.1); + next.head.orientation = Quaternion::rotation_z(move1 * 0.25); + next.shoulder_l.position = Vec3::new( + -s_a.shoulder.0, + s_a.shoulder.1, + s_a.shoulder.2 - foothorir * 1.0, + ); + next.shoulder_l.orientation = + Quaternion::rotation_x(move1 * 1.2 + 1.2 * speednorm + (footrotr * -0.2)); + + next.shoulder_r.position = Vec3::new( + s_a.shoulder.0, + s_a.shoulder.1, + s_a.shoulder.2 - foothoril * 1.0, + ); + next.shoulder_r.orientation = + Quaternion::rotation_x(move1 * 0.8 + 1.2 * speednorm + (footrotl * -0.2)); + }, }, Some(ToolKind::Axe) => { let (move1base, move2, move3) = match stage_section { @@ -439,6 +489,64 @@ impl Animation for ShootAnimation { //* Quaternion::rotation_z(move1 * -PI/2.0); next.arm_control_r.position = Vec3::new(0.0, move1 * 10.0 + move2 * -10.0, 0.0); }, + Some("common.abilities.custom.terracotta_demolisher.throw") => { + let (move1, move2, move3) = match stage_section { + Some(StageSection::Buildup) => (anim_time.powf(0.25), 0.0, 0.0), + Some(StageSection::Action) => (1.0, anim_time, 0.0), + Some(StageSection::Recover) => (1.0, 1.0, anim_time.powi(4)), + _ => (0.0, 0.0, 0.0), + }; + next.head.orientation = Quaternion::rotation_x(move1 * 0.4); + next.control_l.position = Vec3::new(-0.5, 4.0, 1.0); + next.control_r.position = Vec3::new(-0.5, 4.0, 1.0); + next.control_l.orientation = Quaternion::rotation_x(PI / 1.5); + next.control_r.orientation = Quaternion::rotation_x(PI / 1.5); + next.weapon_l.position = Vec3::new(-9.0, 5.0, 0.0); + next.weapon_r.position = Vec3::new(9.0, 5.0, 0.0); + + next.weapon_l.orientation = Quaternion::rotation_x(-PI / 2.0 - 0.1); + next.weapon_r.orientation = Quaternion::rotation_x(-PI / 2.0 - 0.1); + + let twist = move1 * 0.8 + move3 * -0.8; + next.upper_torso.position = + Vec3::new(0.0, s_a.upper_torso.0, s_a.upper_torso.1); + next.upper_torso.orientation = + Quaternion::rotation_x(move1 * 0.8 + move2 * -1.1) + * Quaternion::rotation_z(twist * -0.2 + move1 * -0.1 + move2 * 0.3); + + next.lower_torso.orientation = + Quaternion::rotation_x(move1 * -0.8 + move2 * 1.1) + * Quaternion::rotation_z(twist); + + next.arm_control_r.orientation = Quaternion::rotation_x(move1 * PI / 2.0) + * Quaternion::rotation_y(move1 * -PI / 3.0 + move2 * 1.5); + next.arm_control_r.position = Vec3::new(0.0, move1 * 1.0 + move2 * -1.0, 0.0); + }, + Some("common.abilities.custom.terracotta_demolisher.drop") => { + let (move1base, move2base, move3) = match stage_section { + Some(StageSection::Buildup) => (anim_time.powf(0.25), 0.0, 0.0), + Some(StageSection::Action) => (1.0, anim_time, 0.0), + Some(StageSection::Recover) => (1.0, 1.0, anim_time.powi(4)), + _ => (0.0, 0.0, 0.0), + }; + let pullback = 1.0 - move3; + let move1 = move1base * pullback; + let move2 = move2base * pullback; + next.main.position = Vec3::new(-10.0, -8.0, 12.0); + next.main.orientation = + Quaternion::rotation_y(2.5) * Quaternion::rotation_z(PI / 2.0); + next.hand_l.position = Vec3::new(-s_a.hand.0, s_a.hand.1 + 4.0, s_a.hand.2); + next.hand_r.position = Vec3::new(s_a.hand.0, s_a.hand.1 + 4.0, s_a.hand.2); + next.hand_l.orientation = Quaternion::rotation_x(move1 * 1.5) + * Quaternion::rotation_y(move1 * -1.0 + move2 * 1.5); + next.hand_r.orientation = Quaternion::rotation_x(move1 * 1.5) + * Quaternion::rotation_y(move1 * 1.0 + move2 * -1.5); + next.upper_torso.orientation = + Quaternion::rotation_y(move1 * -0.1 + move2 * 0.1) + * Quaternion::rotation_z(move1 * -0.1 + move2 * 0.1); + next.foot_l.orientation = Quaternion::rotation_y(move1 * 0.3 + move2 * -0.3); + next.foot_r.orientation = Quaternion::rotation_y(move1 * 0.3 + move2 * -0.3); + }, Some("common.abilities.custom.harvester.explodingpumpkin") => { let (move1, move2, move3) = match stage_section { Some(StageSection::Buildup) => (anim_time.powf(0.25), 0.0, 0.0), diff --git a/voxygen/anim/src/biped_large/spritesummon.rs b/voxygen/anim/src/biped_large/spritesummon.rs index 4d9f8d0e22..f3252e97a5 100644 --- a/voxygen/anim/src/biped_large/spritesummon.rs +++ b/voxygen/anim/src/biped_large/spritesummon.rs @@ -54,7 +54,7 @@ impl Animation for SpriteSummonAnimation { next.hand_r.orientation = Quaternion::rotation_x(0.0); match active_tool_kind { - Some(ToolKind::Axe) => { + Some(ToolKind::Axe | ToolKind::Sceptre) => { let (move1base, move2, move3) = match stage_section { Some(StageSection::Buildup) => ((anim_time.powf(0.25)), 0.0, 0.0), Some(StageSection::Action) => (1.0, (anim_time), 0.0), diff --git a/voxygen/anim/src/biped_large/summon.rs b/voxygen/anim/src/biped_large/summon.rs index 34695047c7..c8b82add65 100644 --- a/voxygen/anim/src/biped_large/summon.rs +++ b/voxygen/anim/src/biped_large/summon.rs @@ -121,6 +121,48 @@ impl Animation for SummonAnimation { next.control.orientation = Quaternion::rotation_x(-0.2 + move1 * 1.0) * Quaternion::rotation_y(-0.1 + move2 * -0.8); }, + Some(ToolKind::Sceptre) => { + next.shoulder_l.position = Vec3::new( + -s_a.shoulder.0, + s_a.shoulder.1, + s_a.shoulder.2 - foothorir * 1.0, + ); + next.shoulder_l.orientation = Quaternion::rotation_x( + move1 * 0.8 + 0.6 * speednorm + (footrotr * -0.2) * speednorm, + ); + + next.shoulder_r.position = Vec3::new( + s_a.shoulder.0, + s_a.shoulder.1, + s_a.shoulder.2 - foothoril * 1.0, + ); + next.shoulder_r.orientation = Quaternion::rotation_x( + move1 * 0.8 + 0.6 * speednorm + (footrotl * -0.2) * speednorm, + ); + next.head.orientation = Quaternion::rotation_x(0.0); + next.control_l.position = Vec3::new(-1.0, 3.0, 12.0); + next.control_r.position = Vec3::new( + 1.0 + move1 * 3.0 + move2 * 20.0, + 2.0 + move1 * -5.0 + move2 * 5.0, + 2.0 + move1 * 15.0 + move2 * 0.0, + ); + + next.control.position = Vec3::new( + -3.0 + move2 * 9.0, + 3.0 + s_a.grip.0 / 1.2 + move1 * 8.0 + move2 * 2.0, + -11.0 + -s_a.grip.0 / 2.0 + move1 * 8.0 + move2 * -12.0, + ); + + next.control_l.orientation = Quaternion::rotation_x(PI / 2.0 - move1 * 0.2) + * Quaternion::rotation_y(-0.5 + move2 * -0.4) + * Quaternion::rotation_z(move1 * 0.0); + next.control_r.orientation = Quaternion::rotation_x(PI / 2.5 + move1 * 0.2) + * Quaternion::rotation_y(0.5 + move1 * 0.5 + move2 * 0.0) + * Quaternion::rotation_z(move1 * 0.5 + move2 * 0.8); + + next.control.orientation = Quaternion::rotation_x(-0.2 + move1 * 1.0) + * Quaternion::rotation_y(-0.1 + move2 * -0.8); + }, Some(ToolKind::Natural) => match ability_id { Some("common.abilities.custom.tidalwarrior.totem") => { let (move1base, move2base, move3) = match stage_section { diff --git a/voxygen/anim/src/biped_large/wield.rs b/voxygen/anim/src/biped_large/wield.rs index 4279bc3431..91b86661a3 100644 --- a/voxygen/anim/src/biped_large/wield.rs +++ b/voxygen/anim/src/biped_large/wield.rs @@ -497,7 +497,7 @@ impl Animation for WieldAnimation { next.shoulder_r.orientation = Quaternion::rotation_y(0.4) * Quaternion::rotation_x(0.4); }, - "Husk Brute" => { + "Husk Brute" | "TerracottaDemolisher" => { if speed > 0.1 { next.hand_l.position = Vec3::new(-s_a.hand.0, s_a.hand.1, s_a.hand.2); diff --git a/voxygen/anim/src/biped_small/combomelee.rs b/voxygen/anim/src/biped_small/combomelee.rs index 17f72776ec..3a4d51de3b 100644 --- a/voxygen/anim/src/biped_small/combomelee.rs +++ b/voxygen/anim/src/biped_small/combomelee.rs @@ -78,7 +78,7 @@ impl Animation for ComboAnimation { }, Some( "common.abilities.axesimple.doublestrike" - | "common.abilities.custom.boreal_warrior.hammer", + | "common.abilities.custom.boreal_warrior.hammer.singlestrike", ) => { let anim_time = anim_time.min(1.0); let (move1base, move2base, move3) = match stage_section { diff --git a/voxygen/anim/src/biped_small/mod.rs b/voxygen/anim/src/biped_small/mod.rs index 677682bd84..6e28435b93 100644 --- a/voxygen/anim/src/biped_small/mod.rs +++ b/voxygen/anim/src/biped_small/mod.rs @@ -10,6 +10,7 @@ pub mod ripostemelee; pub mod run; pub mod shockwave; pub mod shoot; +pub mod spritesummon; pub mod stunned; pub mod summon; pub mod wield; @@ -19,8 +20,8 @@ pub use self::{ alpha::AlphaAnimation, beam::BeamAnimation, block::BlockAnimation, combomelee::ComboAnimation, dash::DashAnimation, idle::IdleAnimation, leapmelee::LeapAnimation, rapidmelee::RapidMeleeAnimation, ripostemelee::RiposteMeleeAnimation, run::RunAnimation, - shockwave::ShockwaveAnimation, shoot::ShootAnimation, stunned::StunnedAnimation, - summon::SummonAnimation, wield::WieldAnimation, + shockwave::ShockwaveAnimation, shoot::ShootAnimation, spritesummon::SpriteSummonAnimation, + stunned::StunnedAnimation, summon::SummonAnimation, wield::WieldAnimation, }; use super::{make_bone, vek::*, FigureBoneData, Offsets, Skeleton}; @@ -164,6 +165,8 @@ impl<'a> From<&'a Body> for SkeletonAttr { (Irrwurz, _) => (-1.0, 9.0), (Clockwork, _) => (3.0, 3.5), (Flamekeeper, _) => (3.0, 3.5), + (ShamanicSpirit, _) => (-0.5, 4.5), + (Jiangshi, _) => (-1.0, 6.5), }, chest: match (body.species, body.body_type) { (Gnome, _) => (0.0, 9.0), @@ -182,6 +185,8 @@ impl<'a> From<&'a Body> for SkeletonAttr { (Irrwurz, _) => (0.0, 6.0), (Clockwork, _) => (0.0, 14.0), (Flamekeeper, _) => (0.0, 14.0), + (ShamanicSpirit, _) => (0.0, 14.5), + (Jiangshi, _) => (0.0, 14.0), }, pants: match (body.species, body.body_type) { (Gnome, _) => (0.0, -3.0), @@ -200,6 +205,8 @@ impl<'a> From<&'a Body> for SkeletonAttr { (Irrwurz, _) => (-5.5, -0.5), (Clockwork, _) => (-1.0, -8.0), (Flamekeeper, _) => (-1.0, -8.0), + (ShamanicSpirit, _) => (0.0, -8.0), + (Jiangshi, _) => (0.5, -6.0), }, tail: match (body.species, body.body_type) { (Gnome, _) => (0.0, 0.0), @@ -218,6 +225,8 @@ impl<'a> From<&'a Body> for SkeletonAttr { (Irrwurz, _) => (0.0, -1.0), (Clockwork, _) => (0.0, 0.0), (Flamekeeper, _) => (0.0, 0.0), + (ShamanicSpirit, _) => (0.0, 0.0), + (Jiangshi, _) => (0.0, 0.0), }, hand: match (body.species, body.body_type) { (Gnome, _) => (4.0, 0.5, -1.0), @@ -236,6 +245,8 @@ impl<'a> From<&'a Body> for SkeletonAttr { (Irrwurz, _) => (3.5, 2.0, 3.0), (Clockwork, _) => (4.0, 1.5, -3.5), (Flamekeeper, _) => (4.0, 1.5, -3.5), + (ShamanicSpirit, _) => (5.0, 0.0, 1.0), + (Jiangshi, _) => (5.0, -1.0, 3.0), }, foot: match (body.species, body.body_type) { (Gnome, _) => (3.0, 0.0, 4.0), @@ -254,6 +265,8 @@ impl<'a> From<&'a Body> for SkeletonAttr { (Irrwurz, _) => (4.0, 0.0, 6.0), (Clockwork, _) => (3.5, 3.0, 7.0), (Flamekeeper, _) => (3.5, 3.0, 7.0), + (ShamanicSpirit, _) => (3.5, 3.0, 7.0), + (Jiangshi, _) => (3.0, 0.0, 8.0), }, grip: match (body.species, body.body_type) { (Gnome, _) => (0.0, 0.0, 5.0), @@ -272,6 +285,8 @@ impl<'a> From<&'a Body> for SkeletonAttr { (Irrwurz, _) => (0.0, 0.0, 7.0), (Clockwork, _) => (0.0, 0.0, 8.0), (Flamekeeper, _) => (0.0, 0.0, 8.0), + (ShamanicSpirit, _) => (0.0, 0.0, 8.0), + (Jiangshi, _) => (0.0, 0.0, 8.0), }, scaler: match (body.species, body.body_type) { (Gnome, _) => 0.8, @@ -290,6 +305,8 @@ impl<'a> From<&'a Body> for SkeletonAttr { (Irrwurz, _) => 1.0, (Clockwork, _) => 1.5, (Flamekeeper, _) => 4.0, + (ShamanicSpirit, _) => 1.0, + (Jiangshi, _) => 1.0, }, } } diff --git a/voxygen/anim/src/biped_small/spritesummon.rs b/voxygen/anim/src/biped_small/spritesummon.rs new file mode 100644 index 0000000000..96b87f477c --- /dev/null +++ b/voxygen/anim/src/biped_small/spritesummon.rs @@ -0,0 +1,86 @@ +use super::{ + super::{vek::*, Animation}, + BipedSmallSkeleton, SkeletonAttr, +}; +use common::{comp::item::ToolKind, states::utils::StageSection}; + +pub struct SpriteSummonAnimation; + +type SpriteSummonAnimationDependency = ( + Option, + Vec3, + Vec3, + Vec3, + f32, + Vec3, + f32, + Option, + f32, +); + +impl Animation for SpriteSummonAnimation { + type Dependency<'a> = SpriteSummonAnimationDependency; + type Skeleton = BipedSmallSkeleton; + + #[cfg(feature = "use-dyn-lib")] + const UPDATE_FN: &'static [u8] = b"biped_small_spritesummon\0"; + + #[cfg_attr(feature = "be-dyn-lib", export_name = "biped_small_spritesummon")] + + fn update_skeleton_inner( + skeleton: &Self::Skeleton, + ( + active_tool_kind, + _velocity, + _orientation, + _last_ori, + global_time, + _avg_vel, + _acc_vel, + stage_section, + timer, + ): Self::Dependency<'_>, + anim_time: f32, + _rate: &mut f32, + s_a: &SkeletonAttr, + ) -> Self::Skeleton { + let mut next = (*skeleton).clone(); + + let anim_time = anim_time.min(1.0); + let (move1base, twitch, move2base, move3) = match stage_section { + Some(StageSection::Buildup) => (anim_time.sqrt(), (anim_time * 13.0).sin(), 0.0, 0.0), + Some(StageSection::Action) => (1.0, 1.0, anim_time.powi(4), 0.0), + Some(StageSection::Recover) => (1.0, 1.0, 1.0, anim_time), + _ => (0.0, 0.0, 0.0, 0.0), + }; + let pullback = 1.0 - move3; + let twitch = twitch * pullback; + let subtract = global_time - timer; + let check = subtract - subtract.trunc(); + let mirror = (check - 0.5).signum(); + let move1 = move1base * pullback * mirror; + let move2 = move2base * pullback * mirror; + let move1abs = move1base * pullback; + let move2abs = move2base * pullback; + next.hand_l.position = Vec3::new(s_a.grip.0 * 4.0, 0.0, s_a.grip.2); + next.hand_r.position = Vec3::new(-s_a.grip.0 * 4.0, 0.0, s_a.grip.2); + next.main.orientation = Quaternion::rotation_x(0.0); + next.hand_l.orientation = Quaternion::rotation_x(0.0); + next.hand_r.orientation = Quaternion::rotation_x(0.0); + match active_tool_kind { + Some(ToolKind::Natural) => { + next.head.orientation = + Quaternion::rotation_x(move1abs * 0.5) * Quaternion::rotation_y(twitch * 0.5); + next.chest.orientation = Quaternion::rotation_x(move1abs * 0.5 + move2abs * -1.0) + * Quaternion::rotation_z(move1 * 1.2 + move2 * -1.8); + next.hand_l.position = Vec3::new(-s_a.hand.0, s_a.hand.1, s_a.hand.2); + next.hand_l.orientation = Quaternion::rotation_x(1.2); + next.hand_r.position = Vec3::new(s_a.hand.0, s_a.hand.1, s_a.hand.2); + next.hand_r.orientation = Quaternion::rotation_x(1.2); + next.main.position = Vec3::new(0.0, 10.0 + 5.0 * move1abs, 4.0 + 4.0 * move1abs); + }, + _ => {}, + } + next + } +} diff --git a/voxygen/anim/src/biped_small/wield.rs b/voxygen/anim/src/biped_small/wield.rs index f39055a5eb..12188cff49 100644 --- a/voxygen/anim/src/biped_small/wield.rs +++ b/voxygen/anim/src/biped_small/wield.rs @@ -3,13 +3,13 @@ use super::{ biped_small_wield_bow, biped_small_wield_spear, biped_small_wield_sword, BipedSmallSkeleton, SkeletonAttr, }; -use common::comp::item::ToolKind; +use common::comp::item::tool::{AbilitySpec, ToolKind}; use std::f32::consts::PI; pub struct WieldAnimation; -type WieldAnimationDependency = ( - Option, +type WieldAnimationDependency<'a> = ( + (Option, Option<&'a AbilitySpec>), Vec3, Vec3, Vec3, @@ -19,7 +19,7 @@ type WieldAnimationDependency = ( ); impl Animation for WieldAnimation { - type Dependency<'a> = WieldAnimationDependency; + type Dependency<'a> = WieldAnimationDependency<'a>; type Skeleton = BipedSmallSkeleton; #[cfg(feature = "use-dyn-lib")] @@ -29,7 +29,15 @@ impl Animation for WieldAnimation { fn update_skeleton_inner( skeleton: &Self::Skeleton, - (active_tool_kind, velocity, _orientation, _last_ori, _global_time, _avg_vel, acc_vel): Self::Dependency<'_>, + ( + (active_tool_kind, active_tool_spec), + velocity, + _orientation, + _last_ori, + _global_time, + _avg_vel, + acc_vel, + ): Self::Dependency<'_>, anim_time: f32, _rate: &mut f32, s_a: &SkeletonAttr, @@ -155,6 +163,25 @@ impl Animation for WieldAnimation { Some(ToolKind::Dagger | ToolKind::Sword) => { biped_small_wield_sword(&mut next, s_a, speednorm, slow); }, + Some(ToolKind::Natural) => { + if let Some(AbilitySpec::Custom(spec)) = active_tool_spec { + match spec.as_str() { + "ShamanicSpirit" => { + next.hand_l.position = Vec3::new(-s_a.hand.0, s_a.hand.1, s_a.hand.2); + next.hand_l.orientation = Quaternion::rotation_x(1.2); + next.hand_r.position = Vec3::new(s_a.hand.0, s_a.hand.1, s_a.hand.2); + next.hand_r.orientation = Quaternion::rotation_x(1.2); + next.main.position = Vec3::new(0.0, 12.0, 5.0); + }, + _ => { + next.hand_l.position = Vec3::new(-s_a.hand.0, s_a.hand.1, s_a.hand.2); + next.hand_l.orientation = Quaternion::rotation_x(1.2); + next.hand_r.position = Vec3::new(s_a.hand.0, s_a.hand.1, s_a.hand.2); + next.hand_r.orientation = Quaternion::rotation_x(1.2); + }, + } + } + }, _ => { next.hand_l.position = Vec3::new(-s_a.hand.0, s_a.hand.1, s_a.hand.2); next.hand_l.orientation = Quaternion::rotation_x(1.2); diff --git a/voxygen/anim/src/character/music.rs b/voxygen/anim/src/character/music.rs index 375eaf1275..c2d8c19451 100644 --- a/voxygen/anim/src/character/music.rs +++ b/voxygen/anim/src/character/music.rs @@ -119,7 +119,8 @@ impl Animation for MusicAnimation { "common.abilities.music.lyre" | "common.abilities.music.icy_talharpa" | "common.abilities.music.shamisen" - | "common.abilities.music.kalimba", + | "common.abilities.music.kalimba" + | "common.abilities.music.steeltonguedrum", ) => 0.3, _ => 1.0, }; @@ -202,7 +203,7 @@ impl Animation for MusicAnimation { Some( "common.abilities.music.lyre" | "common.abilities.music.wildskin_drum" - | "common.abilities.music.steeldrum" + | "common.abilities.music.steeltonguedrum" | "common.abilities.music.icy_talharpa", ) => { next.hand_l.position = Vec3::new( diff --git a/voxygen/anim/src/character/wield.rs b/voxygen/anim/src/character/wield.rs index 71b24c7c69..899da75366 100644 --- a/voxygen/anim/src/character/wield.rs +++ b/voxygen/anim/src/character/wield.rs @@ -281,7 +281,7 @@ impl Animation for WieldAnimation { Some(ToolKind::Instrument) => { if let Some(AbilitySpec::Custom(spec)) = active_tool_spec { match spec.as_str() { - "Lyre" | "IcyTalharpa" | "WildskinDrum" | "Steeldrum" => { + "Lyre" | "IcyTalharpa" | "WildskinDrum" | "Steeltonguedrum" => { if speed < 0.5 { next.head.orientation = Quaternion::rotation_z(head_look.x) * Quaternion::rotation_x( diff --git a/voxygen/anim/src/golem/beam.rs b/voxygen/anim/src/golem/beam.rs index 5949bef641..bab0062b78 100644 --- a/voxygen/anim/src/golem/beam.rs +++ b/voxygen/anim/src/golem/beam.rs @@ -6,7 +6,7 @@ use common::{states::utils::StageSection, util::Dir}; pub struct BeamAnimation; impl Animation for BeamAnimation { - type Dependency<'a> = (Option, f32, f32, Dir); + type Dependency<'a> = (Option, f32, f32, Dir, Option<&'a str>); type Skeleton = GolemSkeleton; #[cfg(feature = "use-dyn-lib")] @@ -16,7 +16,7 @@ impl Animation for BeamAnimation { fn update_skeleton_inner( skeleton: &Self::Skeleton, - (stage_section, _global_time, _timer, look_dir): Self::Dependency<'_>, + (stage_section, _global_time, _timer, look_dir, ability_id): Self::Dependency<'_>, anim_time: f32, _rate: &mut f32, s_a: &SkeletonAttr, @@ -34,41 +34,50 @@ impl Animation for BeamAnimation { let move1 = move1base * pullback; let move2 = move2base * pullback; - next.head.orientation = Quaternion::rotation_x(move1iso * 0.5 + move2 * (look_dir.z * 1.0)); - next.head.position = Vec3::new( - 0.0, - s_a.head.0, - s_a.head.1 - move2 * 5.0 * (look_dir.z * 1.0).min(0.0), - ); + match ability_id { + Some("common.abilities.custom.mogwai.breathe") => { + next.jaw.orientation = Quaternion::rotation_x(-0.3 * move1); + }, + _ => { + next.head.orientation = + Quaternion::rotation_x(move1iso * 0.5 + move2 * (look_dir.z * 1.0)); + next.head.position = Vec3::new( + 0.0, + s_a.head.0, + s_a.head.1 - move2 * 5.0 * (look_dir.z * 1.0).min(0.0), + ); - next.upper_torso.orientation = - Quaternion::rotation_x(move1iso * 0.3) * Quaternion::rotation_z(0.0); + next.upper_torso.orientation = + Quaternion::rotation_x(move1iso * 0.3) * Quaternion::rotation_z(0.0); - next.lower_torso.orientation = - Quaternion::rotation_z(0.0) * Quaternion::rotation_x(move1iso * -0.3); + next.lower_torso.orientation = + Quaternion::rotation_z(0.0) * Quaternion::rotation_x(move1iso * -0.3); - next.shoulder_l.orientation = - Quaternion::rotation_x(move1 * 0.8) * Quaternion::rotation_y(move1 * -0.5); + next.shoulder_l.orientation = + Quaternion::rotation_x(move1 * 0.8) * Quaternion::rotation_y(move1 * -0.5); - next.shoulder_r.orientation = - Quaternion::rotation_x(move1 * 0.8) * Quaternion::rotation_y(move1 * 0.5); - next.shoulder_l.position = Vec3::new( - -s_a.shoulder.0, - s_a.shoulder.1 + move1 * 2.0, - s_a.shoulder.2 + move1 * -2.0, - ); - next.shoulder_r.position = Vec3::new( - s_a.shoulder.0, - s_a.shoulder.1 + move1 * 2.0, - s_a.shoulder.2 + move1 * -2.0, - ); + next.shoulder_r.orientation = + Quaternion::rotation_x(move1 * 0.8) * Quaternion::rotation_y(move1 * 0.5); + next.shoulder_l.position = Vec3::new( + -s_a.shoulder.0, + s_a.shoulder.1 + move1 * 2.0, + s_a.shoulder.2 + move1 * -2.0, + ); + next.shoulder_r.position = Vec3::new( + s_a.shoulder.0, + s_a.shoulder.1 + move1 * 2.0, + s_a.shoulder.2 + move1 * -2.0, + ); - next.hand_l.orientation = - Quaternion::rotation_z(0.0) * Quaternion::rotation_y(move1 * -1.1); + next.hand_l.orientation = + Quaternion::rotation_z(0.0) * Quaternion::rotation_y(move1 * -1.1); - next.hand_r.orientation = Quaternion::rotation_y(0.0) * Quaternion::rotation_y(move1 * 1.1); + next.hand_r.orientation = + Quaternion::rotation_y(0.0) * Quaternion::rotation_y(move1 * 1.1); - next.torso.position = Vec3::new(0.0, 0.0, 0.0); + next.torso.position = Vec3::new(0.0, 0.0, 0.0); + }, + } next } } diff --git a/voxygen/anim/src/golem/mod.rs b/voxygen/anim/src/golem/mod.rs index 7865bff60a..b44ae7021c 100644 --- a/voxygen/anim/src/golem/mod.rs +++ b/voxygen/anim/src/golem/mod.rs @@ -141,6 +141,7 @@ impl<'a> From<&'a Body> for SkeletonAttr { (CoralGolem, _) => (-1.0, 3.0), (Gravewarden, _) => (-2.0, 7.0), (AncientEffigy, _) => (-2.0, 8.0), + (Mogwai, _) => (-8.0, 2.0), }, jaw: match (body.species, body.body_type) { (StoneGolem, _) => (0.0, 0.0), @@ -150,6 +151,7 @@ impl<'a> From<&'a Body> for SkeletonAttr { (CoralGolem, _) => (0.0, 0.0), (Gravewarden, _) => (0.0, 0.0), (AncientEffigy, _) => (0.0, 0.0), + (Mogwai, _) => (-6.0, -5.0), }, upper_torso: match (body.species, body.body_type) { (StoneGolem, _) => (0.0, 34.5), @@ -159,6 +161,7 @@ impl<'a> From<&'a Body> for SkeletonAttr { (CoralGolem, _) => (0.0, 25.0), (Gravewarden, _) => (0.0, 26.5), (AncientEffigy, _) => (0.0, 18.0), + (Mogwai, _) => (0.0, 18.0), }, lower_torso: match (body.species, body.body_type) { (StoneGolem, _) => (0.0, -10.5), @@ -168,6 +171,7 @@ impl<'a> From<&'a Body> for SkeletonAttr { (CoralGolem, _) => (0.0, -11.5), (Gravewarden, _) => (0.0, -4.5), (AncientEffigy, _) => (0.0, -4.5), + (Mogwai, _) => (0.0, -4.5), }, shoulder: match (body.species, body.body_type) { (StoneGolem, _) => (8.0, -1.5, 4.0), @@ -177,6 +181,7 @@ impl<'a> From<&'a Body> for SkeletonAttr { (CoralGolem, _) => (11.0, 1.0, 0.0), (Gravewarden, _) => (8.0, 2.0, 3.0), (AncientEffigy, _) => (8.0, 2.0, 3.0), + (Mogwai, _) => (8.0, 2.0, 3.0), }, hand: match (body.species, body.body_type) { (StoneGolem, _) => (12.5, -1.0, -7.0), @@ -186,6 +191,7 @@ impl<'a> From<&'a Body> for SkeletonAttr { (CoralGolem, _) => (2.5, -1.5, -5.0), (Gravewarden, _) => (8.5, -1.0, -7.0), (AncientEffigy, _) => (8.5, -1.0, -7.0), + (Mogwai, _) => (8.5, -1.0, -7.0), }, leg: match (body.species, body.body_type) { (StoneGolem, _) => (4.0, 0.0, -3.5), @@ -195,6 +201,7 @@ impl<'a> From<&'a Body> for SkeletonAttr { (CoralGolem, _) => (2.5, 0.5, -3.0), (Gravewarden, _) => (1.0, 0.5, -6.0), (AncientEffigy, _) => (1.0, 0.5, -6.0), + (Mogwai, _) => (1.0, 0.5, -6.0), }, foot: match (body.species, body.body_type) { (StoneGolem, _) => (3.5, 0.5, -9.5), @@ -204,6 +211,7 @@ impl<'a> From<&'a Body> for SkeletonAttr { (CoralGolem, _) => (2.5, 1.0, -1.5), (Gravewarden, _) => (3.5, -1.0, -8.5), (AncientEffigy, _) => (3.5, -1.0, -8.5), + (Mogwai, _) => (3.5, -1.0, -8.5), }, scaler: match (body.species, body.body_type) { (StoneGolem, _) => 1.5, @@ -213,6 +221,7 @@ impl<'a> From<&'a Body> for SkeletonAttr { (CoralGolem, _) => 1.0, (Gravewarden, _) => 1.5, (AncientEffigy, _) => 1.0, + (Mogwai, _) => 1.0, }, tempo: match (body.species, body.body_type) { (StoneGolem, _) => 1.0, @@ -222,6 +231,7 @@ impl<'a> From<&'a Body> for SkeletonAttr { (CoralGolem, _) => 1.0, (Gravewarden, _) => 1.0, (AncientEffigy, _) => 1.0, + (Mogwai, _) => 1.0, }, } } diff --git a/voxygen/src/audio/sfx/mod.rs b/voxygen/src/audio/sfx/mod.rs index 1e824446ee..a0890a27a3 100644 --- a/voxygen/src/audio/sfx/mod.rs +++ b/voxygen/src/audio/sfx/mod.rs @@ -86,7 +86,7 @@ use client::Client; use common::{ assets::{self, AssetExt, AssetHandle}, comp::{ - beam, biped_large, biped_small, bird_large, humanoid, + beam, biped_large, biped_small, bird_large, golem, humanoid, item::{item_key::ItemKey, AbilitySpec, ItemDefinitionId, ItemKind, ToolKind}, object, poise::PoiseState, @@ -166,6 +166,7 @@ pub enum SfxEvent { Utterance(UtteranceKind, VoiceKind), Lightning, CyclopsCharge, + TerracottaStatueCharge, LaserBeam, Steam, FuseCharge, @@ -469,7 +470,8 @@ impl SfxMgr { let sfx_trigger_item = triggers.get_key_value(&SfxEvent::CyclopsCharge); audio.emit_sfx(sfx_trigger_item, *pos, Some(2.0), underwater); }, - Outcome::FlamethrowerCharge { pos, .. } => { + Outcome::FlamethrowerCharge { pos, .. } + | Outcome::TerracottaStatueCharge { pos, .. } => { let sfx_trigger_item = triggers.get_key_value(&SfxEvent::CyclopsCharge); audio.emit_sfx(sfx_trigger_item, *pos, Some(2.0), underwater); }, @@ -492,6 +494,29 @@ impl SfxMgr { let sfx_trigger_item = triggers.get_key_value(&SfxEvent::GigaRoar); audio.emit_sfx(sfx_trigger_item, *pos, Some(2.0), underwater); }, + biped_small::Species::ShamanicSpirit | biped_small::Species::Jiangshi => { + let sfx_trigger_item = triggers.get_key_value(&SfxEvent::Klonk); + audio.emit_sfx(sfx_trigger_item, *pos, Some(2.0), underwater); + }, + _ => {}, + }, + Body::BipedLarge(body) => match body.species { + biped_large::Species::Cursekeeper => { + let sfx_trigger_item = triggers.get_key_value(&SfxEvent::Swoosh); + audio.emit_sfx(sfx_trigger_item, *pos, Some(2.0), underwater); + }, + biped_large::Species::TerracottaBesieger + | biped_large::Species::TerracottaPursuer => { + let sfx_trigger_item = triggers.get_key_value(&SfxEvent::Klonk); + audio.emit_sfx(sfx_trigger_item, *pos, Some(2.0), underwater); + }, + _ => {}, + }, + Body::Golem(body) => match body.species { + golem::Species::Mogwai => { + let sfx_trigger_item = triggers.get_key_value(&SfxEvent::Klonk); + audio.emit_sfx(sfx_trigger_item, *pos, Some(2.0), underwater); + }, _ => {}, }, Body::Object(object::Body::Flamethrower) => { @@ -547,6 +572,7 @@ impl SfxMgr { | object::Body::ArrowSnake | object::Body::ArrowTurret | object::Body::ArrowClay + | object::Body::BoltBesieger | object::Body::SpectralSwordSmall | object::Body::SpectralSwordLarge, ) => { @@ -565,8 +591,11 @@ impl SfxMgr { let sfx_trigger_item = triggers.get_key_value(&SfxEvent::FireShot); audio.emit_sfx(sfx_trigger_item, *pos, None, underwater); }, - Body::Object(object::Body::LaserBeam) - | Body::Object(object::Body::LightningBolt) => { + Body::Object( + object::Body::LaserBeam + | object::Body::LaserBeamSmall + | object::Body::LightningBolt, + ) => { let sfx_trigger_item = triggers.get_key_value(&SfxEvent::LaserBeam); audio.emit_sfx(sfx_trigger_item, *pos, None, underwater); }, @@ -592,6 +621,7 @@ impl SfxMgr { | object::Body::ArrowSnake | object::Body::ArrowTurret | object::Body::ArrowClay + | object::Body::BoltBesieger | object::Body::SpectralSwordSmall | object::Body::SpectralSwordLarge, ) => { diff --git a/voxygen/src/discord.rs b/voxygen/src/discord.rs index 30f5ef5c84..0c9799580f 100644 --- a/voxygen/src/discord.rs +++ b/voxygen/src/discord.rs @@ -114,6 +114,9 @@ impl ActivityUpdate { let location = match site { Dungeon(Old) => format!("Battling evil in {chunk_name}"), Dungeon(Gnarling) => format!("Hunting Gnarlings in {chunk_name}"), + Dungeon(Adlet) => format!("Finding the Yeti in {chunk_name}"), + Dungeon(SeaChapel) => format!("Gathering sea treasures in {chunk_name}"), + Dungeon(Terracotta) => format!("Exploring ruins in {chunk_name}"), Cave => "In a Cave".to_string(), Settlement(Default) => format!("Visiting {chunk_name}"), Settlement(CliffTown) => format!("Climbing the towers of {chunk_name}"), diff --git a/voxygen/src/hud/img_ids.rs b/voxygen/src/hud/img_ids.rs index 6b64780780..fff7cdd125 100644 --- a/voxygen/src/hud/img_ids.rs +++ b/voxygen/src/hud/img_ids.rs @@ -535,6 +535,9 @@ image_ids! { mmap_site_sea_chapel_hover: "voxygen.element.ui.map.buttons.sea_chapel_hover", mmap_site_sea_chapel_bg: "voxygen.element.ui.map.buttons.sea_chapel_bg", mmap_site_sea_chapel: "voxygen.element.ui.map.buttons.sea_chapel", + mmap_site_terracotta_hover: "voxygen.element.ui.map.buttons.terracotta_hover", + mmap_site_terracotta_bg: "voxygen.element.ui.map.buttons.terracotta_bg", + mmap_site_terracotta: "voxygen.element.ui.map.buttons.terracotta", mmap_site_dungeon: "voxygen.element.ui.map.buttons.dungeon", mmap_site_dungeon_hover: "voxygen.element.ui.map.buttons.dungeon_hover", mmap_site_dungeon_bg: "voxygen.element.ui.map.buttons.dungeon_bg", diff --git a/voxygen/src/hud/map.rs b/voxygen/src/hud/map.rs index e9cbe267e4..40699a45ca 100644 --- a/voxygen/src/hud/map.rs +++ b/voxygen/src/hud/map.rs @@ -922,7 +922,8 @@ impl<'a> Widget for Map<'a> { SiteKind::Cave => i18n.get_msg("hud-map-cave"), SiteKind::Tree => i18n.get_msg("hud-map-tree"), SiteKind::Gnarling => i18n.get_msg("hud-map-gnarling"), - SiteKind::ChapelSite => i18n.get_msg("hud-map-chapel_Site"), + SiteKind::ChapelSite => i18n.get_msg("hud-map-chapel_site"), + SiteKind::Terracotta => i18n.get_msg("hud-map-terracotta"), SiteKind::Bridge => i18n.get_msg("hud-map-bridge"), SiteKind::Adlet => i18n.get_msg("hud-map-adlet"), SiteKind::Haniwa => i18n.get_msg("hud-map-haniwa"), @@ -951,6 +952,7 @@ impl<'a> Widget for Map<'a> { SiteKind::Cave => (None, i18n.get_msg("hud-map-cave")), SiteKind::Tree => (None, i18n.get_msg("hud-map-tree")), SiteKind::Gnarling => (Some(0), i18n.get_msg("hud-map-gnarling")), + SiteKind::Terracotta => (Some(5), i18n.get_msg("hud-map-terracotta")), SiteKind::ChapelSite => (Some(4), i18n.get_msg("hud-map-chapel_site")), SiteKind::Bridge => (None, i18n.get_msg("hud-map-bridge")), SiteKind::Adlet => (Some(1), i18n.get_msg("hud-map-adlet")), @@ -961,6 +963,7 @@ impl<'a> Widget for Map<'a> { let site_btn = Button::image(match &site.kind { SiteKind::Town => self.imgs.mmap_site_town, SiteKind::ChapelSite => self.imgs.mmap_site_sea_chapel, + SiteKind::Terracotta => self.imgs.mmap_site_terracotta, SiteKind::Castle => self.imgs.mmap_site_castle, SiteKind::Cave => self.imgs.mmap_site_cave, SiteKind::Tree => self.imgs.mmap_site_tree, @@ -984,6 +987,7 @@ impl<'a> Widget for Map<'a> { .hover_image(match &site.kind { SiteKind::Town => self.imgs.mmap_site_town_hover, SiteKind::ChapelSite => self.imgs.mmap_site_sea_chapel_hover, + SiteKind::Terracotta => self.imgs.mmap_site_terracotta_hover, SiteKind::Castle => self.imgs.mmap_site_castle_hover, SiteKind::Cave => self.imgs.mmap_site_cave_hover, SiteKind::Tree => self.imgs.mmap_site_tree_hover, @@ -1008,6 +1012,7 @@ impl<'a> Widget for Map<'a> { SiteKind::Dungeon { .. } | SiteKind::Gnarling | SiteKind::ChapelSite + | SiteKind::Terracotta | SiteKind::Adlet | SiteKind::Haniwa | SiteKind::DwarvenMine => match difficulty { @@ -1038,6 +1043,7 @@ impl<'a> Widget for Map<'a> { | SiteKind::ChapelSite | SiteKind::DwarvenMine | SiteKind::Haniwa + | SiteKind::Terracotta | SiteKind::Adlet => show_dungeons, SiteKind::Castle => show_castles, SiteKind::Cave => show_caves, @@ -1099,6 +1105,7 @@ impl<'a> Widget for Map<'a> { | SiteKind::Gnarling | SiteKind::ChapelSite | SiteKind::Haniwa + | SiteKind::Terracotta | SiteKind::Adlet => { if show_dungeons { dif_img.set(state.ids.site_difs[i], ui) diff --git a/voxygen/src/hud/minimap.rs b/voxygen/src/hud/minimap.rs index 1ccc45af85..32b101145d 100644 --- a/voxygen/src/hud/minimap.rs +++ b/voxygen/src/hud/minimap.rs @@ -695,6 +695,7 @@ impl<'a> Widget for MiniMap<'a> { let difficulty = match &site.kind { SiteKind::Town => None, SiteKind::ChapelSite => Some(4), + SiteKind::Terracotta => Some(5), SiteKind::Dungeon { difficulty } => Some(*difficulty), SiteKind::Castle => None, SiteKind::Cave => None, @@ -709,6 +710,7 @@ impl<'a> Widget for MiniMap<'a> { Image::new(match &site.kind { SiteKind::Town => self.imgs.mmap_site_town_bg, SiteKind::ChapelSite => self.imgs.mmap_site_sea_chapel_bg, + SiteKind::Terracotta => self.imgs.mmap_site_terracotta_bg, SiteKind::Dungeon { .. } => self.imgs.mmap_site_dungeon_bg, SiteKind::Castle => self.imgs.mmap_site_castle_bg, SiteKind::Cave => self.imgs.mmap_site_cave_bg, @@ -738,6 +740,7 @@ impl<'a> Widget for MiniMap<'a> { Image::new(match &site.kind { SiteKind::Town => self.imgs.mmap_site_town, SiteKind::ChapelSite => self.imgs.mmap_site_sea_chapel, + SiteKind::Terracotta => self.imgs.mmap_site_terracotta, SiteKind::Dungeon { .. } => self.imgs.mmap_site_dungeon, SiteKind::Castle => self.imgs.mmap_site_castle, SiteKind::Cave => self.imgs.mmap_site_cave, diff --git a/voxygen/src/hud/mod.rs b/voxygen/src/hud/mod.rs index 40a55e958f..225baf6fbc 100755 --- a/voxygen/src/hud/mod.rs +++ b/voxygen/src/hud/mod.rs @@ -5351,7 +5351,8 @@ pub fn get_sprite_desc(sprite: SpriteKind, localized_strings: &Localization) -> | SpriteKind::DungeonChest2 | SpriteKind::DungeonChest3 | SpriteKind::DungeonChest4 - | SpriteKind::DungeonChest5 => "common-sprite-chest", + | SpriteKind::DungeonChest5 + | SpriteKind::TerracottaChest => "common-sprite-chest", SpriteKind::Mud => "common-sprite-mud", SpriteKind::Grave => "common-sprite-grave", SpriteKind::ChairSingle | SpriteKind::ChairDouble => "common-sprite-chair", diff --git a/voxygen/src/hud/util.rs b/voxygen/src/hud/util.rs index 5892c11041..90a8ec52b3 100644 --- a/voxygen/src/hud/util.rs +++ b/voxygen/src/hud/util.rs @@ -588,7 +588,7 @@ pub fn ability_image(imgs: &img_ids::Imgs, ability_id: &str) -> image::Id { "common.abilities.music.wildskin_drum" => imgs.instrument, "common.abilities.music.icy_talharpa" => imgs.instrument, "common.abilities.music.washboard" => imgs.instrument, - "common.abilities.music.steeldrum" => imgs.instrument, + "common.abilities.music.steeltonguedrum" => imgs.instrument, "common.abilities.music.shamisen" => imgs.instrument, _ => imgs.not_found, } diff --git a/voxygen/src/scene/figure/mod.rs b/voxygen/src/scene/figure/mod.rs index 26a2094eff..bddce5228d 100644 --- a/voxygen/src/scene/figure/mod.rs +++ b/voxygen/src/scene/figure/mod.rs @@ -3668,7 +3668,7 @@ impl FigureMgr { anim::biped_small::WieldAnimation::update_skeleton( &target_base, ( - active_tool_kind, + (active_tool_kind, active_tool_spec), rel_vel, ori * anim::vek::Vec3::::unit_y(), state.last_ori * anim::vek::Vec3::::unit_y(), @@ -4009,6 +4009,38 @@ impl FigureMgr { skeleton_attr, ) }, + CharacterState::SpriteSummon(s) => { + let stage_time = s.timer.as_secs_f32(); + let stage_progress = match s.stage_section { + StageSection::Buildup => { + stage_time / s.static_data.buildup_duration.as_secs_f32() + }, + StageSection::Action => { + stage_time / s.static_data.cast_duration.as_secs_f32() + }, + StageSection::Recover => { + stage_time / s.static_data.recover_duration.as_secs_f32() + }, + _ => 0.0, + }; + anim::biped_small::SpriteSummonAnimation::update_skeleton( + &target_base, + ( + active_tool_kind, + rel_vel, + ori * anim::vek::Vec3::::unit_y(), + state.last_ori * anim::vek::Vec3::::unit_y(), + time, + rel_avg_vel, + state.acc_vel, + Some(s.stage_section), + state.state_time, + ), + stage_progress, + &mut state_animation_rate, + skeleton_attr, + ) + }, CharacterState::BasicSummon(s) => { let stage_time = s.timer.as_secs_f32(); let stage_progress = match s.stage_section { @@ -6104,7 +6136,13 @@ impl FigureMgr { anim::golem::BeamAnimation::update_skeleton( &target_base, - (Some(s.stage_section), time, state.state_time, look_dir), + ( + Some(s.stage_section), + time, + state.state_time, + look_dir, + ability_id, + ), stage_progress, &mut state_animation_rate, skeleton_attr, diff --git a/voxygen/src/scene/particle.rs b/voxygen/src/scene/particle.rs index eb9177b9ad..498f9cc1bd 100644 --- a/voxygen/src/scene/particle.rs +++ b/voxygen/src/scene/particle.rs @@ -396,6 +396,15 @@ impl ParticleMgr { *pos + Vec3::new(0.0, 0.0, 1.5 + 0.5 * rng.gen_range(0.0..0.2)), )); }, + Outcome::TerracottaStatueCharge { pos } => { + self.particles.push(Particle::new_directed( + Duration::from_secs_f32(rng.gen_range(0.1..0.2)), + time, + ParticleMode::FireworkYellow, + *pos + Vec3::new(0.0, 0.0, 4.0), + *pos + Vec3::new(0.0, 0.0, 5.0 + 0.5 * rng.gen_range(0.3..0.8)), + )); + }, Outcome::Death { pos, .. } => { self.particles.resize_with(self.particles.len() + 40, || { Particle::new( diff --git a/voxygen/src/scene/trail.rs b/voxygen/src/scene/trail.rs index 88ada76d37..2f563751eb 100644 --- a/voxygen/src/scene/trail.rs +++ b/voxygen/src/scene/trail.rs @@ -57,7 +57,8 @@ impl TrailMgr { | object::Body::MultiArrow | object::Body::ArrowSnake | object::Body::ArrowTurret - | object::Body::ArrowClay, + | object::Body::ArrowClay + | object::Body::BoltBesieger, ) ) { diff --git a/world/src/block/mod.rs b/world/src/block/mod.rs index 251e2ff3b6..d7705dd6de 100644 --- a/world/src/block/mod.rs +++ b/world/src/block/mod.rs @@ -407,6 +407,17 @@ pub fn block_from_structure( }), )); }, + StructureBlock::TerracottaKeyhole(consumes) => { + return Some(( + Block::air(SpriteKind::TerracottaKeyhole), + Some(SpriteCfg { + unlock: Some(UnlockKind::Consumes(ItemDefinitionIdOwned::Simple( + consumes.clone(), + ))), + ..SpriteCfg::default() + }), + )); + }, }; Some((block?, None)) diff --git a/world/src/civ/mod.rs b/world/src/civ/mod.rs index 372726cfd2..2cb667da7a 100644 --- a/world/src/civ/mod.rs +++ b/world/src/civ/mod.rs @@ -278,7 +278,7 @@ impl Civs { let world_dims = ctx.sim.get_aabr(); for _ in 0..initial_civ_count * 3 { attempt(5, || { - let (loc, kind) = match ctx.rng.gen_range(0..105) { + let (loc, kind) = match ctx.rng.gen_range(0..115) { 0..=4 => { if index.features().site2_giant_trees { ( @@ -394,7 +394,17 @@ impl Civs { )?, SiteKind::Haniwa, ), - /*75..=80 => ( + 75..=85 => ( + find_site_loc( + &mut ctx, + &ProximityRequirementsBuilder::new() + .avoid_all_of(this.terracotta_enemies(), 40) + .finalize(&world_dims), + &SiteKind::Terracotta, + )?, + SiteKind::Terracotta, + ), + /*86..=91 => ( find_site_loc( &mut ctx, &ProximityRequirementsBuilder::new() @@ -404,7 +414,7 @@ impl Civs { )?, SiteKind::DwarvenMine, ), - 81..=86 => ( + 92..=97 => ( find_site_loc( &mut ctx, &ProximityRequirementsBuilder::new() @@ -415,7 +425,7 @@ impl Civs { )?, SiteKind::Castle, ), - 87..=92 => (SiteKind::Citadel, (&castle_enemies, 20)), + 98..=103 => (SiteKind::Citadel, (&castle_enemies, 20)), */ _ => ( find_site_loc( @@ -457,6 +467,7 @@ impl Civs { SiteKind::JungleRuin => (8i32, 3.0), SiteKind::DesertCity => (64i32, 25.0), SiteKind::ChapelSite => (36i32, 10.0), + SiteKind::Terracotta => (64i32, 35.0), SiteKind::Tree => (12i32, 8.0), SiteKind::GiantTree => (12i32, 8.0), SiteKind::Gnarling => (16i32, 10.0), @@ -626,6 +637,9 @@ impl Civs { SiteKind::ChapelSite => WorldSite::chapel_site( site2::Site::generate_chapel_site(&Land::from_sim(ctx.sim), &mut rng, wpos), ), + SiteKind::Terracotta => WorldSite::terracotta( + site2::Site::generate_terracotta(&Land::from_sim(ctx.sim), &mut rng, wpos), + ), SiteKind::Citadel => WorldSite::gnarling(site2::Site::generate_citadel( &Land::from_sim(ctx.sim), &mut rng, @@ -1529,6 +1543,13 @@ impl Civs { }) } + fn terracotta_enemies(&self) -> impl Iterator> + '_ { + self.sites().filter_map(|s| match s.kind { + SiteKind::Tree | SiteKind::GiantTree => None, + _ => Some(s.center), + }) + } + fn dungeon_enemies(&self) -> impl Iterator> + '_ { self.sites().filter_map(|s| match s.kind { SiteKind::Tree | SiteKind::GiantTree => None, @@ -1933,6 +1954,7 @@ pub enum SiteKind { CoastalTown, DesertCity, ChapelSite, + Terracotta, Tree, GiantTree, Gnarling, @@ -2047,6 +2069,14 @@ impl SiteKind { matches!(chunk.get_biome(), BiomeKind::Ocean) && CONFIG.sea_level < chunk.alt + 1.0 }, + SiteKind::Terracotta => { + (0.9..1.0).contains(&chunk.temp) + && on_land() + && (chunk.water_alt - CONFIG.sea_level) > 50.0 + && on_flat_terrain() + && !chunk.river.near_water() + && !chunk.near_cliffs() + }, SiteKind::Castle => { if chunk.tree_density > 0.4 || chunk.river.near_water() || chunk.near_cliffs() { return false; diff --git a/world/src/lib.rs b/world/src/lib.rs index 429e03bdae..15836e8795 100644 --- a/world/src/lib.rs +++ b/world/src/lib.rs @@ -213,6 +213,7 @@ impl World { civ::SiteKind::Gnarling => world_msg::SiteKind::Gnarling, //civ::SiteKind::DwarvenMine => world_msg::SiteKind::DwarvenMine, civ::SiteKind::ChapelSite => world_msg::SiteKind::ChapelSite, + civ::SiteKind::Terracotta => world_msg::SiteKind::Terracotta, civ::SiteKind::Citadel => world_msg::SiteKind::Castle, civ::SiteKind::Bridge(_, _) => world_msg::SiteKind::Bridge, civ::SiteKind::Adlet => world_msg::SiteKind::Adlet, diff --git a/world/src/site/economy/context.rs b/world/src/site/economy/context.rs index 79ede3dd65..9cf07f69ee 100644 --- a/world/src/site/economy/context.rs +++ b/world/src/site/economy/context.rs @@ -135,6 +135,7 @@ impl Environment { SiteKind::JungleRuin(_) => {}, SiteKind::ChapelSite(_) => {}, SiteKind::DwarvenMine(_) => {}, + SiteKind::Terracotta(_) => {}, SiteKind::Bridge(_) => {}, SiteKind::PirateHideout(_) => {}, SiteKind::RockCircle(_) => {}, diff --git a/world/src/site/mod.rs b/world/src/site/mod.rs index 68544822f2..6fa028986b 100644 --- a/world/src/site/mod.rs +++ b/world/src/site/mod.rs @@ -73,6 +73,7 @@ pub enum SiteKind { ChapelSite(site2::Site), DwarvenMine(site2::Site), CoastalTown(site2::Site), + Terracotta(site2::Site), GiantTree(site2::Site), Gnarling(site2::Site), Bridge(site2::Site), @@ -212,6 +213,13 @@ impl Site { } } + pub fn terracotta(tr: site2::Site) -> Self { + Self { + kind: SiteKind::Terracotta(tr), + economy: Economy::default(), + } + } + pub fn tree(t: Tree) -> Self { Self { kind: SiteKind::Tree(t), @@ -250,6 +258,7 @@ impl Site { SiteKind::DesertCity(dc) => dc.radius(), SiteKind::ChapelSite(p) => p.radius(), SiteKind::DwarvenMine(dm) => dm.radius(), + SiteKind::Terracotta(tr) => tr.radius(), SiteKind::Tree(t) => t.radius(), SiteKind::GiantTree(gt) => gt.radius(), SiteKind::Gnarling(g) => g.radius(), @@ -276,6 +285,7 @@ impl Site { SiteKind::DesertCity(dc) => dc.origin, SiteKind::ChapelSite(p) => p.origin, SiteKind::DwarvenMine(dm) => dm.origin, + SiteKind::Terracotta(tr) => tr.origin, SiteKind::Tree(t) => t.origin, SiteKind::GiantTree(gt) => gt.origin, SiteKind::Gnarling(g) => g.origin, @@ -302,6 +312,7 @@ impl Site { SiteKind::DesertCity(dc) => dc.spawn_rules(wpos), SiteKind::ChapelSite(p) => p.spawn_rules(wpos), SiteKind::DwarvenMine(dm) => dm.spawn_rules(wpos), + SiteKind::Terracotta(tr) => tr.spawn_rules(wpos), SiteKind::Tree(t) => t.spawn_rules(wpos), SiteKind::GiantTree(gt) => gt.spawn_rules(wpos), SiteKind::Gnarling(g) => g.spawn_rules(wpos), @@ -327,6 +338,7 @@ impl Site { SiteKind::Camp(cp) => cp.name(), SiteKind::DesertCity(dc) => dc.name(), SiteKind::ChapelSite(p) => p.name(), + SiteKind::Terracotta(tr) => tr.name(), SiteKind::DwarvenMine(dm) => dm.name(), SiteKind::Tree(_) => "Giant Tree", SiteKind::GiantTree(gt) => gt.name(), @@ -373,6 +385,7 @@ impl Site { SiteKind::Camp(cp) => cp.render(canvas, dynamic_rng), SiteKind::DesertCity(dc) => dc.render(canvas, dynamic_rng), SiteKind::ChapelSite(p) => p.render(canvas, dynamic_rng), + SiteKind::Terracotta(tr) => tr.render(canvas, dynamic_rng), SiteKind::DwarvenMine(dm) => dm.render(canvas, dynamic_rng), SiteKind::Tree(t) => t.render(canvas, dynamic_rng), SiteKind::GiantTree(gt) => gt.render(canvas, dynamic_rng), @@ -413,6 +426,7 @@ impl Site { SiteKind::Camp(_) => {}, SiteKind::DesertCity(_) => {}, SiteKind::ChapelSite(p) => p.apply_supplement(dynamic_rng, wpos2d, supplement), + SiteKind::Terracotta(tr) => tr.apply_supplement(dynamic_rng, wpos2d, supplement), SiteKind::DwarvenMine(dm) => dm.apply_supplement(dynamic_rng, wpos2d, supplement), SiteKind::Tree(_) => {}, SiteKind::GiantTree(gt) => gt.apply_supplement(dynamic_rng, wpos2d, supplement), @@ -455,6 +469,7 @@ impl Site { SiteKind::DesertCity(site2) => Some(site2), SiteKind::ChapelSite(site2) => Some(site2), SiteKind::DwarvenMine(site2) => Some(site2), + SiteKind::Terracotta(site2) => Some(site2), SiteKind::GiantTree(site2) => Some(site2), SiteKind::Gnarling(site2) => Some(site2), SiteKind::Bridge(site2) => Some(site2), diff --git a/world/src/site/namegen.rs b/world/src/site/namegen.rs index 59a5cdfd23..7be51dcbd9 100644 --- a/world/src/site/namegen.rs +++ b/world/src/site/namegen.rs @@ -556,7 +556,9 @@ impl<'a, R: Rng> NameGen<'a, R> { if !vowel.is_empty() { name += vowel.choose(self.rng).unwrap() }; - name += middle.choose(self.rng).unwrap(); + if !middle.is_empty() { + name += middle.choose(self.rng).unwrap(); + } } name += end.choose(self.rng).unwrap(); @@ -701,6 +703,29 @@ impl<'a, R: Rng> NameGen<'a, R> { self.generate_theme_from_parts(&start, &middle, &vowel, &end) } + // chinese inspired location names for terracotta ruins + pub fn generate_terracotta(&mut self) -> String { + let start = [ + "wang", "li", "zhang", "liu", "chen", "yang", "gong", "zhao", "wu", "zhou", "ming", + "jin", "xiao", "feng", "ho", "xiang", "yuan", "yu", "chien", "xi", "qin", "dao", "bao", + "ping", "qu", "yan", "deng", "ku", "ko", "la", "ge", "fu", "gao", "yong", "wo", "qi", + "mo", "gong", "shi", "xing", "xian", "biao", "kai", "bei", "ga", "zhou", "liu", "ba", + "fei", "tui", "de", "teng", "shou", "xiong", "diao", "lei", "shan", "shin", "pin", + "gin", "gen", "huen", "san", "hong", "long", "kon", "jing", "meng", "mei", + ]; + let middle = []; + let vowel = []; + let end = [ + "tian", "shi", "zhong", "xie", "biao", "neng", "zuo", "ze", "zhi", "hao", "pao", + "liang", "yong", "chou", "zhou", "peng", "yang", "huang", "bo", "yao", "fu", "xia", + "chen", "ling", "jia", "xu", "gou", "ya", "lang", "he", "ho", "nan", "hua", "xue", + "ji", "jian", "jiu", "xi", "ling", "dan", "dian", "shin", "gao", "yi", "zuo", "san", + "jie", "hua", "jin", "zhi", "zhe", "sing", "zai", "hun", "fen", "nen", "huan", "bian", + "cha", "wu", "wei", "jiao", "hu", "he", "bao", "bi", + ]; + self.generate_theme_from_parts(&start, &middle, &vowel, &end) + } + // inuit inspired location names for adlet stronghold pub fn generate_adlet(mut self) -> String { let start = [ diff --git a/world/src/site2/mod.rs b/world/src/site2/mod.rs index 81a5fdcff0..8842bb6eb0 100644 --- a/world/src/site2/mod.rs +++ b/world/src/site2/mod.rs @@ -110,6 +110,9 @@ impl Site { PlotKind::Adlet(ad) => Some(ad.spawn_rules(wpos)), PlotKind::SeaChapel(p) => Some(p.spawn_rules(wpos)), PlotKind::Haniwa(ha) => Some(ha.spawn_rules(wpos)), + PlotKind::TerracottaPalace(tp) => Some(tp.spawn_rules(wpos)), + PlotKind::TerracottaHouse(th) => Some(th.spawn_rules(wpos)), + PlotKind::TerracottaYard(ty) => Some(ty.spawn_rules(wpos)), //PlotKind::DwarvenMine(m) => Some(m.spawn_rules(wpos)), _ => None, }) @@ -547,6 +550,131 @@ impl Site { site } + pub fn generate_terracotta(land: &Land, rng: &mut impl Rng, origin: Vec2) -> Self { + let mut rng = reseed(rng); + let gen_name = NameGen::location(&mut rng).generate_terracotta(); + let suffix = [ + "Tombs", + "Necropolis", + "Ruins", + "Mausoleum", + "Cemetery", + "Burial Grounds", + "Remains", + "Temples", + ] + .choose(&mut rng) + .unwrap(); + let name = match rng.gen_range(0..2) { + 0 => format!("{} {}", gen_name, suffix), + _ => format!("{} of {}", suffix, gen_name), + }; + let mut site = Site { + origin, + name, + ..Site::default() + }; + + site.make_plaza(land, &mut rng); + + let size = 15.0 as i32; + let aabr = Aabr { + min: Vec2::broadcast(-size), + max: Vec2::broadcast(size), + }; + { + let terracotta_palace = + plot::TerracottaPalace::generate(land, &mut reseed(&mut rng), &site, aabr); + let terracotta_palace_alt = terracotta_palace.alt; + let plot = site.create_plot(Plot { + kind: PlotKind::TerracottaPalace(terracotta_palace), + root_tile: aabr.center(), + tiles: aabr_tiles(aabr).collect(), + seed: rng.gen(), + }); + + site.blit_aabr(aabr, Tile { + kind: TileKind::Building, + plot: Some(plot), + hard_alt: Some(terracotta_palace_alt), + }); + } + let build_chance = Lottery::from(vec![(12.0, 1), (4.0, 2)]); + for _ in 0..16 { + match *build_chance.choose_seeded(rng.gen()) { + 1 => { + // TerracottaHouse + let size = (9.0 + rng.gen::().powf(5.0) * 1.5).round() as u32; + if let Some((aabr, _, _)) = attempt(32, || { + site.find_roadside_aabr( + &mut rng, + 9..(size + 1).pow(2), + Extent2::broadcast(size), + ) + }) { + let terracotta_house = plot::TerracottaHouse::generate( + land, + &mut reseed(&mut rng), + &site, + aabr, + ); + let terracotta_house_alt = terracotta_house.alt; + let plot = site.create_plot(Plot { + kind: PlotKind::TerracottaHouse(terracotta_house), + root_tile: aabr.center(), + tiles: aabr_tiles(aabr).collect(), + seed: rng.gen(), + }); + + site.blit_aabr(aabr, Tile { + kind: TileKind::Building, + plot: Some(plot), + hard_alt: Some(terracotta_house_alt), + }); + } else { + site.make_plaza(land, &mut rng); + } + }, + + 2 => { + // TerracottaYard + let size = (9.0 + rng.gen::().powf(5.0) * 1.5).round() as u32; + if let Some((aabr, _, _)) = attempt(32, || { + site.find_roadside_aabr( + &mut rng, + 9..(size + 1).pow(2), + Extent2::broadcast(size), + ) + }) { + let terracotta_yard = plot::TerracottaYard::generate( + land, + &mut reseed(&mut rng), + &site, + aabr, + ); + let terracotta_yard_alt = terracotta_yard.alt; + let plot = site.create_plot(Plot { + kind: PlotKind::TerracottaYard(terracotta_yard), + root_tile: aabr.center(), + tiles: aabr_tiles(aabr).collect(), + seed: rng.gen(), + }); + + site.blit_aabr(aabr, Tile { + kind: TileKind::Building, + plot: Some(plot), + hard_alt: Some(terracotta_yard_alt), + }); + } else { + site.make_plaza(land, &mut rng); + } + }, + _ => {}, + } + } + site + } + pub fn generate_giant_tree(land: &Land, rng: &mut impl Rng, origin: Vec2) -> Self { let mut rng = reseed(rng); let mut site = Site { @@ -1946,6 +2074,15 @@ impl Site { }, //PlotKind::DwarvenMine(_dwarven_mine) => dwarven_mine.render_collect(self, // canvas), + PlotKind::TerracottaPalace(terracotta_palace) => { + terracotta_palace.render_collect(self, canvas) + }, + PlotKind::TerracottaHouse(terracotta_house) => { + terracotta_house.render_collect(self, canvas) + }, + PlotKind::TerracottaYard(terracotta_yard) => { + terracotta_yard.render_collect(self, canvas) + }, PlotKind::DesertCityMultiPlot(desert_city_multi_plot) => { desert_city_multi_plot.render_collect(self, canvas) }, diff --git a/world/src/site2/plot.rs b/world/src/site2/plot.rs index 236a333130..97fec96bc2 100644 --- a/world/src/site2/plot.rs +++ b/world/src/site2/plot.rs @@ -24,6 +24,9 @@ mod savannah_pit; mod savannah_workshop; mod sea_chapel; pub mod tavern; +mod terracotta_house; +mod terracotta_palace; +mod terracotta_yard; mod troll_cave; mod workshop; @@ -36,7 +39,8 @@ pub use self::{ gnarling::GnarlingFortification, haniwa::Haniwa, house::House, jungle_ruin::JungleRuin, pirate_hideout::PirateHideout, rock_circle::RockCircle, savannah_hut::SavannahHut, savannah_pit::SavannahPit, savannah_workshop::SavannahWorkshop, sea_chapel::SeaChapel, - tavern::Tavern, troll_cave::TrollCave, workshop::Workshop, + tavern::Tavern, terracotta_house::TerracottaHouse, terracotta_palace::TerracottaPalace, + terracotta_yard::TerracottaYard, troll_cave::TrollCave, workshop::Workshop, }; use super::*; @@ -107,4 +111,7 @@ pub enum PlotKind { TrollCave(TrollCave), Camp(Camp), //DwarvenMine(DwarvenMine), + TerracottaPalace(TerracottaPalace), + TerracottaHouse(TerracottaHouse), + TerracottaYard(TerracottaYard), } diff --git a/world/src/site2/plot/terracotta_house.rs b/world/src/site2/plot/terracotta_house.rs new file mode 100644 index 0000000000..a638f15540 --- /dev/null +++ b/world/src/site2/plot/terracotta_house.rs @@ -0,0 +1,405 @@ +use super::*; +use crate::{ + assets::AssetHandle, + site2::gen::PrimitiveTransform, + util::{RandomField, Sampler, DIAGONALS, NEIGHBORS}, + Land, +}; +use common::{ + generation::EntityInfo, + terrain::{BlockKind, SpriteKind, Structure as PrefabStructure, StructuresGroup}, +}; +use lazy_static::lazy_static; +use rand::prelude::*; +use std::{f32::consts::TAU, sync::Arc}; +use vek::*; + +/// Represents house data generated by the `generate()` method +pub struct TerracottaHouse { + /// Axis aligned bounding region for the house + bounds: Aabr, + /// Approximate altitude of the door tile + pub(crate) alt: i32, +} + +impl TerracottaHouse { + pub fn generate(land: &Land, _rng: &mut impl Rng, site: &Site, tile_aabr: Aabr) -> Self { + let bounds = Aabr { + min: site.tile_wpos(tile_aabr.min), + max: site.tile_wpos(tile_aabr.max), + }; + Self { + bounds, + alt: land.get_alt_approx(site.tile_center_wpos((tile_aabr.max - tile_aabr.min) / 2)) + as i32 + + 2, + } + } + + pub fn spawn_rules(&self, wpos: Vec2) -> SpawnRules { + SpawnRules { + waypoints: false, + trees: wpos.distance_squared(self.bounds.center()) > (85_i32).pow(2), + ..SpawnRules::default() + } + } +} + +impl Structure for TerracottaHouse { + #[cfg(feature = "use-dyn-lib")] + const UPDATE_FN: &'static [u8] = b"render_terracotta_house\0"; + + #[cfg_attr(feature = "be-dyn-lib", export_name = "render_terracotta_house")] + fn render_inner(&self, _site: &Site, _land: &Land, painter: &Painter) { + let base = self.alt + 3; + let center = self.bounds.center(); + let mut rng = thread_rng(); + let clay_broken = Fill::Sampling(Arc::new(|center| { + Some(match (RandomField::new(0).get(center)) % 42 { + 0..=8 => Block::new(BlockKind::Rock, Rgb::new(242, 161, 53)), + 9..=17 => Block::new(BlockKind::Rock, Rgb::new(253, 199, 81)), + 18..=26 => Block::new(BlockKind::Rock, Rgb::new(254, 210, 91)), + 27..=35 => Block::new(BlockKind::Rock, Rgb::new(254, 216, 101)), + 36..=38 => Block::new(BlockKind::Air, Rgb::new(0, 0, 0)), + _ => Block::new(BlockKind::Rock, Rgb::new(250, 185, 71)), + }) + })); + let clay_unbroken = Fill::Sampling(Arc::new(|center| { + Some(match (RandomField::new(0).get(center)) % 40 { + 0..=8 => Block::new(BlockKind::Rock, Rgb::new(242, 161, 53)), + 9..=17 => Block::new(BlockKind::Rock, Rgb::new(253, 199, 81)), + 18..=26 => Block::new(BlockKind::Rock, Rgb::new(254, 210, 91)), + 27..=35 => Block::new(BlockKind::Rock, Rgb::new(254, 216, 101)), + _ => Block::new(BlockKind::Rock, Rgb::new(250, 185, 71)), + }) + })); + let grass_fill = Fill::Sampling(Arc::new(|wpos| { + Some(match (RandomField::new(0).get(wpos)) % 20 { + 1..=2 => Block::air(SpriteKind::JungleRedGrass), + 3..=7 => Block::air(SpriteKind::JungleLeafyPlant), + 8 => Block::air(SpriteKind::JungleFern), + _ => Block::new(BlockKind::Air, Rgb::new(0, 0, 0)), + }) + })); + let roof_color = Fill::Sampling(Arc::new(|center| { + Some(match (RandomField::new(0).get(center)) % 400 { + 0..=4 => Block::new(BlockKind::Rock, Rgb::new(242, 161, 53)), + 5..=9 => Block::new(BlockKind::Rock, Rgb::new(253, 199, 81)), + 10..=14 => Block::new(BlockKind::Rock, Rgb::new(254, 210, 91)), + 15..=19 => Block::new(BlockKind::Rock, Rgb::new(254, 216, 101)), + 20..=21 => Block::new(BlockKind::Air, Rgb::new(0, 0, 0)), + 22..=23 => Block::new(BlockKind::Rock, Rgb::new(250, 185, 71)), + _ => Block::new(BlockKind::GlowingRock, Rgb::new(73, 53, 42)), + }) + })); + let sand = Fill::Brick(BlockKind::Misc, Rgb::new(235, 178, 99), 12); + let size = 30; + let room_size = 15 * (size / 10); + let roof_size = 16 * (size / 10); + let carve_size = 14 * (size / 10) + 2; + let roof_height = room_size / 3; + let storeys = 5; + let var = size / 5; + let clear_var = var / 2; + let clear_limit = painter.aabb(Aabb { + min: (center - (room_size / 2) - 2).with_z(base), + max: (center + (room_size / 2) + 2).with_z(base + (2 * room_size)), + }); + let clear_limit_down = painter.aabb(Aabb { + min: (center - (room_size / 2) - 5).with_z(base - (2 * room_size)), + max: (center + (room_size / 2) + 5).with_z(base), + }); + let decay = RandomField::new(0).get(center.with_z(base)) % 2; + // models + let model_radius = (room_size / 2) + 4; + for dir in DIAGONALS { + let pos = center + dir * model_radius; + // foundation + painter + .cylinder(Aabb { + min: (pos - 10).with_z(base - room_size), + max: (pos + 10).with_z(base - 3), + }) + .fill(clay_unbroken.clone()); + painter + .cylinder(Aabb { + min: (pos - 10).with_z(base - 4), + max: (pos + 10).with_z(base - 3), + }) + .fill(clay_broken.clone()); + painter + .cylinder(Aabb { + min: (pos - 9).with_z(base - 4), + max: (pos + 9).with_z(base - 3), + }) + .fill(sand.clone()); + // jungle sprites + painter + .cylinder(Aabb { + min: (pos - 7).with_z(base - 3), + max: (pos + 7).with_z(base - 2), + }) + .fill(grass_fill.clone()); + // models + let model_pos = pos.with_z(base - 5); + match RandomField::new(0).get(model_pos) % 2 { + 0 => { + lazy_static! { + pub static ref MODEL: AssetHandle = + PrefabStructure::load_group( + "site_structures.terracotta.terracotta_decor_small" + ); + } + let rng = RandomField::new(0).get(model_pos) % 62; + let model = MODEL.read(); + let model = model[rng as usize % model.len()].clone(); + painter + .prim(Primitive::Prefab(Box::new(model.clone()))) + .translate(model_pos) + .fill(Fill::Prefab(Box::new(model), model_pos, rng)); + }, + + _ => { + lazy_static! { + pub static ref MODEL: AssetHandle = + PrefabStructure::load_group("trees.palms"); + } + let rng = RandomField::new(0).get(model_pos) % 62; + let model = MODEL.read(); + let model = model[rng as usize % model.len()].clone(); + painter + .prim(Primitive::Prefab(Box::new(model.clone()))) + .translate(model_pos) + .fill(Fill::Prefab(Box::new(model), model_pos, rng)); + }, + } + } + // foundation + painter + .superquadric( + Aabb { + min: (center - (room_size / 2) - 10).with_z(base - room_size - 15), + max: (center + (room_size / 2) + 10).with_z(base + 5), + }, + 2.5, + ) + .fill(clay_unbroken.clone()); + // base room + painter + .superquadric( + Aabb { + min: (center - (room_size / 2)).with_z(base - (room_size / 2)), + max: (center + (room_size / 2)).with_z(base + (room_size / 2)), + }, + 2.5, + ) + .fill(clay_broken.clone()); + // solid bottom + painter + .superquadric( + Aabb { + min: (center - (room_size / 2)).with_z(base - (room_size / 2)), + max: (center + (room_size / 2)).with_z(base + (room_size / 2)), + }, + 2.5, + ) + .intersect(clear_limit_down) + .fill(clay_unbroken.clone()); + // roof and top rooms + for s in 0..storeys { + painter + .superquadric( + Aabb { + min: (center - (roof_size / 2) + (s * var)).with_z( + base + roof_height - (size / 4) + (s * (roof_size / 4)) + (s * var), + ), + max: (center + (roof_size / 2) - (s * var)).with_z( + base + roof_height - (size / 4) + roof_size + (s * (roof_size / 4)) + - (s * var), + ), + }, + 2.5, + ) + .fill(clay_broken.clone()); + painter + .superquadric( + Aabb { + min: (center - (roof_size / 2) + (s * var) + 1).with_z( + base + roof_height - (size / 4) + (s * (roof_size / 4)) + (s * var) + 1, + ), + max: (center + (roof_size / 2) - (s * var) - 1).with_z( + base + roof_height - (size / 4) + roof_size + (s * (roof_size / 4)) + - (s * var) + - 1, + ), + }, + 2.5, + ) + .fill(roof_color.clone()); + for dir in CARDINALS { + let pos = center + dir * (size - (s * var)); + + painter + .superquadric( + Aabb { + min: (pos - (carve_size / 2) + (s * clear_var)).with_z( + base + roof_height + (s * (roof_size / 4)) + (s * clear_var), + ), + max: (pos + (carve_size / 2) - (s * clear_var)).with_z( + base + roof_height + carve_size + (s * (roof_size / 4)) + - (s * clear_var), + ), + }, + 2.5, + ) + .intersect(clear_limit) + .clear(); + } + } + // clear base room & entries + painter + .superquadric( + Aabb { + min: (center - (room_size / 2) + 5).with_z(base - (room_size / 2) + 5), + max: (center + (room_size / 2) - 5).with_z(base + (room_size / 2) - 5), + }, + 2.5, + ) + .union( + painter + .superquadric( + Aabb { + min: Vec2::new( + center.x - (room_size / 4), + center.y - (3 * room_size / 4), + ) + .with_z(base - (room_size / 4)), + max: Vec2::new( + center.x + (room_size / 4), + center.y + (3 * room_size / 4), + ) + .with_z(base + (room_size / 4)), + }, + 2.5, + ) + .union( + painter.superquadric( + Aabb { + min: Vec2::new( + center.x - (3 * room_size / 4), + center.y - (room_size / 4), + ) + .with_z(base - (room_size / 4)), + max: Vec2::new( + center.x + (3 * room_size / 4), + center.y + (room_size / 4), + ) + .with_z(base + (room_size / 4)), + }, + 2.5, + ), + ), + ) + .intersect(clear_limit) + .clear(); + // clear top + painter + .superquadric( + Aabb { + min: (center - (room_size / 3)) + .with_z(base + (3 * (room_size / 10)) - (room_size / 3)), + max: (center + (room_size / 3)) + .with_z(base + (3 * (room_size / 10)) + (room_size / 4)), + }, + 2.5, + ) + .clear(); + painter + .superquadric( + Aabb { + min: (center - (room_size / 4)) + .with_z(base + (3 * (room_size / 10)) - (room_size / 4)), + max: (center + (room_size / 4)) + .with_z(base + (3 * (room_size / 10)) + (room_size / 3)), + }, + 2.5, + ) + .clear(); + // solid floor + painter + .cylinder(Aabb { + min: (center - (room_size / 2) + 1).with_z(base - 1), + max: (center + (room_size / 2) - 1).with_z(base), + }) + .fill(clay_unbroken.clone()); + + // npcs + // guards + let radius_guards = (room_size / 4) + 4; + let guards = 4.0_f32; + let phi_guards = TAU / guards; + for n in 1..=guards as i32 { + let pos = Vec2::new( + center.x + (radius_guards as f32 * ((n as f32 * phi_guards).cos())) as i32, + center.y + (radius_guards as f32 * ((n as f32 * phi_guards).sin())) as i32, + ) + .with_z(base); + terracotta_palace::spawn_random_entity(pos, painter, 1..=1); + } + if decay == 0 { + // statues + for dir in CARDINALS { + let pos = center + dir * ((room_size / 4) + 4); + painter.sprite(pos.with_z(base), SpriteKind::TerracottaStatue); + } + // iron spike trap + painter + .cylinder(Aabb { + min: (center - (room_size / 6)).with_z(base - 12), + max: (center + (room_size / 6)).with_z(base), + }) + .clear(); + painter + .cylinder(Aabb { + min: (center - (room_size / 6)).with_z(base - 13), + max: (center + (room_size / 6)).with_z(base - 12), + }) + .fill(Fill::Block(Block::air(SpriteKind::IronSpike))); + painter + .cylinder(Aabb { + min: (center - (room_size / 6)).with_z(base - 1), + max: (center + (room_size / 6)).with_z(base), + }) + .fill(Fill::Block(Block::air(SpriteKind::TerracottaBlock))); + painter + .cylinder(Aabb { + min: (center).with_z(base - 14), + max: (center + 1).with_z(base), + }) + .fill(clay_unbroken); + // miniboss + painter.spawn(EntityInfo::at(center.with_z(base).as_()).with_asset_expect( + "common.entity.dungeon.terracotta.terracotta_statue_key_chance", + &mut rng, + None, + )); + } else { + let decay_limiter = painter.aabb(Aabb { + min: (center - (room_size / 2)).with_z(base + 4), + max: (center + (room_size / 2)).with_z(base + (5 * roof_height)), + }); + for dir in NEIGHBORS { + let carve_pos = center + dir * room_size; + let decay_var = RandomField::new(0).get(carve_pos.with_z(base)) % 15; + painter + .line( + carve_pos.with_z(base), + center.with_z(base + (5 * roof_height)), + 10.0 + decay_var as f32, + ) + .intersect(decay_limiter) + .clear(); + } + } + } +} diff --git a/world/src/site2/plot/terracotta_palace.rs b/world/src/site2/plot/terracotta_palace.rs new file mode 100644 index 0000000000..4ad8911820 --- /dev/null +++ b/world/src/site2/plot/terracotta_palace.rs @@ -0,0 +1,1086 @@ +use super::*; +use crate::{ + assets::AssetHandle, + site2::gen::PrimitiveTransform, + util::{RandomField, Sampler, DIAGONALS, NEIGHBORS}, + Land, +}; +use common::{ + generation::EntityInfo, + terrain::{BlockKind, SpriteKind, Structure as PrefabStructure, StructuresGroup}, +}; +use lazy_static::lazy_static; +use rand::prelude::*; +use std::{f32::consts::TAU, ops::RangeInclusive, sync::Arc}; +use vek::*; + +/// Represents house data generated by the `generate()` method +pub struct TerracottaPalace { + /// Axis aligned bounding region for the house + bounds: Aabr, + /// Approximate altitude of the door tile + pub(crate) alt: i32, +} + +impl TerracottaPalace { + pub fn generate(land: &Land, _rng: &mut impl Rng, site: &Site, tile_aabr: Aabr) -> Self { + let bounds = Aabr { + min: site.tile_wpos(tile_aabr.min), + max: site.tile_wpos(tile_aabr.max), + }; + Self { + bounds, + alt: land.get_alt_approx(site.tile_center_wpos((tile_aabr.max - tile_aabr.min) / 2)) + as i32 + + 2, + } + } + + pub fn spawn_rules(&self, wpos: Vec2) -> SpawnRules { + SpawnRules { + waypoints: false, + trees: wpos.distance_squared(self.bounds.center()) > (85_i32).pow(2), + ..SpawnRules::default() + } + } +} + +impl Structure for TerracottaPalace { + #[cfg(feature = "use-dyn-lib")] + const UPDATE_FN: &'static [u8] = b"render_terracotta_palace\0"; + + #[cfg_attr(feature = "be-dyn-lib", export_name = "render_terracotta_palace")] + fn render_inner(&self, _site: &Site, _land: &Land, painter: &Painter) { + let base = self.alt + 1; + let center = self.bounds.center(); + let mut rng = thread_rng(); + let clay_broken = Fill::Sampling(Arc::new(|center| { + Some(match (RandomField::new(0).get(center)) % 42 { + 0..=8 => Block::new(BlockKind::Rock, Rgb::new(242, 161, 53)), + 9..=17 => Block::new(BlockKind::Rock, Rgb::new(253, 199, 81)), + 18..=26 => Block::new(BlockKind::Rock, Rgb::new(254, 210, 91)), + 27..=35 => Block::new(BlockKind::Rock, Rgb::new(254, 216, 101)), + 36..=38 => Block::new(BlockKind::Air, Rgb::new(0, 0, 0)), + _ => Block::new(BlockKind::Rock, Rgb::new(250, 185, 71)), + }) + })); + let clay_broken_2 = Fill::Sampling(Arc::new(|center| { + Some(match (RandomField::new(0).get(center)) % 64 { + 0..=8 => Block::new(BlockKind::Rock, Rgb::new(242, 161, 53)), + 9..=17 => Block::new(BlockKind::Rock, Rgb::new(253, 199, 81)), + 18..=26 => Block::new(BlockKind::Rock, Rgb::new(254, 210, 91)), + 27..=35 => Block::new(BlockKind::Rock, Rgb::new(254, 216, 101)), + 36..=40 => Block::new(BlockKind::Rock, Rgb::new(250, 185, 71)), + _ => Block::new(BlockKind::Air, Rgb::new(0, 0, 0)), + }) + })); + let clay_unbroken = Fill::Sampling(Arc::new(|center| { + Some(match (RandomField::new(0).get(center)) % 40 { + 0..=8 => Block::new(BlockKind::Rock, Rgb::new(242, 161, 53)), + 9..=17 => Block::new(BlockKind::Rock, Rgb::new(253, 199, 81)), + 18..=26 => Block::new(BlockKind::Rock, Rgb::new(254, 210, 91)), + 27..=35 => Block::new(BlockKind::Rock, Rgb::new(254, 216, 101)), + _ => Block::new(BlockKind::Rock, Rgb::new(250, 185, 71)), + }) + })); + let grass_fill = Fill::Sampling(Arc::new(|wpos| { + Some(match (RandomField::new(0).get(wpos)) % 20 { + 1..=2 => Block::air(SpriteKind::JungleRedGrass), + 3..=7 => Block::air(SpriteKind::JungleLeafyPlant), + 8 => Block::air(SpriteKind::JungleFern), + _ => Block::new(BlockKind::Air, Rgb::new(0, 0, 0)), + }) + })); + let roof_color = Fill::Sampling(Arc::new(|center| { + Some(match (RandomField::new(0).get(center)) % 400 { + 0..=4 => Block::new(BlockKind::Rock, Rgb::new(242, 161, 53)), + 5..=9 => Block::new(BlockKind::Rock, Rgb::new(253, 199, 81)), + 10..=14 => Block::new(BlockKind::Rock, Rgb::new(254, 210, 91)), + 15..=19 => Block::new(BlockKind::Rock, Rgb::new(254, 216, 101)), + 20..=21 => Block::new(BlockKind::Air, Rgb::new(0, 0, 0)), + 22..=23 => Block::new(BlockKind::Rock, Rgb::new(250, 185, 71)), + _ => Block::new(BlockKind::GlowingRock, Rgb::new(73, 53, 42)), + }) + })); + let sand = Fill::Brick(BlockKind::Sand, Rgb::new(235, 178, 99), 12); + let size = 60; + let room_size = 15 * (size / 10); + let roof_size = 16 * (size / 10); + let carve_size = 14 * (size / 10); + let roof_height = room_size / 3; + let storeys = 5; + let var = size / 5; + let clear_var = var / 2; + let clear_limit = painter.aabb(Aabb { + min: (center - (room_size / 2) - 2).with_z(base), + max: (center + (room_size / 2) + 2).with_z(base + (2 * room_size)), + }); + let clear_limit_down = painter.aabb(Aabb { + min: (center - (room_size / 2) - 5).with_z(base - (2 * room_size)), + max: (center + (room_size / 2) + 5).with_z(base), + }); + let spikes_fill = Fill::Sampling(Arc::new(|center| { + Some(match (RandomField::new(0).get(center)) % 8 { + 0 => Block::air(SpriteKind::IronSpike), + _ => Block::new(BlockKind::Air, Rgb::new(0, 0, 0)), + }) + })); + // npcs in upper chamber rooms + let mut chamber_npcs = vec![ + "common.entity.dungeon.terracotta.cursekeeper_fake", + "common.entity.dungeon.terracotta.cursekeeper_fake", + "common.entity.dungeon.terracotta.cursekeeper_fake", + "common.entity.dungeon.terracotta.cursekeeper", + ]; + let mut statue_npcs = vec![ + "common.entity.dungeon.terracotta.terracotta_statue_key", + "common.entity.dungeon.terracotta.terracotta_statue", + "common.entity.dungeon.terracotta.terracotta_statue", + "common.entity.dungeon.terracotta.terracotta_statue", + ]; + let mut cellar_statue_npcs = vec![ + "common.entity.dungeon.terracotta.terracotta_statue_key", + "common.entity.dungeon.terracotta.terracotta_statue", + "common.entity.dungeon.terracotta.terracotta_statue", + ]; + // models + let model_radius = (2 * (room_size / 3)) + 6; + for dir in NEIGHBORS { + let pos = center + dir * model_radius; + let palm_model_pos = Vec2::new(pos.x + 2, pos.y); + let found_var_a = (RandomField::new(0).get(pos.with_z(base)) % 10) as i32; + let found_var_b = (RandomField::new(0).get(pos.with_z(base + 1)) % 10) as i32; + let height_var = (found_var_a + found_var_b) / 2; + // foundation and decayed wall + let foundation_limiter_1 = painter.aabb(Aabb { + min: (pos - (room_size / 3) - 1 - found_var_a).with_z(base - room_size), + max: (pos + (room_size / 3) + 1 + found_var_b).with_z(base - 1 + height_var), + }); + painter + .rounded_aabb(Aabb { + min: (pos - (room_size / 3) - 1 - found_var_a).with_z(base - room_size), + max: (pos + (room_size / 3) + 1 + found_var_b).with_z(base + (room_size / 2)), + }) + .intersect(foundation_limiter_1) + .fill(clay_unbroken.clone()); + let foundation_limiter_2 = painter.aabb(Aabb { + min: (pos - (room_size / 3) - 1 - found_var_a).with_z(base - 2), + max: (pos + (room_size / 3) + 1 + found_var_b).with_z(base + height_var), + }); + painter + .rounded_aabb(Aabb { + min: (pos - (room_size / 3) - 1 - found_var_a).with_z(base - (room_size / 2)), + max: (pos + (room_size / 3) + 1 + found_var_b).with_z(base + (room_size / 2)), + }) + .intersect(foundation_limiter_2) + .fill(clay_broken_2.clone()); + let foundation_limiter_3 = painter.aabb(Aabb { + min: (pos - (room_size / 3) - 1 - found_var_a).with_z(base - 2), + max: (pos + (room_size / 3) + 1 + found_var_b).with_z(base + height_var + 8), + }); + painter + .rounded_aabb(Aabb { + min: (pos - (room_size / 3) + 2 - found_var_a).with_z(base - (room_size / 2)), + max: (pos + (room_size / 3) - 2 + found_var_b).with_z(base + (room_size / 2)), + }) + .intersect(foundation_limiter_3) + .clear(); + let foundation_limiter_4 = painter.aabb(Aabb { + min: (pos - (room_size / 3) - found_var_a).with_z(base - 2), + max: (pos + (room_size / 3) + found_var_b).with_z(base - 1), + }); + painter + .rounded_aabb(Aabb { + min: (pos - (room_size / 3) - found_var_a).with_z(base - (room_size / 2)), + max: (pos + (room_size / 3) + found_var_b).with_z(base + (room_size / 2)), + }) + .intersect(foundation_limiter_4) + .fill(sand.clone()); + // wall decay + for dir in NEIGHBORS { + let decay_pos = pos + (dir * (room_size / 3)); + painter + .sphere(Aabb { + min: (decay_pos - 8).with_z(base), + max: (decay_pos + 8).with_z(base + 16), + }) + .clear(); + } + // jungle sprites + painter + .cylinder(Aabb { + min: (pos - 12).with_z(base - 1), + max: (pos + 12).with_z(base), + }) + .fill(grass_fill.clone()); + // models + let model_pos = pos.with_z(base - 5); + lazy_static! { + pub static ref MODEL: AssetHandle = PrefabStructure::load_group( + "site_structures.terracotta.terracotta_decor_large" + ); + } + let rng = RandomField::new(0).get(model_pos) % 62; + let model = MODEL.read(); + let model = model[rng as usize % model.len()].clone(); + painter + .prim(Primitive::Prefab(Box::new(model.clone()))) + .translate(model_pos) + .fill(Fill::Prefab(Box::new(model), model_pos, rng)); + for dir in DIAGONALS { + let model_pos = palm_model_pos + dir * 12; + match RandomField::new(0).get(model_pos.with_z(base)) % 4 { + 0 => {}, + _ => { + for p in 0..2 { + let palm_pos = (model_pos + 3 + (2 * p)).with_z(base - 5); + // no palm tree above exit + let exit = Aabb { + min: (center - (room_size / 2) - 8).with_z(base - 6), + max: (center - (room_size / 2) + 8).with_z(base - 4), + }; + if !exit.contains_point(palm_pos) { + lazy_static! { + pub static ref MODEL: AssetHandle = + PrefabStructure::load_group("trees.palms"); + } + let rng = RandomField::new(0).get(palm_pos) % 62; + let model = MODEL.read(); + let model = model[rng as usize % model.len()].clone(); + painter + .prim(Primitive::Prefab(Box::new(model.clone()))) + .translate(palm_pos) + .fill(Fill::Prefab(Box::new(model), palm_pos, rng)); + } + } + }, + } + } + } + // pavillon + let mut pavillons = vec![]; + let pavillon_dist_x = room_size / 3; + let pavillon_dist_y = 2 * (room_size / 3); + let pavillon_size_1 = room_size / 8; + let pavillon_size_2 = room_size / 10; + for dir in DIAGONALS { + pavillons.push(Vec2::new( + center.x + dir.x * pavillon_dist_x, + center.y + dir.y * pavillon_dist_y, + )); + pavillons.push(Vec2::new( + center.x + dir.x * pavillon_dist_y, + center.y + dir.y * pavillon_dist_x, + )); + } + for pavillon_pos in pavillons { + let entry_carve_limiter = painter.aabb(Aabb { + min: (pavillon_pos - pavillon_size_1).with_z(base - pavillon_size_1), + max: (pavillon_pos + pavillon_size_1).with_z(base + pavillon_size_1), + }); + let top_carve_limiter = painter.aabb(Aabb { + min: (pavillon_pos - pavillon_size_2).with_z(base + pavillon_size_1 - 2), + max: (pavillon_pos + pavillon_size_2) + .with_z(base + pavillon_size_1 + pavillon_size_2 - 2), + }); + // base + painter + .superquadric( + Aabb { + min: (pavillon_pos - pavillon_size_1).with_z(base - pavillon_size_1), + max: (pavillon_pos + pavillon_size_1).with_z(base + pavillon_size_1), + }, + 2.5, + ) + .fill(clay_broken.clone()); + // top + painter + .superquadric( + Aabb { + min: (pavillon_pos - pavillon_size_2).with_z(base + pavillon_size_1 - 2), + max: (pavillon_pos + pavillon_size_2) + .with_z(base + pavillon_size_1 + pavillon_size_2 - 2), + }, + 2.5, + ) + .fill(clay_broken.clone()); + painter + .superquadric( + Aabb { + min: (pavillon_pos - pavillon_size_2 + 1) + .with_z(base + pavillon_size_1 - 1), + max: (pavillon_pos + pavillon_size_2 - 1) + .with_z(base + pavillon_size_1 + pavillon_size_2 - 3), + }, + 2.5, + ) + .fill(roof_color.clone()); + painter + .aabb(Aabb { + min: (pavillon_pos - 2).with_z(base + pavillon_size_1 + pavillon_size_2 - 3), + max: (pavillon_pos + 2).with_z(base + pavillon_size_1 + pavillon_size_2 - 2), + }) + .fill(roof_color.clone()); + painter + .aabb(Aabb { + min: (pavillon_pos - 1).with_z(base + pavillon_size_1 + pavillon_size_2 - 2), + max: (pavillon_pos + 1).with_z(base + pavillon_size_1 + pavillon_size_2), + }) + .fill(roof_color.clone()); + for dir in CARDINALS { + let pavillon_carve_pos = pavillon_pos + dir * pavillon_size_2; + // entries + painter + .superquadric( + Aabb { + min: (pavillon_carve_pos - pavillon_size_2 + 3).with_z(base - 1), + max: (pavillon_carve_pos + pavillon_size_2 - 2) + .with_z(base + pavillon_size_2 - 1), + }, + 2.5, + ) + .intersect(entry_carve_limiter) + .clear(); + // top carve + painter + .superquadric( + Aabb { + min: (pavillon_carve_pos - pavillon_size_2 + 2) + .with_z(base + pavillon_size_1 + 2), + max: (pavillon_carve_pos + pavillon_size_2 - 2) + .with_z(base + pavillon_size_1 + pavillon_size_2 + 2), + }, + 2.5, + ) + .intersect(top_carve_limiter) + .clear(); + } + // center clear + painter + .cylinder(Aabb { + min: (pavillon_pos - pavillon_size_2 + 2).with_z(base - 1), + max: (pavillon_pos + pavillon_size_2 - 2).with_z(base + 5), + }) + .clear(); + // solid floor + painter + .cylinder(Aabb { + min: (pavillon_pos - pavillon_size_2 - 2).with_z(base - 2), + max: (pavillon_pos + pavillon_size_2 + 2).with_z(base - 1), + }) + .fill(clay_unbroken.clone()); + } + // base room + painter + .superquadric( + Aabb { + min: (center - (room_size / 2)).with_z(base - (room_size / 2)), + max: (center + (room_size / 2)).with_z(base + (room_size / 2)), + }, + 2.5, + ) + .fill(clay_broken.clone()); + // solid bottom + painter + .superquadric( + Aabb { + min: (center - (room_size / 2)).with_z(base - (room_size / 2)), + max: (center + (room_size / 2)).with_z(base + (room_size / 2)), + }, + 2.5, + ) + .intersect(clear_limit_down) + .fill(clay_unbroken.clone()); + // roof and top rooms + for s in 0..storeys { + painter + .superquadric( + Aabb { + min: (center - (roof_size / 2) + (s * var)).with_z( + base + roof_height - (size / 4) + (s * (roof_size / 4)) + (s * var), + ), + max: (center + (roof_size / 2) - (s * var)).with_z( + base + roof_height - (size / 4) + roof_size + (s * (roof_size / 4)) + - (s * var), + ), + }, + 2.5, + ) + .fill(clay_broken.clone()); + painter + .superquadric( + Aabb { + min: (center - (roof_size / 2) + (s * var) + 1).with_z( + base + roof_height - (size / 4) + (s * (roof_size / 4)) + (s * var) + 1, + ), + max: (center + (roof_size / 2) - (s * var) - 1).with_z( + base + roof_height - (size / 4) + roof_size + (s * (roof_size / 4)) + - (s * var) + - 1, + ), + }, + 2.5, + ) + .fill(roof_color.clone()); + for dir in CARDINALS { + let pos = center + dir * (size - (s * var)); + + painter + .superquadric( + Aabb { + min: (pos - (carve_size / 2) + (s * clear_var)).with_z( + base + roof_height + (s * (roof_size / 4)) + (s * clear_var), + ), + max: (pos + (carve_size / 2) - (s * clear_var)).with_z( + base + roof_height + carve_size + (s * (roof_size / 4)) + - (s * clear_var), + ), + }, + 2.5, + ) + .intersect(clear_limit) + .clear(); + } + } + // clear base room & entries + painter + .superquadric( + Aabb { + min: (center - (room_size / 2) + 5).with_z(base - (room_size / 2) + 5), + max: (center + (room_size / 2) - 5).with_z(base + (room_size / 2) - 5), + }, + 2.5, + ) + .union( + painter + .superquadric( + Aabb { + min: Vec2::new( + center.x - (room_size / 4), + center.y - (3 * room_size / 4), + ) + .with_z(base - (room_size / 4)), + max: Vec2::new( + center.x + (room_size / 4), + center.y + (3 * room_size / 4), + ) + .with_z(base + (room_size / 4)), + }, + 2.5, + ) + .union( + painter.superquadric( + Aabb { + min: Vec2::new( + center.x - (3 * room_size / 4), + center.y - (room_size / 4), + ) + .with_z(base - (room_size / 4)), + max: Vec2::new( + center.x + (3 * room_size / 4), + center.y + (room_size / 4), + ) + .with_z(base + (room_size / 4)), + }, + 2.5, + ), + ), + ) + .intersect(clear_limit) + .clear(); + // clear top + painter + .superquadric( + Aabb { + min: (center - (room_size / 3)) + .with_z(base + (3 * (room_size / 10)) - (room_size / 3)), + max: (center + (room_size / 3)) + .with_z(base + (3 * (room_size / 10)) + (room_size / 4)), + }, + 2.5, + ) + .clear(); + painter + .superquadric( + Aabb { + min: (center - (room_size / 4)) + .with_z(base + (3 * (room_size / 10)) - (room_size / 4)), + max: (center + (room_size / 4)) + .with_z(base + (3 * (room_size / 10)) + (room_size / 3)), + }, + 2.5, + ) + .clear(); + // top floor with center clearing + painter + .cylinder(Aabb { + min: (center - (room_size / 2) + 8).with_z(base + (3 * (room_size / 10)) - 1), + max: (center + (room_size / 2) - 8).with_z(base + (3 * (room_size / 10)) + 2), + }) + .fill(clay_unbroken.clone()); + painter + .cylinder(Aabb { + min: (center - (room_size / 4)).with_z(base + (3 * (room_size / 10)) - 1), + max: (center + (room_size / 4)).with_z(base + (3 * (room_size / 10)) + 2), + }) + .clear(); + // center podium with spikes + painter + .cylinder(Aabb { + min: (center - (room_size / 4)).with_z(base + (3 * (room_size / 10)) + 1), + max: (center + (room_size / 4)).with_z(base + (3 * (room_size / 10)) + 2), + }) + .fill(Fill::Block(Block::air(SpriteKind::IronSpike))); + painter + .cylinder(Aabb { + min: (center - (room_size / 8) - 5).with_z(base - 1), + max: (center + (room_size / 8) + 5).with_z(base), + }) + .fill(clay_unbroken.clone()); + painter + .cylinder(Aabb { + min: (center - (room_size / 8) - 4).with_z(base), + max: (center + (room_size / 8) + 4).with_z(base + 1), + }) + .fill(Fill::Block(Block::air(SpriteKind::IronSpike))); + painter + .cylinder(Aabb { + min: (center - (room_size / 8) - 3).with_z(base + 1), + max: (center + (room_size / 8) + 3).with_z(base + (3 * (room_size / 10)) + 2), + }) + .fill(spikes_fill); + painter + .cylinder(Aabb { + min: (center - (room_size / 8) - 2).with_z(base - 20), + max: (center + (room_size / 8) + 2).with_z(base + (3 * (room_size / 10)) + 2), + }) + .fill(clay_unbroken.clone()); + painter + .cylinder(Aabb { + min: (center - (room_size / 8)).with_z(base + (3 * (room_size / 10)) + 1), + max: (center + (room_size / 8)).with_z(base + (3 * (room_size / 10)) + 2), + }) + .fill(roof_color.clone()); + painter + .cylinder(Aabb { + min: (center - (room_size / 8)).with_z(base - 10), + max: (center + (room_size / 8)).with_z(base - 15), + }) + .fill(roof_color.clone()); + // cellar + painter + .superquadric( + Aabb { + min: (center - (room_size / 2)).with_z(base - 10 - room_size), + max: (center + (room_size / 2)).with_z(base - 10), + }, + 2.5, + ) + .fill(clay_unbroken.clone()); + // cellar chambers + painter + .line( + Vec2::new(center.x - (room_size / 2) - 8, center.y) + .with_z(base - 10 - (room_size / 2)), + Vec2::new(center.x + (room_size / 2) + 8, center.y) + .with_z(base - 10 - (room_size / 2)), + 8.0, + ) + .fill(clay_unbroken.clone()); + painter + .line( + Vec2::new(center.x, center.y - (room_size / 2) - 8) + .with_z(base - 10 - (room_size / 2)), + Vec2::new(center.x, center.y + (room_size / 2) + 8) + .with_z(base - 10 - (room_size / 2)), + 8.0, + ) + .fill(clay_unbroken.clone()); + painter + .line( + Vec2::new(center.x - (room_size / 2) - 8, center.y) + .with_z(base - 10 - (room_size / 2)), + Vec2::new(center.x + (room_size / 2) + 8, center.y) + .with_z(base - 10 - (room_size / 2)), + 5.0, + ) + .clear(); + painter + .line( + Vec2::new(center.x, center.y - (room_size / 2) - 8) + .with_z(base - 10 - (room_size / 2)), + Vec2::new(center.x, center.y + (room_size / 2) + 8) + .with_z(base - 10 - (room_size / 2)), + 5.0, + ) + .clear(); + // chamber rooms + for dir in CARDINALS { + let room_center = center + dir * ((room_size / 2) + 8); + // floor decor in chamber rooms + painter + .cylinder(Aabb { + min: (room_center - 3).with_z(base - 16 - (room_size / 2) - (room_size / 16)), + max: (room_center + 3).with_z(base - 6 - (room_size / 2) - (room_size / 16)), + }) + .clear(); + // npcs in chamber rooms + let npc_pos = room_center.with_z(base - 16 - (room_size / 2) - (room_size / 16)); + let npc = chamber_npcs + .swap_remove(RandomField::new(0).get(npc_pos) as usize % chamber_npcs.len()); + + painter.spawn(EntityInfo::at(npc_pos.as_()).with_asset_expect(npc, &mut rng, None)); + } + // chamber_1 + painter + .aabb(Aabb { + min: Vec2::new(center.x - (room_size / 2), center.y - 5) + .with_z(base - 10 - (room_size / 2)), + max: Vec2::new(center.x - (room_size / 2) + 1, center.y + 5) + .with_z(base - 10 - (room_size / 2) + 5), + }) + .fill(Fill::Block(Block::air(SpriteKind::TerracottaKeyDoor))); + painter + .aabb(Aabb { + min: Vec2::new(center.x - (room_size / 2), center.y) + .with_z(base - 10 - (room_size / 2) + 1), + max: Vec2::new(center.x - (room_size / 2) + 1, center.y + 1) + .with_z(base - 10 - (room_size / 2) + 2), + }) + .fill(Fill::Block(Block::air(SpriteKind::TerracottaKeyhole))); + // chamber_2 + painter + .aabb(Aabb { + min: Vec2::new(center.x + (room_size / 2) - 1, center.y - 5) + .with_z(base - 10 - (room_size / 2)), + max: Vec2::new(center.x + (room_size / 2), center.y + 5) + .with_z(base - 10 - (room_size / 2) + 5), + }) + .fill(Fill::Block(Block::air(SpriteKind::TerracottaKeyDoor))); + painter + .aabb(Aabb { + min: Vec2::new(center.x + (room_size / 2) - 1, center.y) + .with_z(base - 10 - (room_size / 2) + 1), + max: Vec2::new(center.x + (room_size / 2), center.y + 1) + .with_z(base - 10 - (room_size / 2) + 2), + }) + .fill(Fill::Block(Block::air(SpriteKind::TerracottaKeyhole))); + // chamber_3 + painter + .aabb(Aabb { + min: Vec2::new(center.x - 5, center.y - (room_size / 2)) + .with_z(base - 10 - (room_size / 2)), + max: Vec2::new(center.x + 5, center.y - (room_size / 2) + 1) + .with_z(base - 10 - (room_size / 2) + 5), + }) + .fill(Fill::Block(Block::air(SpriteKind::TerracottaKeyDoor))); + painter + .aabb(Aabb { + min: Vec2::new(center.x, center.y - (room_size / 2)) + .with_z(base - 10 - (room_size / 2) + 1), + max: Vec2::new(center.x + 1, center.y - (room_size / 2) + 1) + .with_z(base - 10 - (room_size / 2) + 2), + }) + .fill(Fill::Block(Block::air(SpriteKind::TerracottaKeyhole))); + // chamber_4 + painter + .aabb(Aabb { + min: Vec2::new(center.x - 5, center.y + (room_size / 2) - 1) + .with_z(base - 10 - (room_size / 2)), + max: Vec2::new(center.x + 5, center.y + (room_size / 2)) + .with_z(base - 10 - (room_size / 2) + 5), + }) + .fill(Fill::Block(Block::air(SpriteKind::TerracottaKeyDoor))); + painter + .aabb(Aabb { + min: Vec2::new(center.x, center.y + (room_size / 2) - 1) + .with_z(base - 10 - (room_size / 2) + 1), + max: Vec2::new(center.x + 1, center.y + (room_size / 2)) + .with_z(base - 10 - (room_size / 2) + 2), + }) + .fill(Fill::Block(Block::air(SpriteKind::TerracottaKeyhole))); + // clear cellar + painter + .superquadric( + Aabb { + min: (center - (room_size / 2) + 1).with_z(base - 10 - room_size + 1), + max: (center + (room_size / 2) - 1).with_z(base - 10 - 1), + }, + 2.5, + ) + .clear(); + // cellar exit tunnel to surface + // hide tunnel to prevent climbing on top to cheese + let sq_limit = painter.aabb(Aabb { + min: (center - (room_size / 4) - 11).with_z(base - 20 - (room_size / 2)), + max: (center - (room_size / 4) + 16).with_z(base - 1), + }); + painter + .superquadric( + Aabb { + min: (center - (room_size / 4) - 9).with_z(base - 20 - (room_size / 2)), + max: (center - (room_size / 4) + 16).with_z(base + 20), + }, + 3.5, + ) + .intersect(sq_limit) + .fill(clay_unbroken.clone()); + let cyl_1_pos = Vec2::new( + center.x - (room_size / 4) - 2, + center.y - (room_size / 4) - 13, + ); + let cyl_2_pos = Vec2::new( + center.x - (room_size / 4) - 12, + center.y - (room_size / 4) - 5, + ); + painter + .aabb(Aabb { + min: (cyl_1_pos - 15).with_z(base - 10 - (room_size / 2)), + max: (cyl_1_pos + 15).with_z(base - 10), + }) + .fill(clay_unbroken.clone()); + + painter + .aabb(Aabb { + min: (cyl_2_pos - 15).with_z(base - 10 - (room_size / 2)), + max: (cyl_2_pos + 15).with_z(base - 10), + }) + .fill(clay_unbroken.clone()); + // tunnel + painter + .line( + (center - (room_size / 4)).with_z(base - 10 - (room_size / 2)), + (center - (room_size / 2)).with_z(base - 5), + 10.0, + ) + .fill(clay_unbroken.clone()); + // exit + let exit_pos = Vec2::new( + center.x - (room_size / 4) + 9, + center.y + 4 - (room_size / 4), + ); + painter + .cylinder(Aabb { + min: (exit_pos - 4).with_z(base - 10 - (room_size / 2)), + max: (exit_pos + 5).with_z(base + 4 - (room_size / 2)), + }) + .fill(clay_unbroken.clone()); + painter + .aabb(Aabb { + min: Vec2::new(exit_pos.x + 5, exit_pos.y - 2).with_z(base - 10 - (room_size / 2)), + max: Vec2::new(exit_pos.x + 6, exit_pos.y + 3).with_z(base + 25 - (room_size / 2)), + }) + .fill(clay_unbroken.clone()); + painter + .aabb(Aabb { + min: Vec2::new(exit_pos.x + 5, exit_pos.y - 1).with_z(base - 10 - (room_size / 2)), + max: Vec2::new(exit_pos.x + 6, exit_pos.y + 2).with_z(base + 6 - (room_size / 2)), + }) + .clear(); + painter + .cylinder(Aabb { + min: (exit_pos - 3).with_z(base - 10 - (room_size / 2)), + max: (exit_pos + 4).with_z(base + 10 - (room_size / 2)), + }) + .clear(); + painter + .aabb(Aabb { + min: Vec2::new(exit_pos.x + 4, exit_pos.y - 1).with_z(base + 3 - (room_size / 2)), + max: Vec2::new(exit_pos.x + 5, exit_pos.y + 2).with_z(base + 6 - (room_size / 2)), + }) + .clear(); + painter + .aabb(Aabb { + min: Vec2::new(exit_pos.x + 4, exit_pos.y - 1).with_z(base + 2 - (room_size / 2)), + max: Vec2::new(exit_pos.x + 5, exit_pos.y + 2).with_z(base + 3 - (room_size / 2)), + }) + .fill(Fill::Block(Block::air(SpriteKind::IronSpike))); + painter + .aabb(Aabb { + min: Vec2::new(exit_pos.x + 5, exit_pos.y - 1).with_z(base - 10 - (room_size / 2)), + max: Vec2::new(exit_pos.x + 6, exit_pos.y + 2).with_z(base + 6 - (room_size / 2)), + }) + .fill(Fill::Block(Block::air(SpriteKind::TerracottaKeyDoor))); + painter + .aabb(Aabb { + min: Vec2::new(exit_pos.x + 5, exit_pos.y).with_z(base - 9 - (room_size / 2)), + max: Vec2::new(exit_pos.x + 6, exit_pos.y + 1).with_z(base - 8 - (room_size / 2)), + }) + .fill(Fill::Block(Block::air(SpriteKind::TerracottaKeyhole))); + // chests + let chests_position = exit_pos + 8; + painter + .cylinder(Aabb { + min: (chests_position - 4).with_z(base - 10 - (room_size / 2)), + max: (chests_position + 5).with_z(base - 9 - (room_size / 2)), + }) + .fill(roof_color.clone()); + painter + .cylinder(Aabb { + min: (chests_position - 3).with_z(base - 10 - (room_size / 2)), + max: (chests_position + 4).with_z(base - 9 - (room_size / 2)), + }) + .fill(clay_unbroken.clone()); + for dir in CARDINALS { + let chest_pos = chests_position + (dir * 2); + painter.sprite( + chest_pos.with_z(base - 9 - (room_size / 2)), + SpriteKind::TerracottaChest, + ); + } + // npcs + // outside statues and npcs on pillars + for dir in DIAGONALS { + let pos = center + dir * ((size / 2) + 6); + painter + .cylinder(Aabb { + min: (pos - 3).with_z(base - (room_size / 2)), + max: (pos + 3).with_z(base + 3), + }) + .fill(clay_broken.clone()); + painter + .cylinder(Aabb { + min: (pos - 4).with_z(base + 3), + max: (pos + 4).with_z(base + 4), + }) + .fill(clay_broken_2.clone()); + painter + .cylinder(Aabb { + min: (pos - 5).with_z(base + 4), + max: (pos + 5).with_z(base + 5), + }) + .fill(clay_broken_2.clone()); + painter + .cylinder(Aabb { + min: (pos - 6).with_z(base + 5), + max: (pos + 6).with_z(base + 6), + }) + .fill(clay_broken.clone()); + painter + .cylinder(Aabb { + min: (pos - 4).with_z(base + 5), + max: (pos + 4).with_z(base + 6), + }) + .fill(Fill::Block(Block::air(SpriteKind::TerracottaBlock))); + painter + .cylinder(Aabb { + min: (pos - 4).with_z(base + 4), + max: (pos + 4).with_z(base + 5), + }) + .fill(Fill::Block(Block::air(SpriteKind::IronSpike))); + painter + .cylinder(Aabb { + min: (pos - 1).with_z(base + 4), + max: (pos + 1).with_z(base + 6), + }) + .fill(clay_broken.clone()); + + let pillar_npc_pos = (center + dir * ((size / 2) + 9)).with_z(base + 6); + let statue_pos = (center + dir * ((size / 2) + 8)).with_z(base + 6); + + spawn_random_entity(pillar_npc_pos, painter, 1..=1); + + // npcs in upper chamber rooms + let statue = statue_npcs + .swap_remove(RandomField::new(0).get(statue_pos) as usize % statue_npcs.len()); + painter.spawn( + EntityInfo::at((statue_pos).as_()).with_asset_expect(statue, &mut rng, None), + ); + } + // clear tunnel + painter + .line( + (center - (room_size / 4)).with_z(base - 10 - (room_size / 2)), + (center - (room_size / 2)).with_z(base), + 7.0, + ) + .clear(); + painter + .cylinder(Aabb { + min: (center - (room_size / 2) - 10).with_z(base), + max: (center - (room_size / 2) + 10).with_z(base + 10), + }) + .clear(); + // cellar entry from podium top + painter + .cylinder(Aabb { + min: (center - (room_size / 8) + 3).with_z(base - 20), + max: (center + (room_size / 8) - 3).with_z(base + (3 * (room_size / 10)) + 2), + }) + .clear(); + painter + .cylinder(Aabb { + min: (center - (room_size / 8) + 3).with_z(base + (3 * (room_size / 10)) + 1), + max: (center + (room_size / 8) - 3).with_z(base + (3 * (room_size / 10)) + 2), + }) + .fill(Fill::Block(Block::air(SpriteKind::IronSpike))); + painter + .cylinder(Aabb { + min: (center - 2).with_z(base + (3 * (room_size / 10)) + 1), + max: (center + 2).with_z(base + (3 * (room_size / 10)) + 2), + }) + .fill(Fill::Block(Block::air(SpriteKind::TerracottaKeyDoor))); + painter + .cylinder(Aabb { + min: (center).with_z(base + (3 * (room_size / 10)) + 1), + max: (center + 1).with_z(base + (3 * (room_size / 10)) + 2), + }) + .fill(Fill::Block(Block::air(SpriteKind::TerracottaKeyhole))); + // cellar floor + painter + .aabb(Aabb { + min: (center - (room_size / 2)).with_z(base - 10 - room_size), + max: (center + (room_size / 2)).with_z(base - 10 - (room_size / 2)), + }) + .fill(clay_unbroken.clone()); + // sprites + // top room lamps and chests + let lamps_top = 6.0_f32; + let radius_lamps_top = (room_size / 4) + 3; + let phi_lamps_top = TAU / lamps_top; + for n in 1..=lamps_top as i32 { + let pos = Vec2::new( + center.x + (radius_lamps_top as f32 * ((n as f32 * phi_lamps_top).cos())) as i32, + center.y + (radius_lamps_top as f32 * ((n as f32 * phi_lamps_top).sin())) as i32, + ); + painter.sprite( + pos.with_z(base + (3 * (room_size / 10)) + 2), + SpriteKind::TerracottaStatue, + ); + } + let chests = 4.0_f32; + let radius_chests = (room_size / 4) + 6; + let phi_chests = TAU / chests; + for n in 1..=chests as i32 { + let pos = Vec2::new( + center.x + (radius_chests as f32 * ((n as f32 * phi_chests).cos())) as i32, + center.y + (radius_chests as f32 * ((n as f32 * phi_chests).sin())) as i32, + ); + painter.sprite( + pos.with_z(base + (3 * (room_size / 10)) + 2), + SpriteKind::TerracottaChest, + ); + } + // main room lamps + let radius_lamps_main = (room_size / 4) + 12; + let lamps_main = 8.0_f32; + let phi_lamps_main = TAU / lamps_main; + for n in 1..=lamps_main as i32 { + let pos = Vec2::new( + center.x + (radius_lamps_main as f32 * ((n as f32 * phi_lamps_main).cos())) as i32, + center.y + (radius_lamps_main as f32 * ((n as f32 * phi_lamps_main).sin())) as i32, + ); + painter.sprite(pos.with_z(base), SpriteKind::TerracottaStatue); + } + // cellar statues + let radius_statues_cellar = (room_size / 2) - 12; + let statues_cellar = 11.0_f32; + let phi_statues_cellar = TAU / statues_cellar; + for n in 1..=statues_cellar as i32 { + let pos = Vec2::new( + center.x + + (radius_statues_cellar as f32 * ((n as f32 * phi_statues_cellar).cos())) + as i32, + center.y + + (radius_statues_cellar as f32 * ((n as f32 * phi_statues_cellar).sin())) + as i32, + ); + match n { + 1 | 5 | 9 => { + painter + .cylinder(Aabb { + min: (pos - 8).with_z(base - 22 - (room_size / 2)), + max: (pos + 8).with_z(base - 10 - (room_size / 2)), + }) + .clear(); + painter + .cylinder(Aabb { + min: (pos - 8).with_z(base - 22 - (room_size / 2)), + max: (pos + 8).with_z(base - 21 - (room_size / 2)), + }) + .fill(Fill::Block(Block::air(SpriteKind::IronSpike))); + painter + .cylinder(Aabb { + min: (pos - 8).with_z(base - 11 - (room_size / 2)), + max: (pos + 8).with_z(base - 10 - (room_size / 2)), + }) + .fill(Fill::Block(Block::air(SpriteKind::TerracottaBlock))); + painter + .cylinder(Aabb { + min: (pos).with_z(base - 22 - (room_size / 2)), + max: (pos + 1).with_z(base - 10 - (room_size / 2)), + }) + .fill(clay_unbroken.clone()); + let cellar_statue_pos = pos.with_z(base - 10 - (room_size / 2)); + let cellar_statue = cellar_statue_npcs.swap_remove( + RandomField::new(0).get(cellar_statue_pos) as usize + % cellar_statue_npcs.len(), + ); + painter.spawn(EntityInfo::at(cellar_statue_pos.as_()).with_asset_expect( + cellar_statue, + &mut rng, + None, + )); + }, + _ => { + painter.sprite( + pos.with_z(base - 10 - (room_size / 2)), + SpriteKind::TerracottaStatue, + ); + }, + } + } + // npcs on top floor + let npcs = 3.0_f32; + let radius_npcs = (room_size / 4) + 6; + let phi_npcs = TAU / npcs; + for n in 1..=npcs as i32 { + let pos = Vec2::new( + center.x + (radius_npcs as f32 * ((n as f32 * phi_npcs).cos())) as i32, + center.y + (radius_npcs as f32 * ((n as f32 * phi_npcs).sin())) as i32, + ) + .with_z(base + (3 * (room_size / 10)) + 2); + spawn_random_entity(pos, painter, 1..=1); + } + // platform mogwai + painter.spawn( + EntityInfo::at((center.with_z(base + (3 * (room_size / 10)) + 2)).as_()) + .with_asset_expect("common.entity.dungeon.terracotta.mogwai", &mut rng, None), + ); + + // main room npcs + let radius_npcs_main = (room_size / 4) + 10; + let npcs_main = 10.0_f32; + let phi_npcs_main = TAU / npcs_main; + for n in 1..=npcs_main as i32 { + let pos = Vec2::new( + center.x + (radius_npcs_main as f32 * ((n as f32 * phi_npcs_main).cos())) as i32, + center.y + (radius_npcs_main as f32 * ((n as f32 * phi_npcs_main).sin())) as i32, + ) + .with_z(base); + spawn_random_entity(pos, painter, 1..=1); + } + } +} + +pub fn spawn_random_entity(pos: Vec3, painter: &Painter, amount: RangeInclusive) { + let mut rng = thread_rng(); + let entities = [ + "common.entity.dungeon.terracotta.besieger", + "common.entity.dungeon.terracotta.demolisher", + "common.entity.dungeon.terracotta.punisher", + "common.entity.dungeon.terracotta.pursuer", + "common.entity.dungeon.terracotta.shamanic_spirit", + "common.entity.dungeon.terracotta.jiangshi", + ]; + for n in amount { + let random_entity_index = rng.gen_range(0..entities.len()); + let random_entity = entities[random_entity_index]; + let position = Vec3::new(pos.x + n, pos.y + n, pos.z); + painter.spawn(EntityInfo::at(position.as_()).with_asset_expect( + random_entity, + &mut rng, + None, + )); + } +} diff --git a/world/src/site2/plot/terracotta_yard.rs b/world/src/site2/plot/terracotta_yard.rs new file mode 100644 index 0000000000..55a10df04c --- /dev/null +++ b/world/src/site2/plot/terracotta_yard.rs @@ -0,0 +1,255 @@ +use super::*; +use crate::{ + assets::AssetHandle, + site2::gen::PrimitiveTransform, + util::{RandomField, Sampler, NEIGHBORS}, + Land, +}; +use common::{ + generation::EntityInfo, + terrain::{BlockKind, SpriteKind, Structure as PrefabStructure, StructuresGroup}, +}; +use lazy_static::lazy_static; +use rand::prelude::*; +use std::{f32::consts::TAU, sync::Arc}; +use vek::*; + +/// Represents house data generated by the `generate()` method +pub struct TerracottaYard { + /// Axis aligned bounding region for the house + bounds: Aabr, + /// Approximate altitude of the door tile + pub(crate) alt: i32, +} + +impl TerracottaYard { + pub fn generate(land: &Land, _rng: &mut impl Rng, site: &Site, tile_aabr: Aabr) -> Self { + let bounds = Aabr { + min: site.tile_wpos(tile_aabr.min), + max: site.tile_wpos(tile_aabr.max), + }; + Self { + bounds, + alt: land.get_alt_approx(site.tile_center_wpos((tile_aabr.max - tile_aabr.min) / 2)) + as i32 + + 2, + } + } + + pub fn spawn_rules(&self, wpos: Vec2) -> SpawnRules { + SpawnRules { + waypoints: false, + trees: wpos.distance_squared(self.bounds.center()) > (85_i32).pow(2), + ..SpawnRules::default() + } + } +} + +impl Structure for TerracottaYard { + #[cfg(feature = "use-dyn-lib")] + const UPDATE_FN: &'static [u8] = b"render_terracotta_yard\0"; + + #[cfg_attr(feature = "be-dyn-lib", export_name = "render_terracotta_yard")] + fn render_inner(&self, _site: &Site, _land: &Land, painter: &Painter) { + let base = self.alt + 4; + let center = self.bounds.center(); + let mut rng = thread_rng(); + let clay_unbroken = Fill::Sampling(Arc::new(|center| { + Some(match (RandomField::new(0).get(center)) % 40 { + 0..=8 => Block::new(BlockKind::Rock, Rgb::new(242, 161, 53)), + 9..=17 => Block::new(BlockKind::Rock, Rgb::new(253, 199, 81)), + 18..=26 => Block::new(BlockKind::Rock, Rgb::new(254, 210, 91)), + 27..=35 => Block::new(BlockKind::Rock, Rgb::new(254, 216, 101)), + _ => Block::new(BlockKind::Rock, Rgb::new(250, 185, 71)), + }) + })); + let clay_broken = Fill::Sampling(Arc::new(|center| { + Some(match (RandomField::new(0).get(center)) % 42 { + 0..=8 => Block::new(BlockKind::Rock, Rgb::new(242, 161, 53)), + 9..=17 => Block::new(BlockKind::Rock, Rgb::new(253, 199, 81)), + 18..=26 => Block::new(BlockKind::Rock, Rgb::new(254, 210, 91)), + 27..=35 => Block::new(BlockKind::Rock, Rgb::new(254, 216, 101)), + 36..=38 => Block::new(BlockKind::Air, Rgb::new(0, 0, 0)), + _ => Block::new(BlockKind::Rock, Rgb::new(250, 185, 71)), + }) + })); + let grass_fill = Fill::Sampling(Arc::new(|wpos| { + Some(match (RandomField::new(0).get(wpos)) % 20 { + 1..=2 => Block::air(SpriteKind::JungleRedGrass), + 3..=7 => Block::air(SpriteKind::JungleLeafyPlant), + 8 => Block::air(SpriteKind::JungleFern), + _ => Block::new(BlockKind::Air, Rgb::new(0, 0, 0)), + }) + })); + let water_fill = Fill::Block(Block::new(BlockKind::Water, Rgb::zero())); + let sand = Fill::Brick(BlockKind::Misc, Rgb::new(235, 178, 99), 12); + let size = 30; + let room_size = 15 * (size / 10); + let water = RandomField::new(0).get(center.with_z(base)) % 2; + // foundation + painter + .superquadric( + Aabb { + min: (center - (room_size / 2) - 10).with_z(base - room_size - 15), + max: (center + (room_size / 2) + 10).with_z(base + 5), + }, + 2.5, + ) + .fill(clay_unbroken.clone()); + // clear floor + let clear_limit = painter.aabb(Aabb { + min: (center - (room_size / 2) - 5).with_z(base), + max: (center + (room_size / 2) + 5).with_z(base + room_size), + }); + painter + .superquadric( + Aabb { + min: (center - (room_size / 2) - 5).with_z(base - (room_size / 2) - 5), + max: (center + (room_size / 2) + 5).with_z(base + room_size), + }, + 2.5, + ) + .intersect(clear_limit) + .clear(); + if water < 1 { + // iron spike trap + painter + .cylinder(Aabb { + min: (center - (room_size / 4)).with_z(base - 12), + max: (center + (room_size / 4)).with_z(base), + }) + .clear(); + painter + .cylinder(Aabb { + min: (center - (room_size / 4)).with_z(base - 13), + max: (center + (room_size / 4)).with_z(base - 12), + }) + .fill(Fill::Block(Block::air(SpriteKind::IronSpike))); + painter + .cylinder(Aabb { + min: (center - (room_size / 4)).with_z(base - 1), + max: (center + (room_size / 4)).with_z(base), + }) + .fill(Fill::Block(Block::air(SpriteKind::TerracottaBlock))); + painter + .cylinder(Aabb { + min: (center).with_z(base - 14), + max: (center + 1).with_z(base), + }) + .fill(clay_unbroken); + // sprites + let radius_lamps_main = (room_size / 4) + 6; + let lamps_main = 8.0_f32; + let phi_lamps_main = TAU / lamps_main; + for n in 1..=lamps_main as i32 { + let pos = Vec2::new( + center.x + + (radius_lamps_main as f32 * ((n as f32 * phi_lamps_main).cos())) as i32, + center.y + + (radius_lamps_main as f32 * ((n as f32 * phi_lamps_main).sin())) as i32, + ); + painter.sprite(pos.with_z(base), SpriteKind::TerracottaStatue); + } + // npcs + // statue + painter.spawn( + EntityInfo::at((center).with_z(base).as_()).with_asset_expect( + "common.entity.dungeon.terracotta.terracotta_statue_key", + &mut rng, + None, + ), + ); + } else { + let basin = painter.superquadric( + Aabb { + min: (center - (room_size / 4) - 12).with_z(base - 12), + max: (center + (room_size / 4) + 12).with_z(base + 12), + }, + 2.5, + ); + basin.clear(); + let water_level = (RandomField::new(0).get(center.with_z(base)) % 8) as i32; + let water_limit = painter.aabb(Aabb { + min: (center - (room_size / 4) - 12).with_z(base - 12), + max: (center + (room_size / 4) + 12).with_z(base - 4 - water_level), + }); + basin.intersect(water_limit).fill(water_fill); + // models + let model_radius = (room_size / 2) + 7; + for dir in NEIGHBORS { + let pos = center + dir * model_radius; + // foundation + painter + .cylinder(Aabb { + min: (pos - 10).with_z(base - room_size), + max: (pos + 10).with_z(base - 3), + }) + .fill(clay_unbroken.clone()); + painter + .cylinder(Aabb { + min: (pos - 10).with_z(base - 4), + max: (pos + 10).with_z(base - 3), + }) + .fill(clay_broken.clone()); + painter + .cylinder(Aabb { + min: (pos - 9).with_z(base - 4), + max: (pos + 9).with_z(base - 3), + }) + .fill(sand.clone()); + // jungle sprites + painter + .cylinder(Aabb { + min: (pos - 7).with_z(base - 3), + max: (pos + 7).with_z(base - 2), + }) + .fill(grass_fill.clone()); + // models + let model_pos = pos.with_z(base - 5); + match RandomField::new(0).get(model_pos) % 2 { + 0 => { + lazy_static! { + pub static ref MODEL: AssetHandle = + PrefabStructure::load_group( + "site_structures.terracotta.terracotta_decor_small" + ); + } + let rng = RandomField::new(0).get(model_pos) % 62; + let model = MODEL.read(); + let model = model[rng as usize % model.len()].clone(); + painter + .prim(Primitive::Prefab(Box::new(model.clone()))) + .translate(model_pos) + .fill(Fill::Prefab(Box::new(model), model_pos, rng)); + }, + + _ => { + lazy_static! { + pub static ref MODEL: AssetHandle = + PrefabStructure::load_group("trees.palms"); + } + let rng = RandomField::new(0).get(model_pos) % 62; + let model = MODEL.read(); + let model = model[rng as usize % model.len()].clone(); + painter + .prim(Primitive::Prefab(Box::new(model.clone()))) + .translate(model_pos) + .fill(Fill::Prefab(Box::new(model), model_pos, rng)); + }, + } + } + } + // guards + let radius_guards = (room_size / 4) + 12; + let guards = 4.0_f32; + let phi_guards = TAU / guards; + for n in 1..=guards as i32 { + let pos = Vec2::new( + center.x + (radius_guards as f32 * ((n as f32 * phi_guards).cos())) as i32, + center.y + (radius_guards as f32 * ((n as f32 * phi_guards).sin())) as i32, + ) + .with_z(base); + terracotta_palace::spawn_random_entity(pos, painter, 1..=1); + } + } +}