diff --git a/assets/common/abilities/ability_set_manifest.ron b/assets/common/abilities/ability_set_manifest.ron index f75c928036..a9cca9666d 100644 --- a/assets/common/abilities/ability_set_manifest.ron +++ b/assets/common/abilities/ability_set_manifest.ron @@ -416,6 +416,11 @@ secondary: Simple(None, "common.abilities.custom.quadmedhoof.basic"), abilities: [], ), + Custom("ClaySteed"): ( + primary: Simple(None, "common.abilities.custom.claysteed.basic"), + secondary: Simple(None, "common.abilities.custom.claysteed.shockwave"), + abilities: [], + ), Custom("Quad Med Basic"): ( primary: Simple(None, "common.abilities.custom.quadmedbasic.singlestrike"), secondary: Simple(None, "common.abilities.custom.quadmedbasic.triplestrike"), @@ -654,13 +659,18 @@ ], ), + Custom("Grave Warden"): ( + primary: Simple(None, "common.abilities.custom.gravewarden.strike"), + secondary: Simple(None, "common.abilities.custom.gravewarden.laser"), + abilities: [ + Simple(None, "common.abilities.custom.gravewarden.shockwave"), + Simple(None, "common.abilities.custom.gravewarden.rocket"), + ], + ), Custom("Clay Golem"): ( primary: Simple(None, "common.abilities.custom.claygolem.strike"), - secondary: Simple(None, "common.abilities.custom.claygolem.laser"), - abilities: [ - Simple(None, "common.abilities.custom.claygolem.shockwave"), - Simple(None, "common.abilities.custom.claygolem.rocket"), - ], + secondary: Simple(None, "common.abilities.custom.claygolem.dashstrike"), + abilities: [], ), Custom("Yeti"): ( primary: Simple(None, "common.abilities.custom.yeti.strike"), @@ -670,6 +680,11 @@ Simple(None, "common.abilities.custom.yeti.snowball"), ], ), + Custom("Ancient Effigy"): ( + primary: Simple(None, "common.abilities.custom.ancienteffigy.laser"), + secondary: Simple(None, "common.abilities.custom.ancienteffigy.blast"), + abilities: [], + ), Custom("Harvester"): ( primary: Simple(None, "common.abilities.custom.harvester.scythe"), secondary: Simple(None, "common.abilities.custom.harvester.firebreath"), @@ -892,6 +907,16 @@ secondary: Simple(None, "common.abilities.music.sitar"), abilities: [], ), + Custom("Steeldrum"): ( + primary: Simple(None, "common.abilities.music.steeldrum"), + secondary: Simple(None, "common.abilities.music.steeldrum"), + abilities: [], + ), + Custom("Shamisen"): ( + primary: Simple(None, "common.abilities.music.shamisen"), + secondary: Simple(None, "common.abilities.music.shamisen"), + abilities: [], + ), Tool(Debug): ( primary: Simple(None, "common.abilities.debug.forwardboost"), secondary: Simple(None, "common.abilities.debug.upboost"), @@ -944,4 +969,25 @@ Simple(None, "common.abilities.adlet.elder.leap"), ], ), + // Haniwa + Custom("Haniwa Soldier"): ( + primary: Simple(None, "common.abilities.haniwa.soldier.strike"), + secondary: Simple(None, "common.abilities.haniwa.soldier.riposte"), + guard: Simple(None, "common.abilities.haniwa.soldier.guard"), + abilities: [], + ), + Custom("Haniwa Guard"): ( + primary: Simple(None, "common.abilities.haniwa.guard.strike"), + secondary: Simple(None, "common.abilities.haniwa.guard.flurry"), + abilities: [ + Simple(None, "common.abilities.haniwa.guard.backpedal") + ], + ), + Custom("Haniwa Archer"): ( + primary: Simple(None, "common.abilities.haniwa.archer.arrow"), + secondary: Simple(None, "common.abilities.haniwa.archer.kick"), + abilities: [ + Simple(None, "common.abilities.haniwa.archer.explosive") + ], + ), }) diff --git a/assets/common/abilities/custom/ancienteffigy/blast.ron b/assets/common/abilities/custom/ancienteffigy/blast.ron new file mode 100644 index 0000000000..349e3180bc --- /dev/null +++ b/assets/common/abilities/custom/ancienteffigy/blast.ron @@ -0,0 +1,16 @@ +BasicRanged( + energy_cost: 0, + buildup_duration: 2.5, + recover_duration: 1.0, + projectile: ClayRocket( + damage: 75.0, + knockback: 35.0, + radius: 10.0, + min_falloff: 0.75, + ), + projectile_body: Object(FireRainDrop), + projectile_speed: 0.0, + num_projectiles: 1, + projectile_spread: 0.0, + move_efficiency: 0.3, +) \ No newline at end of file diff --git a/assets/common/abilities/custom/ancienteffigy/laser.ron b/assets/common/abilities/custom/ancienteffigy/laser.ron new file mode 100644 index 0000000000..1d58fa8d65 --- /dev/null +++ b/assets/common/abilities/custom/ancienteffigy/laser.ron @@ -0,0 +1,19 @@ +BasicBeam( + buildup_duration: 0.9, + recover_duration: 2.8, + beam_duration: 0.25, + damage: 5.5, + tick_rate: 2.0, + range: 40.0, + max_angle: 1.0, + damage_effect: Some(Buff(( + kind: Burning, + dur_secs: 5.0, + strength: DamageFraction(0.50), + chance: 0.75, + ))), + energy_regen: 0, + energy_drain: 0, + ori_rate: 0.5, + specifier: Gravewarden, +) diff --git a/assets/common/abilities/custom/claygolem/dashstrike.ron b/assets/common/abilities/custom/claygolem/dashstrike.ron new file mode 100644 index 0000000000..7b0e381615 --- /dev/null +++ b/assets/common/abilities/custom/claygolem/dashstrike.ron @@ -0,0 +1,28 @@ +ComboMelee2( + strikes: [ + ( + melee_constructor: ( + kind: Bash( + damage: 60, + poise: 40, + knockback: 35.0, + energy_regen: 0, + ), + range: 4.0, + angle: 60.0, + ), + buildup_duration: 2.0, + swing_duration: 0.8, + hit_timing: 0.5, + recover_duration: 3.0, + movement: ( + buildup: Some(Forward(1.0)), + ), + ori_modifier: 0.7, + ), + ], + energy_cost_per_strike: 0, + auto_progress: true, + specifier: Some(ClayGolemDash), +) + diff --git a/assets/common/abilities/custom/claygolem/strike.ron b/assets/common/abilities/custom/claygolem/strike.ron index 8300358338..e206a0d91f 100644 --- a/assets/common/abilities/custom/claygolem/strike.ron +++ b/assets/common/abilities/custom/claygolem/strike.ron @@ -1,19 +1,26 @@ -BasicMelee( - energy_cost: 0, - buildup_duration: 1.2, - swing_duration: 0.1, - hit_timing: 0.4, - recover_duration: 1.0, - melee_constructor: ( - kind: Bash( - damage: 30.0, - poise: 50.0, - knockback: 10.0, - energy_regen: 0.0, +ComboMelee2( + strikes: [ + ( + melee_constructor: ( + kind: Bash( + damage: 60, + poise: 40, + knockback: 35.0, + energy_regen: 0, + ), + range: 4.0, + angle: 60.0, + ), + buildup_duration: 1.4, + swing_duration: 0.1, + hit_timing: 0.5, + recover_duration: 0.5, + movement: ( + swing: Some(Forward(0.5)), + ), + ori_modifier: 0.7, ), - range: 4.0, - angle: 45.0, - multi_target: Some(Normal), - ), - ori_modifier: 1.0, -) + ], + energy_cost_per_strike: 0, + auto_progress: true, +) \ No newline at end of file diff --git a/assets/common/abilities/custom/claysteed/basic.ron b/assets/common/abilities/custom/claysteed/basic.ron new file mode 100644 index 0000000000..08e98ec5a8 --- /dev/null +++ b/assets/common/abilities/custom/claysteed/basic.ron @@ -0,0 +1,18 @@ +BasicMelee( + energy_cost: 0, + buildup_duration: 0.50, + swing_duration: 0.6, + hit_timing: 0.4, + recover_duration: 0.85, + melee_constructor: ( + kind: Bash( + damage:20.0, + poise: 28.0, + knockback: 15.0, + energy_regen: 0.0, + ), + range: 0.8, + angle: 50.0, + ), + ori_modifier: 1.0, +) diff --git a/assets/common/abilities/custom/claysteed/shockwave.ron b/assets/common/abilities/custom/claysteed/shockwave.ron new file mode 100644 index 0000000000..2c9c1efe13 --- /dev/null +++ b/assets/common/abilities/custom/claysteed/shockwave.ron @@ -0,0 +1,18 @@ +Shockwave( + energy_cost: 0, + buildup_duration: 1.0, + swing_duration: 0.12, + recover_duration: 2.0, + damage: 30.0, + poise_damage: 20, + knockback: (strength: 20.0, direction: TowardsUp), + shockwave_angle: 360.0, + shockwave_vertical_angle: 90.0, + shockwave_speed: 25.0, + shockwave_duration: 2.0, + dodgeable: Jump, + move_efficiency: 0.0, + damage_kind: Crushing, + specifier: Ground, + ori_rate: 1.0, +) diff --git a/assets/common/abilities/custom/claygolem/laser.ron b/assets/common/abilities/custom/gravewarden/laser.ron similarity index 93% rename from assets/common/abilities/custom/claygolem/laser.ron rename to assets/common/abilities/custom/gravewarden/laser.ron index f4879337d7..c7cea76c2e 100644 --- a/assets/common/abilities/custom/claygolem/laser.ron +++ b/assets/common/abilities/custom/gravewarden/laser.ron @@ -15,5 +15,5 @@ BasicBeam( energy_regen: 0, energy_drain: 0, ori_rate: 0.07, - specifier: ClayGolem, + specifier: Gravewarden, ) diff --git a/assets/common/abilities/custom/claygolem/rocket.ron b/assets/common/abilities/custom/gravewarden/rocket.ron similarity index 100% rename from assets/common/abilities/custom/claygolem/rocket.ron rename to assets/common/abilities/custom/gravewarden/rocket.ron diff --git a/assets/common/abilities/custom/claygolem/shockwave.ron b/assets/common/abilities/custom/gravewarden/shockwave.ron similarity index 100% rename from assets/common/abilities/custom/claygolem/shockwave.ron rename to assets/common/abilities/custom/gravewarden/shockwave.ron diff --git a/assets/common/abilities/custom/gravewarden/strike.ron b/assets/common/abilities/custom/gravewarden/strike.ron new file mode 100644 index 0000000000..25b3c43203 --- /dev/null +++ b/assets/common/abilities/custom/gravewarden/strike.ron @@ -0,0 +1,26 @@ +ComboMelee2( + strikes: [ + ( + melee_constructor: ( + kind: Bash( + damage: 30, + poise: 50, + knockback: 10.0, + energy_regen: 0, + ), + range: 4.0, + angle: 45.0, + ), + buildup_duration: 1.2, + swing_duration: 0.1, + hit_timing: 0.4, + recover_duration: 1.0, + movement: ( + swing: Some(Forward(0.5)), + ), + ori_modifier: 1.0, + ), + ], + energy_cost_per_strike: 0, + auto_progress: true, +) diff --git a/assets/common/abilities/custom/quadmedhoof/basic.ron b/assets/common/abilities/custom/quadmedhoof/basic.ron index 5d404fd965..3faad48eaa 100644 --- a/assets/common/abilities/custom/quadmedhoof/basic.ron +++ b/assets/common/abilities/custom/quadmedhoof/basic.ron @@ -1,6 +1,6 @@ BasicMelee( energy_cost: 0, - buildup_duration: 1.15, + buildup_duration: 0.55, swing_duration: 0.3, hit_timing: 0.4, recover_duration: 0.85, diff --git a/assets/common/abilities/haniwa/archer/arrow.ron b/assets/common/abilities/haniwa/archer/arrow.ron new file mode 100644 index 0000000000..1fdd599e23 --- /dev/null +++ b/assets/common/abilities/haniwa/archer/arrow.ron @@ -0,0 +1,16 @@ +BasicRanged( + energy_cost: 0, + buildup_duration: 1.3, + recover_duration: 1.2, + projectile: Arrow( + damage: 25, + knockback: 8.0, + energy_regen: 0, + ), + projectile_body: Object(ArrowClay), + projectile_light: None, + projectile_speed: 75.0, + num_projectiles: 1, + projectile_spread: 0.0, + move_efficiency: 0.2, +) diff --git a/assets/common/abilities/haniwa/archer/explosive.ron b/assets/common/abilities/haniwa/archer/explosive.ron new file mode 100644 index 0000000000..f65793f086 --- /dev/null +++ b/assets/common/abilities/haniwa/archer/explosive.ron @@ -0,0 +1,17 @@ +BasicRanged( + energy_cost: 0, + buildup_duration: 2.4, + recover_duration: 0.6, + projectile: ClayRocket( + damage: 30, + knockback: 10.0, + radius: 5.0, + min_falloff: 0.75, + ), + projectile_body: Object(GrenadeClay), + projectile_light: None, + projectile_speed: 50.0, + num_projectiles: 1, + projectile_spread: 0.0, + move_efficiency: 0.5, +) diff --git a/assets/common/abilities/haniwa/archer/kick.ron b/assets/common/abilities/haniwa/archer/kick.ron new file mode 100644 index 0000000000..56c8509ca2 --- /dev/null +++ b/assets/common/abilities/haniwa/archer/kick.ron @@ -0,0 +1,18 @@ +BasicMelee( + energy_cost: 0, + buildup_duration: 0.4, + swing_duration: 0.1, + hit_timing: 0.5, + recover_duration: 0.5, + melee_constructor: ( + kind: Bash( + damage: 20, + poise: 20, + knockback: 25, + energy_regen: 0, + ), + range: 3.0, + angle: 90.0, + ), + ori_modifier: 1.0, +) diff --git a/assets/common/abilities/haniwa/guard/backpedal.ron b/assets/common/abilities/haniwa/guard/backpedal.ron new file mode 100644 index 0000000000..7c8f96a593 --- /dev/null +++ b/assets/common/abilities/haniwa/guard/backpedal.ron @@ -0,0 +1,25 @@ +ComboMelee2( + strikes: [ + ( + melee_constructor: ( + kind: Stab( + damage: 20, + poise: 10, + knockback: 10, + energy_regen: 0, + ), + range: 4.0, + angle: 10.0, + ), + buildup_duration: 0.2, + swing_duration: 0.2, + hit_timing: 0.5, + recover_duration: 0.8, + movement: ( + recover: Some(Reverse(1.5)), + ), + ori_modifier: 1.0, + ), + ], + energy_cost_per_strike: 0, +) diff --git a/assets/common/abilities/haniwa/guard/flurry.ron b/assets/common/abilities/haniwa/guard/flurry.ron new file mode 100644 index 0000000000..806cf4ca04 --- /dev/null +++ b/assets/common/abilities/haniwa/guard/flurry.ron @@ -0,0 +1,19 @@ +RapidMelee( + buildup_duration: 0.5, + swing_duration: 0.3, + recover_duration: 0.5, + melee_constructor: ( + kind: Stab( + damage: 10, + poise: 5, + knockback: 0, + energy_regen: 0, + ), + range: 4.0, + angle: 10.0, + ), + energy_cost: 0, + max_strikes: Some(5), + move_modifier: 0.7, + ori_modifier: 0.7, +) diff --git a/assets/common/abilities/haniwa/guard/strike.ron b/assets/common/abilities/haniwa/guard/strike.ron new file mode 100644 index 0000000000..db8d7773bc --- /dev/null +++ b/assets/common/abilities/haniwa/guard/strike.ron @@ -0,0 +1,18 @@ +BasicMelee( + energy_cost: 0, + buildup_duration: 1.0, + swing_duration: 0.2, + hit_timing: 0.5, + recover_duration: 0.8, + melee_constructor: ( + kind: Stab( + damage: 30, + poise: 15, + knockback: 5, + energy_regen: 0, + ), + range: 4.0, + angle: 10.0, + ), + ori_modifier: 1.0, +) diff --git a/assets/common/abilities/haniwa/soldier/guard.ron b/assets/common/abilities/haniwa/soldier/guard.ron new file mode 100644 index 0000000000..91c4e5ad61 --- /dev/null +++ b/assets/common/abilities/haniwa/soldier/guard.ron @@ -0,0 +1,21 @@ +BasicBlock( + buildup_duration: 0.25, + recover_duration: 0.25, + max_angle: 90.0, + block_strength: 0.5, + parry_window: ( + buildup: false, + recover: false, + ), + energy_cost: 0, + energy_regen: 0, + can_hold: true, + blocked_attacks: ( + melee: true, + projectiles: true, + beams: true, + ground_shockwaves: false, + air_shockwaves: true, + explosions: true, + ), +) \ No newline at end of file diff --git a/assets/common/abilities/haniwa/soldier/riposte.ron b/assets/common/abilities/haniwa/soldier/riposte.ron new file mode 100644 index 0000000000..7885865b1f --- /dev/null +++ b/assets/common/abilities/haniwa/soldier/riposte.ron @@ -0,0 +1,16 @@ +RiposteMelee( + energy_cost: 0, + buildup_duration: 0.7, + swing_duration: 0.3, + recover_duration: 0.2, + melee_constructor: ( + kind: Slash( + damage: 30, + poise: 60, + knockback: 15, + energy_regen: 0, + ), + range: 4.0, + angle: 60.0, + ), +) \ No newline at end of file diff --git a/assets/common/abilities/haniwa/soldier/strike.ron b/assets/common/abilities/haniwa/soldier/strike.ron new file mode 100644 index 0000000000..9a0b9c97d8 --- /dev/null +++ b/assets/common/abilities/haniwa/soldier/strike.ron @@ -0,0 +1,18 @@ +BasicMelee( + energy_cost: 0, + buildup_duration: 0.8, + swing_duration: 0.2, + hit_timing: 0.5, + recover_duration: 0.6, + melee_constructor: ( + kind: Slash( + damage: 40, + poise: 40, + knockback: 10, + energy_regen: 0, + ), + range: 4.0, + angle: 45.0, + ), + ori_modifier: 1.0, +) diff --git a/assets/common/abilities/music/shamisen.ron b/assets/common/abilities/music/shamisen.ron new file mode 100644 index 0000000000..18f0a9b200 --- /dev/null +++ b/assets/common/abilities/music/shamisen.ron @@ -0,0 +1,4 @@ +Music( + play_duration: 0.4, + ori_modifier: 1.0, +) \ No newline at end of file diff --git a/assets/common/abilities/music/steeldrum.ron b/assets/common/abilities/music/steeldrum.ron new file mode 100644 index 0000000000..18f0a9b200 --- /dev/null +++ b/assets/common/abilities/music/steeldrum.ron @@ -0,0 +1,4 @@ +Music( + play_duration: 0.4, + ori_modifier: 1.0, +) \ No newline at end of file diff --git a/assets/common/entity/dungeon/haniwa/ancienteffigy.ron b/assets/common/entity/dungeon/haniwa/ancienteffigy.ron new file mode 100644 index 0000000000..30aa75b68b --- /dev/null +++ b/assets/common/entity/dungeon/haniwa/ancienteffigy.ron @@ -0,0 +1,11 @@ +#![enable(implicit_some)] +( + name: Name("Ancient Effigy"), + body: RandomWith("ancienteffigy"), + alignment: Alignment(Enemy), + loot: LootTable("common.loot_tables.dungeon.haniwa.enemy"), + inventory: ( + loadout: FromBody, + ), + meta: [], +) \ No newline at end of file diff --git a/assets/common/entity/dungeon/haniwa/bonerattler.ron b/assets/common/entity/dungeon/haniwa/bonerattler.ron deleted file mode 100644 index 34de59e0c5..0000000000 --- a/assets/common/entity/dungeon/haniwa/bonerattler.ron +++ /dev/null @@ -1,11 +0,0 @@ -#![enable(implicit_some)] -( - name: Name("Bonerattler"), - body: RandomWith("bonerattler"), - alignment: Alignment(Enemy), - loot: LootTable("common.loot_tables.creature.quad_medium.carapace"), - inventory: ( - loadout: FromBody, - ), - meta: [], -) \ No newline at end of file diff --git a/assets/common/entity/dungeon/haniwa/claygolem.ron b/assets/common/entity/dungeon/haniwa/claygolem.ron index 0cd7b6b928..43f4cbc734 100644 --- a/assets/common/entity/dungeon/haniwa/claygolem.ron +++ b/assets/common/entity/dungeon/haniwa/claygolem.ron @@ -3,7 +3,7 @@ name: Name("Clay Golem"), body: RandomWith("claygolem"), alignment: Alignment(Enemy), - loot: LootTable("common.loot_tables.dungeon.haniwa.claygolem"), + loot: LootTable("common.loot_tables.dungeon.haniwa.enemy"), inventory: ( loadout: FromBody, ), diff --git a/assets/common/entity/dungeon/haniwa/claysteed.ron b/assets/common/entity/dungeon/haniwa/claysteed.ron new file mode 100644 index 0000000000..8dd1a5dd07 --- /dev/null +++ b/assets/common/entity/dungeon/haniwa/claysteed.ron @@ -0,0 +1,11 @@ +#![enable(implicit_some)] +( + name: Automatic, + body: RandomWith("claysteed"), + alignment: Alignment(Enemy), + loot: LootTable("common.loot_tables.dungeon.haniwa.enemy"), + inventory: ( + loadout: FromBody, + ), + meta: [], +) \ No newline at end of file diff --git a/assets/common/entity/dungeon/haniwa/general.ron b/assets/common/entity/dungeon/haniwa/general.ron new file mode 100644 index 0000000000..f37296033a --- /dev/null +++ b/assets/common/entity/dungeon/haniwa/general.ron @@ -0,0 +1,11 @@ +#![enable(implicit_some)] +( + name: Automatic, + body: RandomWith("haniwa_general"), + alignment: Alignment(Enemy), + loot: LootTable("common.loot_tables.dungeon.haniwa.enemy"), + inventory: ( + loadout: FromBody, + ), + meta: [], +) \ No newline at end of file diff --git a/assets/common/entity/dungeon/haniwa/gravewarden.ron b/assets/common/entity/dungeon/haniwa/gravewarden.ron new file mode 100644 index 0000000000..28e46074cf --- /dev/null +++ b/assets/common/entity/dungeon/haniwa/gravewarden.ron @@ -0,0 +1,11 @@ +#![enable(implicit_some)] +( + name: Name("Gravewarden"), + body: RandomWith("gravewarden"), + alignment: Alignment(Enemy), + loot: LootTable("common.loot_tables.dungeon.haniwa.gravewarden"), + 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 ea6b3733cf..49acaf70fc 100644 --- a/assets/common/item_i18n_manifest.ron +++ b/assets/common/item_i18n_manifest.ron @@ -36,6 +36,12 @@ Simple( "common.items.npc_armor.golem.woodgolem", ): "common-items-npc_armor-golem-woodgolem", + Simple( + "common.items.npc_armor.golem.ancienteffigy", + ): "common-items-npc_armor-golem-ancienteffigy", + Simple( + "common.items.npc_armor.golem.gravewarden", + ): "common-items-npc_armor-golem-gravewarden", Simple( "common.items.npc_armor.biped_small.myrmidon.foot.hoplite", ): "common-items-npc_armor-biped_small-myrmidon-foot-hoplite", @@ -519,6 +525,9 @@ Simple( "common.items.npc_armor.quadruped_medium.roshwalr", ): "common-items-npc_armor-quadruped_medium-roshwalr", + Simple( + "common.items.npc_armor.quadruped_medium.claysteed", + ): "common-items-npc_armor-quadruped_medium-claysteed", Simple( "common.items.npc_armor.theropod.rugged", ): "common-items-npc_armor-theropod-rugged", @@ -564,9 +573,15 @@ Simple( "common.items.npc_armor.biped_large.yeti", ): "common-items-npc_armor-biped_large-yeti", + Simple( + "common.items.npc_armor.biped_large.haniwageneral", + ): "common-items-npc_armor-biped_large-haniwageneral", Simple( "common.items.keys.bone_key", ): "object-key_bone", + Simple( + "common.items.keys.haniwa_key", + ): "object-key_haniwa", Simple( "common.items.keys.glass_key", ): "object-key_glass", @@ -2249,6 +2264,12 @@ Simple( "common.items.tool.instruments.wildskin_drum", ): "weapon-tool-wildskin_drum", + Simple( + "common.items.tool.instruments.steeldrum", + ): "weapon-tool-steeldrum", + Simple( + "common.items.tool.instruments.shamisen", + ): "weapon-tool-shamisen", Simple( "common.items.log.bamboo", ): "sprite-wood-item-bamboo", @@ -2379,6 +2400,9 @@ Simple( "common.items.npc_weapons.sword.saurok_sword", ): "common-items-npc_weapons-sword-saurok_sword", + Simple( + "common.items.npc_weapons.sword.haniwa_general_sword", + ): "common-items-npc_weapons-sword-haniwa_general_sword", Simple( "common.items.npc_weapons.unique.akhlut", ): "common-items-npc_weapons-unique-akhlut", @@ -2571,6 +2595,15 @@ Simple( "common.items.npc_weapons.unique.wood_golem_fist", ): "common-items-npc_weapons-unique-wood_golem_fist", + Simple( + "common.items.npc_weapons.unique.ancient_effigy_eyes", + ): "common-items-npc_weapons-unique-ancient_effigy_eyes", + Simple( + "common.items.npc_weapons.unique.claysteed", + ): "common-items-npc_weapons-unique-claysteed", + Simple( + "common.items.npc_weapons.unique.gravewarden_fist", + ): "common-items-npc_weapons-unique-gravewarden_fist", Simple( "common.items.npc_weapons.unique.arthropods.antlion", ): "common-items-npc_weapons-unique-arthropods-antlion", diff --git a/assets/common/items/keys/haniwa_key.ron b/assets/common/items/keys/haniwa_key.ron new file mode 100644 index 0000000000..720b811338 --- /dev/null +++ b/assets/common/items/keys/haniwa_key.ron @@ -0,0 +1,11 @@ +ItemDef( + legacy_name: "Haniwa Keystone", + legacy_description: "Used to open doors. Will break after use.", + kind: Utility( + kind: Key, + ), + amount: 1, + quality: Common, + tags: [Utility], +) + diff --git a/assets/common/items/npc_armor/biped_large/haniwageneral.ron b/assets/common/items/npc_armor/biped_large/haniwageneral.ron new file mode 100644 index 0000000000..8a8203d0be --- /dev/null +++ b/assets/common/items/npc_armor/biped_large/haniwageneral.ron @@ -0,0 +1,13 @@ +ItemDef( + legacy_name: "Haniwa General Armor", + legacy_description: "Worn by haniwa general.", + kind: Armor(( + kind: Chest, + stats: Direct(( + protection: Some(Normal(80.0)), + poise_resilience: Some(Normal(30.0)), + )), + )), + quality: Epic, + tags: [], +) \ No newline at end of file diff --git a/assets/common/items/npc_armor/golem/ancienteffigy.ron b/assets/common/items/npc_armor/golem/ancienteffigy.ron new file mode 100644 index 0000000000..75a167b3a0 --- /dev/null +++ b/assets/common/items/npc_armor/golem/ancienteffigy.ron @@ -0,0 +1,13 @@ +ItemDef( + legacy_name: "Ancient Effigy Armor", + legacy_description: "Worn by ancient effigy.", + kind: Armor(( + kind: Chest, + stats: Direct(( + protection: Some(Normal(100.0)), + poise_resilience: Some(Normal(1.0)), + )), + )), + quality: Legendary, + tags: [], +) \ No newline at end of file diff --git a/assets/common/items/npc_armor/golem/claygolem.ron b/assets/common/items/npc_armor/golem/claygolem.ron index 0e5176c9c0..14d86635ce 100644 --- a/assets/common/items/npc_armor/golem/claygolem.ron +++ b/assets/common/items/npc_armor/golem/claygolem.ron @@ -4,7 +4,7 @@ ItemDef( kind: Armor(( kind: Chest, stats: Direct(( - protection: Some(Normal(180.0)), + protection: Some(Normal(100.0)), poise_resilience: Some(Normal(1.0)), )), )), diff --git a/assets/common/items/npc_armor/golem/gravewarden.ron b/assets/common/items/npc_armor/golem/gravewarden.ron new file mode 100644 index 0000000000..a796d101d2 --- /dev/null +++ b/assets/common/items/npc_armor/golem/gravewarden.ron @@ -0,0 +1,13 @@ +ItemDef( + legacy_name: "Grave Warden Armor", + legacy_description: "Worn by grave warden.", + kind: Armor(( + kind: Chest, + stats: Direct(( + protection: Some(Normal(180.0)), + poise_resilience: Some(Normal(1.0)), + )), + )), + quality: Legendary, + tags: [], +) diff --git a/assets/common/items/npc_armor/quadruped_medium/claysteed.ron b/assets/common/items/npc_armor/quadruped_medium/claysteed.ron new file mode 100644 index 0000000000..139c8dbed1 --- /dev/null +++ b/assets/common/items/npc_armor/quadruped_medium/claysteed.ron @@ -0,0 +1,13 @@ +ItemDef( + legacy_name: "Clay Steed's Thick Fur", + legacy_description: "testing123", + kind: Armor(( + kind: Chest, + stats: Direct(( + protection: Some(Normal(40.0)), + poise_resilience: Some(Normal(1.0)), + )), + )), + quality: Common, + tags: [], +) \ No newline at end of file diff --git a/assets/common/items/npc_weapons/biped_small/haniwa/archer.ron b/assets/common/items/npc_weapons/biped_small/haniwa/archer.ron index 4c437cab84..6c5b178d32 100644 --- a/assets/common/items/npc_weapons/biped_small/haniwa/archer.ron +++ b/assets/common/items/npc_weapons/biped_small/haniwa/archer.ron @@ -6,9 +6,9 @@ ItemDef( hands: Two, stats: ( equip_time_secs: 0.0, - power: 1.6, - effect_power: 0.8, - speed: 0.7, + power: 1.0, + effect_power: 1.0, + speed: 1.0, range: 1.0, energy_efficiency: 1.0, buff_strength: 1.0, @@ -16,5 +16,5 @@ ItemDef( )), quality: Moderate, tags: [], - ability_spec: Some(Custom("Bow Simple")), + ability_spec: Some(Custom("Haniwa Archer")), ) \ No newline at end of file diff --git a/assets/common/items/npc_weapons/biped_small/haniwa/guard.ron b/assets/common/items/npc_weapons/biped_small/haniwa/guard.ron index b86d43fc81..2bb16ff326 100644 --- a/assets/common/items/npc_weapons/biped_small/haniwa/guard.ron +++ b/assets/common/items/npc_weapons/biped_small/haniwa/guard.ron @@ -6,7 +6,7 @@ ItemDef( hands: Two, stats: ( equip_time_secs: 0.0, - power: 1.6, + power: 1.0, effect_power: 1.0, speed: 1.0, range: 1.0, @@ -16,5 +16,5 @@ ItemDef( )), quality: Low, tags: [], - ability_spec: None, + ability_spec: Some(Custom("Haniwa Guard")), ) \ No newline at end of file diff --git a/assets/common/items/npc_weapons/biped_small/haniwa/soldier.ron b/assets/common/items/npc_weapons/biped_small/haniwa/soldier.ron index 5a166f152c..6994a1c999 100644 --- a/assets/common/items/npc_weapons/biped_small/haniwa/soldier.ron +++ b/assets/common/items/npc_weapons/biped_small/haniwa/soldier.ron @@ -2,13 +2,13 @@ ItemDef( legacy_name: "Soldier Sword", legacy_description: "", kind: Tool(( - kind: Dagger, + kind: Sword, hands: Two, stats: ( equip_time_secs: 0.0, - power: 1.6, - effect_power: 0.8, - speed: 0.8, + power: 1.0, + effect_power: 1.0, + speed: 1.0, range: 1.0, energy_efficiency: 1.0, buff_strength: 1.0, @@ -16,5 +16,5 @@ ItemDef( )), quality: Low, tags: [], - ability_spec: Some(Custom("Dagger Simple")), + ability_spec: Some(Custom("Haniwa Soldier")), ) \ No newline at end of file diff --git a/assets/common/items/npc_weapons/sword/haniwa_general_sword.ron b/assets/common/items/npc_weapons/sword/haniwa_general_sword.ron new file mode 100644 index 0000000000..a677728338 --- /dev/null +++ b/assets/common/items/npc_weapons/sword/haniwa_general_sword.ron @@ -0,0 +1,20 @@ +ItemDef( + legacy_name: "Haniwa General Sword", + legacy_description: "Placeholder", + 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("Sword Simple")), +) \ No newline at end of file diff --git a/assets/common/items/npc_weapons/unique/ancient_effigy_eyes.ron b/assets/common/items/npc_weapons/unique/ancient_effigy_eyes.ron new file mode 100644 index 0000000000..0135b1fb2d --- /dev/null +++ b/assets/common/items/npc_weapons/unique/ancient_effigy_eyes.ron @@ -0,0 +1,20 @@ +ItemDef( + legacy_name: "Ancient Effigy Eyes", + 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("Ancient Effigy")), +) \ No newline at end of file diff --git a/assets/common/items/npc_weapons/unique/claysteed.ron b/assets/common/items/npc_weapons/unique/claysteed.ron new file mode 100644 index 0000000000..8e8e3c0b79 --- /dev/null +++ b/assets/common/items/npc_weapons/unique/claysteed.ron @@ -0,0 +1,20 @@ +ItemDef( + legacy_name: "ClaySteed", + 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("ClaySteed")), +) \ No newline at end of file diff --git a/assets/common/items/npc_weapons/unique/gravewarden_fist.ron b/assets/common/items/npc_weapons/unique/gravewarden_fist.ron new file mode 100644 index 0000000000..c60fe9a9a8 --- /dev/null +++ b/assets/common/items/npc_weapons/unique/gravewarden_fist.ron @@ -0,0 +1,20 @@ +ItemDef( + legacy_name: "Grave Warden Fists", + 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("Grave Warden")), +) diff --git a/assets/common/items/tool/instruments/shamisen.ron b/assets/common/items/tool/instruments/shamisen.ron new file mode 100644 index 0000000000..c47c36c6ec --- /dev/null +++ b/assets/common/items/tool/instruments/shamisen.ron @@ -0,0 +1,21 @@ +ItemDef( + legacy_name: "Shamisen", + legacy_description: "Shamisen.", + kind: Tool(( + kind: Instrument, + hands: Two, + stats: ( + equip_time_secs: 0.4, + power: 0.0, + effect_power: 1.0, + speed: 1.0, + crit_chance: 0.0, + range: 0.0, + energy_efficiency: 1.0, + buff_strength: 1.0, + ), + )), + quality: Legendary, + tags: [Utility], + ability_spec: Some(Custom("Shamisen")), +) diff --git a/assets/common/items/tool/instruments/steeldrum.ron b/assets/common/items/tool/instruments/steeldrum.ron new file mode 100644 index 0000000000..e89409ae17 --- /dev/null +++ b/assets/common/items/tool/instruments/steeldrum.ron @@ -0,0 +1,21 @@ +ItemDef( + legacy_name: "Steeldrum", + legacy_description: "Steeldrum.", + kind: Tool(( + kind: Instrument, + hands: Two, + stats: ( + equip_time_secs: 0.4, + power: 0.0, + effect_power: 1.0, + speed: 1.0, + crit_chance: 0.0, + range: 0.0, + energy_efficiency: 1.0, + buff_strength: 1.0, + ), + )), + quality: Legendary, + tags: [Utility], + ability_spec: Some(Custom("Steeldrum")), +) diff --git a/assets/common/loot_tables/dungeon/haniwa/claygolem.ron b/assets/common/loot_tables/dungeon/haniwa/gravewarden.ron similarity index 78% rename from assets/common/loot_tables/dungeon/haniwa/claygolem.ron rename to assets/common/loot_tables/dungeon/haniwa/gravewarden.ron index f6f598f52b..3b2597e6f3 100644 --- a/assets/common/loot_tables/dungeon/haniwa/claygolem.ron +++ b/assets/common/loot_tables/dungeon/haniwa/gravewarden.ron @@ -5,4 +5,5 @@ (3.0, LootTable("common.loot_tables.armor.tier-4")), // Misc (2.0, Item("common.items.armor.misc.neck.haniwa_talisman")), + (0.2, Item("common.items.tool.instruments.shamisen")), ] \ No newline at end of file diff --git a/assets/common/loot_tables/dungeon/haniwa/key.ron b/assets/common/loot_tables/dungeon/haniwa/key.ron new file mode 100644 index 0000000000..8c3743051e --- /dev/null +++ b/assets/common/loot_tables/dungeon/haniwa/key.ron @@ -0,0 +1,3 @@ +[ + (1.0, Item("common.items.keys.haniwa_key")), +] \ No newline at end of file diff --git a/assets/common/npc_names.ron b/assets/common/npc_names.ron index c35b0dd555..8f0d229d7b 100644 --- a/assets/common/npc_names.ron +++ b/assets/common/npc_names.ron @@ -571,6 +571,10 @@ keyword: "bristleback", generic: "Bristleback" ), + claysteed: ( + keyword: "claysteed", + generic: "Clay Steed" + ), ) ), quadruped_small: ( @@ -981,6 +985,10 @@ sea_bishop: ( keyword: "sea_bishop", generic: "Sea Bishop" + ), + haniwa_general: ( + keyword: "haniwa_general", + generic: "Haniwa General" ) ) ), @@ -994,7 +1002,7 @@ species: ( stonegolem: ( keyword: "stonegolem", - generic: "StoneGolem" + generic: "Stone Golem" ), treant: ( keyword: "treant", @@ -1004,13 +1012,21 @@ keyword: "woodgolem", generic: "Wooden Golem" ), + gravewarden: ( + keyword: "gravewarden", + generic: "Gravewarden" + ), claygolem: ( keyword: "claygolem", - generic: "ClayGolem" + generic: "Clay Golem" + ), + ancienteffigy: ( + keyword: "ancienteffigy", + generic: "Ancient Effigy" ), coralgolem: ( keyword: "coralgolem", - generic: "CoralGolem" + generic: "Coral Golem" ) ) ), diff --git a/assets/server/manifests/kits.ron b/assets/server/manifests/kits.ron index 1e520e27e0..4a55ebd6d8 100644 --- a/assets/server/manifests/kits.ron +++ b/assets/server/manifests/kits.ron @@ -412,5 +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.shamisen"),1), ], }) diff --git a/assets/voxygen/audio/sfx.ron b/assets/voxygen/audio/sfx.ron index 04da7f55dc..997f11c4d7 100644 --- a/assets/voxygen/audio/sfx.ron +++ b/assets/voxygen/audio/sfx.ron @@ -760,6 +760,50 @@ threshold: 0.5, subtitle: "subtitle-instrument_lute", ), + Music(Instrument, Custom("Steeldrum")): ( + 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", + ], + threshold: 0.5, + subtitle: "subtitle-instrument_steeldrum", + ), + Music(Instrument, Custom("Shamisen")): ( + files: [ + "voxygen.audio.sfx.instrument.shamisen.shamisen_a", + "voxygen.audio.sfx.instrument.shamisen.shamisen_aec1", + "voxygen.audio.sfx.instrument.shamisen.shamisen_c", + "voxygen.audio.sfx.instrument.shamisen.shamisen_c1", + "voxygen.audio.sfx.instrument.shamisen.shamisen_c1c1a", + "voxygen.audio.sfx.instrument.shamisen.shamisen_cc", + "voxygen.audio.sfx.instrument.shamisen.shamisen_cdc1", + "voxygen.audio.sfx.instrument.shamisen.shamisen_cea", + "voxygen.audio.sfx.instrument.shamisen.shamisen_ceg", + "voxygen.audio.sfx.instrument.shamisen.shamisen_cge", + "voxygen.audio.sfx.instrument.shamisen.shamisen_d", + "voxygen.audio.sfx.instrument.shamisen.shamisen_dac", + "voxygen.audio.sfx.instrument.shamisen.shamisen_e", + "voxygen.audio.sfx.instrument.shamisen.shamisen_ea", + "voxygen.audio.sfx.instrument.shamisen.shamisen_eac1c", + "voxygen.audio.sfx.instrument.shamisen.shamisen_g", + "voxygen.audio.sfx.instrument.shamisen.shamisen_gg", + ], + threshold: 0.5, + subtitle: "subtitle-instrument_shamisen", + ), Music(Instrument, Custom("Sitar")): ( files: [ "voxygen.audio.sfx.instrument.sitar.sitar_c", @@ -1412,6 +1456,13 @@ threshold: 0.3, subtitle: "subtitle-attack-cyclops_charge", ), + FuseCharge: ( + files: [ + "voxygen.audio.sfx.abilities.fuse", + ], + threshold: 0.2, + subtitle: "subtitle-attack-fuse_charge", + ), GigaRoar: ( files: [ "voxygen.audio.sfx.abilities.gigas_frost_roar", diff --git a/assets/voxygen/audio/sfx/abilities/fuse.ogg b/assets/voxygen/audio/sfx/abilities/fuse.ogg new file mode 100644 index 0000000000..10e44a9ae5 --- /dev/null +++ b/assets/voxygen/audio/sfx/abilities/fuse.ogg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e85ebcf22fdbb2ae3ff43aa6afd632bb3db1ce8b789247448c57b55e35e6cf36 +size 16949 diff --git a/assets/voxygen/audio/sfx/instrument/shamisen/shamisen_a.ogg b/assets/voxygen/audio/sfx/instrument/shamisen/shamisen_a.ogg new file mode 100644 index 0000000000..a79d89c528 --- /dev/null +++ b/assets/voxygen/audio/sfx/instrument/shamisen/shamisen_a.ogg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a7bc1d203120ff7f270269ed087eb89120cb2f700c802c92ea18f51ae4778a49 +size 10016 diff --git a/assets/voxygen/audio/sfx/instrument/shamisen/shamisen_aec1.ogg b/assets/voxygen/audio/sfx/instrument/shamisen/shamisen_aec1.ogg new file mode 100644 index 0000000000..f499905490 --- /dev/null +++ b/assets/voxygen/audio/sfx/instrument/shamisen/shamisen_aec1.ogg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a94391e61e5cad47bea5c26c16c73e7ecd21615e134d05b10d1fc98050340ab8 +size 11146 diff --git a/assets/voxygen/audio/sfx/instrument/shamisen/shamisen_c.ogg b/assets/voxygen/audio/sfx/instrument/shamisen/shamisen_c.ogg new file mode 100644 index 0000000000..e2b0808b90 --- /dev/null +++ b/assets/voxygen/audio/sfx/instrument/shamisen/shamisen_c.ogg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:058eced1213acd0b41f45f4632d76fe81020fd64ea101a6e261b67c5b374de50 +size 10765 diff --git a/assets/voxygen/audio/sfx/instrument/shamisen/shamisen_c1.ogg b/assets/voxygen/audio/sfx/instrument/shamisen/shamisen_c1.ogg new file mode 100644 index 0000000000..32ce87c8dd --- /dev/null +++ b/assets/voxygen/audio/sfx/instrument/shamisen/shamisen_c1.ogg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:79f6352d1bde9dc44d4f3d5d46eb50e88e60c3e51dd18871f3da1443623b5d04 +size 9989 diff --git a/assets/voxygen/audio/sfx/instrument/shamisen/shamisen_c1c1a.ogg b/assets/voxygen/audio/sfx/instrument/shamisen/shamisen_c1c1a.ogg new file mode 100644 index 0000000000..0632a35bab --- /dev/null +++ b/assets/voxygen/audio/sfx/instrument/shamisen/shamisen_c1c1a.ogg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:44c4a3e1eee7982856dc9c35e3cac77d6374fef0a682630ae04fffdaed87c1ee +size 11304 diff --git a/assets/voxygen/audio/sfx/instrument/shamisen/shamisen_cc.ogg b/assets/voxygen/audio/sfx/instrument/shamisen/shamisen_cc.ogg new file mode 100644 index 0000000000..6a42baa7c5 --- /dev/null +++ b/assets/voxygen/audio/sfx/instrument/shamisen/shamisen_cc.ogg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e87b18f0557cc2763ab02a332d541646cefa9aec1cb55469f2bc284e2e843d8c +size 10722 diff --git a/assets/voxygen/audio/sfx/instrument/shamisen/shamisen_cdc1.ogg b/assets/voxygen/audio/sfx/instrument/shamisen/shamisen_cdc1.ogg new file mode 100644 index 0000000000..2ca6916db4 --- /dev/null +++ b/assets/voxygen/audio/sfx/instrument/shamisen/shamisen_cdc1.ogg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ed2fc24715f0e63abc6bd49d32fb93243c3dffeccfbec4375e216d2093a59a4f +size 10613 diff --git a/assets/voxygen/audio/sfx/instrument/shamisen/shamisen_cea.ogg b/assets/voxygen/audio/sfx/instrument/shamisen/shamisen_cea.ogg new file mode 100644 index 0000000000..d88e72fc5f --- /dev/null +++ b/assets/voxygen/audio/sfx/instrument/shamisen/shamisen_cea.ogg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4214b6beb043a06c47107ec2aa6c9d18dc68a2608dd9c2dfec6117738f423b9d +size 10762 diff --git a/assets/voxygen/audio/sfx/instrument/shamisen/shamisen_ceg.ogg b/assets/voxygen/audio/sfx/instrument/shamisen/shamisen_ceg.ogg new file mode 100644 index 0000000000..733faa1145 --- /dev/null +++ b/assets/voxygen/audio/sfx/instrument/shamisen/shamisen_ceg.ogg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f46669441c7f336c96e16136c4735f608a8481d2ab556787f4fd2dfede2af873 +size 10457 diff --git a/assets/voxygen/audio/sfx/instrument/shamisen/shamisen_cge.ogg b/assets/voxygen/audio/sfx/instrument/shamisen/shamisen_cge.ogg new file mode 100644 index 0000000000..11f59f0ffa --- /dev/null +++ b/assets/voxygen/audio/sfx/instrument/shamisen/shamisen_cge.ogg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4e2311cad3d56d2e4f635fa058da6b38ef31d3643634e9385873edd3bed6c66b +size 11018 diff --git a/assets/voxygen/audio/sfx/instrument/shamisen/shamisen_d.ogg b/assets/voxygen/audio/sfx/instrument/shamisen/shamisen_d.ogg new file mode 100644 index 0000000000..5532ad5415 --- /dev/null +++ b/assets/voxygen/audio/sfx/instrument/shamisen/shamisen_d.ogg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0af552f892cc9d77406ef5592a074d34217f08b6c38c782e21cf3ec43afed865 +size 9356 diff --git a/assets/voxygen/audio/sfx/instrument/shamisen/shamisen_dac.ogg b/assets/voxygen/audio/sfx/instrument/shamisen/shamisen_dac.ogg new file mode 100644 index 0000000000..75b13170d4 --- /dev/null +++ b/assets/voxygen/audio/sfx/instrument/shamisen/shamisen_dac.ogg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c20c8fe8780b0a56bdf6cdf0cb120bbc53475a1fedb7ebcd22c796cf0c1c5303 +size 10603 diff --git a/assets/voxygen/audio/sfx/instrument/shamisen/shamisen_e.ogg b/assets/voxygen/audio/sfx/instrument/shamisen/shamisen_e.ogg new file mode 100644 index 0000000000..174e22b606 --- /dev/null +++ b/assets/voxygen/audio/sfx/instrument/shamisen/shamisen_e.ogg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:81d3673b17b615ba9ff114de36743654d3e1f8417e4ff553091df12983a44a2a +size 9454 diff --git a/assets/voxygen/audio/sfx/instrument/shamisen/shamisen_ea.ogg b/assets/voxygen/audio/sfx/instrument/shamisen/shamisen_ea.ogg new file mode 100644 index 0000000000..d5d27f9ef0 --- /dev/null +++ b/assets/voxygen/audio/sfx/instrument/shamisen/shamisen_ea.ogg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d371292d8fcaaa9dd0142cc35569e31a14b1837e7103d9cba5fcfcfd15118cfe +size 10842 diff --git a/assets/voxygen/audio/sfx/instrument/shamisen/shamisen_eac1c.ogg b/assets/voxygen/audio/sfx/instrument/shamisen/shamisen_eac1c.ogg new file mode 100644 index 0000000000..69c77bb571 --- /dev/null +++ b/assets/voxygen/audio/sfx/instrument/shamisen/shamisen_eac1c.ogg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:faa19dd56c57c124cc1aa9af98cb883b8723e4add07ea8544df277cbe5abf65c +size 11460 diff --git a/assets/voxygen/audio/sfx/instrument/shamisen/shamisen_g.ogg b/assets/voxygen/audio/sfx/instrument/shamisen/shamisen_g.ogg new file mode 100644 index 0000000000..4c052fcc0c --- /dev/null +++ b/assets/voxygen/audio/sfx/instrument/shamisen/shamisen_g.ogg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:188fa4903fa11bb75d524271db8f48df14788769536e96f3cae8b9ac913173f9 +size 10394 diff --git a/assets/voxygen/audio/sfx/instrument/shamisen/shamisen_gg.ogg b/assets/voxygen/audio/sfx/instrument/shamisen/shamisen_gg.ogg new file mode 100644 index 0000000000..3bef0beaaa --- /dev/null +++ b/assets/voxygen/audio/sfx/instrument/shamisen/shamisen_gg.ogg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:febbe8a2b7dbd629967ea1b8297dc2e677ab4877cbedc5464dc2bd7541f3f952 +size 11164 diff --git a/assets/voxygen/audio/sfx/instrument/steeldrum/steeldrum_a.ogg b/assets/voxygen/audio/sfx/instrument/steeldrum/steeldrum_a.ogg new file mode 100644 index 0000000000..1222590236 --- /dev/null +++ b/assets/voxygen/audio/sfx/instrument/steeldrum/steeldrum_a.ogg @@ -0,0 +1,3 @@ +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 new file mode 100644 index 0000000000..710064fe27 --- /dev/null +++ b/assets/voxygen/audio/sfx/instrument/steeldrum/steeldrum_ac1.ogg @@ -0,0 +1,3 @@ +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 new file mode 100644 index 0000000000..901cc41730 --- /dev/null +++ b/assets/voxygen/audio/sfx/instrument/steeldrum/steeldrum_c.ogg @@ -0,0 +1,3 @@ +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 new file mode 100644 index 0000000000..2f734d56d0 --- /dev/null +++ b/assets/voxygen/audio/sfx/instrument/steeldrum/steeldrum_c1.ogg @@ -0,0 +1,3 @@ +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 new file mode 100644 index 0000000000..155b052588 --- /dev/null +++ b/assets/voxygen/audio/sfx/instrument/steeldrum/steeldrum_c1ae.ogg @@ -0,0 +1,3 @@ +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 new file mode 100644 index 0000000000..67fa2034c5 --- /dev/null +++ b/assets/voxygen/audio/sfx/instrument/steeldrum/steeldrum_c1ag.ogg @@ -0,0 +1,3 @@ +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 new file mode 100644 index 0000000000..289d9531d2 --- /dev/null +++ b/assets/voxygen/audio/sfx/instrument/steeldrum/steeldrum_c1c1.ogg @@ -0,0 +1,3 @@ +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 new file mode 100644 index 0000000000..6ef666dd66 --- /dev/null +++ b/assets/voxygen/audio/sfx/instrument/steeldrum/steeldrum_ce.ogg @@ -0,0 +1,3 @@ +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 new file mode 100644 index 0000000000..fe8c4a729e --- /dev/null +++ b/assets/voxygen/audio/sfx/instrument/steeldrum/steeldrum_d.ogg @@ -0,0 +1,3 @@ +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 new file mode 100644 index 0000000000..e5fbc2241c --- /dev/null +++ b/assets/voxygen/audio/sfx/instrument/steeldrum/steeldrum_d1.ogg @@ -0,0 +1,3 @@ +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 new file mode 100644 index 0000000000..77da3dbfed --- /dev/null +++ b/assets/voxygen/audio/sfx/instrument/steeldrum/steeldrum_d1c1.ogg @@ -0,0 +1,3 @@ +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 new file mode 100644 index 0000000000..0cb7cec6a4 --- /dev/null +++ b/assets/voxygen/audio/sfx/instrument/steeldrum/steeldrum_e.ogg @@ -0,0 +1,3 @@ +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 new file mode 100644 index 0000000000..aa65983c0d --- /dev/null +++ b/assets/voxygen/audio/sfx/instrument/steeldrum/steeldrum_ec1g.ogg @@ -0,0 +1,3 @@ +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 new file mode 100644 index 0000000000..d62fd61b97 --- /dev/null +++ b/assets/voxygen/audio/sfx/instrument/steeldrum/steeldrum_eg.ogg @@ -0,0 +1,3 @@ +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 new file mode 100644 index 0000000000..713fb407cf --- /dev/null +++ b/assets/voxygen/audio/sfx/instrument/steeldrum/steeldrum_g.ogg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:654df76d9b8c0e07186e67fe2adfad1d7127631ee6301d8be42e679f1239f617 +size 8973 diff --git a/assets/voxygen/element/ui/map/buttons/haniwa.png b/assets/voxygen/element/ui/map/buttons/haniwa.png new file mode 100644 index 0000000000..aae3e80bba --- /dev/null +++ b/assets/voxygen/element/ui/map/buttons/haniwa.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d7f402f2ecafee12d642d466861c9e397bad63041e513961a4e18ba0f8b3f45d +size 525 diff --git a/assets/voxygen/element/ui/map/buttons/haniwa_bg.png b/assets/voxygen/element/ui/map/buttons/haniwa_bg.png new file mode 100644 index 0000000000..e1ee2bb45a --- /dev/null +++ b/assets/voxygen/element/ui/map/buttons/haniwa_bg.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c32bae3503c571c7755a53d757dc73725e78df6dea6195a29b854c6dd340697c +size 175 diff --git a/assets/voxygen/element/ui/map/buttons/haniwa_hover.png b/assets/voxygen/element/ui/map/buttons/haniwa_hover.png new file mode 100644 index 0000000000..1f7a07ab7b --- /dev/null +++ b/assets/voxygen/element/ui/map/buttons/haniwa_hover.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:efcafd7456e2ad566d1cb91edc740d30150c21377fe9d0642a99a2b15d89c46c +size 552 diff --git a/assets/voxygen/i18n/en/hud/map.ftl b/assets/voxygen/i18n/en/hud/map.ftl index aa0f3cb784..e763c8a020 100644 --- a/assets/voxygen/i18n/en/hud/map.ftl +++ b/assets/voxygen/i18n/en/hud/map.ftl @@ -35,4 +35,5 @@ hud-map-zoom_minimap_explanation = hud-map-gnarling = Gnarling Fortification hud-map-chapel_site = Sea Chapel hud-map-adlet = Adlet Stronghold +hud-map-haniwa = Haniwa Catacomb hud-map-placed_by = Placed by { $name } \ No newline at end of file diff --git a/assets/voxygen/i18n/en/hud/subtitles.ftl b/assets/voxygen/i18n/en/hud/subtitles.ftl index 8fe36b0a2e..0f46bbfaff 100644 --- a/assets/voxygen/i18n/en/hud/subtitles.ftl +++ b/assets/voxygen/i18n/en/hud/subtitles.ftl @@ -78,6 +78,8 @@ subtitle-instrument_icy_talharpa = Icy Talharpa playing subtitle-instrument_kalimba = Kalimba playing subtitle-instrument_melodica = Melodica playing subtitle-instrument_lute = Lute playing +subtitle-instrument_steeldrum = Steeldrum playing +subtitle-instrument_shamisen = Shamisen playing subtitle-instrument_sitar = Sitar playing subtitle-instrument_guitar = Guitar playing subtitle-instrument_dark_guitar = Dark Guitar playing @@ -104,6 +106,7 @@ subtitle-knocked_down = Knocked down subtitle-attack-ground_slam = Ground slam subtitle-attack-laser_beam = Laser beam subtitle-attack-cyclops_charge = Cyclops charge +subtitle-attack-fuse_charge = Fuse sizzling subtitle-giga_roar = Frost gigas roar subtitle-deep_laugh = Deep Laugh subtitle-attack-flash_freeze = Flash freeze diff --git a/assets/voxygen/i18n/en/item/common.ftl b/assets/voxygen/i18n/en/item/common.ftl index d836ee1fb1..20228bf741 100644 --- a/assets/voxygen/i18n/en/item/common.ftl +++ b/assets/voxygen/i18n/en/item/common.ftl @@ -48,6 +48,12 @@ common-items-npc_armor-golem-claygolem = Clay Golem Armor common-items-npc_armor-golem-woodgolem = Wood Golem Armor .desc = Yeet +common-items-npc_armor-golem-ancienteffigy = Ancient Effigy Armor + .desc = Worn by ancient effigy. + +common-items-npc_armor-golem-gravewarden = Grave Warden Armor + .desc = Worn by grave warden. + common-items-npc_armor-biped_small-myrmidon-foot-hoplite = Myrmidon Hoplite .desc = Ceremonial attire used by members.. @@ -528,6 +534,9 @@ common-items-npc_armor-quadruped_medium-frostfang = Frostfang's Thick Skin common-items-npc_armor-quadruped_medium-roshwalr = Roshwalr's Thick Skin .desc = testing123 +common-items-npc_armor-quadruped_medium-claysteed = Claysteeds's Thick Skin + .desc = testing123 + common-items-npc_armor-theropod-rugged = Theropod Rugged .desc = stronk. @@ -567,6 +576,9 @@ common-items-npc_armor-biped_large-warlord = Giant Warlord Chest common-items-npc_armor-biped_large-yeti = Yeti Hide .desc = Strong as Yeti itself. +common-items-npc_armor-biped_large-haniwageneral = Haniwa General Uniform + .desc = Has seen combat. + common-items-weapons-empty-empty = Empty Item .desc = This item may grant abilities, but is invisible @@ -837,6 +849,9 @@ common-items-npc_weapons-sword-pickaxe_velorite_sword = Velorite Pickaxe common-items-npc_weapons-sword-saurok_sword = Saurok Sword .desc = Placeholder +common-items-npc_weapons-sword-haniwa_general_sword = Haniwa General Sword + .desc = Placeholder + common-items-npc_weapons-unique-akhlut = Quad Med Basic .desc = testing123 @@ -1029,6 +1044,15 @@ common-items-npc_weapons-unique-wendigo_magic = Wendigo Magic common-items-npc_weapons-unique-wood_golem_fist = Wood Golem Fists .desc = Yeet +common-items-npc_weapons-unique-ancient_effigy_eyes = Ancient Effigy Eyes + .desc = testing123 + +common-items-npc_weapons-unique-claysteed = Claysteed Hoof + .desc = testing123 + +common-items-npc_weapons-unique-gravewarden_fist = Gravewarden Fist + .desc = testing123 + common-items-npc_weapons-unique-arthropods-antlion = Antlion .desc = testing123 diff --git a/assets/voxygen/i18n/en/item/object.ftl b/assets/voxygen/i18n/en/item/object.ftl index 7ccac12dad..a51cb39cf7 100644 --- a/assets/voxygen/i18n/en/item/object.ftl +++ b/assets/voxygen/i18n/en/item/object.ftl @@ -15,6 +15,9 @@ object-key_bone = Bone Key .desc = Used to open bone locks. Will break after use. +object-key_haniwa = Haniwa Keystone + .desc = Used to open doors. Will break after use. + object-key_glass = Glass Key .desc = Used to open Glass Barriers. Will break after use. diff --git a/assets/voxygen/i18n/en/item/weapon.ftl b/assets/voxygen/i18n/en/item/weapon.ftl index d81380911c..f1c2560d7a 100644 --- a/assets/voxygen/i18n/en/item/weapon.ftl +++ b/assets/voxygen/i18n/en/item/weapon.ftl @@ -207,6 +207,12 @@ weapon-tool-melodica = Melodica weapon-tool-wooden_sitar = Sitar .desc = Wooden Sitar. +weapon-tool-steeldrum = Steeldrum + .desc = Steeldrum. + +weapon-tool-shamisen = Shamisen + .desc = Shamisen. + weapon-tool-washboard = Washboard .desc = Washboard. diff --git a/assets/voxygen/item_image_manifest.ron b/assets/voxygen/item_image_manifest.ron index 95acc5ac91..94a5ef00d3 100644 --- a/assets/voxygen/item_image_manifest.ron +++ b/assets/voxygen/item_image_manifest.ron @@ -1662,6 +1662,14 @@ "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", + (0.0, 0.0, 0.0), (45.0, 90.0, 0.0), 1.0, + ), + Simple("common.items.tool.instruments.shamisen"): VoxTrans( + "voxel.weapon.tool.shamisen", + (0.0, 0.0, 0.0), (45.0, 90.0, 0.0), 1.0, + ), Simple("common.items.tool.instruments.guitar"): VoxTrans( "voxel.weapon.tool.wooden_guitar", (0.0, 0.0, 0.0), (45.0, 90.0, 0.0), 1.1, @@ -4930,6 +4938,10 @@ "voxel.object.key_bone", (0.0, 0.0, 0.0), (-100.0, 250.0, 15.0), 1.0, ), + Simple("common.items.keys.haniwa_key"): VoxTrans( + "voxel.object.key_haniwa", + (0.0, 0.0, 0.0), (-100.0, 250.0, 15.0), 1.0, + ), Simple("common.items.keys.glass_key"): VoxTrans( "voxel.object.key_glass", (0.0, 0.0, 0.0), (-100.0, 250.0, 15.0), 1.0, diff --git a/assets/voxygen/shaders/particle-vert.glsl b/assets/voxygen/shaders/particle-vert.glsl index 33283c538d..f491a0e06c 100644 --- a/assets/voxygen/shaders/particle-vert.glsl +++ b/assets/voxygen/shaders/particle-vert.glsl @@ -94,6 +94,7 @@ const int FIERY_DROPLET_TRACE = 54; const int ENERGY_PHOENIX = 55; const int PHOENIX_BEAM = 56; const int PHOENIX_BUILD_UP_AIM = 57; +const int CLAY_SHRAPNEL = 58; // meters per second squared (acceleration) const float earth_gravity = 9.807; @@ -971,6 +972,18 @@ void main() { spin_in_axis(vec3(rand6, rand7, rand8), perc_t * 10.0 + 3.0 * rand9) ); break; + case CLAY_SHRAPNEL: + float clay_color = 0.025 + 0.02 * rand1; + attr = Attr( + linear_motion( + vec3(0), + normalize(vec3(rand4, rand5, rand6)) * 15.0 + grav_vel(earth_gravity) + ), + vec3(5 * (1 - percent())), + vec4(vec3(clay_color * 3, clay_color * 2, clay_color), 1), + spin_in_axis(vec3(1,0,0),0) + ); + break; default: attr = Attr( linear_motion( diff --git a/assets/voxygen/voxel/biped_large_central_manifest.ron b/assets/voxygen/voxel/biped_large_central_manifest.ron index 730df509fa..0c1ed53af7 100644 --- a/assets/voxygen/voxel/biped_large_central_manifest.ron +++ b/assets/voxygen/voxel/biped_large_central_manifest.ron @@ -1300,4 +1300,60 @@ central: ("armor.empty"), ) ), + (HaniwaGeneral, Male): ( + head: ( + offset: (-7.5, 0.0, -6.5), + central: ("npc.haniwa.general.haniwa_general"), + ), + torso_upper: ( + offset: (-6.5, -4.0, -4.5), + central: ("npc.haniwa.general.haniwa_general"), + model_index: 1, + ), + torso_lower: ( + offset: (-7.5, -6.0, -5.0), + central: ("npc.haniwa.general.haniwa_general"), + 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"), + ) + ), + (HaniwaGeneral, Female): ( + head: ( + offset: (-7.5, 0.0, -6.5), + central: ("npc.haniwa.general.haniwa_general"), + ), + torso_upper: ( + offset: (-6.5, -4.0, -4.5), + central: ("npc.haniwa.general.haniwa_general"), + model_index: 1, + ), + torso_lower: ( + offset: (-7.5, -6.0, -5.0), + central: ("npc.haniwa.general.haniwa_general"), + 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 18571716b0..835c820eb0 100644 --- a/assets/voxygen/voxel/biped_large_lateral_manifest.ron +++ b/assets/voxygen/voxel/biped_large_lateral_manifest.ron @@ -1699,4 +1699,88 @@ lateral: ("armor.empty"), ), ), + (HaniwaGeneral, Male): ( + shoulder_l: ( + offset: (-3.5, -3.0, -7.0), + lateral: ("npc.haniwa.general.haniwa_general"), + model_index: 3, + ), + shoulder_r: ( + offset: (-3.5, -3.0, -7.0), + lateral: ("npc.haniwa.general.haniwa_general"), + model_index: 4, + ), + hand_l: ( + offset: (-2.5, -2.0, -8.0), + lateral: ("npc.haniwa.general.haniwa_general"), + model_index: 5, + ), + hand_r: ( + offset: (-2.5, -2.0, -8.0), + lateral: ("npc.haniwa.general.haniwa_general"), + model_index: 6, + ), + leg_l: ( + offset: (-2.5, -3.0, -3.0), + lateral: ("npc.haniwa.general.haniwa_general"), + model_index: 7, + ), + leg_r: ( + offset: (-2.5, -3.0, -3.0), + lateral: ("npc.haniwa.general.haniwa_general"), + model_index: 8, + ), + foot_l: ( + offset: (-1.5, -3.0, -2.5), + lateral: ("npc.haniwa.general.haniwa_general"), + model_index: 9, + ), + foot_r: ( + offset: (-1.5, -3.0, -2.5), + lateral: ("npc.haniwa.general.haniwa_general"), + model_index: 10, + ), + ), + (HaniwaGeneral, Female): ( + shoulder_l: ( + offset: (-3.5, -3.0, -7.0), + lateral: ("npc.haniwa.general.haniwa_general"), + model_index: 3, + ), + shoulder_r: ( + offset: (-3.5, -3.0, -7.0), + lateral: ("npc.haniwa.general.haniwa_general"), + model_index: 4, + ), + hand_l: ( + offset: (-2.5, -2.0, -8.0), + lateral: ("npc.haniwa.general.haniwa_general"), + model_index: 5, + ), + hand_r: ( + offset: (-2.5, -2.0, -8.0), + lateral: ("npc.haniwa.general.haniwa_general"), + model_index: 6, + ), + leg_l: ( + offset: (-2.5, -3.0, -3.0), + lateral: ("npc.haniwa.general.haniwa_general"), + model_index: 7, + ), + leg_r: ( + offset: (-2.5, -3.0, -3.0), + lateral: ("npc.haniwa.general.haniwa_general"), + model_index: 8, + ), + foot_l: ( + offset: (-1.5, -3.0, -2.5), + lateral: ("npc.haniwa.general.haniwa_general"), + model_index: 9, + ), + foot_r: ( + offset: (-1.5, -3.0, -2.5), + lateral: ("npc.haniwa.general.haniwa_general"), + model_index: 10, + ), + ), }) \ 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 0f399bb7da..93f20fde1f 100644 --- a/assets/voxygen/voxel/biped_weapon_manifest.ron +++ b/assets/voxygen/voxel/biped_weapon_manifest.ron @@ -1160,6 +1160,14 @@ 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)), + color: None + ), + Tool("common.items.tool.instruments.shamisen"): ( + vox_spec: ("weapon.tool.shamisen", (-2.5, -6.0, 0.0)), + color: None + ), Tool("common.items.tool.instruments.guitar"): ( vox_spec: ("weapon.tool.wooden_guitar", (-4.5, -6.0, 0.0)), color: None @@ -1639,10 +1647,14 @@ vox_spec: ("weapon.sword.long_2h_saurok", (-2.5, -4.0, -5.0)), color: None ), - Tool("common.items.npc_weapons.sword.adlet_elder_sword"): ( + Tool("common.items.npc_weapons.sword.haniwa_general_sword"): ( vox_spec: ("weapon.sword.adlet_elder_sword", (-2.5, -5.0, -5.0)), color: None ), + Tool("common.items.npc_weapons.sword.haniwa_general_sword"): ( + vox_spec: ("weapon.sword.haniwa_general_sword", (-2.5, -5.0, -5.0)), + color: None + ), Tool("common.items.npc_weapons.bow.saurok_bow"): ( vox_spec: ("weapon.bow.longbow_saurok", (-2.5, -4.0, -16.5)), color: None diff --git a/assets/voxygen/voxel/golem_central_manifest.ron b/assets/voxygen/voxel/golem_central_manifest.ron index 5d8b7d4e71..b16aaf2b4a 100644 --- a/assets/voxygen/voxel/golem_central_manifest.ron +++ b/assets/voxygen/voxel/golem_central_manifest.ron @@ -71,10 +71,10 @@ central: ("npc.treant.male.chest_lower"), ), ), - (ClayGolem, Male): ( + (Gravewarden, Male): ( head: ( offset: (-10.5, -3.0, -3.0), - central: ("npc.claygolem.male.head"), + central: ("npc.gravewarden.male.head"), ), jaw: ( offset: (-9.5, 0.0, -3.0), @@ -82,29 +82,113 @@ ), torso_upper: ( offset: (-9.5, -7.0, -6.5), - central: ("npc.claygolem.male.chest_upper"), + central: ("npc.gravewarden.male.chest_upper"), ), torso_lower: ( offset: (-9.5, -7.0, -8.0), - central: ("npc.claygolem.male.chest_lower"), + central: ("npc.gravewarden.male.chest_lower"), + ), + ), + (Gravewarden, Female): ( + head: ( + offset: (-10.5, -3.0, -3.0), + central: ("npc.gravewarden.male.head"), + ), + jaw: ( + offset: (-9.5, 0.0, -3.0), + central: ("armor.empty"), + ), + torso_upper: ( + offset: (-9.5, -7.0, -6.5), + central: ("npc.gravewarden.male.chest_upper"), + ), + torso_lower: ( + offset: (-9.5, -7.0, -8.0), + central: ("npc.gravewarden.male.chest_lower"), + ), + ), + (ClayGolem, Male): ( + head: ( + offset: (-7.5, -3.5, -3.0), + central: ("npc.claygolem.male.claygolem"), + model_index: 0, + ), + jaw: ( + offset: (-9.5, 0.0, -3.0), + central: ("armor.empty"), + ), + torso_upper: ( + offset: (-13.5, -7.5, -8.0), + central: ("npc.claygolem.male.claygolem"), + model_index: 1, + ), + torso_lower: ( + offset: (-8.5, -7.0, -7.0), + central: ("npc.claygolem.male.claygolem"), + model_index: 2, ), ), (ClayGolem, Female): ( head: ( - offset: (-10.5, -3.0, -3.0), - central: ("npc.claygolem.male.head"), + offset: (-7.5, -3.5, -3.0), + central: ("npc.claygolem.male.claygolem"), + model_index: 0, ), jaw: ( offset: (-9.5, 0.0, -3.0), central: ("armor.empty"), ), torso_upper: ( - offset: (-9.5, -7.0, -6.5), - central: ("npc.claygolem.male.chest_upper"), + offset: (-13.5, -7.5, -8.0), + central: ("npc.claygolem.male.claygolem"), + model_index: 1, ), torso_lower: ( - offset: (-9.5, -7.0, -8.0), - central: ("npc.claygolem.male.chest_lower"), + offset: (-8.5, -7.0, -7.0), + central: ("npc.claygolem.male.claygolem"), + model_index: 2, + ), + ), + (AncientEffigy, Male): ( + head: ( + offset: (-7.5, -3.0, -5.0), + central: ("npc.ancienteffigy.male.ancienteffigy"), + model_index: 0, + ), + jaw: ( + offset: (-9.5, 0.0, -3.0), + central: ("armor.empty"), + ), + torso_upper: ( + offset: (-11.5, -5.0, -5.5), + central: ("npc.ancienteffigy.male.ancienteffigy"), + model_index: 1, + ), + torso_lower: ( + offset: (-7.5, -5.5, -5.5), + central: ("npc.ancienteffigy.male.ancienteffigy"), + model_index: 2, + ), + ), + (AncientEffigy, Female): ( + head: ( + offset: (-7.5, -3.0, -5.0), + central: ("npc.ancienteffigy.male.ancienteffigy"), + model_index: 0, + ), + jaw: ( + offset: (-9.5, 0.0, -3.0), + central: ("armor.empty"), + ), + torso_upper: ( + offset: (-11.5, -5.0, -5.5), + central: ("npc.ancienteffigy.male.ancienteffigy"), + model_index: 1, + ), + torso_lower: ( + offset: (-7.5, -5.5, -5.5), + central: ("npc.ancienteffigy.male.ancienteffigy"), + model_index: 2, ), ), (WoodGolem, Male): ( diff --git a/assets/voxygen/voxel/golem_lateral_manifest.ron b/assets/voxygen/voxel/golem_lateral_manifest.ron index 78f096f7a4..8594afef82 100644 --- a/assets/voxygen/voxel/golem_lateral_manifest.ron +++ b/assets/voxygen/voxel/golem_lateral_manifest.ron @@ -135,73 +135,227 @@ lateral: ("npc.treant.male.foot_r"), ) ), - (ClayGolem, Male): ( + (Gravewarden, Male): ( shoulder_l: ( offset: (-13.0, -3.5, -6.5), - lateral: ("npc.claygolem.male.shoulder_l"), + lateral: ("npc.gravewarden.male.shoulder_l"), ), shoulder_r: ( offset: (0.0, -3.5, -6.5), - lateral: ("npc.claygolem.male.shoulder_r"), + lateral: ("npc.gravewarden.male.shoulder_r"), ), hand_l: ( offset: (-7.5, -6.5, -17.0), - lateral: ("npc.claygolem.male.hand_l"), + lateral: ("npc.gravewarden.male.hand_l"), ), hand_r: ( offset: (-7.5, -6.5, -17.0), - lateral: ("npc.claygolem.male.hand_r"), + lateral: ("npc.gravewarden.male.hand_r"), ), leg_l: ( offset: (-8.0, -4.0, -10.0), - lateral: ("npc.claygolem.male.leg_l"), + lateral: ("npc.gravewarden.male.leg_l"), ), leg_r: ( offset: (0.0, -4.0, -10.0), - lateral: ("npc.claygolem.male.leg_r"), + lateral: ("npc.gravewarden.male.leg_r"), ), foot_l: ( offset: (-2.5, -3.0, -7.0), - lateral: ("npc.claygolem.male.foot_l"), + lateral: ("npc.gravewarden.male.foot_l"), ), foot_r: ( offset: (-2.5, -3.0, -7.0), - lateral: ("npc.claygolem.male.foot_r"), + lateral: ("npc.gravewarden.male.foot_r"), ) ), + (Gravewarden, Female): ( + shoulder_l: ( + offset: (-13.0, -3.5, -6.5), + lateral: ("npc.gravewarden.male.shoulder_l"), + ), + shoulder_r: ( + offset: (0.0, -3.5, -6.5), + lateral: ("npc.gravewarden.male.shoulder_r"), + ), + hand_l: ( + offset: (-7.5, -6.5, -17.0), + lateral: ("npc.gravewarden.male.hand_l"), + ), + hand_r: ( + offset: (-7.5, -6.5, -17.0), + lateral: ("npc.gravewarden.male.hand_r"), + ), + leg_l: ( + offset: (-8.0, -4.0, -10.0), + lateral: ("npc.gravewarden.male.leg_l"), + ), + leg_r: ( + offset: (0.0, -4.0, -10.0), + lateral: ("npc.gravewarden.male.leg_r"), + ), + foot_l: ( + offset: (-2.5, -3.0, -7.0), + lateral: ("npc.gravewarden.male.foot_l"), + ), + foot_r: ( + offset: (-2.5, -3.0, -7.0), + lateral: ("npc.gravewarden.male.foot_r"), + ) + ), + (ClayGolem, Male): ( + shoulder_l: ( + offset: (-9.0, -2.5, -4.0), + lateral: ("npc.claygolem.male.claygolem"), + model_index: 3, + ), + shoulder_r: ( + offset: (0.0, -2.5, -4.0), + lateral: ("npc.claygolem.male.claygolem"), + model_index: 4, + ), + hand_l: ( + offset: (-5.5, -5.0, -18.0), + lateral: ("npc.claygolem.male.claygolem"), + model_index: 5, + ), + hand_r: ( + offset: (-5.5, -5.0, -18.0), + lateral: ("npc.claygolem.male.claygolem"), + model_index: 6, + ), + leg_l: ( + offset: (-7.0, -4.0, -7.0), + lateral: ("npc.claygolem.male.claygolem"), + model_index: 7, + ), + leg_r: ( + offset: (0.0, -4.0, -7.0), + lateral: ("npc.claygolem.male.claygolem"), + model_index: 8, + ), + foot_l: ( + offset: (-4.0, -5.0, -7.0), + lateral: ("npc.claygolem.male.claygolem"), + model_index: 9, + ), + foot_r: ( + offset: (-4.0, -5.0, -7.0), + lateral: ("npc.claygolem.male.claygolem"), + model_index: 10, + ), + ), (ClayGolem, Female): ( shoulder_l: ( - offset: (-13.0, -3.5, -6.5), - lateral: ("npc.claygolem.male.shoulder_l"), + offset: (-9.0, -2.5, -4.0), + lateral: ("npc.claygolem.male.claygolem"), + model_index: 3, ), shoulder_r: ( - offset: (0.0, -3.5, -6.5), - lateral: ("npc.claygolem.male.shoulder_r"), + offset: (0.0, -2.5, -4.0), + lateral: ("npc.claygolem.male.claygolem"), + model_index: 4, ), hand_l: ( - offset: (-7.5, -6.5, -17.0), - lateral: ("npc.claygolem.male.hand_l"), + offset: (-5.5, -5.0, -18.0), + lateral: ("npc.claygolem.male.claygolem"), + model_index: 5, ), hand_r: ( - offset: (-7.5, -6.5, -17.0), - lateral: ("npc.claygolem.male.hand_r"), + offset: (-5.5, -5.0, -18.0), + lateral: ("npc.claygolem.male.claygolem"), + model_index: 6, ), leg_l: ( - offset: (-8.0, -4.0, -10.0), - lateral: ("npc.claygolem.male.leg_l"), + offset: (-7.0, -4.0, -7.0), + lateral: ("npc.claygolem.male.claygolem"), + model_index: 7, ), leg_r: ( - offset: (0.0, -4.0, -10.0), - lateral: ("npc.claygolem.male.leg_r"), + offset: (0.0, -4.0, -7.0), + lateral: ("npc.claygolem.male.claygolem"), + model_index: 8, ), foot_l: ( - offset: (-2.5, -3.0, -7.0), - lateral: ("npc.claygolem.male.foot_l"), + offset: (-4.0, -5.0, -7.0), + lateral: ("npc.claygolem.male.claygolem"), + model_index: 9, ), foot_r: ( - offset: (-2.5, -3.0, -7.0), - lateral: ("npc.claygolem.male.foot_r"), - ) + offset: (-4.0, -5.0, -7.0), + lateral: ("npc.claygolem.male.claygolem"), + model_index: 10, + ), + ), + (AncientEffigy, 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"), + ), + ), + (AncientEffigy, 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"), + ), ), (WoodGolem, Male): ( shoulder_l: ( diff --git a/assets/voxygen/voxel/item_drop_manifest.ron b/assets/voxygen/voxel/item_drop_manifest.ron index 8cbf53f90d..54518d661b 100644 --- a/assets/voxygen/voxel/item_drop_manifest.ron +++ b/assets/voxygen/voxel/item_drop_manifest.ron @@ -408,6 +408,8 @@ 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.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", Simple("common.items.tool.instruments.guitar_dark"): "voxel.weapon.tool.black_velvet_guitar", @@ -946,6 +948,7 @@ // Keys and Lockpicks Simple("common.items.keys.rusty_tower_key"): "voxel.object.key_rusty-0", Simple("common.items.keys.bone_key"): "voxel.object.key_bone", + Simple("common.items.keys.haniwa_key"): "voxel.object.key_haniwa", Simple("common.items.keys.glass_key"): "voxel.object.key_glass", Simple("common.items.utility.lockpick_0"): "voxel.object.lockpick", Simple("common.items.keys.quarry_keys.ancient"): "voxel.object.key_rusty-0", diff --git a/assets/voxygen/voxel/npc/ancienteffigy/male/ancienteffigy.vox b/assets/voxygen/voxel/npc/ancienteffigy/male/ancienteffigy.vox new file mode 100644 index 0000000000..69460d3542 --- /dev/null +++ b/assets/voxygen/voxel/npc/ancienteffigy/male/ancienteffigy.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bb40de858dc3b654791b7f0c46d72a4f819accf8f670123ee2152eef9a58c91c +size 11754 diff --git a/assets/voxygen/voxel/npc/claygolem/male/claygolem.vox b/assets/voxygen/voxel/npc/claygolem/male/claygolem.vox new file mode 100644 index 0000000000..8f64d12457 --- /dev/null +++ b/assets/voxygen/voxel/npc/claygolem/male/claygolem.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f7972091a7e149291c6d5282460c23a32ea8eab6c84acdf9445adf0601c698fe +size 32482 diff --git a/assets/voxygen/voxel/npc/claysteed/male/claysteed.vox b/assets/voxygen/voxel/npc/claysteed/male/claysteed.vox new file mode 100644 index 0000000000..a55fdaf713 --- /dev/null +++ b/assets/voxygen/voxel/npc/claysteed/male/claysteed.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:83a57aee603569169142b2fb72227d5a4e8ce2ad0f60f4967d4d601f9f91ffbd +size 34302 diff --git a/assets/voxygen/voxel/npc/claygolem/male/chest_lower.vox b/assets/voxygen/voxel/npc/gravewarden/male/chest_lower.vox similarity index 100% rename from assets/voxygen/voxel/npc/claygolem/male/chest_lower.vox rename to assets/voxygen/voxel/npc/gravewarden/male/chest_lower.vox diff --git a/assets/voxygen/voxel/npc/claygolem/male/chest_upper.vox b/assets/voxygen/voxel/npc/gravewarden/male/chest_upper.vox similarity index 100% rename from assets/voxygen/voxel/npc/claygolem/male/chest_upper.vox rename to assets/voxygen/voxel/npc/gravewarden/male/chest_upper.vox diff --git a/assets/voxygen/voxel/npc/claygolem/male/foot_l.vox b/assets/voxygen/voxel/npc/gravewarden/male/foot_l.vox similarity index 100% rename from assets/voxygen/voxel/npc/claygolem/male/foot_l.vox rename to assets/voxygen/voxel/npc/gravewarden/male/foot_l.vox diff --git a/assets/voxygen/voxel/npc/claygolem/male/foot_r.vox b/assets/voxygen/voxel/npc/gravewarden/male/foot_r.vox similarity index 100% rename from assets/voxygen/voxel/npc/claygolem/male/foot_r.vox rename to assets/voxygen/voxel/npc/gravewarden/male/foot_r.vox diff --git a/assets/voxygen/voxel/npc/claygolem/male/hand_l.vox b/assets/voxygen/voxel/npc/gravewarden/male/hand_l.vox similarity index 100% rename from assets/voxygen/voxel/npc/claygolem/male/hand_l.vox rename to assets/voxygen/voxel/npc/gravewarden/male/hand_l.vox diff --git a/assets/voxygen/voxel/npc/claygolem/male/hand_r.vox b/assets/voxygen/voxel/npc/gravewarden/male/hand_r.vox similarity index 100% rename from assets/voxygen/voxel/npc/claygolem/male/hand_r.vox rename to assets/voxygen/voxel/npc/gravewarden/male/hand_r.vox diff --git a/assets/voxygen/voxel/npc/claygolem/male/head.vox b/assets/voxygen/voxel/npc/gravewarden/male/head.vox similarity index 100% rename from assets/voxygen/voxel/npc/claygolem/male/head.vox rename to assets/voxygen/voxel/npc/gravewarden/male/head.vox diff --git a/assets/voxygen/voxel/npc/claygolem/male/leg_l.vox b/assets/voxygen/voxel/npc/gravewarden/male/leg_l.vox similarity index 100% rename from assets/voxygen/voxel/npc/claygolem/male/leg_l.vox rename to assets/voxygen/voxel/npc/gravewarden/male/leg_l.vox diff --git a/assets/voxygen/voxel/npc/claygolem/male/leg_r.vox b/assets/voxygen/voxel/npc/gravewarden/male/leg_r.vox similarity index 100% rename from assets/voxygen/voxel/npc/claygolem/male/leg_r.vox rename to assets/voxygen/voxel/npc/gravewarden/male/leg_r.vox diff --git a/assets/voxygen/voxel/npc/claygolem/male/shoulder_l.vox b/assets/voxygen/voxel/npc/gravewarden/male/shoulder_l.vox similarity index 100% rename from assets/voxygen/voxel/npc/claygolem/male/shoulder_l.vox rename to assets/voxygen/voxel/npc/gravewarden/male/shoulder_l.vox diff --git a/assets/voxygen/voxel/npc/claygolem/male/shoulder_r.vox b/assets/voxygen/voxel/npc/gravewarden/male/shoulder_r.vox similarity index 100% rename from assets/voxygen/voxel/npc/claygolem/male/shoulder_r.vox rename to assets/voxygen/voxel/npc/gravewarden/male/shoulder_r.vox diff --git a/assets/voxygen/voxel/npc/haniwa/general/haniwa_general.vox b/assets/voxygen/voxel/npc/haniwa/general/haniwa_general.vox new file mode 100644 index 0000000000..124721d532 --- /dev/null +++ b/assets/voxygen/voxel/npc/haniwa/general/haniwa_general.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9c12665ab88a9fb5681d3e649126d4c39a3aea4f9884f9521ee54d4b366d4b02 +size 32723 diff --git a/assets/voxygen/voxel/object/haniwa_sentry/bone.vox b/assets/voxygen/voxel/object/haniwa_sentry/bone.vox new file mode 100644 index 0000000000..5098216545 --- /dev/null +++ b/assets/voxygen/voxel/object/haniwa_sentry/bone.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7f41def66d941518938c8cf2430df9781859fb03932451dd4471436a69a9bb69 +size 6650 diff --git a/assets/voxygen/voxel/object/haniwa_sentry/bone0.vox b/assets/voxygen/voxel/object/haniwa_sentry/bone0.vox deleted file mode 100644 index 5f500c2207..0000000000 --- a/assets/voxygen/voxel/object/haniwa_sentry/bone0.vox +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:3d70d98406757152ce20a554ce5b0adaf9f270bcdd537f95be1da7c76da894a4 -size 2712 diff --git a/assets/voxygen/voxel/object/haniwa_sentry/bone1.vox b/assets/voxygen/voxel/object/haniwa_sentry/bone1.vox deleted file mode 100644 index e6ec05c7ca..0000000000 --- a/assets/voxygen/voxel/object/haniwa_sentry/bone1.vox +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:74cc8a7bbb270078568d55f2ebc29d2625c85ccc39963351f5da8f27738744b9 -size 2440 diff --git a/assets/voxygen/voxel/object/key_haniwa.vox b/assets/voxygen/voxel/object/key_haniwa.vox new file mode 100644 index 0000000000..f99e1373af --- /dev/null +++ b/assets/voxygen/voxel/object/key_haniwa.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a76ab8f3781fa08be8d6497d795fc69fe1dbb1c1ee557fcee1aa27fbb6af4124 +size 1356 diff --git a/assets/voxygen/voxel/object_manifest.ron b/assets/voxygen/voxel/object_manifest.ron index 0b299202e3..6c2bd0aca1 100644 --- a/assets/voxygen/voxel/object_manifest.ron +++ b/assets/voxygen/voxel/object_manifest.ron @@ -719,6 +719,16 @@ central: ("armor.empty"), ) ), + ArrowClay: ( + bone0: ( + offset: (-1.5, -6.0, -1.5), + central: ("weapon.projectile.clay-arrow"), + ), + bone1: ( + offset: (0.0, 0.0, 0.0), + central: ("armor.empty"), + ) + ), SilverOre: ( bone0: ( offset: (-4.5, -5.0, 0.0), @@ -749,14 +759,26 @@ central: ("armor.empty"), ) ), + GrenadeClay: ( + bone0: ( + offset: (-0.5, -6.0, -1.5), + central: ("weapon.projectile.clay-missile"), + ), + bone1: ( + offset: (0.0, 0.0, 0.0), + central: ("armor.empty"), + ) + ), HaniwaSentry: ( bone0: ( offset: (-5.5, -4.5, -5.5), - central: ("object.haniwa_sentry.bone0"), + central: ("object.haniwa_sentry.bone"), + model_index: 0, ), bone1: ( offset: (-5.5, -5.5, -3.0), - central: ("object.haniwa_sentry.bone1"), + central: ("object.haniwa_sentry.bone"), + model_index: 1, ) ), SeaLantern: ( diff --git a/assets/voxygen/voxel/quadruped_medium_central_manifest.ron b/assets/voxygen/voxel/quadruped_medium_central_manifest.ron index 9ca3c87341..be9d37f207 100644 --- a/assets/voxygen/voxel/quadruped_medium_central_manifest.ron +++ b/assets/voxygen/voxel/quadruped_medium_central_manifest.ron @@ -2171,4 +2171,74 @@ central: ("npc.bristleback.male.tail"), ), ), + (ClaySteed, Male): ( + head: ( + offset: (-4.0, -2.0, -6.0), + central: ("npc.claysteed.male.claysteed"), + model_index: 8, + ), + neck: ( + offset: (-4.0, -3.5, -7.0), + central: ("npc.claysteed.male.claysteed"), + model_index: 7, + ), + jaw: ( + offset: (-2.0, 0.0, -2.0), + central: ("armor.empty"), + ), + torso_front: ( + offset: (-5.0, -9.0, -7.0), + central: ("npc.claysteed.male.claysteed"), + model_index: 6, + ), + torso_back: ( + offset: (-5.0, -12.0, -6.0), + central: ("npc.claysteed.male.claysteed"), + model_index: 5, + ), + ears: ( + offset: (-4.0, -1.0, 0.0), + central: ("armor.empty"), + ), + tail: ( + offset: (-2.0, -11.0, -7.0), + central: ("npc.claysteed.male.claysteed"), + model_index: 4, + ), + ), + (ClaySteed, Female): ( + head: ( + offset: (-4.0, -2.0, -6.0), + central: ("npc.claysteed.male.claysteed"), + model_index: 8, + ), + neck: ( + offset: (-4.0, -3.5, -7.0), + central: ("npc.claysteed.male.claysteed"), + model_index: 7, + ), + jaw: ( + offset: (-2.0, 0.0, -2.0), + central: ("armor.empty"), + ), + torso_front: ( + offset: (-5.0, -9.0, -7.0), + central: ("npc.claysteed.male.claysteed"), + model_index: 6, + ), + torso_back: ( + offset: (-5.0, -12.0, -6.0), + central: ("npc.claysteed.male.claysteed"), + model_index: 5, + ), + ears: ( + offset: (-4.0, -1.0, 0.0), + central: ("armor.empty"), + ), + tail: ( + offset: (-2.0, -11.0, -7.0), + central: ("npc.claysteed.male.claysteed"), + model_index: 4, + ), + ), }) diff --git a/assets/voxygen/voxel/quadruped_medium_lateral_manifest.ron b/assets/voxygen/voxel/quadruped_medium_lateral_manifest.ron index 19a0cfdf7c..42e9f0d03f 100644 --- a/assets/voxygen/voxel/quadruped_medium_lateral_manifest.ron +++ b/assets/voxygen/voxel/quadruped_medium_lateral_manifest.ron @@ -2463,4 +2463,88 @@ lateral: ("npc.bristleback.male.foot_br"), ), ), + (ClaySteed, Male): ( + leg_fl: ( + offset: (-2.0, -2.5, -6.0), + lateral: ("npc.claysteed.male.claysteed"), + model_index: 3, + ), + leg_fr: ( + offset: (-2.0, -2.5, -6.0), + lateral: ("npc.claysteed.male.claysteed"), + model_index: 3, + ), + leg_bl: ( + offset: (-2.5, -3.0, -5.0), + lateral: ("npc.claysteed.male.claysteed"), + model_index: 2, + ), + leg_br: ( + offset: (-2.5, -3.0, -5.0), + lateral: ("npc.claysteed.male.claysteed"), + model_index: 2, + ), + foot_fl: ( + offset: (-2.5, -2.5, -7.0), + lateral: ("npc.claysteed.male.claysteed"), + model_index: 1, + ), + foot_fr: ( + offset: (-2.5, -2.5, -7.0), + lateral: ("npc.claysteed.male.claysteed"), + model_index: 1, + ), + foot_bl: ( + offset: (-2.5, -2.5, -8.0), + lateral: ("npc.claysteed.male.claysteed"), + model_index: 0, + ), + foot_br: ( + offset: (-2.5, -2.5, -8.0), + lateral: ("npc.claysteed.male.claysteed"), + model_index: 0, + ), + ), + (ClaySteed, Female): ( + leg_fl: ( + offset: (-2.0, -2.5, -6.0), + lateral: ("npc.claysteed.male.claysteed"), + model_index: 3, + ), + leg_fr: ( + offset: (-2.0, -2.5, -6.0), + lateral: ("npc.claysteed.male.claysteed"), + model_index: 3, + ), + leg_bl: ( + offset: (-2.5, -3.0, -5.0), + lateral: ("npc.claysteed.male.claysteed"), + model_index: 2, + ), + leg_br: ( + offset: (-2.5, -3.0, -5.0), + lateral: ("npc.claysteed.male.claysteed"), + model_index: 2, + ), + foot_fl: ( + offset: (-2.5, -2.5, -7.0), + lateral: ("npc.claysteed.male.claysteed"), + model_index: 1, + ), + foot_fr: ( + offset: (-2.5, -2.5, -7.0), + lateral: ("npc.claysteed.male.claysteed"), + model_index: 1, + ), + foot_bl: ( + offset: (-2.5, -2.5, -8.0), + lateral: ("npc.claysteed.male.claysteed"), + model_index: 0, + ), + foot_br: ( + offset: (-2.5, -2.5, -8.0), + lateral: ("npc.claysteed.male.claysteed"), + model_index: 0, + ), + ), }) diff --git a/assets/voxygen/voxel/sprite/chests/chest_haniwa_urn.vox b/assets/voxygen/voxel/sprite/chests/chest_haniwa_urn.vox new file mode 100644 index 0000000000..492361ab0d --- /dev/null +++ b/assets/voxygen/voxel/sprite/chests/chest_haniwa_urn.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2790d079d350a9fd362da8b273733f6de925d8ec248300b7c386b74b5b9df2c1 +size 2636 diff --git a/assets/voxygen/voxel/sprite/furniture/haniwa_door_block.vox b/assets/voxygen/voxel/sprite/furniture/haniwa_door_block.vox new file mode 100644 index 0000000000..ae1bce33d5 --- /dev/null +++ b/assets/voxygen/voxel/sprite/furniture/haniwa_door_block.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:db071479c2e62c2b139988e12502edebfaa145e90c14bea35e53c37974db9e26 +size 6420 diff --git a/assets/voxygen/voxel/sprite/furniture/haniwa_keyhole_block.vox b/assets/voxygen/voxel/sprite/furniture/haniwa_keyhole_block.vox new file mode 100644 index 0000000000..73434a1f15 --- /dev/null +++ b/assets/voxygen/voxel/sprite/furniture/haniwa_keyhole_block.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6267cfa1208883109f22fd246ddcbbeace5b0fcd6555cc3924039bc78d62d6ea +size 5916 diff --git a/assets/voxygen/voxel/sprite/furniture/haniwa_trap_triggered-0.vox b/assets/voxygen/voxel/sprite/furniture/haniwa_trap_triggered-0.vox new file mode 100644 index 0000000000..34c2c4f648 --- /dev/null +++ b/assets/voxygen/voxel/sprite/furniture/haniwa_trap_triggered-0.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c812d1b380e086083a5e04d3dcea542caf601410f69ddc5d35309c0854c73843 +size 5068 diff --git a/assets/voxygen/voxel/sprite/furniture/haniwa_trap_triggered-1.vox b/assets/voxygen/voxel/sprite/furniture/haniwa_trap_triggered-1.vox new file mode 100644 index 0000000000..de337f954d --- /dev/null +++ b/assets/voxygen/voxel/sprite/furniture/haniwa_trap_triggered-1.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:df8eb11d432241c808644c76ca965108b5518898cd7b9d7ce8990c313c964885 +size 5236 diff --git a/assets/voxygen/voxel/sprite/misc/sea_decor_block.vox b/assets/voxygen/voxel/sprite/misc/sea_decor_block.vox index 07cbd29bec..85098ea10a 100644 --- a/assets/voxygen/voxel/sprite/misc/sea_decor_block.vox +++ b/assets/voxygen/voxel/sprite/misc/sea_decor_block.vox @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4709c5acc8fcc98d332749c5e4b327df63d5e88e625080edc4427ec193229c17 -size 6420 +oid sha256:aa74d72dcff22ea5dcabee9fdb9137f3032e6c8cc32b0643a5203d13aefff5e5 +size 6536 diff --git a/assets/voxygen/voxel/sprite_manifest.ron b/assets/voxygen/voxel/sprite_manifest.ron index c855ee56c1..07688e94f3 100644 --- a/assets/voxygen/voxel/sprite_manifest.ron +++ b/assets/voxygen/voxel/sprite_manifest.ron @@ -1027,6 +1027,65 @@ GlassKeyhole: Some(( ], wind_sway: 0.0, )), +// Haniwa KeyDoor +HaniwaKeyDoor: Some(( + variations: [ + ( + model: "voxygen.voxel.sprite.furniture.haniwa_door_block", + offset: (-5.5, -5.5, -0.0), + lod_axes: (1.0, 1.0, 1.0), + ), + ], + wind_sway: 0.0, +)), +// Haniwa Keyhole +HaniwaKeyhole: Some(( + variations: [ + ( + model: "voxygen.voxel.sprite.furniture.haniwa_keyhole_block", + offset: (-5.5, -5.5, -0.0), + lod_axes: (1.0, 1.0, 1.0), + ), + ], + wind_sway: 0.0, +)), +HaniwaUrn: Some(( + variations: [ + ( + model: "voxygen.voxel.sprite.chests.chest_haniwa_urn", + offset: (-7.5, -6.0, -0.0), + lod_axes: (1.0, 1.0, 1.0), + ), + + ], + wind_sway: 0.0, +)), +// Haniwa Trap +HaniwaTrap: Some(( + variations: [ + ( + model: "voxygen.voxel.sprite.furniture.haniwa_door_block", + offset: (-5.5, -5.5, -0.0), + lod_axes: (1.0, 1.0, 1.0), + ), + ], + wind_sway: 0.0, +)), +HaniwaTrapTriggered: Some(( + variations: [ + ( + model: "voxygen.voxel.sprite.furniture.haniwa_trap_triggered-0", + offset: (-5.5, -5.5, -0.0), + lod_axes: (1.0, 1.0, 1.0), + ), + ( + model: "voxygen.voxel.sprite.furniture.haniwa_trap_triggered-1", + offset: (-5.5, -5.5, -0.0), + lod_axes: (1.0, 1.0, 1.0), + ), + ], + wind_sway: 0.0, +)), // Welwitch Welwitch: Some(( variations: [ diff --git a/assets/voxygen/voxel/weapon/projectile/clay-arrow.vox b/assets/voxygen/voxel/weapon/projectile/clay-arrow.vox new file mode 100644 index 0000000000..5a21f74007 --- /dev/null +++ b/assets/voxygen/voxel/weapon/projectile/clay-arrow.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6e6f126c5630652033bd3e6ff03826524e4eed48c993d85864c335481b3882b2 +size 1172 diff --git a/assets/voxygen/voxel/weapon/sword/haniwa_general_sword.vox b/assets/voxygen/voxel/weapon/sword/haniwa_general_sword.vox new file mode 100644 index 0000000000..2e93f2cc95 --- /dev/null +++ b/assets/voxygen/voxel/weapon/sword/haniwa_general_sword.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:291b5ee8934569c76ec786eb612d3f448ed6e15e56aa397867a2a87211e91dcd +size 1396 diff --git a/assets/voxygen/voxel/weapon/tool/shamisen.vox b/assets/voxygen/voxel/weapon/tool/shamisen.vox new file mode 100644 index 0000000000..e49e29df7e --- /dev/null +++ b/assets/voxygen/voxel/weapon/tool/shamisen.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:31ea171512a2fb06aa3b525ae2458486bd0876bab4a40508a616de82950f07a8 +size 1508 diff --git a/assets/voxygen/voxel/weapon/tool/steeldrum.vox b/assets/voxygen/voxel/weapon/tool/steeldrum.vox new file mode 100644 index 0000000000..42b71acf45 --- /dev/null +++ b/assets/voxygen/voxel/weapon/tool/steeldrum.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5689fcd5718343af48d9a5d9316654c9a450b9afd16dca59d8a81577cfc94852 +size 1608 diff --git a/assets/world/dungeon/difficulty_distribution.ron b/assets/world/dungeon/difficulty_distribution.ron index 7ebec5c934..1969d17d35 100644 --- a/assets/world/dungeon/difficulty_distribution.ron +++ b/assets/world/dungeon/difficulty_distribution.ron @@ -17,7 +17,6 @@ /// and you will have map full of dungeons of same level ([ (2, 0.20), - (3, 0.15), (4, 0.10), (5, 0.10), ]) diff --git a/assets/world/manifests/site_structures/haniwa/bonsai.ron b/assets/world/manifests/site_structures/haniwa/bonsai.ron new file mode 100644 index 0000000000..18ce4d43e3 --- /dev/null +++ b/assets/world/manifests/site_structures/haniwa/bonsai.ron @@ -0,0 +1,8 @@ +#![enable(unwrap_newtypes)] + +[ + ( + specifier: "world.structure.natural.bonsai", + center: (28, 22, 1) + ), +] diff --git a/assets/world/structure/natural/bonsai.vox b/assets/world/structure/natural/bonsai.vox new file mode 100644 index 0000000000..08c298509e --- /dev/null +++ b/assets/world/structure/natural/bonsai.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:27389bac41142c22f6b6513d65d64857eb424b49ea45c0a751e4c0058e063ac1 +size 50024 diff --git a/common/net/src/msg/world_msg.rs b/common/net/src/msg/world_msg.rs index 9e958ce47f..ed1ad32933 100644 --- a/common/net/src/msg/world_msg.rs +++ b/common/net/src/msg/world_msg.rs @@ -151,6 +151,7 @@ pub enum SiteKind { ChapelSite, Bridge, Adlet, + Haniwa, DwarvenMine, } diff --git a/common/src/comp/ability.rs b/common/src/comp/ability.rs index 20560ef8de..b24a251d4b 100644 --- a/common/src/comp/ability.rs +++ b/common/src/comp/ability.rs @@ -788,6 +788,7 @@ pub enum CharacterAbility { ComboMelee2 { strikes: Vec>, energy_cost_per_strike: f32, + specifier: Option, #[serde(default)] auto_progress: bool, #[serde(default)] @@ -1324,6 +1325,7 @@ impl CharacterAbility { ComboMelee2 { ref mut strikes, ref mut energy_cost_per_strike, + specifier: _, auto_progress: _, meta: _, } => { @@ -2419,12 +2421,14 @@ impl From<(&CharacterAbility, AbilityInfo, &JoinData<'_>)> for CharacterState { CharacterAbility::ComboMelee2 { strikes, energy_cost_per_strike, + specifier, auto_progress, meta: _, } => CharacterState::ComboMelee2(combo_melee2::Data { static_data: combo_melee2::StaticData { strikes: strikes.iter().map(|s| s.to_duration()).collect(), energy_cost_per_strike: *energy_cost_per_strike, + specifier: *specifier, auto_progress: *auto_progress, ability_info, }, diff --git a/common/src/comp/agent.rs b/common/src/comp/agent.rs index 0e5c5e3621..04f23f7fd1 100644 --- a/common/src/comp/agent.rs +++ b/common/src/comp/agent.rs @@ -310,6 +310,7 @@ impl<'a> From<&'a Body> for Psyche { quadruped_medium::Species::Bonerattler => 0.0, quadruped_medium::Species::Tiger => 0.1, quadruped_medium::Species::Roshwalr => 0.0, + quadruped_medium::Species::ClaySteed => 0.0, _ => 0.3, }, Body::QuadrupedLow(quadruped_low) => match quadruped_low.species { @@ -466,6 +467,7 @@ pub enum SoundKind { Explosion, Beam, Shockwave, + Trap, } #[derive(Clone, Copy, Debug)] diff --git a/common/src/comp/beam.rs b/common/src/comp/beam.rs index 6ed495d81d..7b0358b3cd 100644 --- a/common/src/comp/beam.rs +++ b/common/src/comp/beam.rs @@ -36,7 +36,7 @@ pub enum FrontendSpecifier { Flamethrower, LifestealBeam, Cultist, - ClayGolem, + Gravewarden, Bubbles, Steam, Frost, diff --git a/common/src/comp/body.rs b/common/src/comp/body.rs index 8011fdb1b1..61bbb137a0 100644 --- a/common/src/comp/body.rs +++ b/common/src/comp/body.rs @@ -344,6 +344,7 @@ impl Body { biped_large::Species::Swamptroll => 600.0, biped_large::Species::Gigasfrost => 400.0, biped_large::Species::AdletElder => 350.0, + biped_large::Species::HaniwaGeneral => 360.0, _ => 400.0, }, Body::BipedSmall(body) => match body.species { @@ -507,6 +508,7 @@ impl Body { biped_large::Species::Gigasfrost => Vec3::new(6.0, 3.0, 8.0), 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), _ => Vec3::new(4.6, 3.0, 6.0), }, Body::BipedSmall(body) => match body.species { @@ -538,6 +540,8 @@ impl Body { Body::FishSmall(_) => Vec3::new(0.3, 1.2, 0.6), Body::Golem(body) => match body.species { 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), _ => Vec3::new(5.0, 4.5, 7.5), }, Body::Humanoid(humanoid) => { @@ -568,6 +572,7 @@ impl Body { quadruped_medium::Species::Mammoth => Vec3::new(7.5, 11.5, 8.0), quadruped_medium::Species::Ngoubou => Vec3::new(2.0, 3.2, 2.4), quadruped_medium::Species::Llama => Vec3::new(2.0, 2.5, 2.6), + quadruped_medium::Species::ClaySteed => Vec3::new(2.2, 4.8, 4.0), quadruped_medium::Species::Alpaca => Vec3::new(2.0, 2.0, 2.0), quadruped_medium::Species::Camel => Vec3::new(2.0, 4.0, 3.5), quadruped_medium::Species::Wolf => Vec3::new(1.25, 3.0, 1.8), @@ -844,6 +849,7 @@ impl Body { quadruped_medium::Species::Dreadhorn => 370, quadruped_medium::Species::Mammoth => 250, quadruped_medium::Species::Ngoubou => 290, + quadruped_medium::Species::ClaySteed => 400, _ => 70, }, Body::FishMedium(_) => 15, @@ -899,6 +905,7 @@ impl Body { biped_large::Species::AdletElder => 1500, biped_large::Species::Tursus => 300, biped_large::Species::SeaBishop => 550, + biped_large::Species::HaniwaGeneral => 600, _ => 120, }, Body::BipedSmall(biped_small) => match biped_small.species { @@ -927,8 +934,10 @@ impl Body { Body::ItemDrop(_) => 1000, Body::Golem(golem) => match golem.species { golem::Species::WoodGolem => 200, - golem::Species::ClayGolem => 450, + golem::Species::ClayGolem => 350, + golem::Species::Gravewarden => 1000, golem::Species::CoralGolem => 550, + golem::Species::AncientEffigy => 250, _ => 1000, }, Body::Theropod(theropod) => match theropod.species { @@ -1001,22 +1010,37 @@ impl Body { biped_small::Species::Husk | biped_small::Species::Boreal | biped_small::Species::Clockwork + | biped_small::Species::Haniwa ), Body::BipedLarge(b) => matches!( b.species, biped_large::Species::Huskbrute | biped_large::Species::Gigasfrost | biped_large::Species::Dullahan + | biped_large::Species::HaniwaGeneral ), + Body::QuadrupedMedium(b) => { + matches!(b.species, quadruped_medium::Species::ClaySteed) + }, _ => false, }, BuffKind::Crippled => match self { Body::Object(_) | Body::Golem(_) | Body::Ship(_) => true, - Body::BipedLarge(b) => matches!(b.species, biped_large::Species::Dullahan), + Body::BipedLarge(b) => matches!( + b.species, + biped_large::Species::Dullahan | biped_large::Species::HaniwaGeneral {} + ), + Body::BipedSmall(b) => matches!(b.species, biped_small::Species::Haniwa), + Body::QuadrupedMedium(b) => { + matches!(b.species, quadruped_medium::Species::ClaySteed) + }, _ => false, }, BuffKind::Burning => match self { - Body::Golem(g) => matches!(g.species, golem::Species::ClayGolem), + Body::Golem(g) => matches!( + g.species, + golem::Species::Gravewarden | golem::Species::AncientEffigy + ), Body::BipedSmall(b) => matches!( b.species, biped_small::Species::Haniwa @@ -1105,7 +1129,7 @@ impl Body { _ => 1.0, }, Body::Golem(g) => match g.species { - golem::Species::ClayGolem => 2.45, + golem::Species::Gravewarden => 2.45, _ => 1.0, }, Body::QuadrupedLow(b) => match b.species { @@ -1145,6 +1169,7 @@ impl Body { | quadruped_medium::Species::Llama | quadruped_medium::Species::Alpaca | quadruped_medium::Species::Camel + | quadruped_medium::Species::ClaySteed | quadruped_medium::Species::Zebra | quadruped_medium::Species::Donkey | quadruped_medium::Species::Highland @@ -1285,6 +1310,7 @@ impl Body { (quadruped_medium::Species::Llama, _) => [0.0, 0.1, 1.5], (quadruped_medium::Species::Alpaca, _) => [0.0, -0.1, 1.0], (quadruped_medium::Species::Akhlut, _) => [0.6, 0.6, 2.0], + (quadruped_medium::Species::ClaySteed, _) => [0.0, 0.1, 1.5], } }, Body::Ship(ship) => match ship { diff --git a/common/src/comp/body/biped_large.rs b/common/src/comp/body/biped_large.rs index 85228afbb7..4c48b193d6 100644 --- a/common/src/comp/body/biped_large.rs +++ b/common/src/comp/body/biped_large.rs @@ -76,6 +76,7 @@ make_case_elim!( Gigasfrost = 22, AdletElder = 23, SeaBishop = 24, + HaniwaGeneral = 25, } ); @@ -109,6 +110,7 @@ pub struct AllSpecies { pub gigas_frost: SpeciesMeta, pub adlet_elder: SpeciesMeta, pub sea_bishop: SpeciesMeta, + pub haniwa_general: SpeciesMeta, } impl<'a, SpeciesMeta> core::ops::Index<&'a Species> for AllSpecies { @@ -142,11 +144,12 @@ impl<'a, SpeciesMeta> core::ops::Index<&'a Species> for AllSpecies Species::Gigasfrost => &self.gigas_frost, Species::AdletElder => &self.adlet_elder, Species::SeaBishop => &self.sea_bishop, + Species::HaniwaGeneral => &self.haniwa_general, } } } -pub const ALL_SPECIES: [Species; 25] = [ +pub const ALL_SPECIES: [Species; 26] = [ Species::Ogre, Species::Cyclops, Species::Wendigo, @@ -172,6 +175,7 @@ pub const ALL_SPECIES: [Species; 25] = [ Species::Gigasfrost, Species::AdletElder, Species::SeaBishop, + Species::HaniwaGeneral, ]; 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 2ea8a66808..c3017af472 100644 --- a/common/src/comp/body/golem.rs +++ b/common/src/comp/body/golem.rs @@ -39,6 +39,8 @@ make_case_elim!( ClayGolem = 2, WoodGolem = 3, CoralGolem = 4, + Gravewarden = 5, + AncientEffigy = 6, } ); @@ -52,6 +54,8 @@ pub struct AllSpecies { pub claygolem: SpeciesMeta, pub woodgolem: SpeciesMeta, pub coralgolem: SpeciesMeta, + pub gravewarden: SpeciesMeta, + pub ancienteffigy: SpeciesMeta, } impl<'a, SpeciesMeta> core::ops::Index<&'a Species> for AllSpecies { @@ -65,16 +69,20 @@ impl<'a, SpeciesMeta> core::ops::Index<&'a Species> for AllSpecies Species::ClayGolem => &self.claygolem, Species::WoodGolem => &self.woodgolem, Species::CoralGolem => &self.coralgolem, + Species::Gravewarden => &self.gravewarden, + Species::AncientEffigy => &self.ancienteffigy, } } } -pub const ALL_SPECIES: [Species; 5] = [ +pub const ALL_SPECIES: [Species; 7] = [ Species::StoneGolem, Species::Treant, Species::ClayGolem, Species::WoodGolem, Species::CoralGolem, + Species::Gravewarden, + Species::AncientEffigy, ]; 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 2c6dbbdaa3..02918fc64a 100644 --- a/common/src/comp/body/object.rs +++ b/common/src/comp/body/object.rs @@ -114,6 +114,8 @@ make_case_elim!( PortalActive = 99, FieryTornado = 100, FireRainDrop = 101, + ArrowClay = 102, + GrenadeClay = 103, } ); @@ -124,7 +126,7 @@ impl Body { } } -pub const ALL_OBJECTS: [Body; 102] = [ +pub const ALL_OBJECTS: [Body; 104] = [ Body::Arrow, Body::Bomb, Body::Scarecrow, @@ -227,6 +229,8 @@ pub const ALL_OBJECTS: [Body; 102] = [ Body::PortalActive, Body::FieryTornado, Body::FireRainDrop, + Body::ArrowClay, + Body::GrenadeClay, ]; impl From for super::Body { @@ -338,6 +342,8 @@ impl Body { Body::PortalActive => "portal_active", Body::FieryTornado => "fiery_tornado", Body::FireRainDrop => "fire_rain_drop", + Body::ArrowClay => "arrow_clay", + Body::GrenadeClay => "grenade_clay", } } @@ -360,6 +366,7 @@ impl Body { | Body::ArrowSnake | Body::ArrowTurret | Body::MultiArrow + | Body::ArrowClay | Body::Dart | Body::DagonBomb | Body::SpectralSwordSmall @@ -386,6 +393,7 @@ impl Body { Body::Arrow | Body::ArrowSnake | Body::ArrowTurret | Body::MultiArrow | Body::Dart => { 0.003 }, + Body::ArrowClay => 1.0, Body::SpectralSwordSmall => 0.5, Body::SpectralSwordLarge => 50.0, Body::BedBlue => 50.0, @@ -449,7 +457,7 @@ impl Body { Body::WindowSpooky => 10.0, Body::SilverOre => 1000.0, Body::GoldOre => 1000.0, - Body::ClayRocket => 50.0, + Body::ClayRocket | Body::GrenadeClay => 50.0, Body::HaniwaSentry => 300.0, Body::SeaLantern => 1000.0, Body::Snowball => 7360.0, // 2.5 m diamter @@ -479,6 +487,7 @@ impl Body { | Body::ArrowSnake | Body::MultiArrow | Body::ArrowTurret + | Body::ArrowClay | Body::Dart | Body::AdletSpear => Vec3::new(0.01, 0.8, 0.01), Body::AdletTrap => Vec3::new(1.0, 0.6, 0.3), diff --git a/common/src/comp/body/quadruped_medium.rs b/common/src/comp/body/quadruped_medium.rs index 0d6ac2a073..fa64bd45f0 100644 --- a/common/src/comp/body/quadruped_medium.rs +++ b/common/src/comp/body/quadruped_medium.rs @@ -84,6 +84,7 @@ pub enum Species { Alpaca = 35, Akhlut = 36, Bristleback = 37, + ClaySteed = 38, } /// Data representing per-species generic data. @@ -127,6 +128,7 @@ pub struct AllSpecies { pub alpaca: SpeciesMeta, pub akhlut: SpeciesMeta, pub bristleback: SpeciesMeta, + pub claysteed: SpeciesMeta, } impl<'a, SpeciesMeta> core::ops::Index<&'a Species> for AllSpecies { @@ -171,11 +173,12 @@ impl<'a, SpeciesMeta> core::ops::Index<&'a Species> for AllSpecies Species::Alpaca => &self.alpaca, Species::Akhlut => &self.akhlut, Species::Bristleback => &self.bristleback, + Species::ClaySteed => &self.claysteed, } } } -pub const ALL_SPECIES: [Species; 36] = [ +pub const ALL_SPECIES: [Species; 37] = [ Species::Grolgar, Species::Saber, Species::Tiger, @@ -212,6 +215,7 @@ pub const ALL_SPECIES: [Species; 36] = [ Species::Alpaca, Species::Akhlut, Species::Bristleback, + Species::ClaySteed, ]; impl<'a, SpeciesMeta: 'a> IntoIterator for &'a AllSpecies { diff --git a/common/src/comp/fluid_dynamics.rs b/common/src/comp/fluid_dynamics.rs index 97968be1b6..1490bdf9cb 100644 --- a/common/src/comp/fluid_dynamics.rs +++ b/common/src/comp/fluid_dynamics.rs @@ -276,6 +276,7 @@ impl Body { object::Body::Arrow | object::Body::ArrowSnake | object::Body::ArrowTurret + | object::Body::ArrowClay | object::Body::FireworkBlue | object::Body::FireworkGreen | object::Body::FireworkPurple diff --git a/common/src/comp/inventory/loadout_builder.rs b/common/src/comp/inventory/loadout_builder.rs index cea9ca227a..d28025276e 100644 --- a/common/src/comp/inventory/loadout_builder.rs +++ b/common/src/comp/inventory/loadout_builder.rs @@ -548,12 +548,18 @@ fn default_main_tool(body: &Body) -> Item { golem::Species::ClayGolem => Some(Item::new_from_asset_expect( "common.items.npc_weapons.unique.clay_golem_fist", )), + golem::Species::Gravewarden => Some(Item::new_from_asset_expect( + "common.items.npc_weapons.unique.gravewarden_fist", + )), golem::Species::WoodGolem => Some(Item::new_from_asset_expect( "common.items.npc_weapons.unique.wood_golem_fist", )), golem::Species::CoralGolem => Some(Item::new_from_asset_expect( "common.items.npc_weapons.unique.coral_golem_fist", )), + golem::Species::AncientEffigy => Some(Item::new_from_asset_expect( + "common.items.npc_weapons.unique.ancient_effigy_eyes", + )), _ => None, }, Body::QuadrupedMedium(quadruped_medium) => match quadruped_medium.species { @@ -571,6 +577,9 @@ fn default_main_tool(body: &Body) -> Item { | quadruped_medium::Species::Alpaca => Some(Item::new_from_asset_expect( "common.items.npc_weapons.unique.quadmedhoof", )), + quadruped_medium::Species::ClaySteed => Some(Item::new_from_asset_expect( + "common.items.npc_weapons.unique.claysteed", + )), quadruped_medium::Species::Saber | quadruped_medium::Species::Bonerattler | quadruped_medium::Species::Darkhound @@ -787,6 +796,9 @@ fn default_main_tool(body: &Body) -> Item { (biped_large::Species::SeaBishop, _) => Some(Item::new_from_asset_expect( "common.items.npc_weapons.unique.sea_bishop_sceptre", )), + (biped_large::Species::HaniwaGeneral, _) => Some(Item::new_from_asset_expect( + "common.items.npc_weapons.sword.haniwa_general_sword", + )), }, Body::Object(body) => match body { object::Body::Crossbow => Some(Item::new_from_asset_expect( @@ -1021,6 +1033,9 @@ impl LoadoutBuilder { biped_large::Species::Gigasfrost => { Some("common.items.npc_armor.biped_large.gigas_frost") }, + biped_large::Species::HaniwaGeneral => { + Some("common.items.npc_armor.biped_large.haniwageneral") + }, _ => None, }, Body::BirdLarge(body) => match body.species { @@ -1036,7 +1051,9 @@ impl LoadoutBuilder { }, Body::Golem(body) => match body.species { golem::Species::ClayGolem => Some("common.items.npc_armor.golem.claygolem"), + 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"), _ => None, }, Body::QuadrupedLow(body) => match body.species { @@ -1064,6 +1081,9 @@ impl LoadoutBuilder { quadruped_medium::Species::Roshwalr => { Some("common.items.npc_armor.quadruped_medium.roshwalr") }, + quadruped_medium::Species::ClaySteed => { + Some("common.items.npc_armor.quadruped_medium.claysteed") + }, _ => None, }, Body::Theropod(body) => match body.species { diff --git a/common/src/outcome.rs b/common/src/outcome.rs index b20d587258..42cd251f10 100644 --- a/common/src/outcome.rs +++ b/common/src/outcome.rs @@ -109,6 +109,9 @@ pub enum Outcome { FlamethrowerCharge { pos: Vec3, }, + FuseCharge { + pos: Vec3, + }, Utterance { pos: Vec3, body: comp::Body, @@ -134,6 +137,9 @@ pub enum Outcome { Swoosh { pos: Vec3, }, + Slash { + pos: Vec3, + }, FireShockwave { pos: Vec3, }, @@ -149,6 +155,9 @@ pub enum Outcome { FromTheAshes { pos: Vec3, }, + ClayGolemDash { + pos: Vec3, + }, } impl Outcome { @@ -169,6 +178,7 @@ impl Outcome { | Outcome::FlashFreeze { pos } | Outcome::Whoosh { pos } | Outcome::Swoosh { pos } + | Outcome::Slash { pos } | Outcome::IceSpikes { pos } | Outcome::Steam { pos } | Outcome::FireShockwave { pos } @@ -176,11 +186,13 @@ impl Outcome { | Outcome::Utterance { pos, .. } | Outcome::CyclopsCharge { pos } | Outcome::FlamethrowerCharge { pos } + | Outcome::FuseCharge { pos } | Outcome::LaserBeam { pos } | Outcome::GroundDig { pos } | Outcome::PortalActivated { pos } | Outcome::TeleportedByPortal { pos} | Outcome::FromTheAshes { pos } + | Outcome::ClayGolemDash { pos } | Outcome::Glider { pos, .. } => Some(*pos), Outcome::BreakBlock { pos, .. } | Outcome::SpriteUnlocked { pos } diff --git a/common/src/states/basic_ranged.rs b/common/src/states/basic_ranged.rs index 3868368155..a03549285a 100644 --- a/common/src/states/basic_ranged.rs +++ b/common/src/states/basic_ranged.rs @@ -1,8 +1,9 @@ use crate::{ combat::{self, CombatEffect}, comp::{ - character_state::OutputEvents, object::Body::LaserBeam, Body, CharacterState, LightEmitter, - Pos, ProjectileConstructor, StateUpdate, + character_state::OutputEvents, + object::Body::{GrenadeClay, LaserBeam}, + Body, CharacterState, LightEmitter, Pos, ProjectileConstructor, StateUpdate, }, event::{LocalEvent, ServerEvent}, outcome::Outcome, @@ -67,13 +68,26 @@ impl CharacterBehavior for Data { timer: tick_attack_or_default(data, self.timer, None), ..*self }); - if self.static_data.projectile_body == Body::Object(LaserBeam) { - // Send local event used for frontend shenanigans - output_events.emit_local(LocalEvent::CreateOutcome( - Outcome::CyclopsCharge { - pos: data.pos.0 + *data.ori.look_dir() * (data.body.max_radius()), - }, - )); + match self.static_data.projectile_body { + Body::Object(LaserBeam) => { + // Send local event used for frontend shenanigans + output_events.emit_local(LocalEvent::CreateOutcome( + Outcome::CyclopsCharge { + pos: data.pos.0 + + *data.ori.look_dir() * (data.body.max_radius()), + }, + )); + }, + Body::Object(GrenadeClay) => { + // Send local event used for frontend shenanigans + output_events.emit_local(LocalEvent::CreateOutcome( + Outcome::FuseCharge { + pos: data.pos.0 + + *data.ori.look_dir() * (2.5 * data.body.max_radius()), + }, + )); + }, + _ => {}, } } else { // Transitions to recover section of stage diff --git a/common/src/states/combo_melee2.rs b/common/src/states/combo_melee2.rs index 858f5a7119..5f8c5fdb23 100644 --- a/common/src/states/combo_melee2.rs +++ b/common/src/states/combo_melee2.rs @@ -3,8 +3,11 @@ use crate::{ comp::{ character_state::OutputEvents, tool::Stats, CharacterState, MeleeConstructor, StateUpdate, }, + event::LocalEvent, + outcome::Outcome, states::{ behavior::{CharacterBehavior, JoinData}, + combo_melee2, utils::*, }, }; @@ -81,6 +84,8 @@ pub struct StaticData { pub strikes: Vec>, /// The amount of energy consumed with each swing pub energy_cost_per_strike: f32, + /// Used to specify the attack to the frontend + pub specifier: Option, /// Whether or not the state should progress through all strikes /// automatically once the state is entered pub auto_progress: bool, @@ -134,6 +139,12 @@ impl CharacterBehavior for Data { c.stage_section = StageSection::Action; } } + if let Some(FrontendSpecifier::ClayGolemDash) = self.static_data.specifier { + // Send local event used for frontend shenanigans + output_events.emit_local(LocalEvent::CreateOutcome(Outcome::ClayGolemDash { + pos: data.pos.0, + })); + } }, StageSection::Action => { if let Some(movement) = strike_data.movement.swing { @@ -238,3 +249,8 @@ fn next_strike(data: &JoinData, update: &mut StateUpdate) { end_melee_ability(data, update) } } + +#[derive(Copy, Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] +pub enum FrontendSpecifier { + ClayGolemDash, +} diff --git a/common/src/states/sprite_interact.rs b/common/src/states/sprite_interact.rs index c90bac03e3..dd6af8388f 100644 --- a/common/src/states/sprite_interact.rs +++ b/common/src/states/sprite_interact.rs @@ -190,6 +190,7 @@ impl From for Option { | SpriteKind::Bomb => Some(SpriteInteractKind::Collectible), SpriteKind::Keyhole | SpriteKind::BoneKeyhole + | SpriteKind::HaniwaKeyhole | SpriteKind::GlassKeyhole | SpriteKind::KeyholeBars => Some(SpriteInteractKind::Unlock), // Collectible checked in addition to container for case that sprite requires a tool to diff --git a/common/src/states/utils.rs b/common/src/states/utils.rs index 9140a33cf9..90b8b410e0 100644 --- a/common/src/states/utils.rs +++ b/common/src/states/utils.rs @@ -6,6 +6,7 @@ use crate::{ buff::{BuffCategory, BuffChange}, character_state::OutputEvents, controller::InventoryManip, + golem, inventory::slot::{ArmorSlot, EquipSlot, Slot}, item::{ armor::Friction, @@ -97,6 +98,7 @@ impl Body { quadruped_medium::Species::Alpaca => 110.0, quadruped_medium::Species::Akhlut => 90.0, quadruped_medium::Species::Bristleback => 135.0, + quadruped_medium::Species::ClaySteed => 120.0, }, Body::BipedLarge(body) => match body.species { biped_large::Species::Slysaurok => 100.0, @@ -122,7 +124,10 @@ impl Body { }, Body::Object(_) => 0.0, Body::ItemDrop(_) => 0.0, - Body::Golem(_) => 60.0, + Body::Golem(body) => match body.species { + golem::Species::ClayGolem => 120.0, + _ => 60.0, + }, Body::Theropod(_) => 135.0, Body::QuadrupedLow(quadruped_low) => match quadruped_low.species { quadruped_low::Species::Crocodile => 130.0, diff --git a/common/src/terrain/block.rs b/common/src/terrain/block.rs index 803c60ea71..154510a4bb 100644 --- a/common/src/terrain/block.rs +++ b/common/src/terrain/block.rs @@ -369,6 +369,7 @@ impl Block { | SpriteKind::DungeonChest4 | SpriteKind::DungeonChest5 | SpriteKind::CoralChest + | SpriteKind::HaniwaUrn | SpriteKind::Crate => Some(rtsim::ChunkResource::Loot), _ => None, } @@ -420,7 +421,7 @@ impl Block { SpriteKind::Lantern => Some(24), SpriteKind::SeashellLantern | SpriteKind::GlowIceCrystal => Some(16), SpriteKind::SeaDecorEmblem => Some(12), - SpriteKind::SeaDecorBlock => Some(10), + SpriteKind::SeaDecorBlock | SpriteKind::HaniwaKeyDoor => Some(10), SpriteKind::Mine => Some(2), _ => None, }, @@ -502,6 +503,12 @@ impl Block { | SpriteKind::DungeonChest3 | SpriteKind::DungeonChest4 | SpriteKind::DungeonChest5 + | SpriteKind::CoralChest + | SpriteKind::HaniwaUrn + | SpriteKind::HaniwaKeyDoor + | SpriteKind::HaniwaKeyhole + | SpriteKind::HaniwaTrap + | SpriteKind::HaniwaTrapTriggered | SpriteKind::ChestBuried | SpriteKind::SeaDecorBlock | SpriteKind::SeaDecorChain @@ -510,8 +517,9 @@ impl Block { | SpriteKind::Rope | SpriteKind::IronSpike | SpriteKind::HotSurface - | SpriteKind::FireBlock => None, - SpriteKind::GlassBarrier | SpriteKind::GlassKeyhole => None, + | SpriteKind::FireBlock + | SpriteKind::GlassBarrier + | SpriteKind::GlassKeyhole => None, SpriteKind::EnsnaringVines | SpriteKind::EnsnaringWeb | SpriteKind::SeaUrchin diff --git a/common/src/terrain/sprite.rs b/common/src/terrain/sprite.rs index d6b828e311..337f82ea97 100644 --- a/common/src/terrain/sprite.rs +++ b/common/src/terrain/sprite.rs @@ -120,11 +120,12 @@ sprites! { DungeonChest4 = 0x35, DungeonChest5 = 0x36, CoralChest = 0x37, - CommonLockedChest = 0x38, - ChestBuried = 0x39, - Crate = 0x3A, - Barrel = 0x3B, - CrateBlock = 0x3C, + HaniwaUrn = 0x38, + CommonLockedChest = 0x39, + ChestBuried = 0x3A, + Crate = 0x3B, + Barrel = 0x3C, + CrateBlock = 0x3D, // Standalone lights Lantern = 0x40, StreetLamp = 0x41, @@ -292,6 +293,8 @@ sprites! { KeyDoor = 0x06, GlassKeyhole = 0x07, KeyholeBars = 0x08, + HaniwaKeyDoor = 0x09, + HaniwaKeyhole = 0x0A, // Windows Window1 = 0x10, Window2 = 0x11, @@ -316,6 +319,8 @@ sprites! { SeaDecorChain = 0x41, IronSpike = 0x42, DoorBars = 0x43, + HaniwaTrap = 0x44, + HaniwaTrapTriggered = 0x45, }, // Decorative items, both natural and artificial Decor = 6 has Ori { @@ -391,6 +396,7 @@ impl SpriteKind { SpriteKind::DungeonChest4 => 1.09, SpriteKind::DungeonChest5 => 1.09, SpriteKind::CoralChest => 1.09, + SpriteKind::HaniwaUrn => 1.09, SpriteKind::SeaDecorChain => 1.09, SpriteKind::SeaDecorBlock => 1.00, SpriteKind::SeaDecorWindowHor => 0.55, @@ -458,6 +464,10 @@ impl SpriteKind { | SpriteKind::KeyDoor | SpriteKind::BoneKeyhole | SpriteKind::BoneKeyDoor + | SpriteKind::HaniwaKeyhole + | SpriteKind::HaniwaKeyDoor + | SpriteKind::HaniwaTrap + | SpriteKind::HaniwaTrapTriggered | SpriteKind::Bomb | SpriteKind::OneWayWall | SpriteKind::DoorBars @@ -626,6 +636,7 @@ impl SpriteKind { SpriteKind::CommonLockedChest => table("common.loot_tables.dungeon.sahagin.chest"), 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::Mud => table("common.loot_tables.sprite.mud"), SpriteKind::Grave => table("common.loot_tables.sprite.mud"), SpriteKind::Crate => table("common.loot_tables.sprite.crate"), @@ -638,6 +649,7 @@ impl SpriteKind { SpriteKind::MagicalBarrier => table("common.loot_tables.sprite.chest"), SpriteKind::Keyhole | SpriteKind::BoneKeyhole + | SpriteKind::HaniwaKeyhole | SpriteKind::GlassKeyhole | SpriteKind::KeyholeBars => { return Some(None); @@ -736,6 +748,9 @@ impl SpriteKind { SpriteKind::BoneKeyhole => UnlockKind::Consumes( ItemDefinitionId::Simple("common.items.keys.bone_key").to_owned(), ), + SpriteKind::HaniwaKeyhole => UnlockKind::Consumes( + ItemDefinitionId::Simple("common.items.keys.haniwa_key").to_owned(), + ), SpriteKind::GlassKeyhole => UnlockKind::Consumes( ItemDefinitionId::Simple("common.items.keys.glass_key").to_owned(), ), diff --git a/common/src/terrain/structure.rs b/common/src/terrain/structure.rs index 7b2a003e01..e7486a93f9 100644 --- a/common/src/terrain/structure.rs +++ b/common/src/terrain/structure.rs @@ -47,6 +47,7 @@ make_case_elim!( GlassKeyhole(consumes: String) = 27, Sign(content: Content, ori: u8) = 28, KeyholeBars(consumes: String) = 29, + HaniwaKeyhole(consumes: String) = 30, } ); diff --git a/common/systems/src/buff.rs b/common/systems/src/buff.rs index c4f9ea769a..7840a1a667 100644 --- a/common/systems/src/buff.rs +++ b/common/systems/src/buff.rs @@ -1,6 +1,7 @@ use common::{ combat::DamageContributor, comp::{ + agent::{Sound, SoundKind}, aura::Auras, body::{object, Body}, buff::{ @@ -13,6 +14,7 @@ use common::{ Pos, Stats, }, event::{Emitter, EventBus, ServerEvent}, + outcome::Outcome, resources::{DeltaTime, Secs, Time}, terrain::SpriteKind, uid::{IdMaps, Uid}, @@ -25,12 +27,14 @@ use specs::{ shred, Entities, Entity, LendJoin, ParJoin, Read, ReadExpect, ReadStorage, SystemData, WriteStorage, }; +use vek::Vec3; #[derive(SystemData)] pub struct ReadData<'a> { entities: Entities<'a>, dt: Read<'a, DeltaTime>, server_bus: Read<'a, EventBus>, + outcome_bus: Read<'a, EventBus>, inventories: ReadStorage<'a, Inventory>, healths: ReadStorage<'a, Health>, energies: ReadStorage<'a, Energy>, @@ -57,6 +61,7 @@ impl<'a> System<'a> for Sys { fn run(job: &mut Job, (read_data, mut stats): Self::SystemData) { let mut server_emitter = read_data.server_bus.emitter(); + let mut outcome = read_data.outcome_bus.emitter(); let dt = read_data.dt.0; // Set to false to avoid spamming server stats.set_event_emission(false); @@ -172,7 +177,39 @@ impl<'a> System<'a> for Sys { } if matches!( physics_state.on_ground.and_then(|b| b.get_sprite()), - Some(SpriteKind::IronSpike) + Some(SpriteKind::HaniwaTrap) + ) && !body.immune_to(BuffKind::Bleeding) + { + // TODO: Determine a better place to emit sprite change events + if let Some(pos) = read_data.positions.get(entity) { + // If touching Trap - change sprite and apply Bleeding buff + server_emitter.emit(ServerEvent::CreateSprite { + pos: Vec3::new(pos.0.x as i32, pos.0.y as i32, pos.0.z as i32 - 1), + sprite: SpriteKind::HaniwaTrapTriggered, + del_timeout: Some((4.0, 1.0)), + }); + server_emitter.emit(ServerEvent::Sound { + sound: Sound::new(SoundKind::Trap, pos.0, 12.0, read_data.time.0), + }); + outcome.emit(Outcome::Slash { pos: pos.0 }); + + server_emitter.emit(ServerEvent::Buff { + entity, + buff_change: BuffChange::Add(Buff::new( + BuffKind::Bleeding, + BuffData::new(5.0, Some(Secs(3.0))), + Vec::new(), + BuffSource::World, + *read_data.time, + Some(&stat), + Some(health), + )), + }); + } + } + if matches!( + physics_state.on_ground.and_then(|b| b.get_sprite()), + Some(SpriteKind::IronSpike | SpriteKind::HaniwaTrapTriggered) ) { // If touching Iron Spike apply Bleeding buff server_emitter.emit(ServerEvent::Buff { @@ -255,6 +292,7 @@ impl<'a> System<'a> for Sys { )), }); } + // If on FireBlock vines, apply burning buff if matches!( physics_state.in_fluid, Some(Fluid::Liquid { diff --git a/rtsim/src/gen/site.rs b/rtsim/src/gen/site.rs index 4eb43e0363..d53e82ddf8 100644 --- a/rtsim/src/gen/site.rs +++ b/rtsim/src/gen/site.rs @@ -36,6 +36,7 @@ impl Site { | SiteKind::RockCircle(_) | SiteKind::TrollCave(_) | SiteKind::Camp(_) + | SiteKind::Haniwa(_) | SiteKind::Adlet(_) => Some(false), SiteKind::DwarvenMine(_) => Some(false), // Neutral diff --git a/server/agent/src/action_nodes.rs b/server/agent/src/action_nodes.rs index 8e8f8017a0..8100c20a3e 100644 --- a/server/agent/src/action_nodes.rs +++ b/server/agent/src/action_nodes.rs @@ -1051,6 +1051,7 @@ impl<'a> AgentData<'a> { }, "Quad Med Basic" => Tactic::QuadMedBasic, "Quad Med Hoof" => Tactic::QuadMedHoof, + "ClaySteed" => Tactic::ClaySteed, "Roshwalr" => Tactic::Roshwalr, "Asp" | "Maneater" => Tactic::QuadLowRanged, "Quad Low Breathe" | "Quad Low Beam" | "Basilisk" => { @@ -1083,12 +1084,14 @@ impl<'a> AgentData<'a> { "Bushly" | "Irrwurz" | "Driggle" | "Mossy Snail" => { Tactic::SimpleDouble }, + "Clay Golem" => Tactic::ClayGolem, + "Ancient Effigy" => Tactic::AncientEffigy, "Mindflayer" => Tactic::Mindflayer, "Flamekeeper" => Tactic::Flamekeeper, "Minotaur" => Tactic::Minotaur, "Cyclops" => Tactic::Cyclops, "Dullahan" => Tactic::Dullahan, - "Clay Golem" => Tactic::ClayGolem, + "Grave Warden" => Tactic::GraveWarden, "Tidal Warrior" => Tactic::TidalWarrior, "Tidal Totem" | "Tornado" @@ -1126,6 +1129,9 @@ impl<'a> AgentData<'a> { abilities: [4, 0, 0, 0, 0], }, "Adlet Elder" => Tactic::AdletElder, + "Haniwa Soldier" => Tactic::HaniwaSoldier, + "Haniwa Guard" => Tactic::HaniwaGuard, + "Haniwa Archer" => Tactic::HaniwaArcher, _ => Tactic::SimpleMelee, }, AbilitySpec::Tool(tool_kind) => tool_tactic(*tool_kind), @@ -1501,6 +1507,19 @@ impl<'a> AgentData<'a> { tgt_data, read_data, ), + Tactic::ClayGolem => { + self.handle_clay_golem_attack(agent, controller, &attack_data, tgt_data, read_data) + }, + Tactic::ClaySteed => { + self.handle_clay_steed_attack(agent, controller, &attack_data, tgt_data, read_data) + }, + Tactic::AncientEffigy => self.handle_ancient_effigy_attack( + agent, + controller, + &attack_data, + tgt_data, + read_data, + ), Tactic::Minotaur => { self.handle_minotaur_attack(agent, controller, &attack_data, tgt_data, read_data) }, @@ -1510,9 +1529,13 @@ impl<'a> AgentData<'a> { Tactic::Dullahan => { self.handle_dullahan_attack(agent, controller, &attack_data, tgt_data, read_data) }, - Tactic::ClayGolem => { - self.handle_clay_golem_attack(agent, controller, &attack_data, tgt_data, read_data) - }, + Tactic::GraveWarden => self.handle_grave_warden_attack( + agent, + controller, + &attack_data, + tgt_data, + read_data, + ), Tactic::TidalWarrior => self.handle_tidal_warrior_attack( agent, controller, @@ -1626,6 +1649,15 @@ impl<'a> AgentData<'a> { Tactic::AdletElder => { self.handle_adlet_elder(agent, controller, &attack_data, tgt_data, read_data, rng) }, + Tactic::HaniwaSoldier => { + self.handle_haniwa_soldier(agent, controller, &attack_data, tgt_data, read_data) + }, + Tactic::HaniwaGuard => { + self.handle_haniwa_guard(agent, controller, &attack_data, tgt_data, read_data, rng) + }, + Tactic::HaniwaArcher => { + self.handle_haniwa_archer(agent, controller, &attack_data, tgt_data, read_data) + }, } } diff --git a/server/agent/src/attack.rs b/server/agent/src/attack.rs index b4c00451aa..3d7f66cd11 100644 --- a/server/agent/src/attack.rs +++ b/server/agent/src/attack.rs @@ -3867,7 +3867,7 @@ impl<'a> AgentData<'a> { ); } - pub fn handle_clay_golem_attack( + pub fn handle_grave_warden_attack( &self, agent: &mut Agent, controller: &mut Controller, @@ -3948,7 +3948,7 @@ impl<'a> AgentData<'a> { controller.push_basic_input(InputKind::Ability(0)); } } - // Make clay golem move towards target + // Make grave warden move towards target self.path_toward_target( agent, controller, @@ -5785,4 +5785,451 @@ impl<'a> AgentData<'a> { ); } } + + pub fn handle_clay_steed_attack( + &self, + agent: &mut Agent, + controller: &mut Controller, + attack_data: &AttackData, + tgt_data: &TargetData, + read_data: &ReadData, + ) { + enum ActionStateTimers { + AttackTimer, + } + const HOOF_ATTACK_RANGE: f32 = 1.0; + const HOOF_ATTACK_ANGLE: f32 = 50.0; + + agent.combat_state.timers[ActionStateTimers::AttackTimer as usize] += read_data.dt.0; + if agent.combat_state.timers[ActionStateTimers::AttackTimer as usize] > 10.0 { + // Reset timer + agent.combat_state.timers[ActionStateTimers::AttackTimer as usize] = 0.0; + } + + if attack_data.angle < HOOF_ATTACK_ANGLE + && attack_data.dist_sqrd + < (HOOF_ATTACK_RANGE + self.body.map_or(0.0, |b| b.max_radius())).powi(2) + { + controller.inputs.move_dir = Vec2::zero(); + controller.push_basic_input(InputKind::Primary); + } else if agent.combat_state.timers[ActionStateTimers::AttackTimer as usize] < 5.0 { + controller.push_basic_input(InputKind::Secondary); + } else { + self.path_toward_target( + agent, + controller, + tgt_data.pos.0, + read_data, + Path::Full, + None, + ); + } + } + + pub fn handle_ancient_effigy_attack( + &self, + agent: &mut Agent, + controller: &mut Controller, + attack_data: &AttackData, + tgt_data: &TargetData, + read_data: &ReadData, + ) { + enum ActionStateTimers { + BlastTimer, + } + const MAX_ATTACK_RANGE: f32 = 20.0; + + 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, + ) + }; + + if agent.combat_state.timers[ActionStateTimers::BlastTimer as usize] > 2.0 { + // blast + controller.push_basic_input(InputKind::Secondary); + // Reset timer + if matches!(self.char_state, CharacterState::BasicRanged(c) if matches!(c.stage_section, StageSection::Recover)) + { + agent.combat_state.timers[ActionStateTimers::BlastTimer as usize] = 0.0; + } + } else if line_of_sight_with_target() + && attack_data.angle < 60.0 + && attack_data.dist_sqrd < MAX_ATTACK_RANGE.powi(2) + { + controller.inputs.move_dir = Vec2::zero(); + if attack_data.in_min_range() { + controller.push_basic_input(InputKind::Primary); + agent.combat_state.timers[ActionStateTimers::BlastTimer as usize] += read_data.dt.0; + } else { + controller.push_basic_input(InputKind::Primary); + } + } else if attack_data.dist_sqrd < MAX_PATH_DIST.powi(2) { + self.path_toward_target( + agent, + controller, + tgt_data.pos.0, + read_data, + Path::Separate, + None, + ); + } else { + self.path_toward_target( + agent, + controller, + tgt_data.pos.0, + read_data, + Path::Partial, + None, + ); + } + } + + pub fn handle_clay_golem_attack( + &self, + agent: &mut Agent, + controller: &mut Controller, + attack_data: &AttackData, + tgt_data: &TargetData, + read_data: &ReadData, + ) { + const MIN_DASH_RANGE: f32 = 15.0; + + if attack_data.angle < 60.0 { + controller.inputs.move_dir = Vec2::zero(); + if attack_data.in_min_range() { + controller.push_basic_input(InputKind::Primary); + } else if attack_data.dist_sqrd > MIN_DASH_RANGE.powi(2) { + controller.push_basic_input(InputKind::Secondary); + } else { + self.path_toward_target( + agent, + controller, + tgt_data.pos.0, + read_data, + Path::Partial, + None, + ); + } + } else if attack_data.dist_sqrd < MAX_PATH_DIST.powi(2) { + self.path_toward_target( + agent, + controller, + tgt_data.pos.0, + read_data, + Path::Separate, + None, + ); + } + } + + pub fn handle_haniwa_soldier( + &self, + agent: &mut Agent, + controller: &mut Controller, + attack_data: &AttackData, + tgt_data: &TargetData, + read_data: &ReadData, + ) { + const DEFENSIVE_CONDITION: usize = 0; + const RIPOSTE_TIMER: usize = 0; + const MODE_CYCLE_TIMER: usize = 1; + + let primary = self.extract_ability(AbilityInput::Primary); + let secondary = self.extract_ability(AbilityInput::Secondary); + let could_use_input = |input| match input { + InputKind::Primary => primary.as_ref().map_or(false, |p| { + p.could_use( + attack_data, + self, + tgt_data, + read_data, + AbilityPreferences::default(), + ) + }), + InputKind::Secondary => secondary.as_ref().map_or(false, |s| { + s.could_use( + attack_data, + self, + tgt_data, + read_data, + AbilityPreferences::default(), + ) + }), + _ => false, + }; + + agent.combat_state.timers[RIPOSTE_TIMER] += read_data.dt.0; + agent.combat_state.timers[MODE_CYCLE_TIMER] += read_data.dt.0; + + if agent.combat_state.timers[MODE_CYCLE_TIMER] > 7.0 { + agent.combat_state.conditions[DEFENSIVE_CONDITION] = + !agent.combat_state.conditions[DEFENSIVE_CONDITION]; + agent.combat_state.timers[MODE_CYCLE_TIMER] = 0.0; + } + + if matches!(self.char_state, CharacterState::RiposteMelee(_)) { + agent.combat_state.timers[RIPOSTE_TIMER] = 0.0; + } + + let try_move = if agent.combat_state.conditions[DEFENSIVE_CONDITION] { + controller.push_basic_input(InputKind::Block); + true + } else if agent.combat_state.timers[RIPOSTE_TIMER] > 10.0 + && could_use_input(InputKind::Secondary) + { + controller.push_basic_input(InputKind::Secondary); + false + } else if could_use_input(InputKind::Primary) { + controller.push_basic_input(InputKind::Primary); + false + } else { + true + }; + + if try_move && attack_data.dist_sqrd > 2_f32.powi(2) { + self.path_toward_target( + agent, + controller, + tgt_data.pos.0, + read_data, + Path::Separate, + None, + ); + } + } + + pub fn handle_haniwa_guard( + &self, + agent: &mut Agent, + controller: &mut Controller, + attack_data: &AttackData, + tgt_data: &TargetData, + read_data: &ReadData, + rng: &mut impl Rng, + ) { + const BACKPEDAL_DIST: f32 = 5.0; + const ROTATE_CCW_CONDITION: usize = 0; + const FLURRY_TIMER: usize = 0; + const BACKPEDAL_TIMER: usize = 1; + const SWITCH_ROTATE_TIMER: usize = 2; + const SWITCH_ROTATE_COUNTER: usize = 0; + + let primary = self.extract_ability(AbilityInput::Primary); + let secondary = self.extract_ability(AbilityInput::Secondary); + let abilities = [self.extract_ability(AbilityInput::Auxiliary(0))]; + let could_use_input = |input| match input { + InputKind::Primary => primary.as_ref().map_or(false, |p| { + p.could_use( + attack_data, + self, + tgt_data, + read_data, + AbilityPreferences::default(), + ) + }), + InputKind::Secondary => secondary.as_ref().map_or(false, |s| { + s.could_use( + attack_data, + self, + tgt_data, + read_data, + AbilityPreferences::default(), + ) + }), + InputKind::Ability(x) => abilities[x].as_ref().map_or(false, |a| { + a.could_use( + attack_data, + self, + tgt_data, + read_data, + AbilityPreferences::default(), + ) + }), + _ => false, + }; + + if !agent.combat_state.initialized { + agent.combat_state.conditions[ROTATE_CCW_CONDITION] = rng.gen_bool(0.5); + agent.combat_state.counters[SWITCH_ROTATE_COUNTER] = rng.gen_range(5.0..20.0); + agent.combat_state.initialized = true; + } + + let continue_flurry = match self.char_state { + CharacterState::BasicMelee(_) => { + agent.combat_state.timers[FLURRY_TIMER] += read_data.dt.0; + false + }, + CharacterState::RapidMelee(c) => { + agent.combat_state.timers[FLURRY_TIMER] = 0.0; + !matches!(c.stage_section, StageSection::Recover) + }, + CharacterState::ComboMelee2(_) => { + agent.combat_state.timers[BACKPEDAL_TIMER] = 0.0; + false + }, + _ => false, + }; + agent.combat_state.timers[SWITCH_ROTATE_TIMER] += read_data.dt.0; + agent.combat_state.timers[BACKPEDAL_TIMER] += read_data.dt.0; + + if agent.combat_state.timers[SWITCH_ROTATE_TIMER] + > agent.combat_state.counters[SWITCH_ROTATE_COUNTER] + { + agent.combat_state.conditions[ROTATE_CCW_CONDITION] = + !agent.combat_state.conditions[ROTATE_CCW_CONDITION]; + agent.combat_state.counters[SWITCH_ROTATE_COUNTER] = rng.gen_range(5.0..20.0); + } + + let move_farther = attack_data.dist_sqrd < BACKPEDAL_DIST.powi(2); + let move_closer = if continue_flurry && could_use_input(InputKind::Secondary) { + controller.push_basic_input(InputKind::Secondary); + false + } else if agent.combat_state.timers[BACKPEDAL_TIMER] > 10.0 + && move_farther + && could_use_input(InputKind::Ability(0)) + { + controller.push_basic_input(InputKind::Ability(0)); + false + } else if agent.combat_state.timers[FLURRY_TIMER] > 6.0 + && could_use_input(InputKind::Secondary) + { + controller.push_basic_input(InputKind::Secondary); + false + } else if could_use_input(InputKind::Primary) { + controller.push_basic_input(InputKind::Primary); + false + } else { + true + }; + + if let Some((bearing, speed)) = agent.chaser.chase( + &*read_data.terrain, + self.pos.0, + self.vel.0, + tgt_data.pos.0, + TraversalConfig { + min_tgt_dist: 1.25, + ..self.traversal_config + }, + ) { + if entities_have_line_of_sight( + self.pos, + self.body, + self.scale, + tgt_data.pos, + tgt_data.body, + tgt_data.scale, + read_data, + ) && attack_data.angle < 45.0 + { + let angle = match ( + agent.combat_state.conditions[ROTATE_CCW_CONDITION], + move_closer, + move_farther, + ) { + (true, true, false) => rng.gen_range(-1.5..-0.5), + (true, false, true) => rng.gen_range(-2.2..-1.7), + (true, _, _) => rng.gen_range(-1.7..-1.5), + (false, true, false) => rng.gen_range(0.5..1.5), + (false, false, true) => rng.gen_range(1.7..2.2), + (false, _, _) => rng.gen_range(1.5..1.7), + }; + controller.inputs.move_dir = bearing + .xy() + .rotated_z(angle) + .try_normalized() + .unwrap_or_else(Vec2::zero) + * speed; + } else { + controller.inputs.move_dir = + bearing.xy().try_normalized().unwrap_or_else(Vec2::zero) * speed; + self.jump_if(bearing.z > 1.5, controller); + } + } + } + + pub fn handle_haniwa_archer( + &self, + agent: &mut Agent, + controller: &mut Controller, + attack_data: &AttackData, + tgt_data: &TargetData, + read_data: &ReadData, + ) { + const KICK_TIMER: usize = 0; + const EXPLOSIVE_TIMER: usize = 1; + + let primary = self.extract_ability(AbilityInput::Primary); + let secondary = self.extract_ability(AbilityInput::Secondary); + let abilities = [self.extract_ability(AbilityInput::Auxiliary(0))]; + let could_use_input = |input| match input { + InputKind::Primary => primary.as_ref().map_or(false, |p| { + p.could_use( + attack_data, + self, + tgt_data, + read_data, + AbilityPreferences::default(), + ) + }), + InputKind::Secondary => secondary.as_ref().map_or(false, |s| { + s.could_use( + attack_data, + self, + tgt_data, + read_data, + AbilityPreferences::default(), + ) + }), + InputKind::Ability(x) => abilities[x].as_ref().map_or(false, |a| { + a.could_use( + attack_data, + self, + tgt_data, + read_data, + AbilityPreferences::default(), + ) + }), + _ => false, + }; + + agent.combat_state.timers[KICK_TIMER] += read_data.dt.0; + agent.combat_state.timers[EXPLOSIVE_TIMER] += read_data.dt.0; + + match self.char_state.ability_info().map(|ai| ai.input) { + Some(InputKind::Secondary) => { + agent.combat_state.timers[KICK_TIMER] = 0.0; + }, + Some(InputKind::Ability(0)) => { + agent.combat_state.timers[EXPLOSIVE_TIMER] = 0.0; + }, + _ => {}, + } + + if agent.combat_state.timers[KICK_TIMER] > 4.0 && could_use_input(InputKind::Secondary) { + controller.push_basic_input(InputKind::Secondary); + } else if agent.combat_state.timers[EXPLOSIVE_TIMER] > 15.0 + && could_use_input(InputKind::Ability(0)) + { + controller.push_basic_input(InputKind::Ability(0)); + } else if could_use_input(InputKind::Primary) { + controller.push_basic_input(InputKind::Primary); + } else { + self.path_toward_target( + agent, + controller, + tgt_data.pos.0, + read_data, + Path::Separate, + None, + ); + } + } } diff --git a/server/agent/src/data.rs b/server/agent/src/data.rs index eea12e5053..384485a033 100755 --- a/server/agent/src/data.rs +++ b/server/agent/src/data.rs @@ -175,6 +175,9 @@ pub enum Tactic { RadialTurret, FieryTornado, SimpleDouble, + ClayGolem, + ClaySteed, + AncientEffigy, // u8s are weights that each ability gets used, if it can be used RandomAbilities { primary: u8, @@ -218,7 +221,7 @@ pub enum Tactic { // Specific species tactics Mindflayer, Minotaur, - ClayGolem, + GraveWarden, TidalWarrior, Yeti, Harvester, @@ -245,6 +248,11 @@ pub enum Tactic { AdletIcepicker, AdletTracker, AdletElder, + + // Haniwa + HaniwaSoldier, + HaniwaGuard, + HaniwaArcher, } #[derive(Copy, Clone, Debug)] diff --git a/server/src/events/inventory_manip.rs b/server/src/events/inventory_manip.rs index 2d241599fd..74c9e92ecc 100644 --- a/server/src/events/inventory_manip.rs +++ b/server/src/events/inventory_manip.rs @@ -329,6 +329,7 @@ pub fn handle_inventory(server: &mut Server, entity: EcsEntity, manip: comp::Inv if let Some(kind_to_destroy) = match block.get_sprite() { Some(SpriteKind::Keyhole) => Some(SpriteKind::KeyDoor), Some(SpriteKind::BoneKeyhole) => Some(SpriteKind::BoneKeyDoor), + Some(SpriteKind::HaniwaKeyhole) => Some(SpriteKind::HaniwaKeyDoor), Some(SpriteKind::GlassKeyhole) => Some(SpriteKind::GlassBarrier), Some(SpriteKind::KeyholeBars) => Some(SpriteKind::DoorBars), _ => None, diff --git a/voxygen/anim/src/biped_large/mod.rs b/voxygen/anim/src/biped_large/mod.rs index d851f0e4a6..13e6c72447 100644 --- a/voxygen/anim/src/biped_large/mod.rs +++ b/voxygen/anim/src/biped_large/mod.rs @@ -266,6 +266,7 @@ 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), }, jaw: match (body.species, body.body_type) { (Ogre, _) => (0.0, 0.0), @@ -293,6 +294,7 @@ impl<'a> From<&'a Body> for SkeletonAttr { (Gigasfrost, _) => (-1.0, 5.5), (AdletElder, _) => (10.5, -7.0), (SeaBishop, _) => (5.0, -4.5), + (HaniwaGeneral, _) => (10.5, -7.0), }, upper_torso: match (body.species, body.body_type) { (Ogre, Male) => (0.0, 27.5), @@ -321,6 +323,7 @@ impl<'a> From<&'a Body> for SkeletonAttr { (Gigasfrost, _) => (-1.0, 30.0), (AdletElder, _) => (3.0, 19.0), (SeaBishop, _) => (0.0, 15.0), + (HaniwaGeneral, _) => (3.0, 16.0), }, lower_torso: match (body.species, body.body_type) { (Ogre, Male) => (1.0, -7.0), @@ -349,6 +352,7 @@ impl<'a> From<&'a Body> for SkeletonAttr { (Gigasfrost, _) => (0.0, -5.5), (AdletElder, _) => (0.0, -4.0), (SeaBishop, _) => (0.0, -1.0), + (HaniwaGeneral, _) => (-1.0, -3.5), }, tail: match (body.species, body.body_type) { (Werewolf, _) => (-5.5, -2.0), @@ -386,6 +390,7 @@ impl<'a> From<&'a Body> for SkeletonAttr { (Gigasfrost, _) => (10.5, 0.5, 0.0), (AdletElder, _) => (8.5, 1.0, 2.5), (SeaBishop, _) => (7.0, 0.0, 1.0), + (HaniwaGeneral, _) => (9.0, -1.0, 4.5), }, hand: match (body.species, body.body_type) { (Ogre, Male) => (14.5, 0.0, -4.0), @@ -414,6 +419,7 @@ impl<'a> From<&'a Body> for SkeletonAttr { (Gigasfrost, _) => (17.0, 0.5, -6.0), (AdletElder, _) => (8.0, 1.5, -2.5), (SeaBishop, _) => (10.0, 0.0, -3.0), + (HaniwaGeneral, _) => (10.0, -1.0, -3.0), }, leg: match (body.species, body.body_type) { (Ogre, Male) => (0.0, 0.0, -4.0), @@ -442,6 +448,7 @@ impl<'a> From<&'a Body> for SkeletonAttr { (Gigasfrost, _) => (6.0, 0.0, -10.0), (AdletElder, _) => (3.0, -1.5, -4.0), (SeaBishop, _) => (3.0, 1.0, -14.0), + (HaniwaGeneral, _) => (3.0, 0.0, -5.0), }, foot: match (body.species, body.body_type) { (Ogre, Male) => (4.0, 1.0, -12.0), @@ -470,6 +477,7 @@ impl<'a> From<&'a Body> for SkeletonAttr { (Gigasfrost, _) => (6.5, 2.0, -19.5), (AdletElder, _) => (4.0, 3.5, -10.0), (SeaBishop, _) => (5.5, 3.0, -6.5), + (HaniwaGeneral, _) => (3.0, 1.0, -10.0), }, scaler: match (body.species, body.body_type) { (Ogre, Male) => 1.12, @@ -498,6 +506,7 @@ impl<'a> From<&'a Body> for SkeletonAttr { (Gigasfrost, _) => 1.7, (AdletElder, _) => 1.0, (SeaBishop, _) => 1.0, + (HaniwaGeneral, _) => 1.0, }, tempo: match (body.species, body.body_type) { (Ogre, Male) => 0.9, @@ -537,6 +546,7 @@ impl<'a> From<&'a Body> for SkeletonAttr { (Gigasfrost, _) => (16.0, 0.0), (AdletElder, _) => (10.0, 0.0), (SeaBishop, _) => (6.0, 0.0), + (HaniwaGeneral, _) => (10.0, 0.0), }, shl: match (body.species, body.body_type) { (Dullahan, _) => (-4.75, -11.0, 8.5, 1.47, -0.2, 0.0), @@ -630,6 +640,7 @@ fn mount_point(body: &Body) -> Vec3 { (Gigasfrost, _) => (1.0, 2.0, 4.0), (AdletElder, _) => (0.0, 0.0, -1.0), (SeaBishop, _) => (0.0, 0.0, -1.0), + (HaniwaGeneral, _) => (0.0, 0.0, -1.0), } .into() } diff --git a/voxygen/anim/src/biped_small/alpha.rs b/voxygen/anim/src/biped_small/alpha.rs index 874b75cb0d..50da89f3f9 100644 --- a/voxygen/anim/src/biped_small/alpha.rs +++ b/voxygen/anim/src/biped_small/alpha.rs @@ -1,7 +1,8 @@ use super::{ super::{vek::*, Animation}, biped_small_alpha_axe, biped_small_alpha_dagger, biped_small_alpha_spear, - init_biped_small_alpha, BipedSmallSkeleton, SkeletonAttr, + biped_small_wield_bow, biped_small_wield_sword, init_biped_small_alpha, BipedSmallSkeleton, + SkeletonAttr, }; use common::{comp::item::ToolKind, states::utils::StageSection}; use std::f32::consts::PI; @@ -40,7 +41,7 @@ impl Animation for AlphaAnimation { _last_ori, global_time, _avg_vel, - _acc_vel, + acc_vel, stage_section, timer, ): Self::Dependency<'_>, @@ -53,9 +54,6 @@ impl Animation for AlphaAnimation { let speednorm = speed / 9.4; let speednormcancel = 1.0 - speednorm; - let fast = (anim_time * 10.0).sin(); - let fastalt = (anim_time * 10.0 + PI / 2.0).sin(); - let anim_time = anim_time.min(1.0); let (move1base, move2base, move3) = match stage_section { Some(StageSection::Buildup) => (anim_time.sqrt(), 0.0, 0.0), @@ -81,8 +79,7 @@ impl Animation for AlphaAnimation { s_a, move1abs, move2abs, - fast, - fastalt, + anim_time, speednormcancel, ); }, @@ -92,6 +89,21 @@ impl Animation for AlphaAnimation { Some(ToolKind::Dagger) => { biped_small_alpha_dagger(&mut next, s_a, move1abs, move2abs); }, + Some(ToolKind::Sword) => { + let slow = (anim_time * 2.0).sin(); + biped_small_wield_sword(&mut next, s_a, speednorm, slow); + + next.chest.orientation.rotate_z(1.2 * move1abs); + next.head.orientation.rotate_z(-0.6 * move1abs); + next.pants.orientation.rotate_z(-0.6 * move1abs); + next.control.orientation.rotate_x(0.8 * move1abs); + next.control.orientation.rotate_y(-0.4 * move1abs); + + next.chest.orientation.rotate_z(-3.0 * move2abs); + next.head.orientation.rotate_z(1.5 * move2abs); + next.pants.orientation.rotate_z(2.0 * move2abs); + next.control.orientation.rotate_x(-3.0 * move2abs); + }, Some(ToolKind::Staff) => match ability_id { Some("common.abilities.custom.dwarves.flamekeeper.flamecrush") => { next.control_l.position = Vec3::new(2.0 - s_a.grip.0 * 2.0, 1.0, 3.0); @@ -154,6 +166,27 @@ impl Animation for AlphaAnimation { next.head.orientation = Quaternion::rotation_z(move1 * -0.8 + move2 * 0.8); }, }, + Some(ToolKind::Bow) => match ability_id { + Some("common.abilities.haniwa.archer.kick") => { + let fastacc = (acc_vel * 2.0).sin(); + biped_small_wield_bow(&mut next, s_a, anim_time, speed, fastacc); + + next.chest.orientation.rotate_z(move1abs * 1.1); + next.control.orientation.rotate_z(move1abs * -0.9); + next.control.position += Vec3::new(7.0, 1.0, 0.0) * move1abs; + next.head.orientation.rotate_z(move1abs * -0.8); + next.foot_l.orientation.rotate_z(move1abs * 1.1); + + next.chest.orientation.rotate_z(move2abs * -2.3); + next.control.orientation.rotate_z(move2abs * 1.9); + next.control.position += Vec3::new(-7.0, -1.0, 0.0) * move2abs; + next.head.orientation.rotate_z(move2abs * 0.9); + next.foot_l.orientation.rotate_y(move2abs * 1.3); + next.foot_l.orientation.rotate_z(move2abs * -2.9); + next.foot_l.position += Vec3::new(3.0, 8.0, 4.0) * move2abs; + }, + _ => {}, + }, Some(ToolKind::Natural) => { let tension = match stage_section { Some(StageSection::Buildup) => (anim_time * 10.0).sin(), diff --git a/voxygen/anim/src/biped_small/block.rs b/voxygen/anim/src/biped_small/block.rs new file mode 100644 index 0000000000..c0cc43fd3c --- /dev/null +++ b/voxygen/anim/src/biped_small/block.rs @@ -0,0 +1,64 @@ +use super::{ + super::{vek::*, Animation}, + biped_small_wield_sword, init_biped_small_alpha, BipedSmallSkeleton, SkeletonAttr, +}; +use common::states::utils::StageSection; + +pub struct BlockAnimation; + +type BlockAnimationDependency<'a> = (Option<&'a str>, StageSection); + +impl Animation for BlockAnimation { + type Dependency<'a> = BlockAnimationDependency<'a>; + type Skeleton = BipedSmallSkeleton; + + #[cfg(feature = "use-dyn-lib")] + const UPDATE_FN: &'static [u8] = b"biped_small_block\0"; + + #[cfg_attr(feature = "be-dyn-lib", export_name = "biped_small_block")] + fn update_skeleton_inner( + skeleton: &Self::Skeleton, + (ability_id, stage_section): Self::Dependency<'_>, + anim_time: f32, + rate: &mut f32, + s_a: &SkeletonAttr, + ) -> Self::Skeleton { + *rate = 1.0; + let mut next = (*skeleton).clone(); + + init_biped_small_alpha(&mut next, s_a); + + match ability_id { + Some("common.abilities.haniwa.soldier.guard") => { + let slow = (anim_time * 2.0).sin(); + biped_small_wield_sword(&mut next, s_a, 0.0, slow); + + let (move1, move2, move3) = match stage_section { + StageSection::Buildup => (anim_time, 0.0, 0.0), + StageSection::Action => (1.0, anim_time, 0.0), + StageSection::Recover => (1.0, 1.0, anim_time), + _ => (0.0, 0.0, 0.0), + }; + let pullback = 1.0 - move3; + let move1 = move1 * pullback; + let _move2 = move2 * pullback; + + next.detach_right = true; + // For some reason there's a discontinuity when using detach_right, two offsets + // below seem to help + next.control_r.position += next.control.position + + Vec3::new(0.0, -2.0, 1.0) + + Vec3::new(2.0 * move3, -1.0 * move3, 2.0 * move3); + next.control_r.orientation = next.control.orientation * next.control_r.orientation; + + next.control.orientation.rotate_x(move1 * -0.7); + next.control.orientation.rotate_z(move1 * -1.4); + next.control_r.orientation.rotate_x(move1 * 1.2); + next.control_r.position += Vec3::new(0.0, 5.0 * move1, 6.0 * move1); + }, + _ => {}, + } + + next + } +} diff --git a/voxygen/anim/src/biped_small/combomelee.rs b/voxygen/anim/src/biped_small/combomelee.rs index 8a0ff7cbe8..17f72776ec 100644 --- a/voxygen/anim/src/biped_small/combomelee.rs +++ b/voxygen/anim/src/biped_small/combomelee.rs @@ -1,10 +1,9 @@ use super::{ super::{vek::*, Animation}, biped_small_alpha_axe, biped_small_alpha_dagger, biped_small_alpha_spear, - init_biped_small_alpha, BipedSmallSkeleton, SkeletonAttr, + biped_small_wield_spear, init_biped_small_alpha, BipedSmallSkeleton, SkeletonAttr, }; use common::states::utils::StageSection; -use std::f32::consts::PI; pub struct ComboAnimation; impl Animation for ComboAnimation { @@ -115,8 +114,6 @@ impl Animation for ComboAnimation { let speed = Vec2::::from(velocity).magnitude(); let speednorm = speed / 9.4; let speednormcancel = 1.0 - speednorm; - let fast = (anim_time * 10.0).sin(); - let fastalt = (anim_time * 10.0 + PI / 2.0).sin(); let (move1base, move2base, move3) = match stage_section { StageSection::Buildup => (anim_time.sqrt(), 0.0, 0.0), @@ -134,11 +131,26 @@ impl Animation for ComboAnimation { s_a, move1abs, move2abs, - fast, - fastalt, + anim_time, speednormcancel, ); }, + Some("common.abilities.haniwa.guard.backpedal") => { + init_biped_small_alpha(&mut next, s_a); + biped_small_wield_spear(&mut next, s_a, anim_time, 0.0, 0.0); + + let (move1, move2, move3) = match stage_section { + StageSection::Buildup => (anim_time.powf(0.25), 0.0, 0.0), + StageSection::Action => (1.0, anim_time, 0.0), + StageSection::Recover => (1.0, 1.0, anim_time.powf(0.25)), + _ => (0.0, 0.0, 0.0), + }; + let pullback = 1.0 - move3; + let move1 = move1 * pullback; + let move2 = move2 * pullback; + + biped_small_alpha_spear(&mut next, s_a, move1, move2, anim_time, 0.0); + }, _ => {}, } } diff --git a/voxygen/anim/src/biped_small/mod.rs b/voxygen/anim/src/biped_small/mod.rs index ead28a2d8f..677682bd84 100644 --- a/voxygen/anim/src/biped_small/mod.rs +++ b/voxygen/anim/src/biped_small/mod.rs @@ -1,9 +1,12 @@ pub mod alpha; pub mod beam; +pub mod block; pub mod combomelee; pub mod dash; pub mod idle; pub mod leapmelee; +pub mod rapidmelee; +pub mod ripostemelee; pub mod run; pub mod shockwave; pub mod shoot; @@ -13,8 +16,9 @@ pub mod wield; // Reexports pub use self::{ - alpha::AlphaAnimation, beam::BeamAnimation, combomelee::ComboAnimation, dash::DashAnimation, - idle::IdleAnimation, leapmelee::LeapAnimation, run::RunAnimation, + 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, }; @@ -39,7 +43,9 @@ skeleton_impls!(struct BipedSmallSkeleton { control, control_l, control_r, - + :: // Begin non-bone fields + // Allows right hand to not be moved by control bone + detach_right: bool, }); impl Skeleton for BipedSmallSkeleton { @@ -72,7 +78,14 @@ impl Skeleton for BipedSmallSkeleton { make_bone(pants_mat * Mat4::::from(self.tail)), make_bone(control_mat * Mat4::::from(self.main)), make_bone(control_mat * control_l_mat * Mat4::::from(self.hand_l)), - make_bone(control_mat * control_r_mat * Mat4::::from(self.hand_r)), + make_bone( + if self.detach_right { + chest_mat + } else { + control_mat + } * control_r_mat + * Mat4::::from(self.hand_r), + ), make_bone(base_mat * Mat4::::from(self.foot_l)), make_bone(base_mat * Mat4::::from(self.foot_r)), ]; @@ -296,10 +309,12 @@ pub fn biped_small_alpha_spear( s_a: &SkeletonAttr, move1abs: f32, move2abs: f32, - fast: f32, - fastalt: f32, + anim_time: f32, speednormcancel: f32, ) { + let fast = (anim_time * 10.0).sin(); + let fastalt = (anim_time * 10.0 + PI / 2.0).sin(); + next.head.position = Vec3::new(0.0, s_a.head.0, s_a.head.1); next.head.orientation = Quaternion::rotation_x(move1abs * 0.2 + move2abs * 0.3) * Quaternion::rotation_z(move1abs * -0.2 + move2abs * 0.6) @@ -401,3 +416,97 @@ pub fn biped_small_alpha_dagger( * Quaternion::rotation_y(move1abs * -0.4 + move2abs * 1.0) * Quaternion::rotation_z(-0.3 + move2abs * -2.2); } + +pub fn biped_small_wield_sword( + next: &mut BipedSmallSkeleton, + s_a: &SkeletonAttr, + speednorm: f32, + slow: f32, +) { + next.control_l.position = Vec3::new(2.0 - s_a.grip.0 * 2.0, 1.0, 3.0); + next.control_r.position = Vec3::new(9.0 + s_a.grip.0 * 2.0, -1.0, -2.0 + speednorm * -3.0); + + next.control.position = Vec3::new( + -5.0, + -1.0 + s_a.grip.2, + -1.0 + -s_a.grip.2 / 2.5 + s_a.grip.0 * -2.0 + speednorm * 2.0, + ); + + next.control_l.orientation = Quaternion::rotation_x(PI / 2.0 + slow * 0.1) + * Quaternion::rotation_y(-0.0) + * Quaternion::rotation_z(-0.0); + next.control_r.orientation = Quaternion::rotation_x(0.5 + slow * 0.1 + s_a.grip.0 * 0.2) + * Quaternion::rotation_y(0.2 + slow * 0.0 + s_a.grip.0 * 0.2) + * Quaternion::rotation_z(-0.0); + + next.control.orientation = Quaternion::rotation_x(-0.3 + 0.2 * speednorm) + * Quaternion::rotation_y(-0.2 * speednorm) + * Quaternion::rotation_z(-0.3); +} + +pub fn biped_small_wield_spear( + next: &mut BipedSmallSkeleton, + s_a: &SkeletonAttr, + anim_time: f32, + speed: f32, + fastacc: f32, +) { + let speednorm = speed / 9.4; + let speednormcancel = 1.0 - speednorm; + let fastalt = (anim_time * 10.0 + PI / 2.0).sin(); + let slow = (anim_time * 2.0).sin(); + + next.control_l.position = Vec3::new(1.0 - s_a.grip.0 * 2.0, 2.0, -2.0); + next.control_r.position = Vec3::new(-1.0 + s_a.grip.0 * 2.0, 2.0, 2.0); + + next.control.position = Vec3::new( + -3.0, + s_a.grip.2, + -s_a.grip.2 / 2.5 + + s_a.grip.0 * -2.0 + + fastacc * 1.5 + + fastalt * 0.5 * speednormcancel + + speednorm * 2.0, + ); + + next.control_l.orientation = + Quaternion::rotation_x(PI / 1.5 + slow * 0.1) * Quaternion::rotation_y(-0.3); + next.control_r.orientation = Quaternion::rotation_x(PI / 1.5 + slow * 0.1 + s_a.grip.0 * 0.2) + * Quaternion::rotation_y(0.5 + slow * 0.0 + s_a.grip.0 * 0.2); + + next.control.orientation = Quaternion::rotation_x(-1.35 + 0.5 * speednorm); +} + +pub fn biped_small_wield_bow( + next: &mut BipedSmallSkeleton, + s_a: &SkeletonAttr, + anim_time: f32, + speed: f32, + fastacc: f32, +) { + let speednorm = speed / 9.4; + let speednormcancel = 1.0 - speednorm; + let fastalt = (anim_time * 10.0 + PI / 2.0).sin(); + let slow = (anim_time * 2.0).sin(); + + next.control_l.position = Vec3::new(1.0 - s_a.grip.0 * 2.0, 0.0, 0.0); + next.control_r.position = Vec3::new(-1.0 + s_a.grip.0 * 2.0, 6.0, -2.0); + + next.control.position = Vec3::new( + -1.0, + 2.0 + s_a.grip.2, + 3.0 + -s_a.grip.2 / 2.5 + + s_a.grip.0 * -2.0 + + fastacc * 1.5 + + fastalt * 0.5 * speednormcancel + + speednorm * 2.0, + ); + + next.control_l.orientation = + Quaternion::rotation_x(PI / 2.0 + slow * 0.1) * Quaternion::rotation_y(-0.3); + next.control_r.orientation = Quaternion::rotation_x(PI / 2.0 + slow * 0.1 + s_a.grip.0 * 0.2) + * Quaternion::rotation_y(0.5 + slow * 0.0 + s_a.grip.0 * 0.2); + + next.control.orientation = + Quaternion::rotation_x(-0.3 + 0.5 * speednorm) * Quaternion::rotation_y(0.5 * speednorm); +} diff --git a/voxygen/anim/src/biped_small/rapidmelee.rs b/voxygen/anim/src/biped_small/rapidmelee.rs new file mode 100644 index 0000000000..c497d6fad6 --- /dev/null +++ b/voxygen/anim/src/biped_small/rapidmelee.rs @@ -0,0 +1,50 @@ +use super::{ + super::Animation, biped_small_alpha_spear, biped_small_wield_spear, init_biped_small_alpha, + BipedSmallSkeleton, SkeletonAttr, +}; +use common::states::utils::StageSection; + +pub struct RapidMeleeAnimation; +impl Animation for RapidMeleeAnimation { + type Dependency<'a> = (Option<&'a str>, StageSection, (u32, Option)); + type Skeleton = BipedSmallSkeleton; + + #[cfg(feature = "use-dyn-lib")] + const UPDATE_FN: &'static [u8] = b"biped_small_rapid_melee\0"; + + #[cfg_attr(feature = "be-dyn-lib", export_name = "biped_small_rapid_melee")] + fn update_skeleton_inner( + skeleton: &Self::Skeleton, + (ability_id, stage_section, (_current_strike, _max_strikes)): Self::Dependency<'_>, + anim_time: f32, + rate: &mut f32, + s_a: &SkeletonAttr, + ) -> Self::Skeleton { + *rate = 1.0; + let mut next = (*skeleton).clone(); + + init_biped_small_alpha(&mut next, s_a); + + match ability_id { + Some("common.abilities.haniwa.guard.flurry") => { + biped_small_wield_spear(&mut next, s_a, anim_time, 0.0, 0.0); + + let (move1, move2, move3) = match stage_section { + StageSection::Buildup => (anim_time.powf(0.25), 0.0, 0.0), + StageSection::Action => (1.0, anim_time, 0.0), + StageSection::Recover => (1.0, 1.0, anim_time), + _ => (0.0, 0.0, 0.0), + }; + let pullback = 1.0 - move3; + let move1 = move1 * pullback; + let move2 = ((move2 - 0.5).abs() * -2.0 + 1.0) * 0.75; + let move2 = move2 * pullback; + + biped_small_alpha_spear(&mut next, s_a, move1, move2, anim_time, 0.0); + }, + _ => {}, + } + + next + } +} diff --git a/voxygen/anim/src/biped_small/ripostemelee.rs b/voxygen/anim/src/biped_small/ripostemelee.rs new file mode 100644 index 0000000000..668f54b611 --- /dev/null +++ b/voxygen/anim/src/biped_small/ripostemelee.rs @@ -0,0 +1,67 @@ +use super::{ + super::{vek::*, Animation}, + biped_small_wield_sword, init_biped_small_alpha, BipedSmallSkeleton, SkeletonAttr, +}; +use common::states::utils::StageSection; + +pub struct RiposteMeleeAnimation; +impl Animation for RiposteMeleeAnimation { + type Dependency<'a> = (Option<&'a str>, StageSection); + type Skeleton = BipedSmallSkeleton; + + #[cfg(feature = "use-dyn-lib")] + const UPDATE_FN: &'static [u8] = b"biped_small_riposte_melee\0"; + + #[cfg_attr(feature = "be-dyn-lib", export_name = "biped_small_riposte_melee")] + fn update_skeleton_inner( + skeleton: &Self::Skeleton, + (ability_id, stage_section): Self::Dependency<'_>, + anim_time: f32, + rate: &mut f32, + s_a: &SkeletonAttr, + ) -> Self::Skeleton { + *rate = 1.0; + let mut next = (*skeleton).clone(); + + init_biped_small_alpha(&mut next, s_a); + + match ability_id { + Some("common.abilities.haniwa.soldier.riposte") => { + let slow = (anim_time * 2.0).sin(); + biped_small_wield_sword(&mut next, s_a, 0.0, slow); + + let (move1, move2, move3) = match stage_section { + StageSection::Buildup => (anim_time.powf(0.25), 0.0, 0.0), + StageSection::Action => (1.0, anim_time, 0.0), + StageSection::Recover => (1.0, 1.0, anim_time), + _ => (0.0, 0.0, 0.0), + }; + let pullback = 1.0 - move3; + let move1 = move1 * pullback; + let move2 = move2 * pullback; + let move2fast = move2.max(0.001).powf(0.25) * pullback; + let move2slow = move2.powi(4) * pullback; + + next.detach_right = true; + // For some reason there's a discontinuity when using detach_right, two offsets + // below seem to help + next.control_r.position += next.control.position + + Vec3::new(0.0, -2.0, 1.0) + + Vec3::new(2.0 * move3, -1.0 * move3, 2.0 * move3); + next.control_r.orientation = next.control.orientation * next.control_r.orientation; + + next.control.orientation.rotate_z(move1 * 1.9); + next.control.position += Vec3::new(0.0 * move1, 2.0 * move1, 13.0 * move1); + next.control.orientation.rotate_y(move1 * 2.7); + + next.control.orientation.rotate_y(move2fast * -2.1); + next.control.orientation.rotate_z(move2 * -1.8); + next.control.orientation.rotate_x(move2slow * -3.2); + next.control.position += Vec3::new(move2 * 3.0, move2 * -2.0, move2 * -10.0); + }, + _ => {}, + } + + next + } +} diff --git a/voxygen/anim/src/biped_small/wield.rs b/voxygen/anim/src/biped_small/wield.rs index 33600489b7..f39055a5eb 100644 --- a/voxygen/anim/src/biped_small/wield.rs +++ b/voxygen/anim/src/biped_small/wield.rs @@ -1,6 +1,7 @@ use super::{ super::{vek::*, Animation}, - BipedSmallSkeleton, SkeletonAttr, + biped_small_wield_bow, biped_small_wield_spear, biped_small_wield_sword, BipedSmallSkeleton, + SkeletonAttr, }; use common::comp::item::ToolKind; use std::f32::consts::PI; @@ -74,26 +75,7 @@ impl Animation for WieldAnimation { match active_tool_kind { Some(ToolKind::Spear) => { - next.control_l.position = Vec3::new(1.0 - s_a.grip.0 * 2.0, 2.0, -2.0); - next.control_r.position = Vec3::new(-1.0 + s_a.grip.0 * 2.0, 2.0, 2.0); - - next.control.position = Vec3::new( - -3.0, - s_a.grip.2, - -s_a.grip.2 / 2.5 - + s_a.grip.0 * -2.0 - + fastacc * 1.5 - + fastalt * 0.5 * speednormcancel - + speednorm * 2.0, - ); - - next.control_l.orientation = - Quaternion::rotation_x(PI / 1.5 + slow * 0.1) * Quaternion::rotation_y(-0.3); - next.control_r.orientation = - Quaternion::rotation_x(PI / 1.5 + slow * 0.1 + s_a.grip.0 * 0.2) - * Quaternion::rotation_y(0.5 + slow * 0.0 + s_a.grip.0 * 0.2); - - next.control.orientation = Quaternion::rotation_x(-1.35 + 0.5 * speednorm); + biped_small_wield_spear(&mut next, s_a, anim_time, speed, fastacc); }, Some(ToolKind::Blowgun) => { next.control_l.position = Vec3::new(1.0 - s_a.grip.0 * 2.0, 0.0, 3.0); @@ -118,27 +100,7 @@ impl Animation for WieldAnimation { next.control.orientation = Quaternion::rotation_x(-2.2 + 0.5 * speednorm); }, Some(ToolKind::Bow) => { - next.control_l.position = Vec3::new(1.0 - s_a.grip.0 * 2.0, 0.0, 0.0); - next.control_r.position = Vec3::new(-1.0 + s_a.grip.0 * 2.0, 6.0, -2.0); - - next.control.position = Vec3::new( - -1.0, - 2.0 + s_a.grip.2, - 3.0 + -s_a.grip.2 / 2.5 - + s_a.grip.0 * -2.0 - + fastacc * 1.5 - + fastalt * 0.5 * speednormcancel - + speednorm * 2.0, - ); - - next.control_l.orientation = - Quaternion::rotation_x(PI / 2.0 + slow * 0.1) * Quaternion::rotation_y(-0.3); - next.control_r.orientation = - Quaternion::rotation_x(PI / 2.0 + slow * 0.1 + s_a.grip.0 * 0.2) - * Quaternion::rotation_y(0.5 + slow * 0.0 + s_a.grip.0 * 0.2); - - next.control.orientation = Quaternion::rotation_x(-0.3 + 0.5 * speednorm) - * Quaternion::rotation_y(0.5 * speednorm); + biped_small_wield_bow(&mut next, s_a, anim_time, speed, fastacc); }, Some(ToolKind::Staff) => { next.control_l.position = Vec3::new(2.0 - s_a.grip.0 * 2.0, 1.0, 3.0); @@ -190,28 +152,8 @@ impl Animation for WieldAnimation { * Quaternion::rotation_y(-0.2 * speednorm) * Quaternion::rotation_z(-0.3); }, - Some(ToolKind::Dagger) => { - next.control_l.position = Vec3::new(2.0 - s_a.grip.0 * 2.0, 1.0, 3.0); - next.control_r.position = - Vec3::new(9.0 + s_a.grip.0 * 2.0, -1.0, -2.0 + speednorm * -3.0); - - next.control.position = Vec3::new( - -5.0, - -1.0 + s_a.grip.2, - -1.0 + -s_a.grip.2 / 2.5 + s_a.grip.0 * -2.0 + speednorm * 2.0, - ); - - next.control_l.orientation = Quaternion::rotation_x(PI / 2.0 + slow * 0.1) - * Quaternion::rotation_y(-0.0) - * Quaternion::rotation_z(-0.0); - next.control_r.orientation = - Quaternion::rotation_x(0.5 + slow * 0.1 + s_a.grip.0 * 0.2) - * Quaternion::rotation_y(0.2 + slow * 0.0 + s_a.grip.0 * 0.2) - * Quaternion::rotation_z(-0.0); - - next.control.orientation = Quaternion::rotation_x(-0.3 + 0.2 * speednorm) - * Quaternion::rotation_y(-0.2 * speednorm) - * Quaternion::rotation_z(-0.3); + Some(ToolKind::Dagger | ToolKind::Sword) => { + biped_small_wield_sword(&mut next, s_a, speednorm, slow); }, _ => { next.hand_l.position = Vec3::new(-s_a.hand.0, s_a.hand.1, s_a.hand.2); diff --git a/voxygen/anim/src/character/music.rs b/voxygen/anim/src/character/music.rs index 84cfdc3f78..375eaf1275 100644 --- a/voxygen/anim/src/character/music.rs +++ b/voxygen/anim/src/character/music.rs @@ -103,18 +103,24 @@ impl Animation for MusicAnimation { Some(ToolKind::Instrument) => { // instrument specific head_bop let head_bop = match ability_id { - Some("common.abilities.music.flute") - | Some("common.abilities.music.glass_flute") - | Some("common.abilities.music.melodica") => 0.2, + Some( + "common.abilities.music.flute" + | "common.abilities.music.glass_flute" + | "common.abilities.music.melodica", + ) => 0.2, + Some( + "common.abilities.music.guitar" + | "common.abilities.music.dark_guitar" + | "common.abilities.music.lute" + | "common.abilities.music.sitar", + ) => 0.5, - Some("common.abilities.music.guitar") - | Some("common.abilities.music.dark_guitar") - | Some("common.abilities.music.lute") - | Some("common.abilities.music.sitar") => 0.5, - - Some("common.abilities.music.lyre") - | Some("common.abilities.music.icy_talharpa") - | Some("common.abilities.music.kalimba") => 0.3, + Some( + "common.abilities.music.lyre" + | "common.abilities.music.icy_talharpa" + | "common.abilities.music.shamisen" + | "common.abilities.music.kalimba", + ) => 0.3, _ => 1.0, }; next.head.position = Vec3::new(0.0, s_a.head.0, s_a.head.1); @@ -146,8 +152,7 @@ impl Animation for MusicAnimation { * Quaternion::rotation_y(3.0) * Quaternion::rotation_z(PI / -3.0); }, - Some("common.abilities.music.flute") - | Some("common.abilities.music.glass_flute") => { + Some("common.abilities.music.flute" | "common.abilities.music.glass_flute") => { next.hand_l.position = Vec3::new( 4.0 - s_a.hand.0, 6.0 + s_a.hand.1 + shortealt * -0.5, @@ -169,8 +174,9 @@ impl Animation for MusicAnimation { * Quaternion::rotation_y(PI) * Quaternion::rotation_z(0.05); }, - Some("common.abilities.music.guitar") - | Some("common.abilities.music.dark_guitar") => { + Some( + "common.abilities.music.guitar" | "common.abilities.music.dark_guitar", + ) => { next.hand_l.position = Vec3::new( 1.0 - s_a.hand.0, 6.0 + s_a.hand.1 + shortealt * -1.0, @@ -193,9 +199,12 @@ impl Animation for MusicAnimation { * Quaternion::rotation_y(2.0) * Quaternion::rotation_z(PI / -3.0); }, - Some("common.abilities.music.lyre") - | Some("common.abilities.music.wildskin_drum") - | Some("common.abilities.music.icy_talharpa") => { + Some( + "common.abilities.music.lyre" + | "common.abilities.music.wildskin_drum" + | "common.abilities.music.steeldrum" + | "common.abilities.music.icy_talharpa", + ) => { next.hand_l.position = Vec3::new( 3.0 - s_a.hand.0, 4.0 + s_a.hand.1 + shortealt * -0.1, @@ -239,7 +248,7 @@ impl Animation for MusicAnimation { * Quaternion::rotation_y(-0.75) * Quaternion::rotation_z(PI - 0.2); }, - Some("common.abilities.music.lute") => { + Some("common.abilities.music.lute" | "common.abilities.music.shamisen") => { next.hand_l.position = Vec3::new( 2.0 - s_a.hand.0, 5.0 + s_a.hand.1 + shortealt * -1.0, diff --git a/voxygen/anim/src/character/wield.rs b/voxygen/anim/src/character/wield.rs index 695ea11d53..71b24c7c69 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" => { + "Lyre" | "IcyTalharpa" | "WildskinDrum" | "Steeldrum" => { if speed < 0.5 { next.head.orientation = Quaternion::rotation_z(head_look.x) * Quaternion::rotation_x( @@ -392,7 +392,7 @@ impl Animation for WieldAnimation { * Quaternion::rotation_y(2.0 + u_slow * 0.1) * Quaternion::rotation_z(u_slowalt * 0.1); }, - "Lute" => { + "Lute" | "Shamisen" => { if speed < 0.5 { next.head.orientation = Quaternion::rotation_z(head_look.x) * Quaternion::rotation_x( diff --git a/voxygen/anim/src/golem/combomelee.rs b/voxygen/anim/src/golem/combomelee.rs index e69de29bb2..f7d7827d9b 100644 --- a/voxygen/anim/src/golem/combomelee.rs +++ b/voxygen/anim/src/golem/combomelee.rs @@ -0,0 +1,112 @@ +use super::{ + super::{vek::*, Animation}, + GolemSkeleton, SkeletonAttr, +}; +use common::states::utils::{AbilityInfo, StageSection}; + +pub struct ComboAnimation; +impl Animation for ComboAnimation { + type Dependency<'a> = ( + Option<&'a str>, + Option, + Option, + usize, + Vec2, + ); + type Skeleton = GolemSkeleton; + + #[cfg(feature = "use-dyn-lib")] + const UPDATE_FN: &'static [u8] = b"golem_combo\0"; + + #[cfg_attr(feature = "be-dyn-lib", export_name = "golem_combo")] + fn update_skeleton_inner( + skeleton: &Self::Skeleton, + (ability_id, stage_section, _ability_info, current_strike, _move_dir): Self::Dependency<'_>, + anim_time: f32, + rate: &mut f32, + _s_a: &SkeletonAttr, + ) -> Self::Skeleton { + *rate = 1.0; + let mut next = (*skeleton).clone(); + + let multi_strike_pullback = 1.0 + - if matches!(stage_section, Some(StageSection::Recover)) { + anim_time.powi(4) + } else { + 0.0 + }; + + for strike in 0..=current_strike { + let (move1, move2) = if strike == current_strike { + match stage_section { + Some(StageSection::Buildup) => { + (((anim_time.max(0.4) - 0.4) * 1.5).powf(0.5), 0.0) + }, + Some(StageSection::Action) => (1.0, (anim_time.min(0.4) * 2.5).powi(2)), + Some(StageSection::Recover) => (1.0, 1.0), + _ => (0.0, 0.0), + } + } else { + (1.0, 1.0) + }; + let move1 = move1 * multi_strike_pullback; + let move2 = move2 * multi_strike_pullback; + + match ability_id { + Some("common.abilities.custom.claygolem.dashstrike") => match strike { + 0..=2 => { + next.head.orientation = Quaternion::rotation_x(-0.2) + * Quaternion::rotation_z(move1 * -1.2 + move2 * 2.0); + + next.upper_torso.orientation = Quaternion::rotation_x(move1 * -0.6) + * Quaternion::rotation_z(move1 * 1.2 + move2 * -3.2); + + next.lower_torso.orientation = + Quaternion::rotation_z(move1 * -1.2 + move2 * 3.2) + * Quaternion::rotation_x(move1 * 0.6); + + next.shoulder_l.orientation = Quaternion::rotation_y(move1 * 0.8) + * Quaternion::rotation_x(move1 * -1.0 + move2 * 1.6); + + next.shoulder_r.orientation = Quaternion::rotation_x(move1 * 0.4); + + next.hand_l.orientation = Quaternion::rotation_z(0.0) + * Quaternion::rotation_x(move1 * -1.0 + move2 * 1.8); + + next.hand_r.orientation = Quaternion::rotation_y(move1 * 0.5) + * Quaternion::rotation_x(move1 * 0.4); + next.torso.position = Vec3::new(0.0, move1 * 3.7, -8.0 + move2 * 8.0); + }, + _ => {}, + }, + _ => match strike { + 0..=2 => { + next.head.orientation = Quaternion::rotation_x(-0.2) + * Quaternion::rotation_z(move1 * -1.2 + move2 * 2.0); + + next.upper_torso.orientation = Quaternion::rotation_x(move1 * -0.6) + * Quaternion::rotation_z(move1 * 1.2 + move2 * -3.2); + + next.lower_torso.orientation = + Quaternion::rotation_z(move1 * -1.2 + move2 * 3.2) + * Quaternion::rotation_x(move1 * 0.6); + + next.shoulder_l.orientation = Quaternion::rotation_y(move1 * 0.8) + * Quaternion::rotation_x(move1 * -1.0 + move2 * 1.6); + + next.shoulder_r.orientation = Quaternion::rotation_x(move1 * 0.4); + + next.hand_l.orientation = Quaternion::rotation_z(0.0) + * Quaternion::rotation_x(move1 * -1.0 + move2 * 1.8); + + next.hand_r.orientation = Quaternion::rotation_y(move1 * 0.5) + * Quaternion::rotation_x(move1 * 0.4); + next.torso.position = Vec3::new(0.0, move1 * 3.7, move1 * -1.6); + }, + _ => {}, + }, + } + } + next + } +} diff --git a/voxygen/anim/src/golem/mod.rs b/voxygen/anim/src/golem/mod.rs index f49520519e..7865bff60a 100644 --- a/voxygen/anim/src/golem/mod.rs +++ b/voxygen/anim/src/golem/mod.rs @@ -1,5 +1,6 @@ pub mod alpha; pub mod beam; +pub mod combomelee; pub mod idle; pub mod run; pub mod shockwave; @@ -7,8 +8,8 @@ pub mod shoot; // Reexports pub use self::{ - alpha::AlphaAnimation, beam::BeamAnimation, idle::IdleAnimation, run::RunAnimation, - shockwave::ShockwaveAnimation, shoot::ShootAnimation, + alpha::AlphaAnimation, beam::BeamAnimation, combomelee::ComboAnimation, idle::IdleAnimation, + run::RunAnimation, shockwave::ShockwaveAnimation, shoot::ShootAnimation, }; use super::{make_bone, vek::*, FigureBoneData, Offsets, Skeleton}; @@ -135,9 +136,11 @@ impl<'a> From<&'a Body> for SkeletonAttr { head: match (body.species, body.body_type) { (StoneGolem, _) => (0.0, 2.0), (Treant, _) => (18.0, -8.0), - (ClayGolem, _) => (-2.0, 7.0), + (ClayGolem, _) => (0.0, 7.0), (WoodGolem, _) => (3.0, 6.0), (CoralGolem, _) => (-1.0, 3.0), + (Gravewarden, _) => (-2.0, 7.0), + (AncientEffigy, _) => (-2.0, 8.0), }, jaw: match (body.species, body.body_type) { (StoneGolem, _) => (0.0, 0.0), @@ -145,48 +148,62 @@ impl<'a> From<&'a Body> for SkeletonAttr { (ClayGolem, _) => (0.0, 0.0), (WoodGolem, _) => (0.0, 0.0), (CoralGolem, _) => (0.0, 0.0), + (Gravewarden, _) => (0.0, 0.0), + (AncientEffigy, _) => (0.0, 0.0), }, upper_torso: match (body.species, body.body_type) { (StoneGolem, _) => (0.0, 34.5), (Treant, _) => (0.0, 28.5), - (ClayGolem, _) => (0.0, 26.5), + (ClayGolem, _) => (0.0, 23.0), (WoodGolem, _) => (0.0, 24.5), (CoralGolem, _) => (0.0, 25.0), + (Gravewarden, _) => (0.0, 26.5), + (AncientEffigy, _) => (0.0, 18.0), }, lower_torso: match (body.species, body.body_type) { (StoneGolem, _) => (0.0, -10.5), (Treant, _) => (0.0, -10.5), - (ClayGolem, _) => (0.0, -4.5), + (ClayGolem, _) => (0.0, -7.5), (WoodGolem, _) => (0.0, -4.5), (CoralGolem, _) => (0.0, -11.5), + (Gravewarden, _) => (0.0, -4.5), + (AncientEffigy, _) => (0.0, -4.5), }, shoulder: match (body.species, body.body_type) { (StoneGolem, _) => (8.0, -1.5, 4.0), (Treant, _) => (8.0, 4.5, -3.0), - (ClayGolem, _) => (8.0, 2.0, 3.0), + (ClayGolem, _) => (8.0, -1.0, -1.0), (WoodGolem, _) => (6.0, 2.0, 1.0), (CoralGolem, _) => (11.0, 1.0, 0.0), + (Gravewarden, _) => (8.0, 2.0, 3.0), + (AncientEffigy, _) => (8.0, 2.0, 3.0), }, hand: match (body.species, body.body_type) { (StoneGolem, _) => (12.5, -1.0, -7.0), (Treant, _) => (8.5, -1.0, -7.0), - (ClayGolem, _) => (8.5, -1.0, -7.0), + (ClayGolem, _) => (6.5, 0.0, -2.0), (WoodGolem, _) => (5.5, -1.0, -6.0), (CoralGolem, _) => (2.5, -1.5, -5.0), + (Gravewarden, _) => (8.5, -1.0, -7.0), + (AncientEffigy, _) => (8.5, -1.0, -7.0), }, leg: match (body.species, body.body_type) { (StoneGolem, _) => (4.0, 0.0, -3.5), (Treant, _) => (2.0, 9.5, -1.0), - (ClayGolem, _) => (1.0, 0.5, -6.0), + (ClayGolem, _) => (1.0, 0.0, -3.0), (WoodGolem, _) => (2.0, 0.5, -6.0), (CoralGolem, _) => (2.5, 0.5, -3.0), + (Gravewarden, _) => (1.0, 0.5, -6.0), + (AncientEffigy, _) => (1.0, 0.5, -6.0), }, foot: match (body.species, body.body_type) { (StoneGolem, _) => (3.5, 0.5, -9.5), (Treant, _) => (3.5, -5.0, -8.5), - (ClayGolem, _) => (3.5, -1.0, -8.5), + (ClayGolem, _) => (3.5, 0.0, -5.5), (WoodGolem, _) => (2.5, 1.0, -5.5), (CoralGolem, _) => (2.5, 1.0, -1.5), + (Gravewarden, _) => (3.5, -1.0, -8.5), + (AncientEffigy, _) => (3.5, -1.0, -8.5), }, scaler: match (body.species, body.body_type) { (StoneGolem, _) => 1.5, @@ -194,6 +211,8 @@ impl<'a> From<&'a Body> for SkeletonAttr { (ClayGolem, _) => 1.5, (WoodGolem, _) => 1.5, (CoralGolem, _) => 1.0, + (Gravewarden, _) => 1.5, + (AncientEffigy, _) => 1.0, }, tempo: match (body.species, body.body_type) { (StoneGolem, _) => 1.0, @@ -201,6 +220,8 @@ impl<'a> From<&'a Body> for SkeletonAttr { (ClayGolem, _) => 1.0, (WoodGolem, _) => 1.0, (CoralGolem, _) => 1.0, + (Gravewarden, _) => 1.0, + (AncientEffigy, _) => 1.0, }, } } diff --git a/voxygen/anim/src/golem/shoot.rs b/voxygen/anim/src/golem/shoot.rs index 018797ac30..11d15679fc 100644 --- a/voxygen/anim/src/golem/shoot.rs +++ b/voxygen/anim/src/golem/shoot.rs @@ -8,7 +8,7 @@ use core::f32::consts::PI; pub struct ShootAnimation; impl Animation for ShootAnimation { - 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")] @@ -18,7 +18,7 @@ impl Animation for ShootAnimation { 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, @@ -32,6 +32,11 @@ impl Animation for ShootAnimation { _ => (0.0, 0.0, 0.0), }; + // AncientEffigy shrink + if let Some("common.abilities.custom.ancienteffigy.blast") = ability_id { + next.upper_torso.scale = Vec3::one() * (1.0 - move1base); + } + let pullback = 1.0 - move3; let move1 = move1base * pullback; diff --git a/voxygen/anim/src/quadruped_medium/mod.rs b/voxygen/anim/src/quadruped_medium/mod.rs index 91b53198e4..f4332a8917 100644 --- a/voxygen/anim/src/quadruped_medium/mod.rs +++ b/voxygen/anim/src/quadruped_medium/mod.rs @@ -121,7 +121,7 @@ impl Skeleton for QuadrupedMediumSkeleton { Camel | Hirdrasil | Horse | Kelpie | Zebra => { Some((head_mat * Vec4::new(0.0, 2.0, 5.0, 1.0)).xyz()) }, - Darkhound | Llama | Snowleopard | Tiger | Wolf => { + Darkhound | Llama | Snowleopard | Tiger | Wolf | ClaySteed => { Some((head_mat * Vec4::new(0.0, 4.0, 1.0, 1.0)).xyz()) }, Dreadhorn | Mammoth | Moose | Tarasque => { @@ -240,6 +240,7 @@ impl<'a> From<&'a Body> for SkeletonAttr { (Alpaca, _) => (0.5, 7.5), (Akhlut, _) => (1.0, 3.5), (Bristleback, _) => (-3.0, -2.0), + (ClaySteed, _) => (-0.5, 6.0), }, neck: match (body.species, body.body_type) { (Grolgar, _) => (1.0, -1.0), @@ -280,6 +281,7 @@ impl<'a> From<&'a Body> for SkeletonAttr { (Alpaca, _) => (-1.5, 3.0), (Akhlut, _) => (8.5, -1.0), (Bristleback, _) => (6.0, 2.5), + (ClaySteed, _) => (1.5, 1.5), }, jaw: match (body.species, body.body_type) { (Grolgar, _) => (7.0, 2.0), @@ -321,6 +323,7 @@ impl<'a> From<&'a Body> for SkeletonAttr { (Alpaca, _) => (3.0, -2.5), (Akhlut, _) => (0.0, -4.5), (Bristleback, _) => (8.0, -6.0), + (ClaySteed, _) => (4.0, -1.0), }, tail: match (body.species, body.body_type) { (Grolgar, _) => (-11.5, -0.5), @@ -361,6 +364,7 @@ impl<'a> From<&'a Body> for SkeletonAttr { (Alpaca, _) => (-8.5, 3.5), (Akhlut, _) => (-14.0, -2.0), (Bristleback, _) => (-7.0, -5.5), + (ClaySteed, _) => (-11.0, 4.0), }, torso_front: match (body.species, body.body_type) { (Grolgar, _) => (10.0, 13.0), @@ -401,6 +405,7 @@ impl<'a> From<&'a Body> for SkeletonAttr { (Alpaca, _) => (7.0, 11.5), (Akhlut, _) => (5.5, 14.5), (Bristleback, _) => (1.5, 9.0), + (ClaySteed, _) => (7.0, 15.0), }, torso_back: match (body.species, body.body_type) { (Grolgar, _) => (-10.0, 1.5), @@ -441,6 +446,7 @@ impl<'a> From<&'a Body> for SkeletonAttr { (Alpaca, _) => (-6.0, 0.0), (Akhlut, _) => (-7.0, 1.0), (Bristleback, _) => (-4.0, 2.0), + (ClaySteed, _) => (-6.0, 0.0), }, ears: match (body.species, body.body_type) { (Grolgar, _) => (5.0, 8.0), @@ -482,6 +488,7 @@ impl<'a> From<&'a Body> for SkeletonAttr { (Alpaca, _) => (1.0, 2.0), (Akhlut, _) => (12.0, -3.0), (Bristleback, _) => (6.0, 1.0), + (ClaySteed, _) => (1.0, 3.5), }, leg_f: match (body.species, body.body_type) { (Grolgar, _) => (7.5, -5.5, -1.0), @@ -522,6 +529,7 @@ impl<'a> From<&'a Body> for SkeletonAttr { (Alpaca, _) => (3.5, -2.5, -0.5), (Akhlut, _) => (8.0, -2.0, 0.5), (Bristleback, _) => (6.0, 1.0, -2.0), + (ClaySteed, _) => (4.0, -1.5, -2.0), }, leg_b: match (body.species, body.body_type) { (Grolgar, _) => (6.0, -6.5, -4.0), @@ -562,6 +570,7 @@ impl<'a> From<&'a Body> for SkeletonAttr { (Alpaca, _) => (3.5, -7.0, 0.0), (Akhlut, _) => (6.0, -7.5, -2.0), (Bristleback, _) => (4.5, -3.0, -2.0), + (ClaySteed, _) => (4.5, -8.0, -3.0), }, feet_f: match (body.species, body.body_type) { (Grolgar, _) => (0.0, 0.0, -4.0), @@ -602,6 +611,7 @@ impl<'a> From<&'a Body> for SkeletonAttr { (Alpaca, _) => (0.0, -0.5, -5.0), (Akhlut, _) => (0.0, 0.0, -5.0), (Bristleback, _) => (0.0, -0.5, -2.0), + (ClaySteed, _) => (-0.5, 0.0, -6.0), }, feet_b: match (body.species, body.body_type) { (Grolgar, _) => (0.5, -1.5, -3.0), @@ -642,6 +652,7 @@ impl<'a> From<&'a Body> for SkeletonAttr { (Alpaca, _) => (-0.5, -0.5, -5.5), (Akhlut, _) => (1.5, -1.0, -4.5), (Bristleback, _) => (-0.5, 0.0, -4.0), + (ClaySteed, _) => (0.0, -0.5, -4.0), }, scaler: match (body.species, body.body_type) { (Grolgar, _) => 1.05, @@ -671,6 +682,7 @@ impl<'a> From<&'a Body> for SkeletonAttr { (Ngoubou, _) => 1.0, (Akhlut, _) => 1.4, (Bristleback, _) => 1.1, + (ClaySteed, _) => 1.75, _ => 0.9, }, startangle: match (body.species, body.body_type) { @@ -794,6 +806,7 @@ fn mount_point(body: &Body) -> Vec3 { (Alpaca, _) => (0.0, -9.0, 0.0), (Akhlut, _) => (0.0, -6.0, 1.0), (Bristleback, _) => (0.0, -9.0, 3.0), + (ClaySteed, _) => (0.0, -6.0, 2.0), } .into() } diff --git a/voxygen/src/audio/sfx/mod.rs b/voxygen/src/audio/sfx/mod.rs index 16837b570a..310f7b5824 100644 --- a/voxygen/src/audio/sfx/mod.rs +++ b/voxygen/src/audio/sfx/mod.rs @@ -168,6 +168,7 @@ pub enum SfxEvent { CyclopsCharge, LaserBeam, Steam, + FuseCharge, Music(ToolKind, AbilitySpec), Yeet, Klonk, @@ -456,7 +457,7 @@ impl SfxMgr { audio.emit_ui_sfx(sfx_trigger_item, Some((power * 3.0).min(2.9))); } }, - Outcome::GroundSlam { pos, .. } => { + Outcome::GroundSlam { pos, .. } | Outcome::ClayGolemDash { pos, .. } => { let sfx_trigger_item = triggers.get_key_value(&SfxEvent::GroundSlam); audio.emit_sfx(sfx_trigger_item, *pos, Some(2.0), underwater); }, @@ -472,6 +473,10 @@ impl SfxMgr { let sfx_trigger_item = triggers.get_key_value(&SfxEvent::CyclopsCharge); audio.emit_sfx(sfx_trigger_item, *pos, Some(2.0), underwater); }, + Outcome::FuseCharge { pos, .. } => { + let sfx_trigger_item = triggers.get_key_value(&SfxEvent::FuseCharge); + audio.emit_sfx(sfx_trigger_item, *pos, Some(2.0), underwater); + }, Outcome::FlashFreeze { pos, .. } => { let sfx_trigger_item = triggers.get_key_value(&SfxEvent::FlashFreeze); audio.emit_sfx(sfx_trigger_item, *pos, Some(2.0), underwater); @@ -541,6 +546,7 @@ impl SfxMgr { | object::Body::MultiArrow | object::Body::ArrowSnake | object::Body::ArrowTurret + | object::Body::ArrowClay | object::Body::SpectralSwordSmall | object::Body::SpectralSwordLarge, ) => { @@ -553,6 +559,7 @@ impl SfxMgr { | object::Body::BoltNature | object::Body::BoltIcicle | object::Body::SpearIcicle + | object::Body::GrenadeClay | object::Body::SpitPoison, ) => { let sfx_trigger_item = triggers.get_key_value(&SfxEvent::FireShot); @@ -584,6 +591,7 @@ impl SfxMgr { | object::Body::MultiArrow | object::Body::ArrowSnake | object::Body::ArrowTurret + | object::Body::ArrowClay | object::Body::SpectralSwordSmall | object::Body::SpectralSwordLarge, ) => { @@ -651,7 +659,7 @@ impl SfxMgr { audio.emit_sfx(sfx_trigger_item, *pos, None, underwater); } }, - beam::FrontendSpecifier::ClayGolem | beam::FrontendSpecifier::WebStrand => {}, + beam::FrontendSpecifier::Gravewarden | beam::FrontendSpecifier::WebStrand => {}, }, Outcome::SpriteUnlocked { pos } => { // TODO: Dedicated sound effect! @@ -786,6 +794,15 @@ impl SfxMgr { underwater, ); }, + Outcome::Slash { pos, .. } => { + let sfx_trigger_item = triggers.get_key_value(&SfxEvent::SmashKlonk); + audio.emit_sfx( + sfx_trigger_item, + pos.map(|e| e + 0.5), + Some(3.0), + underwater, + ); + }, Outcome::ExpChange { .. } | Outcome::ComboChange { .. } => {}, } } diff --git a/voxygen/src/hud/img_ids.rs b/voxygen/src/hud/img_ids.rs index 13a99e3483..738faa5017 100644 --- a/voxygen/src/hud/img_ids.rs +++ b/voxygen/src/hud/img_ids.rs @@ -559,6 +559,9 @@ image_ids! { mmap_site_adlet: "voxygen.element.ui.map.buttons.adlet", mmap_site_adlet_hover: "voxygen.element.ui.map.buttons.adlet_hover", mmap_site_adlet_bg: "voxygen.element.ui.map.buttons.adlet_bg", + mmap_site_haniwa: "voxygen.element.ui.map.buttons.haniwa", + mmap_site_haniwa_hover: "voxygen.element.ui.map.buttons.haniwa_hover", + mmap_site_haniwa_bg: "voxygen.element.ui.map.buttons.haniwa_bg", mmap_site_minotaur: "voxygen.element.ui.map.buttons.minotaur", mmap_site_minotaur_hover: "voxygen.element.ui.map.buttons.minotaur_hover", mmap_site_minotaur_bg: "voxygen.element.ui.map.buttons.minotaur_bg", diff --git a/voxygen/src/hud/map.rs b/voxygen/src/hud/map.rs index 40f5bbc08e..e9cbe267e4 100644 --- a/voxygen/src/hud/map.rs +++ b/voxygen/src/hud/map.rs @@ -925,6 +925,7 @@ impl<'a> Widget for Map<'a> { SiteKind::ChapelSite => i18n.get_msg("hud-map-chapel_Site"), SiteKind::Bridge => i18n.get_msg("hud-map-bridge"), SiteKind::Adlet => i18n.get_msg("hud-map-adlet"), + SiteKind::Haniwa => i18n.get_msg("hud-map-haniwa"), SiteKind::DwarvenMine => i18n.get_msg("hud-map-df_mine"), }); let (difficulty, desc) = match &site.kind { @@ -950,9 +951,10 @@ 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::ChapelSite => (Some(3), i18n.get_msg("hud-map-chapel_site")), + 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")), + SiteKind::Haniwa => (Some(3), i18n.get_msg("hud-map-haniwa")), SiteKind::DwarvenMine => (Some(5), i18n.get_msg("hud-map-df_mine")), }; let desc = desc.into_owned() + &get_site_economy(site_rich); @@ -964,6 +966,7 @@ impl<'a> Widget for Map<'a> { SiteKind::Tree => self.imgs.mmap_site_tree, SiteKind::Gnarling => self.imgs.mmap_site_gnarling, SiteKind::Adlet => self.imgs.mmap_site_adlet, + SiteKind::Haniwa => self.imgs.mmap_site_haniwa, SiteKind::DwarvenMine => self.imgs.mmap_site_mine, SiteKind::Dungeon { difficulty } => match difficulty { 4 => self.imgs.mmap_site_minotaur, @@ -986,6 +989,7 @@ impl<'a> Widget for Map<'a> { SiteKind::Tree => self.imgs.mmap_site_tree_hover, SiteKind::Gnarling => self.imgs.mmap_site_gnarling_hover, SiteKind::Adlet => self.imgs.mmap_site_adlet_hover, + SiteKind::Haniwa => self.imgs.mmap_site_haniwa_hover, SiteKind::DwarvenMine => self.imgs.mmap_site_mine_hover, SiteKind::Dungeon { difficulty } => match difficulty { 4 => self.imgs.mmap_site_minotaur_hover, @@ -1005,6 +1009,7 @@ impl<'a> Widget for Map<'a> { | SiteKind::Gnarling | SiteKind::ChapelSite | SiteKind::Adlet + | SiteKind::Haniwa | SiteKind::DwarvenMine => match difficulty { Some(0) => QUALITY_LOW, Some(1) => QUALITY_COMMON, @@ -1032,6 +1037,7 @@ impl<'a> Widget for Map<'a> { | SiteKind::Gnarling | SiteKind::ChapelSite | SiteKind::DwarvenMine + | SiteKind::Haniwa | SiteKind::Adlet => show_dungeons, SiteKind::Castle => show_castles, SiteKind::Cave => show_caves, @@ -1092,6 +1098,7 @@ impl<'a> Widget for Map<'a> { SiteKind::Dungeon { .. } | SiteKind::Gnarling | SiteKind::ChapelSite + | SiteKind::Haniwa | 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 6120951bc9..1ccc45af85 100644 --- a/voxygen/src/hud/minimap.rs +++ b/voxygen/src/hud/minimap.rs @@ -694,7 +694,7 @@ impl<'a> Widget for MiniMap<'a> { }; let difficulty = match &site.kind { SiteKind::Town => None, - SiteKind::ChapelSite => Some(0), + SiteKind::ChapelSite => Some(4), SiteKind::Dungeon { difficulty } => Some(*difficulty), SiteKind::Castle => None, SiteKind::Cave => None, @@ -702,6 +702,7 @@ impl<'a> Widget for MiniMap<'a> { SiteKind::Gnarling => Some(0), SiteKind::Bridge => None, SiteKind::Adlet => Some(1), + SiteKind::Haniwa => Some(3), SiteKind::DwarvenMine => Some(5), }; @@ -715,6 +716,7 @@ impl<'a> Widget for MiniMap<'a> { SiteKind::Gnarling => self.imgs.mmap_site_gnarling_bg, SiteKind::Bridge => self.imgs.mmap_site_bridge_bg, SiteKind::Adlet => self.imgs.mmap_site_adlet_bg, + SiteKind::Haniwa => self.imgs.mmap_site_haniwa_bg, SiteKind::DwarvenMine => self.imgs.mmap_site_mine_bg, }) .x_y_position_relative_to( @@ -743,6 +745,7 @@ impl<'a> Widget for MiniMap<'a> { SiteKind::Gnarling => self.imgs.mmap_site_gnarling, SiteKind::Bridge => self.imgs.mmap_site_bridge, SiteKind::Adlet => self.imgs.mmap_site_adlet, + SiteKind::Haniwa => self.imgs.mmap_site_haniwa, SiteKind::DwarvenMine => self.imgs.mmap_site_mine, }) .middle_of(state.ids.mmap_site_icons_bgs[i]) diff --git a/voxygen/src/hud/util.rs b/voxygen/src/hud/util.rs index 7b3eae7894..5892c11041 100644 --- a/voxygen/src/hud/util.rs +++ b/voxygen/src/hud/util.rs @@ -588,6 +588,8 @@ 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.shamisen" => imgs.instrument, _ => imgs.not_found, } } diff --git a/voxygen/src/render/pipelines/particle.rs b/voxygen/src/render/pipelines/particle.rs index ee80e61dc2..f8d8d0242e 100644 --- a/voxygen/src/render/pipelines/particle.rs +++ b/voxygen/src/render/pipelines/particle.rs @@ -109,6 +109,7 @@ pub enum ParticleMode { EnergyPhoenix = 55, PhoenixBeam = 56, PhoenixBuildUpAim = 57, + ClayShrapnel = 58, } impl ParticleMode { diff --git a/voxygen/src/scene/figure/mod.rs b/voxygen/src/scene/figure/mod.rs index 954370c1ee..5060cf6bcc 100644 --- a/voxygen/src/scene/figure/mod.rs +++ b/voxygen/src/scene/figure/mod.rs @@ -4042,6 +4042,76 @@ impl FigureMgr { skeleton_attr, ) }, + CharacterState::BasicBlock(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, + StageSection::Recover => { + stage_time / s.static_data.recover_duration.as_secs_f32() + }, + _ => 0.0, + }; + anim::biped_small::BlockAnimation::update_skeleton( + &target_base, + (ability_id, s.stage_section), + stage_progress, + &mut state_animation_rate, + skeleton_attr, + ) + }, + CharacterState::RapidMelee(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.swing_duration.as_secs_f32() + }, + StageSection::Recover => { + stage_time / s.static_data.recover_duration.as_secs_f32() + }, + _ => 0.0, + }; + + anim::biped_small::RapidMeleeAnimation::update_skeleton( + &target_base, + ( + ability_id, + s.stage_section, + (s.current_strike, s.static_data.max_strikes), + ), + stage_progress, + &mut state_animation_rate, + skeleton_attr, + ) + }, + CharacterState::RiposteMelee(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.swing_duration.as_secs_f32() + }, + StageSection::Recover => { + stage_time / s.static_data.recover_duration.as_secs_f32() + }, + _ => 0.0, + }; + + anim::biped_small::RiposteMeleeAnimation::update_skeleton( + &target_base, + (ability_id, s.stage_section), + stage_progress, + &mut state_animation_rate, + skeleton_attr, + ) + }, // TODO! _ => target_base, }; @@ -6005,7 +6075,13 @@ impl FigureMgr { anim::golem::ShootAnimation::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, @@ -6057,6 +6133,37 @@ impl FigureMgr { skeleton_attr, ) }, + CharacterState::ComboMelee2(s) => { + let timer = s.timer.as_secs_f32(); + let current_strike = s.completed_strikes % s.static_data.strikes.len(); + let strike_data = s.static_data.strikes[current_strike]; + let progress = match s.stage_section { + StageSection::Buildup => { + timer / strike_data.buildup_duration.as_secs_f32() + }, + StageSection::Action => { + timer / strike_data.swing_duration.as_secs_f32() + }, + StageSection::Recover => { + timer / strike_data.recover_duration.as_secs_f32() + }, + _ => 0.0, + }; + + anim::golem::ComboAnimation::update_skeleton( + &target_base, + ( + ability_id, + Some(s.stage_section), + Some(s.static_data.ability_info), + current_strike, + move_dir, + ), + progress, + &mut state_animation_rate, + skeleton_attr, + ) + }, CharacterState::Shockwave(s) => { let stage_time = s.timer.as_secs_f32(); let stage_progress = match s.stage_section { diff --git a/voxygen/src/scene/particle.rs b/voxygen/src/scene/particle.rs index 16ff4e9a9a..631786e043 100644 --- a/voxygen/src/scene/particle.rs +++ b/voxygen/src/scene/particle.rs @@ -386,7 +386,7 @@ impl ParticleMgr { *pos + Vec3::new(0.0, 0.0, 5.6 + 0.5 * rng.gen_range(0.0..0.2)), )); }, - Outcome::FlamethrowerCharge { pos } => { + Outcome::FlamethrowerCharge { pos } | Outcome::FuseCharge { pos } => { self.particles.push(Particle::new_directed( Duration::from_secs_f32(rng.gen_range(0.1..0.2)), time, @@ -433,6 +433,16 @@ impl ParticleMgr { ) }); }, + Outcome::ClayGolemDash { pos, .. } => { + self.particles.resize_with(self.particles.len() + 100, || { + Particle::new( + Duration::from_millis(1000), + time, + ParticleMode::ClayShrapnel, + *pos, + ) + }); + }, Outcome::ProjectileShot { .. } | Outcome::Beam { .. } | Outcome::ExpChange { .. } @@ -446,6 +456,7 @@ impl ParticleMgr { | Outcome::Glider { .. } | Outcome::Whoosh { .. } | Outcome::Swoosh { .. } + | Outcome::Slash { .. } | Outcome::Steam { .. } | Outcome::FireShockwave { .. } | Outcome::PortalActivated { .. } @@ -1411,13 +1422,13 @@ impl ParticleMgr { )); } }, - beam::FrontendSpecifier::ClayGolem => { + beam::FrontendSpecifier::Gravewarden => { self.particles.resize_with(self.particles.len() + 2, || { Particle::new_directed( Duration::from_secs_f64(beam.duration.0), time, ParticleMode::Laser, - beam.bezier.start, + beam.bezier.start + beam_dir * 1.5, beam.bezier.start + beam_dir * beam.range, ) }) diff --git a/voxygen/src/scene/trail.rs b/voxygen/src/scene/trail.rs index 67b5f3c74b..88ada76d37 100644 --- a/voxygen/src/scene/trail.rs +++ b/voxygen/src/scene/trail.rs @@ -56,7 +56,8 @@ impl TrailMgr { object::Body::Arrow | object::Body::MultiArrow | object::Body::ArrowSnake - | object::Body::ArrowTurret, + | object::Body::ArrowTurret + | object::Body::ArrowClay, ) ) { diff --git a/world/src/block/mod.rs b/world/src/block/mod.rs index 2810843f95..a2cc6bf85c 100644 --- a/world/src/block/mod.rs +++ b/world/src/block/mod.rs @@ -371,6 +371,17 @@ pub fn block_from_structure( }), )); }, + StructureBlock::HaniwaKeyhole(consumes) => { + return Some(( + Block::air(SpriteKind::HaniwaKeyhole), + Some(SpriteCfg { + unlock: Some(UnlockKind::Consumes(ItemDefinitionIdOwned::Simple( + consumes.clone(), + ))), + ..SpriteCfg::default() + }), + )); + }, StructureBlock::KeyholeBars(consumes) => { return Some(( Block::air(SpriteKind::KeyholeBars), diff --git a/world/src/civ/mod.rs b/world/src/civ/mod.rs index 31567ed27b..372726cfd2 100644 --- a/world/src/civ/mod.rs +++ b/world/src/civ/mod.rs @@ -384,7 +384,17 @@ impl Civs { )?, SiteKind::Camp, ), - /*70..=75 => ( + 70..=74 => ( + find_site_loc( + &mut ctx, + &ProximityRequirementsBuilder::new() + .avoid_all_of(this.mine_site_enemies(), 40) + .finalize(&world_dims), + &SiteKind::Haniwa, + )?, + SiteKind::Haniwa, + ), + /*75..=80 => ( find_site_loc( &mut ctx, &ProximityRequirementsBuilder::new() @@ -394,7 +404,7 @@ impl Civs { )?, SiteKind::DwarvenMine, ), - 76..=81 => ( + 81..=86 => ( find_site_loc( &mut ctx, &ProximityRequirementsBuilder::new() @@ -405,7 +415,7 @@ impl Civs { )?, SiteKind::Castle, ), - 82..=87 => (SiteKind::Citadel, (&castle_enemies, 20)), + 87..=92 => (SiteKind::Citadel, (&castle_enemies, 20)), */ _ => ( find_site_loc( @@ -453,6 +463,7 @@ impl Civs { SiteKind::Citadel => (16i32, 0.0), SiteKind::Bridge(_, _) => (0, 0.0), SiteKind::Adlet => (16i32, 0.0), + SiteKind::Haniwa => (32i32, 16.0), SiteKind::PirateHideout => (8i32, 3.0), SiteKind::RockCircle => (8i32, 3.0), SiteKind::TrollCave => (4i32, 1.5), @@ -633,6 +644,11 @@ impl Civs { wpos, index_ref, )), + SiteKind::Haniwa => WorldSite::haniwa(site2::Site::generate_haniwa( + &Land::from_sim(ctx.sim), + &mut rng, + wpos, + )), } }); sim_site.site_tmp = Some(site); @@ -1492,6 +1508,13 @@ impl Civs { }) } + fn haniwa_enemies(&self) -> impl Iterator> + '_ { + self.sites().filter_map(|s| match s.kind { + SiteKind::Tree | SiteKind::GiantTree => None, + _ => Some(s.center), + }) + } + fn chapel_site_enemies(&self) -> impl Iterator> + '_ { self.sites().filter_map(|s| match s.kind { SiteKind::Tree | SiteKind::GiantTree => None, @@ -1916,6 +1939,7 @@ pub enum SiteKind { Citadel, Bridge(Vec2, Vec2), Adlet, + Haniwa, PirateHideout, RockCircle, TrollCave, @@ -1972,6 +1996,11 @@ impl SiteKind { && !chunk.river.near_water() && on_flat_terrain() },*/ + SiteKind::Haniwa => { + on_land() + && on_flat_terrain() + && (-0.3..0.4).contains(&chunk.temp) + }, SiteKind::GiantTree | SiteKind::Tree => { on_land() && on_flat_terrain() diff --git a/world/src/lib.rs b/world/src/lib.rs index 02a4565a65..a5f5ad3f22 100644 --- a/world/src/lib.rs +++ b/world/src/lib.rs @@ -216,6 +216,7 @@ impl World { civ::SiteKind::Citadel => world_msg::SiteKind::Castle, civ::SiteKind::Bridge(_, _) => world_msg::SiteKind::Bridge, civ::SiteKind::Adlet => world_msg::SiteKind::Adlet, + civ::SiteKind::Haniwa => world_msg::SiteKind::Haniwa, }, wpos: site.center * TerrainChunkSize::RECT_SIZE.map(|e| e as i32), } diff --git a/world/src/site/economy/context.rs b/world/src/site/economy/context.rs index 68e74966e2..79ede3dd65 100644 --- a/world/src/site/economy/context.rs +++ b/world/src/site/economy/context.rs @@ -131,6 +131,7 @@ impl Environment { SiteKind::GiantTree(_) => (), SiteKind::Gnarling(_) => {}, SiteKind::Adlet(_) => {}, + SiteKind::Haniwa(_) => {}, SiteKind::JungleRuin(_) => {}, SiteKind::ChapelSite(_) => {}, SiteKind::DwarvenMine(_) => {}, diff --git a/world/src/site/mod.rs b/world/src/site/mod.rs index c16ddf5143..68544822f2 100644 --- a/world/src/site/mod.rs +++ b/world/src/site/mod.rs @@ -77,6 +77,7 @@ pub enum SiteKind { Gnarling(site2::Site), Bridge(site2::Site), Adlet(site2::Site), + Haniwa(site2::Site), PirateHideout(site2::Site), JungleRuin(site2::Site), RockCircle(site2::Site), @@ -113,6 +114,13 @@ impl Site { } } + pub fn haniwa(ha: site2::Site) -> Self { + Self { + kind: SiteKind::Haniwa(ha), + economy: Economy::default(), + } + } + pub fn castle(c: Castle) -> Self { Self { kind: SiteKind::Castle(c), @@ -247,6 +255,7 @@ impl Site { SiteKind::Gnarling(g) => g.radius(), SiteKind::Bridge(b) => b.radius(), SiteKind::Adlet(ad) => ad.radius(), + SiteKind::Haniwa(ha) => ha.radius(), } } @@ -272,6 +281,7 @@ impl Site { SiteKind::Gnarling(g) => g.origin, SiteKind::Bridge(b) => b.origin, SiteKind::Adlet(ad) => ad.origin, + SiteKind::Haniwa(ha) => ha.origin, } } @@ -297,6 +307,7 @@ impl Site { SiteKind::Gnarling(g) => g.spawn_rules(wpos), SiteKind::Bridge(b) => b.spawn_rules(wpos), SiteKind::Adlet(ad) => ad.spawn_rules(wpos), + SiteKind::Haniwa(ha) => ha.spawn_rules(wpos), } } @@ -322,6 +333,7 @@ impl Site { SiteKind::Gnarling(g) => g.name(), SiteKind::Bridge(b) => b.name(), SiteKind::Adlet(ad) => ad.name(), + SiteKind::Haniwa(ha) => ha.name(), } } @@ -367,6 +379,7 @@ impl Site { SiteKind::Gnarling(g) => g.render(canvas, dynamic_rng), SiteKind::Bridge(b) => b.render(canvas, dynamic_rng), SiteKind::Adlet(ad) => ad.render(canvas, dynamic_rng), + SiteKind::Haniwa(ha) => ha.render(canvas, dynamic_rng), } } @@ -406,6 +419,7 @@ impl Site { SiteKind::Gnarling(g) => g.apply_supplement(dynamic_rng, wpos2d, supplement), SiteKind::Bridge(b) => b.apply_supplement(dynamic_rng, wpos2d, supplement), SiteKind::Adlet(ad) => ad.apply_supplement(dynamic_rng, wpos2d, supplement), + SiteKind::Haniwa(ha) => ha.apply_supplement(dynamic_rng, wpos2d, supplement), } } @@ -445,6 +459,7 @@ impl Site { SiteKind::Gnarling(site2) => Some(site2), SiteKind::Bridge(site2) => Some(site2), SiteKind::Adlet(site2) => Some(site2), + SiteKind::Haniwa(site2) => Some(site2), } } } diff --git a/world/src/site/namegen.rs b/world/src/site/namegen.rs index b1911fdbe4..59a5cdfd23 100644 --- a/world/src/site/namegen.rs +++ b/world/src/site/namegen.rs @@ -553,7 +553,9 @@ impl<'a, R: Rng> NameGen<'a, R> { let mut name = String::new(); name += start.choose(self.rng).unwrap(); for _ in 0..self.approx_syllables.saturating_sub(2) { - name += vowel.choose(self.rng).unwrap(); + if !vowel.is_empty() { + name += vowel.choose(self.rng).unwrap() + }; name += middle.choose(self.rng).unwrap(); } name += end.choose(self.rng).unwrap(); @@ -666,6 +668,39 @@ impl<'a, R: Rng> NameGen<'a, R> { self.generate_theme_from_parts(&start, &middle, &vowel, &end) } + // japanese inspired location names for haniwa + pub fn generate_haniwa(&mut self) -> String { + let start = [ + "a", "e", "o", "i", "u", "ka", "ki", "ku", "ke", "ko", "sa", "shi", "su", "se", "so", + "ta", "chi", "tsu", "te", "to", "na", "ne", "no", "ni", "nu", "ha", "hi", "fu", "he", + "ho", "ma", "mi", "mu", "me", "mo", "ra", "ri", "ru", "re", "ro", "wa", "ya", "yu", + "yo", "ga", "gi", "gu", "ge", "go", "za", "ji", "zu", "ze", "zo", "da", "de", "do", + "jo", "ju", "ja", "sho", "shu", "sha", "kya", "kyu", "kyo", "gya", "gyu", "gyo", "ba", + "bi", "bu", "be", "bo", "hya", "hyo", "ryu", "ryo", + ]; + let vowel = []; + let middle = [ + "a", "e", "o", "i", "u", "ka", "ki", "ku", "ke", "ko", "sa", "shi", "su", "se", "so", + "ta", "chi", "tsu", "te", "to", "na", "ne", "no", "ni", "nu", "ha", "hi", "fu", "he", + "ho", "ma", "mi", "mu", "me", "mo", "ra", "ri", "ru", "re", "ro", "wa", "ya", "yu", + "yo", "ga", "gi", "gu", "ge", "go", "za", "ji", "zu", "ze", "zo", "da", "de", "do", + "n", "jo", "ju", "ja", "sho", "shu", "sha", "pa", "pi", "pu", "pe", "po", + ]; + let end = [ + "maru", "mura", "machi", "yama", "da", "do", "don", "den", "fun", "taro", "dachi", + "mon", "ta", "yo", "chi", "poko", "gami", "ji", "guchi", "gachi", "goku", "gasha", + "do", "to", "saka", "zaru", "nami", "numa", "kichi", "juro", "jo", "keshi", "gara", + "goro", "tatsu", "tetsu", "niwa", "mo", "no", "nojo", "hachi", "ichi", "san", "saki", + "shima", "tsuchi", "gumo", "toko", "zuchi", "shi", "shiro", "jiro", "sho", "shu", + "tsu", "hara", "hama", "naga", "kan", "ken", "hage", "tai", "gyo", "kyo", "zo", "gu", + "zaki", "dai", "moto", "me", "saki", "kami", "gata", "date", "kawa", "gawa", "garu", + "tami", "yoro", "hiro", "ki", "kai", "gato", "mizu", "gin", "gon", "ppu", "matsu", + "yake", "koku", "miya", "zawa", "sen", "shiro", "kuro", "ppo", "kata", "riku", "sha", + "ishi", "yoko", "su", "gi", "ko", "hagi", "wa", + ]; + 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 d8bac19dae..81a5fdcff0 100644 --- a/world/src/site2/mod.rs +++ b/world/src/site2/mod.rs @@ -107,7 +107,9 @@ impl Site { .filter_map(|plot| match &plot.kind { PlotKind::Dungeon(d) => Some(d.spawn_rules(wpos)), PlotKind::Gnarling(g) => Some(g.spawn_rules(wpos)), - PlotKind::Adlet(a) => Some(a.spawn_rules(wpos)), + 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::DwarvenMine(m) => Some(m.spawn_rules(wpos)), _ => None, }) @@ -1356,6 +1358,54 @@ impl Site { site } + pub fn generate_haniwa(land: &Land, rng: &mut impl Rng, origin: Vec2) -> Self { + let mut rng = reseed(rng); + let mut site = Site { + origin, + name: format!( + "{} {}", + NameGen::location(&mut rng).generate_haniwa(), + [ + "Catacombs", + "Crypt", + "Tomb", + "Gravemound", + "Tunnels", + "Vault", + "Chambers", + "Halls", + "Tumulus", + "Barrow", + ] + .choose(&mut rng) + .unwrap() + ), + ..Site::default() + }; + let size = 24.0 as i32; + let aabr = Aabr { + min: Vec2::broadcast(-size), + max: Vec2::broadcast(size), + }; + { + let haniwa = plot::Haniwa::generate(land, &mut reseed(&mut rng), &site, aabr); + let haniwa_alt = haniwa.alt; + let plot = site.create_plot(Plot { + kind: PlotKind::Haniwa(haniwa), + 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(haniwa_alt), + }); + } + site + } + pub fn generate_chapel_site(land: &Land, rng: &mut impl Rng, origin: Vec2) -> Self { let mut rng = reseed(rng); let mut site = Site { @@ -1886,6 +1936,7 @@ impl Site { PlotKind::Dungeon(dungeon) => dungeon.render_collect(self, canvas), PlotKind::Gnarling(gnarling) => gnarling.render_collect(self, canvas), PlotKind::Adlet(adlet) => adlet.render_collect(self, canvas), + PlotKind::Haniwa(haniwa) => haniwa.render_collect(self, canvas), PlotKind::GiantTree(giant_tree) => giant_tree.render_collect(self, canvas), PlotKind::CliffTower(cliff_tower) => cliff_tower.render_collect(self, canvas), PlotKind::SavannahPit(savannah_pit) => savannah_pit.render_collect(self, canvas), diff --git a/world/src/site2/plot.rs b/world/src/site2/plot.rs index ccb9118aff..236a333130 100644 --- a/world/src/site2/plot.rs +++ b/world/src/site2/plot.rs @@ -14,6 +14,7 @@ pub mod dungeon; mod dwarven_mine; mod giant_tree; mod gnarling; +mod haniwa; mod house; mod jungle_ruin; mod pirate_hideout; @@ -32,7 +33,7 @@ pub use self::{ coastal_workshop::CoastalWorkshop, desert_city_arena::DesertCityArena, desert_city_multiplot::DesertCityMultiPlot, desert_city_temple::DesertCityTemple, dungeon::Dungeon, dwarven_mine::DwarvenMine, giant_tree::GiantTree, - gnarling::GnarlingFortification, house::House, jungle_ruin::JungleRuin, + 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, @@ -93,6 +94,7 @@ pub enum PlotKind { Dungeon(Dungeon), Gnarling(GnarlingFortification), Adlet(AdletStronghold), + Haniwa(Haniwa), GiantTree(GiantTree), CliffTower(CliffTower), Citadel(Citadel), diff --git a/world/src/site2/plot/dungeon.rs b/world/src/site2/plot/dungeon.rs index 49f04c8520..7a98692d65 100644 --- a/world/src/site2/plot/dungeon.rs +++ b/world/src/site2/plot/dungeon.rs @@ -230,7 +230,6 @@ impl Room { if tile_pos == enemy_spawn_tile && wpos2d == tile_wcenter.xy() { let entities = match self.difficulty { 2 => enemy_2(dynamic_rng, tile_wcenter), - 3 => enemy_3(dynamic_rng, tile_wcenter), 4 => enemy_4(dynamic_rng, tile_wcenter), 5 => enemy_5(dynamic_rng, tile_wcenter), _ => enemy_fallback(dynamic_rng, tile_wcenter), @@ -252,16 +251,9 @@ impl Room { - 16 }) .map(|e| e as f32 / 16.0); - match self.difficulty { - 3 => { - let turret = turret_3(dynamic_rng, pos); - supplement.add_entity(turret); - }, - 5 => { - let turret = turret_5(dynamic_rng, pos); - supplement.add_entity(turret); - }, - _ => {}, + if self.difficulty == 5 { + let turret = turret_5(dynamic_rng, pos); + supplement.add_entity(turret); }; } } @@ -287,7 +279,6 @@ impl Room { if tile_pos == miniboss_spawn_tile && tile_wcenter.xy() == wpos2d { let entities = match self.difficulty { 2 => mini_boss_2(dynamic_rng, tile_wcenter), - 3 => mini_boss_3(dynamic_rng, tile_wcenter), 4 => mini_boss_4(dynamic_rng, tile_wcenter), 5 => mini_boss_5(dynamic_rng, tile_wcenter), _ => mini_boss_fallback(dynamic_rng, tile_wcenter), @@ -319,7 +310,6 @@ impl Room { if tile_pos == boss_spawn_tile && wpos2d == tile_wcenter.xy() { let entities = match self.difficulty { 2 => boss_2(dynamic_rng, tile_wcenter), - 3 => boss_3(dynamic_rng, tile_wcenter), 4 => boss_4(dynamic_rng, tile_wcenter), 5 => boss_5(dynamic_rng, tile_wcenter), _ => boss_fallback(dynamic_rng, tile_wcenter), @@ -723,24 +713,6 @@ fn enemy_2(dynamic_rng: &mut impl Rng, tile_wcenter: Vec3) -> Vec) -> Vec { - let number = dynamic_rng.gen_range(2..=4); - let mut entities = Vec::new(); - entities.resize_with(number, || { - // TODO: give enemies health skills? - let entity = EntityInfo::at(tile_wcenter.map(|e| e as f32)); - match dynamic_rng.gen_range(0..=4) { - 0 => entity.with_asset_expect("common.entity.dungeon.haniwa.archer", dynamic_rng, None), - 1 => { - entity.with_asset_expect("common.entity.dungeon.haniwa.soldier", dynamic_rng, None) - }, - _ => entity.with_asset_expect("common.entity.dungeon.haniwa.guard", dynamic_rng, None), - } - }); - - entities -} - fn enemy_4(dynamic_rng: &mut impl Rng, tile_wcenter: Vec3) -> Vec { let number = dynamic_rng.gen_range(2..=4); let mut entities = Vec::new(); @@ -802,10 +774,6 @@ fn enemy_fallback(dynamic_rng: &mut impl Rng, tile_wcenter: Vec3) -> Vec) -> EntityInfo { - EntityInfo::at(pos).with_asset_expect("common.entity.dungeon.haniwa.sentry", dynamic_rng, None) -} - fn turret_5(dynamic_rng: &mut impl Rng, pos: Vec3) -> EntityInfo { EntityInfo::at(pos).with_asset_expect("common.entity.dungeon.cultist.turret", dynamic_rng, None) } @@ -819,18 +787,6 @@ fn boss_2(dynamic_rng: &mut impl Rng, tile_wcenter: Vec3) -> Vec) -> Vec { - let mut entities = Vec::new(); - entities.resize_with(2, || { - EntityInfo::at(tile_wcenter.map(|e| e as f32)).with_asset_expect( - "common.entity.dungeon.haniwa.claygolem", - dynamic_rng, - None, - ) - }); - - entities -} fn boss_4(dynamic_rng: &mut impl Rng, tile_wcenter: Vec3) -> Vec { vec![ @@ -874,18 +830,6 @@ fn mini_boss_2(dynamic_rng: &mut impl Rng, tile_wcenter: Vec3) -> Vec) -> Vec { - let mut entities = Vec::new(); - entities.resize_with(3, || { - EntityInfo::at(tile_wcenter.map(|e| e as f32)).with_asset_expect( - "common.entity.dungeon.haniwa.bonerattler", - dynamic_rng, - None, - ) - }); - entities -} - fn mini_boss_4(dynamic_rng: &mut impl Rng, tile_wcenter: Vec3) -> Vec { vec![ EntityInfo::at(tile_wcenter.map(|e| e as f32)).with_asset_expect( @@ -1304,7 +1248,6 @@ impl Floor { )); let chest_sprite_fill = Fill::Block(Block::air(match difficulty { 2 => SpriteKind::DungeonChest2, - 3 => SpriteKind::DungeonChest3, 4 => SpriteKind::DungeonChest4, 5 => SpriteKind::DungeonChest5, _ => SpriteKind::Chest, @@ -1524,7 +1467,6 @@ mod tests { let mut dynamic_rng = thread_rng(); let tile_wcenter = Vec3::new(0, 0, 0); boss_2(&mut dynamic_rng, tile_wcenter); - boss_3(&mut dynamic_rng, tile_wcenter); boss_4(&mut dynamic_rng, tile_wcenter); boss_5(&mut dynamic_rng, tile_wcenter); boss_fallback(&mut dynamic_rng, tile_wcenter); @@ -1536,7 +1478,6 @@ mod tests { let mut dynamic_rng = thread_rng(); let random_position = Vec3::new(0, 0, 0); enemy_2(&mut dynamic_rng, random_position); - enemy_3(&mut dynamic_rng, random_position); enemy_4(&mut dynamic_rng, random_position); enemy_5(&mut dynamic_rng, random_position); enemy_fallback(&mut dynamic_rng, random_position); @@ -1548,7 +1489,6 @@ mod tests { let mut dynamic_rng = thread_rng(); let tile_wcenter = Vec3::new(0, 0, 0); mini_boss_2(&mut dynamic_rng, tile_wcenter); - mini_boss_3(&mut dynamic_rng, tile_wcenter); mini_boss_4(&mut dynamic_rng, tile_wcenter); mini_boss_5(&mut dynamic_rng, tile_wcenter); mini_boss_fallback(&mut dynamic_rng, tile_wcenter); @@ -1558,7 +1498,6 @@ mod tests { fn test_creating_turrets() { let mut dynamic_rng = thread_rng(); let pos = Vec3::new(0.0, 0.0, 0.0); - turret_3(&mut dynamic_rng, pos); turret_5(&mut dynamic_rng, pos); } } diff --git a/world/src/site2/plot/haniwa.rs b/world/src/site2/plot/haniwa.rs new file mode 100644 index 0000000000..5833096e51 --- /dev/null +++ b/world/src/site2/plot/haniwa.rs @@ -0,0 +1,911 @@ +use super::*; +use crate::{ + assets::AssetHandle, + site2::gen::PrimitiveTransform, + util::{sampler::Sampler, RandomField, DIAGONALS, LOCALITY, NEIGHBORS}, + Land, +}; +use common::{ + generation::EntityInfo, + terrain::{Structure as PrefabStructure, StructuresGroup}, +}; +use lazy_static::lazy_static; +use rand::prelude::*; +use std::{ + f32::consts::{PI, TAU}, + sync::Arc, +}; +use vek::*; + +pub struct Haniwa { + base: i32, + diameter: i32, + tree_pos: Vec3, + room_size: i32, + rotation: f32, + pub(crate) alt: i32, + pub(crate) center: Vec2, + pub(crate) entrance_pos: Vec3, + pub(crate) mob_room_positions: Vec>, + pub(crate) center_room_positions: Vec>, + pub(crate) room_positions: Vec>, + pub(crate) boss_room_position: Vec3, + pub(crate) mini_boss_room_positions: Vec>, +} +impl Haniwa { + 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), + }; + let center = bounds.center(); + let base = land.get_alt_approx(center) as i32; + let diameter = (150 + RandomField::new(0).get(center.with_z(base)) % 10) as i32; + let dir_select = (RandomField::new(0).get(center.with_z(base)) % 4) as usize; + let rotation = (PI / 2.0) - ((PI / 2.0) * dir_select as f32); + let entrance_dir = CARDINALS[dir_select]; + let tree_dir = -entrance_dir; + let entrance_pos = (center + (entrance_dir * (2 * (diameter / 3)))).with_z(base); + let tree_distance = diameter / 2; + let tree_pos = (center + (tree_dir * tree_distance)).with_z(base); + let room_size = diameter / 4; + let mut floors = vec![]; + for f in 1..=3 { + let floor = base - ((diameter / 5) * f) - 2; + floors.push(floor) + } + let mut mob_room_positions = vec![]; + let mut mini_boss_room_positions = vec![]; + let mut center_room_positions = vec![]; + let mut room_positions = vec![]; + for floor in floors.iter().take(floors.len() - 1) { + let (room_distribution, room_distance) = + if RandomField::new(0).get(center.with_z(*floor)) % 2 > 0 { + (DIAGONALS, (3 * (room_size / 2)) + 2) + } else { + (CARDINALS, 2 * (room_size - 2)) + }; + for dir in room_distribution { + let room_center = center + dir * room_distance; + mob_room_positions.push(room_center.with_z(floor - (room_size / 4) + 1)); + room_positions.push(room_center.with_z(floor - (room_size / 4) + 1)); + } + mini_boss_room_positions.push(center.with_z(floor - (room_size / 4) + 1)); + } + for floor in &floors { + center_room_positions.push(center.with_z(floor - (room_size / 4) + 1)); + room_positions.push(center.with_z(floor - (room_size / 4) + 1)); + } + let boss_room_position = center_room_positions[center_room_positions.len() - 1]; + Self { + alt: land.get_alt_approx(site.tile_center_wpos(tile_aabr.center())) as i32 + 2, + center, + base, + diameter, + entrance_pos, + tree_pos, + room_size, + rotation, + room_positions, + mob_room_positions, + center_room_positions, + boss_room_position, + mini_boss_room_positions, + } + } + + pub fn spawn_rules(&self, wpos: Vec2) -> SpawnRules { + SpawnRules { + waypoints: false, + trees: wpos.distance_squared(self.center) > (self.diameter / 2).pow(2), + ..SpawnRules::default() + } + } +} + +impl Structure for Haniwa { + #[cfg(feature = "use-dyn-lib")] + const UPDATE_FN: &'static [u8] = b"render_haniwa\0"; + + #[cfg_attr(feature = "be-dyn-lib", export_name = "render_haniwa")] + fn render_inner(&self, _site: &Site, _land: &Land, painter: &Painter) { + let center = self.center; + let base = self.base; + let diameter = self.diameter; + let entrance = self.entrance_pos; + let mut thread_rng = thread_rng(); + let rock = Fill::Brick(BlockKind::Rock, Rgb::new(96, 123, 131), 24); + let key_door = Fill::Block(Block::air(SpriteKind::HaniwaKeyDoor)); + let key_hole = Fill::Block(Block::air(SpriteKind::HaniwaKeyhole)); + let trap = Fill::Block(Block::air(SpriteKind::HaniwaTrap)); + let rock_broken = Fill::Sampling(Arc::new(|center| { + Some(match (RandomField::new(0).get(center)) % 48 { + 0..=8 => Block::new(BlockKind::Rock, Rgb::new(97, 124, 134)), + 9..=17 => Block::new(BlockKind::Rock, Rgb::new(92, 118, 128)), + 18..=26 => Block::new(BlockKind::Rock, Rgb::new(85, 111, 121)), + 27..=35 => Block::new(BlockKind::Rock, Rgb::new(82, 108, 117)), + 36..=40 => Block::new(BlockKind::Air, Rgb::new(0, 0, 0)), + _ => Block::new(BlockKind::Rock, Rgb::new(96, 123, 131)), + }) + })); + let lanterns = Fill::Sampling(Arc::new(|center| { + Some(match (RandomField::new(0).get(center)) % 200 { + 0 => Block::air(SpriteKind::FireBowlGround), + _ => Block::new(BlockKind::Air, Rgb::new(0, 0, 0)), + }) + })); + let iron_spikes = Fill::Block(Block::air(SpriteKind::IronSpike)); + let rock_iron_spikes = Fill::Sampling(Arc::new(|center| { + Some(match (RandomField::new(0).get(center)) % 100 { + 0..=8 => Block::new(BlockKind::Rock, Rgb::new(97, 124, 134)), + 9..=17 => Block::new(BlockKind::Rock, Rgb::new(92, 118, 128)), + 18..=26 => Block::new(BlockKind::Rock, Rgb::new(85, 111, 121)), + 27..=35 => Block::new(BlockKind::Rock, Rgb::new(82, 108, 117)), + 36..=40 => Block::new(BlockKind::Rock, Rgb::new(96, 123, 131)), + _ => Block::air(SpriteKind::IronSpike), + }) + })); + let grass = Fill::Brick(BlockKind::Rock, Rgb::new(72, 87, 22), 24); + // room npcs + let npcs = [ + "common.entity.dungeon.haniwa.guard", + "common.entity.dungeon.haniwa.soldier", + ]; + let height_handle = diameter / 8; + let cone_length = 8; + let cone_radius = (diameter / 2) as f32; + let cones = diameter / 4; + let cone_positions = place_circular(center, cone_radius, cones); + // tree platform + let outside_radius = cone_radius as i32; + let tree_pos = Vec2::new(self.tree_pos.x, self.tree_pos.y); + let platform_size = 23; + painter + .cylinder(Aabb { + min: (tree_pos - platform_size).with_z(base - 5), + max: (tree_pos + platform_size).with_z(base - 10 + platform_size - 1), + }) + .fill(rock_broken.clone()); + painter + .cylinder(Aabb { + min: (tree_pos - platform_size).with_z(base - 10 + platform_size - 1), + max: (tree_pos + platform_size).with_z(base - 10 + platform_size), + }) + .fill(grass.clone()); + let carve_positions = place_circular(tree_pos, platform_size as f32, 15); + for carve_pos in carve_positions { + painter + .line( + carve_pos.with_z(base + 2), + carve_pos.with_z(base - 5 + platform_size), + 3.5, + ) + .clear(); + } + // gangway + painter + .ramp( + Aabb { + min: Vec2::new(center.x - outside_radius, center.y - 16).with_z(base + 10), + max: Vec2::new(center.x + (outside_radius / 2) + 8, center.y + 16) + .with_z(base + 28), + }, + Dir::X, + ) + .rotate_about(Mat3::rotation_z(self.rotation).as_(), center.with_z(base)) + .fill(grass.clone()); + painter + .ramp( + Aabb { + min: Vec2::new(center.x - outside_radius, center.y - 16).with_z(base + 9), + max: Vec2::new(center.x + (outside_radius / 2) + 8, center.y + 16) + .with_z(base + 27), + }, + Dir::X, + ) + .rotate_about(Mat3::rotation_z(self.rotation).as_(), center.with_z(base)) + .fill(rock_broken.clone()); + + let clear_dist_x = outside_radius / 4; + let clear_dist_y = (2 * outside_radius) + (outside_radius / 10); + let clear_radius = 2 * outside_radius; + let clear_limiter = painter + .aabb(Aabb { + min: Vec2::new(center.x - outside_radius, center.y - 16).with_z(base + 9), + max: Vec2::new(center.x + (outside_radius / 2) + 8, center.y + 16) + .with_z(base + 28), + }) + .rotate_about(Mat3::rotation_z(self.rotation).as_(), center.with_z(base)); + for c in 0..=1 { + let clear_pos = Vec2::new( + center.x - clear_dist_x, + center.y - clear_dist_y + (c * (clear_dist_y * 2)), + ); + painter + .cylinder(Aabb { + min: (clear_pos - clear_radius).with_z(base + 9), + max: (clear_pos + clear_radius).with_z(base + 28), + }) + .rotate_about(Mat3::rotation_z(self.rotation).as_(), center.with_z(base)) + .intersect(clear_limiter) + .clear(); + } + + // decor cones + for position in &cone_positions { + for dir in LOCALITY { + let cone_pos = position + (dir * 2); + let cone_var = 10 + RandomField::new(0).get(cone_pos.with_z(base)) as i32 % 10; + painter + .cone_with_radius( + cone_pos.with_z(base), + (cone_length / 3) as f32, + (cone_length + cone_var) as f32, + ) + .fill(rock_broken.clone()); + } + } + // repaint platform grass layer + painter + .cylinder(Aabb { + min: (tree_pos - platform_size + 5).with_z(base - 10 + platform_size - 1), + max: (tree_pos + platform_size - 5).with_z(base - 10 + platform_size), + }) + .fill(grass.clone()); + // clear platform upwards + painter + .cylinder(Aabb { + min: (tree_pos - platform_size).with_z(base - 10 + platform_size), + max: (tree_pos + platform_size).with_z(base + platform_size), + }) + .clear(); + // main sphere + let sphere_limiter = painter.aabb(Aabb { + min: (center - diameter - 1).with_z(base - 2), + max: (center + diameter + 1).with_z(base + height_handle + 1), + }); + painter + .sphere(Aabb { + min: (center - diameter - 1).with_z(base - (2 * diameter) + height_handle - 1), + max: (center + diameter + 1).with_z(base + height_handle + 1), + }) + .intersect(sphere_limiter) + .fill(grass.clone()); + painter + .sphere(Aabb { + min: (center - diameter + 1).with_z(base - (2 * diameter) + height_handle + 1), + max: (center + diameter - 1).with_z(base + height_handle - 1), + }) + .intersect(sphere_limiter) + .fill(rock.clone()); + + // decor grass ring + let ring_radius = cone_radius as i32 + 4; + painter + .cylinder(Aabb { + min: (center - ring_radius).with_z(base), + max: (center + ring_radius).with_z(base + 4), + }) + .fill(grass.clone()); + let beams = cones + 8; + let beam_start_radius = cone_radius + 6_f32; + let beam_end_radius = cone_radius + 20_f32; + let beam_start = place_circular(center, beam_start_radius, beams); + let beam_end = place_circular(center, beam_end_radius, beams); + let room_size = self.room_size; + + for b in 0..beams { + painter + .line( + beam_start[b as usize].with_z(base + 2), + beam_end[b as usize].with_z(base + 1), + 2.5, + ) + .fill(grass.clone()); + } + // entrance terrain clear + let entrance_clear = Vec2::new(entrance.x, entrance.y); + for c in 0..8 { + painter + .aabb(Aabb { + min: (entrance_clear - 4 - c).with_z(base + c), + max: (entrance_clear + 4 + c).with_z(base + 1 + c), + }) + .clear(); + } + // entrance tunnel + painter + .vault( + Aabb { + min: Vec2::new(center.x + (diameter / 4), center.y - 12).with_z(base - 5), + max: Vec2::new(center.x + (diameter / 2) + 9, center.y + 12).with_z(base + 22), + }, + Dir::X, + ) + .rotate_about(Mat3::rotation_z(self.rotation).as_(), center.with_z(base)) + .fill(rock_broken.clone()); + for v in 1..=5 { + painter + .vault( + Aabb { + min: Vec2::new(center.x + (diameter / 2) + 8 + v, center.y - 10 + v) + .with_z(base - 5), + max: Vec2::new(center.x + (diameter / 2) + 9 + v, center.y + 10 - v) + .with_z(base + 22 - v), + }, + Dir::X, + ) + .rotate_about(Mat3::rotation_z(self.rotation).as_(), center.with_z(base)) + .fill(rock_broken.clone()); + } + painter + .vault( + Aabb { + min: Vec2::new(center.x + (diameter / 4), center.y - 4).with_z(base), + max: Vec2::new(center.x + (diameter / 2) + 25, center.y + 4).with_z(base + 16), + }, + Dir::X, + ) + .rotate_about(Mat3::rotation_z(self.rotation).as_(), center.with_z(base)) + .clear(); + // entrance lanterns + painter + .aabb(Aabb { + min: Vec2::new(center.x + (diameter / 4), center.y - 4).with_z(base), + max: Vec2::new(center.x + (diameter / 2) + 15, center.y + 4).with_z(base + 1), + }) + .rotate_about(Mat3::rotation_z(self.rotation).as_(), center.with_z(base)) + .fill(lanterns.clone()); + // floor 0 + painter + .cylinder(Aabb { + min: (center - beam_end_radius as i32 - 3).with_z(base - (diameter / 4) - 3), + max: (center + beam_end_radius as i32 + 3).with_z(base), + }) + .fill(rock.clone()); + // entrance trap + painter + .cylinder(Aabb { + min: Vec2::new(center.x + (diameter / 3) - 3, center.y - 2).with_z(base - 1), + max: Vec2::new(center.x + (diameter / 3) + 3, center.y + 3).with_z(base), + }) + .rotate_about(Mat3::rotation_z(self.rotation).as_(), center.with_z(base)) + .fill(trap.clone()); + + // room hulls + for rooms in &self.room_positions { + let room_center = Vec2::new(rooms.x, rooms.y); + let floor = rooms.z + (room_size / 4) + 1; + painter + .superquadric( + Aabb { + min: (room_center - room_size - 2).with_z(floor - (room_size / 4) - 2), + max: (room_center + room_size + 2).with_z(floor + (room_size / 4) + 2), + }, + 4.0, + ) + .fill(rock.clone()); + painter + .superquadric( + Aabb { + min: (room_center - room_size - 1).with_z(floor - (room_size / 4) - 1), + max: (room_center + room_size + 1).with_z(floor + (room_size / 4) + 1), + }, + 4.0, + ) + .fill(rock_broken.clone()); + } + for rooms in &self.room_positions { + // clear rooms + let room_center = Vec2::new(rooms.x, rooms.y); + let floor = rooms.z + (room_size / 4) + 1; + painter + .superquadric( + Aabb { + min: (room_center - room_size).with_z(floor - (room_size / 4)), + max: (room_center + room_size).with_z(floor + (room_size / 4)), + }, + 4.0, + ) + .clear(); + // room floor + painter + .aabb(Aabb { + min: (room_center - room_size).with_z(floor - (room_size / 4) - 2), + max: (room_center + room_size).with_z(floor - (room_size / 4) + 5), + }) + .fill(rock.clone()); + // room lanterns + painter + .aabb(Aabb { + min: (room_center - room_size + 7).with_z(floor - (room_size / 4) + 5), + max: (room_center + room_size - 7).with_z(floor - (room_size / 4) + 6), + }) + .fill(lanterns.clone()); + } + // mob rooms + for rooms in &self.mob_room_positions { + let room_center = Vec2::new(rooms.x, rooms.y); + let floor = rooms.z + (room_size / 4) + 1; + // inner room + painter + .aabb(Aabb { + min: (room_center - (2 * (room_size / 3)) - 1) + .with_z(floor - (room_size / 4) + 5), + max: (room_center + (2 * (room_size / 3)) + 1).with_z(floor + (room_size / 4)), + }) + .fill(rock_broken.clone()); + painter + .aabb(Aabb { + min: (room_center - (2 * (room_size / 3)) + 1) + .with_z(floor - (room_size / 4) + 5), + max: (room_center + (2 * (room_size / 3)) - 1) + .with_z(floor + (room_size / 4) - 1), + }) + .clear(); + // inner room entries + painter + .vault( + Aabb { + min: Vec2::new( + room_center.x - (2 * (room_size / 3)) - 1, + room_center.y - 4, + ) + .with_z(floor - (room_size / 4) + 5), + max: Vec2::new( + room_center.x + (2 * (room_size / 3)) + 1, + room_center.y + 4, + ) + .with_z(floor + (room_size / 8)), + }, + Dir::X, + ) + .clear(); + painter + .vault( + Aabb { + min: Vec2::new( + room_center.x - 4, + room_center.y - (2 * (room_size / 3)) - 1, + ) + .with_z(floor - (room_size / 4) + 5), + max: Vec2::new( + room_center.x + 4, + room_center.y + (2 * (room_size / 3)) + 1, + ) + .with_z(floor + (room_size / 8)), + }, + Dir::Y, + ) + .clear(); + // room lanterns inner + painter + .aabb(Aabb { + min: (room_center - (2 * (room_size / 3)) + 1) + .with_z(floor - (room_size / 4) + 5), + max: (room_center + (2 * (room_size / 3)) - 1) + .with_z(floor - (room_size / 4) + 6), + }) + .fill(lanterns.clone()); + for dir in DIAGONALS { + let pillar_pos = room_center + dir * ((2 * (room_size / 3)) - 6); + let stair_pos = Vec2::new( + room_center.x + dir.x * ((2 * (room_size / 3)) - 10), + room_center.y + dir.y * ((2 * (room_size / 3)) - 3), + ); + if (RandomField::new(0).get((pillar_pos).with_z(base)) % 3) > 0 { + // stairs + painter + .line( + Vec2::new(room_center.x, stair_pos.y) + .with_z(floor - (room_size / 4) - 1), + stair_pos.with_z(floor - (room_size / 4) + 6), + 4.0, + ) + .fill(rock.clone()); + painter + .cylinder(Aabb { + min: (pillar_pos - 6).with_z(floor - (room_size / 4) + 5), + max: (pillar_pos + 6).with_z(floor - (room_size / 4) + 6), + }) + .fill(rock.clone()); + painter + .cylinder(Aabb { + min: (pillar_pos - 6).with_z(floor - (room_size / 4) + 6), + max: (pillar_pos + 6).with_z(floor - (room_size / 4) + 7), + }) + .fill(iron_spikes.clone()); + painter + .cylinder(Aabb { + min: (pillar_pos - 5).with_z(floor - (room_size / 4) + 5), + max: (pillar_pos + 5).with_z(floor - (room_size / 4) + 9), + }) + .fill(rock_broken.clone()); + painter + .cylinder(Aabb { + min: (pillar_pos - 6).with_z(floor - (room_size / 4) + 9), + max: (pillar_pos + 7).with_z(floor - (room_size / 4) + 10), + }) + .fill(rock.clone()); + // chests + if (RandomField::new(0).get((pillar_pos).with_z(base)) % 5) == 0 { + painter + .aabb(Aabb { + min: pillar_pos.with_z(floor - (room_size / 4) + 9), + max: (pillar_pos + 1).with_z(floor - (room_size / 4) + 10), + }) + .fill(rock.clone()); + painter + .aabb(Aabb { + min: pillar_pos.with_z(floor - (room_size / 4) + 10), + max: (pillar_pos + 1).with_z(floor - (room_size / 4) + 11), + }) + .fill(Fill::Block(Block::air(SpriteKind::DungeonChest3))); + } + // room npcs + for _ in 0..=thread_rng.gen_range(0..2) { + // archers on pillars + painter.spawn( + EntityInfo::at(pillar_pos.with_z(floor - (room_size / 4) + 11).as_()) + .with_asset_expect( + "common.entity.dungeon.haniwa.archer", + &mut thread_rng, + None, + ), + ); + } + } + } + for n in 0..=thread_rng.gen_range(2..=4) { + let select = + (RandomField::new(0).get((room_center + n).with_z(floor)) % 2) as usize; + painter.spawn( + EntityInfo::at( + (room_center + 10 + n) + .with_z(floor - (room_size / 4) + 6) + .as_(), + ) + .with_asset_expect(npcs[select], &mut thread_rng, None), + ) + } + let effigy_pos = (room_center - 8).with_z(floor - (room_size / 4) + 6); + if (RandomField::new(0).get(effigy_pos) % 2) as usize > 0 { + painter.spawn(EntityInfo::at(effigy_pos.as_()).with_asset_expect( + "common.entity.dungeon.haniwa.ancienteffigy", + &mut thread_rng, + None, + )); + } + // room chest + match RandomField::new(0).get(room_center.with_z(base)) as i32 % 3 { + 0 => { + for dir in CARDINALS { + let sentry_pos = room_center + dir * 10; + painter.spawn( + EntityInfo::at(sentry_pos.with_z(floor - (room_size / 4) + 6).as_()) + .with_asset_expect( + "common.entity.dungeon.haniwa.sentry", + &mut thread_rng, + None, + ), + ) + } + painter + .aabb(Aabb { + min: (room_center - 1).with_z(floor - (room_size / 4) + 5), + max: (room_center + 2).with_z(floor - (room_size / 4) + 6), + }) + .fill(rock.clone()); + painter + .aabb(Aabb { + min: room_center.with_z(floor - (room_size / 4) + 6), + max: (room_center + 1).with_z(floor - (room_size / 4) + 7), + }) + .fill(Fill::Block(Block::air(SpriteKind::HaniwaUrn))); + }, + 1 => { + painter + .cylinder(Aabb { + min: (room_center - 8).with_z(floor - (room_size / 4) + 5), + max: (room_center + 8).with_z(floor - (room_size / 4) + 6), + }) + .fill(rock_iron_spikes.clone()); + painter + .cylinder(Aabb { + min: (room_center - 7).with_z(floor - (room_size / 4) + 5), + max: (room_center + 7).with_z(floor - (room_size / 4) + 6), + }) + .fill(rock.clone()); + painter + .cylinder(Aabb { + min: (room_center - 7).with_z(floor - (room_size / 4) + 6), + max: (room_center + 7).with_z(floor - (room_size / 4) + 7), + }) + .fill(rock_iron_spikes.clone()); + painter + .cylinder(Aabb { + min: (room_center - 6).with_z(floor - (room_size / 4) + 6), + max: (room_center + 6).with_z(floor - (room_size / 4) + 7), + }) + .fill(rock.clone()); + painter + .cylinder(Aabb { + min: (room_center - 6).with_z(floor - (room_size / 4) + 7), + max: (room_center + 6).with_z(floor - (room_size / 4) + 8), + }) + .fill(rock_iron_spikes.clone()); + painter + .aabb(Aabb { + min: (room_center - 1).with_z(floor - (room_size / 4) + 7), + max: (room_center + 2).with_z(floor - (room_size / 4) + 8), + }) + .fill(rock.clone()); + painter + .aabb(Aabb { + min: room_center.with_z(floor - (room_size / 4) + 8), + max: (room_center + 1).with_z(floor - (room_size / 4) + 9), + }) + .fill(Fill::Block(Block::air(SpriteKind::HaniwaUrn))); + }, + _ => { + for c in 0..=7 { + painter + .cylinder(Aabb { + min: (room_center - 10 + c).with_z(floor - (room_size / 4) + 4), + max: (room_center + 10 - c).with_z(floor - (room_size / 4) + 5), + }) + .fill(match c { + 0 | 2 | 4 | 6 => trap.clone(), + _ => rock.clone(), + }); + } + + painter + .aabb(Aabb { + min: (room_center - 1).with_z(floor - (room_size / 4) + 5), + max: (room_center + 2).with_z(floor - (room_size / 4) + 6), + }) + .fill(rock.clone()); + painter + .aabb(Aabb { + min: room_center.with_z(floor - (room_size / 4) + 6), + max: (room_center + 1).with_z(floor - (room_size / 4) + 7), + }) + .fill(Fill::Block(Block::air(SpriteKind::HaniwaUrn))); + }, + } + } + // center rooms + for rooms in &self.center_room_positions { + let floor = rooms.z + (room_size / 4) + 1; + // room decor + for dir in NEIGHBORS { + let position = center + dir * 20; + for p in 0..4 { + painter + .aabb(Aabb { + min: (position - 1 - p).with_z(floor - (room_size / 4) + 5 + (4 * p)), + max: (position + 2 + p).with_z(floor - (room_size / 4) + 9 + (4 * p)), + }) + .fill(rock_broken.clone()); + } + for t in 0..2 { + let trap_pos = center + (dir * (12 + (t * 14))); + if RandomField::new(0).get((trap_pos).with_z(floor)) % 3 < 1 { + painter + .aabb(Aabb { + min: (trap_pos - 1).with_z(floor - (room_size / 4) + 4), + max: (trap_pos + 1).with_z(floor - (room_size / 4) + 5), + }) + .fill(trap.clone()); + painter + .aabb(Aabb { + min: (trap_pos - 1).with_z(floor - (room_size / 4) + 5), + max: (trap_pos + 1).with_z(floor - (room_size / 4) + 6), + }) + .clear(); + } + } + } + } + // center room stairs + for f in 0..(self.center_room_positions.len() - 1) { + let floor = self.center_room_positions[f].z + (room_size / 4) + 1; + let stairs_floor = floor - 5; + let stairs_start = + Vec2::new(center.x - (diameter / 6) + 2, center.y - (diameter / 6) + 7); + for s in 0..(diameter / 5) { + painter + .vault( + Aabb { + min: Vec2::new(stairs_start.x + s - 1, stairs_start.y - 4) + .with_z(stairs_floor - s - 2), + max: Vec2::new(stairs_start.x + s, stairs_start.y + 4) + .with_z(stairs_floor + 12 - s + 2), + }, + Dir::X, + ) + .fill(rock_broken.clone()); + } + for s in 0..(diameter / 5) { + painter + .vault( + Aabb { + min: Vec2::new(stairs_start.x + s - 1, stairs_start.y - 2) + .with_z(stairs_floor - s), + max: Vec2::new(stairs_start.x + s, stairs_start.y + 2) + .with_z(stairs_floor + 10 - s), + }, + Dir::X, + ) + .clear(); + painter + .aabb(Aabb { + min: Vec2::new(stairs_start.x + s - 1, stairs_start.y - 2) + .with_z(stairs_floor - 1 - s), + max: Vec2::new(stairs_start.x + s, stairs_start.y + 2) + .with_z(stairs_floor - s), + }) + .fill(rock.clone()); + painter + .aabb(Aabb { + min: Vec2::new(stairs_start.x + s - 1, stairs_start.y - 2) + .with_z(stairs_floor - s), + max: Vec2::new(stairs_start.x + s, stairs_start.y + 2) + .with_z(stairs_floor + 1 - s), + }) + .fill(lanterns.clone()); + + let doors = [0, 8, 16, 24]; + if doors.contains(&s) { + painter + .vault( + Aabb { + min: Vec2::new(stairs_start.x + s - 1, stairs_start.y - 2) + .with_z(stairs_floor - s), + max: Vec2::new(stairs_start.x + s, stairs_start.y + 2) + .with_z(stairs_floor + 10 - s), + }, + Dir::X, + ) + .fill(key_door.clone()); + painter + .aabb(Aabb { + min: Vec2::new(stairs_start.x + s - 1, stairs_start.y) + .with_z(stairs_floor + 2 - s), + max: Vec2::new(stairs_start.x + s, stairs_start.y + 1) + .with_z(stairs_floor + 3 - s), + }) + .fill(key_hole.clone()); + } + } + } + + // tunnel stairs + for s in 0..((diameter / 4) - 3) { + painter + .vault( + Aabb { + min: Vec2::new(center.x + (diameter / 4) - s - 1, center.y - 5) + .with_z(base - s - 1), + max: Vec2::new(center.x + (diameter / 4) - s, center.y + 5) + .with_z(base + 16 - s + 1), + }, + Dir::X, + ) + .rotate_about(Mat3::rotation_z(self.rotation).as_(), center.with_z(base)) + .fill(rock_broken.clone()); + + painter + .vault( + Aabb { + min: Vec2::new(center.x + (diameter / 4) - s - 1, center.y - 4) + .with_z(base - s), + max: Vec2::new(center.x + (diameter / 4) - s, center.y + 4) + .with_z(base + 16 - s), + }, + Dir::X, + ) + .rotate_about(Mat3::rotation_z(self.rotation).as_(), center.with_z(base)) + .clear(); + painter + .aabb(Aabb { + min: Vec2::new(center.x + (diameter / 4) - s - 1, center.y - 4) + .with_z(base - 1 - s), + max: Vec2::new(center.x + (diameter / 4) - s, center.y + 4).with_z(base - s), + }) + .rotate_about(Mat3::rotation_z(self.rotation).as_(), center.with_z(base)) + .fill(rock.clone()); + painter + .aabb(Aabb { + min: Vec2::new(center.x + (diameter / 4) - s - 1, center.y - 4) + .with_z(base - s), + max: Vec2::new(center.x + (diameter / 4) - s, center.y + 4) + .with_z(base + 1 - s), + }) + .rotate_about(Mat3::rotation_z(self.rotation).as_(), center.with_z(base)) + .fill(lanterns.clone()); + } + + // tree model + lazy_static! { + pub static ref MODEL: AssetHandle = + PrefabStructure::load_group("site_structures.haniwa.bonsai"); + } + let model_pos = tree_pos.with_z(base - 10 + platform_size); + let rng = RandomField::new(0).get(model_pos) % 10; + 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)); + + // mini_bosses + let golem_pos = Vec3::new( + self.mini_boss_room_positions[0].x, + self.mini_boss_room_positions[0].y, + self.mini_boss_room_positions[0].z + 5, + ); + painter.spawn(EntityInfo::at(golem_pos.as_()).with_asset_expect( + "common.entity.dungeon.haniwa.claygolem", + &mut thread_rng, + None, + )); + // mid_boss + let mid_boss = [ + "common.entity.dungeon.haniwa.general", + "common.entity.dungeon.haniwa.claysteed", + ]; + for npc in mid_boss.iter() { + painter.spawn( + EntityInfo::at( + Vec3::new( + self.mini_boss_room_positions[1].x, + self.mini_boss_room_positions[1].y, + self.mini_boss_room_positions[1].z + 5, + ) + .as_(), + ) + .with_asset_expect(npc, &mut thread_rng, None), + ); + } + // boss + painter.spawn( + EntityInfo::at( + Vec3::new( + self.boss_room_position.x, + self.boss_room_position.y, + self.boss_room_position.z + 5, + ) + .as_(), + ) + .with_asset_expect( + "common.entity.dungeon.haniwa.gravewarden", + &mut thread_rng, + None, + ), + ); + let bonerattler_pos = (center + ((entrance - center) / 3)).with_z(base); + for _ in 0..(1 + RandomField::new(0).get(center.with_z(base)) % 2) as i32 { + painter.spawn(EntityInfo::at(bonerattler_pos.as_()).with_asset_expect( + "common.entity.dungeon.haniwa.claysteed", + &mut thread_rng, + None, + )) + } + } +} + +fn place_circular(center: Vec2, radius: f32, amount: i32) -> Vec> { + let phi = TAU / amount as f32; + let mut positions = vec![]; + for n in 1..=amount { + let pos = Vec2::new( + center.x + (radius * ((n as f32 * phi).cos())) as i32, + center.y + (radius * ((n as f32 * phi).sin())) as i32, + ); + positions.push(pos); + } + positions +} diff --git a/world/src/site2/plot/sea_chapel.rs b/world/src/site2/plot/sea_chapel.rs index 4f6e6f0416..ba675e5974 100644 --- a/world/src/site2/plot/sea_chapel.rs +++ b/world/src/site2/plot/sea_chapel.rs @@ -18,7 +18,7 @@ use std::{ use vek::*; pub struct SeaChapel { - bounds: Aabr, + pub(crate) center: Vec2, pub(crate) alt: i32, } impl SeaChapel { @@ -27,11 +27,20 @@ impl SeaChapel { min: site.tile_wpos(tile_aabr.min), max: site.tile_wpos(tile_aabr.max), }; + let center = bounds.center(); Self { - bounds, + center, alt: CONFIG.sea_level as i32, } } + + pub fn spawn_rules(&self, wpos: Vec2) -> SpawnRules { + SpawnRules { + waypoints: false, + trees: wpos.distance_squared(self.center) > 100_i32.pow(2), + ..SpawnRules::default() + } + } } impl Structure for SeaChapel { @@ -41,7 +50,7 @@ impl Structure for SeaChapel { #[cfg_attr(feature = "be-dyn-lib", export_name = "render_seachapel")] fn render_inner(&self, _site: &Site, _land: &Land, painter: &Painter) { let base = self.alt + 1; - let center = self.bounds.center(); + let center = self.center; let diameter = 54; let variant = center.with_z(base); let mut rng = thread_rng();