diff --git a/CHANGELOG.md b/CHANGELOG.md index 85bd031755..541c4cc63f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -39,6 +39,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Interation hints now appear for sprites and entities - Players can now mount and ride pets - Experimental shaders, that can be enabled in Voxygen's settings (see the book for more information) +- Added arthropods ### Changed diff --git a/assets/common/abilities/ability_set_manifest.ron b/assets/common/abilities/ability_set_manifest.ron index bdfd91bf6b..7f4e5a0ce1 100644 --- a/assets/common/abilities/ability_set_manifest.ron +++ b/assets/common/abilities/ability_set_manifest.ron @@ -228,6 +228,30 @@ secondary: "common.abilities.custom.theropodbasic.dash", abilities: [], ), + Custom("Arthropod Basic"): ( + primary: "common.abilities.custom.arthropodbasic.singlestrike", + secondary: "common.abilities.custom.arthropodbasic.ensnaringweb", + abilities: [], + ), + Custom("Arthropod Leap"): ( + primary: "common.abilities.custom.arthropodbasic.singlestrike", + secondary: "common.abilities.custom.arthropodbasic.ensnaringweb", + abilities: [ + (None, "common.abilities.custom.arthropodbasic.leap"), + ], + ), + Custom("Arthropod Ranged"): ( + primary: "common.abilities.custom.arthropodranged.singlestrike", + secondary: "common.abilities.custom.arthropodranged.ensnaringweb", + abilities: [ + (None, "common.abilities.custom.arthropodranged.poisonball"), + ], + ), + Custom("Arthropod Charge"): ( + primary: "common.abilities.custom.arthropodcharge.singlestrike", + secondary: "common.abilities.custom.arthropodcharge.charge", + abilities: [], + ), Custom("Turret"): ( primary: "common.abilities.custom.turret.arrows", secondary: "common.abilities.custom.turret.arrows", diff --git a/assets/common/abilities/custom/arthropodbasic/ensnaringweb.ron b/assets/common/abilities/custom/arthropodbasic/ensnaringweb.ron new file mode 100644 index 0000000000..a9a598615a --- /dev/null +++ b/assets/common/abilities/custom/arthropodbasic/ensnaringweb.ron @@ -0,0 +1,8 @@ +SpriteSummon( + buildup_duration: 0.6, + cast_duration: 0.4, + recover_duration: 0.3, + sprite: EnsnaringWeb, + summon_distance: (0, 8), + sparseness: 0.67, +) \ No newline at end of file diff --git a/assets/common/abilities/custom/arthropodbasic/leap.ron b/assets/common/abilities/custom/arthropodbasic/leap.ron new file mode 100644 index 0000000000..8f30d570cd --- /dev/null +++ b/assets/common/abilities/custom/arthropodbasic/leap.ron @@ -0,0 +1,19 @@ +LeapMelee( + energy_cost: 0, + buildup_duration: 0.5, + movement_duration: 0.4, + swing_duration: 0.075, + recover_duration: 0.2, + melee_constructor: ( + kind: Bash( + damage: 120.0, + poise: 60.0, + knockback: 4.0, + energy_regen: 0.0, + ), + range: 4.5, + angle: 180.0, + ), + forward_leap_strength: 40.0, + vertical_leap_strength: 10.0, +) diff --git a/assets/common/abilities/custom/arthropodbasic/singlestrike.ron b/assets/common/abilities/custom/arthropodbasic/singlestrike.ron new file mode 100644 index 0000000000..cac334d1a2 --- /dev/null +++ b/assets/common/abilities/custom/arthropodbasic/singlestrike.ron @@ -0,0 +1,34 @@ +ComboMelee( + stage_data: [ + ( + stage: 1, + base_damage: 40, + damage_increase: 0, + base_poise_damage: 15, + poise_damage_increase: 0, + knockback: 3.0, + range: 3.0, + angle: 60.0, + base_buildup_duration: 0.4, + base_swing_duration: 0.1, + hit_timing: 0.5, + base_recover_duration: 0.4, + forward_movement: 1.0, + damage_kind: Crushing, + damage_effect: Some(Buff(( + kind: Poisoned, + dur_secs: 10.0, + strength: DamageFraction(1.0), + chance: 1.0, + ))), + ), + ], + initial_energy_gain: 0, + max_energy_gain: 0, + energy_increase: 0, + speed_increase: 0.0, + max_speed_increase: 0.0, + scales_from_combo: 0, + is_interruptible: false, + ori_modifier: 0.7, +) diff --git a/assets/common/abilities/custom/arthropodcharge/charge.ron b/assets/common/abilities/custom/arthropodcharge/charge.ron new file mode 100644 index 0000000000..b024db8184 --- /dev/null +++ b/assets/common/abilities/custom/arthropodcharge/charge.ron @@ -0,0 +1,28 @@ +DashMelee( + energy_cost: 0, + melee_constructor: ( + kind: Stab( + damage: 12.0, + poise: 25.0, + knockback: 10.0, + energy_regen: 0.0, + ), + scaled: Some(Stab( + damage: 50.0, + poise: 100.0, + knockback: 30.0, + energy_regen: 0.0, + )), + range: 5.0, + angle: 90.0, + ), + energy_drain: 0, + forward_speed: 5.0, + buildup_duration: 0.3, + charge_duration: 4.0, + swing_duration: 0.1, + recover_duration: 0.4, + ori_modifier: 0.3, + charge_through: false, + is_interruptible: false, +) diff --git a/assets/common/abilities/custom/arthropodcharge/singlestrike.ron b/assets/common/abilities/custom/arthropodcharge/singlestrike.ron new file mode 100644 index 0000000000..5923a753d5 --- /dev/null +++ b/assets/common/abilities/custom/arthropodcharge/singlestrike.ron @@ -0,0 +1,34 @@ +ComboMelee( + stage_data: [ + ( + stage: 1, + base_damage: 70, + damage_increase: 0, + base_poise_damage: 28, + poise_damage_increase: 0, + knockback: 3.0, + range: 3.0, + angle: 60.0, + base_buildup_duration: 0.4, + base_swing_duration: 0.1, + hit_timing: 0.5, + base_recover_duration: 0.4, + forward_movement: 1.0, + damage_kind: Crushing, + damage_effect: Some(Buff(( + kind: Poisoned, + dur_secs: 10.0, + strength: DamageFraction(1.0), + chance: 1.0, + ))), + ), + ], + initial_energy_gain: 0, + max_energy_gain: 0, + energy_increase: 0, + speed_increase: 0.0, + max_speed_increase: 0.0, + scales_from_combo: 0, + is_interruptible: false, + ori_modifier: 0.7, +) diff --git a/assets/common/abilities/custom/arthropodranged/ensnaringweb.ron b/assets/common/abilities/custom/arthropodranged/ensnaringweb.ron new file mode 100644 index 0000000000..a9a598615a --- /dev/null +++ b/assets/common/abilities/custom/arthropodranged/ensnaringweb.ron @@ -0,0 +1,8 @@ +SpriteSummon( + buildup_duration: 0.6, + cast_duration: 0.4, + recover_duration: 0.3, + sprite: EnsnaringWeb, + summon_distance: (0, 8), + sparseness: 0.67, +) \ No newline at end of file diff --git a/assets/common/abilities/custom/arthropodranged/poisonball.ron b/assets/common/abilities/custom/arthropodranged/poisonball.ron new file mode 100644 index 0000000000..d68d27a440 --- /dev/null +++ b/assets/common/abilities/custom/arthropodranged/poisonball.ron @@ -0,0 +1,19 @@ +BasicRanged( + energy_cost: 0, + buildup_duration: 0.8, + recover_duration: 0.35, + projectile: Poisonball( + damage: 26.0, + radius: 5.0, + energy_regen: 0, + min_falloff: 0.5, + ), + projectile_body: Object(SpitPoison), + /*projectile_light: Some(LightEmitter { + col: (1.0, 0.75, 0.11).into(), + ..Default::default() + }),*/ + projectile_speed: 70.0, + num_projectiles: 3, + projectile_spread: 0.2, +) diff --git a/assets/common/abilities/custom/arthropodranged/singlestrike.ron b/assets/common/abilities/custom/arthropodranged/singlestrike.ron new file mode 100644 index 0000000000..4c09fc092f --- /dev/null +++ b/assets/common/abilities/custom/arthropodranged/singlestrike.ron @@ -0,0 +1,34 @@ +ComboMelee( + stage_data: [ + ( + stage: 1, + base_damage: 60, + damage_increase: 0, + base_poise_damage: 28, + poise_damage_increase: 0, + knockback: 3.0, + range: 3.0, + angle: 60.0, + base_buildup_duration: 0.4, + base_swing_duration: 0.1, + hit_timing: 0.5, + base_recover_duration: 0.4, + forward_movement: 1.0, + damage_kind: Crushing, + damage_effect: Some(Buff(( + kind: Poisoned, + dur_secs: 10.0, + strength: DamageFraction(1.0), + chance: 1.0, + ))), + ), + ], + initial_energy_gain: 0, + max_energy_gain: 0, + energy_increase: 0, + speed_increase: 0.0, + max_speed_increase: 0.0, + scales_from_combo: 0, + is_interruptible: false, + ori_modifier: 0.7, +) diff --git a/assets/common/abilities/custom/wendigomagic/frostbomb.ron b/assets/common/abilities/custom/wendigomagic/frostbomb.ron index 55e0e0f542..37f8295f9f 100644 --- a/assets/common/abilities/custom/wendigomagic/frostbomb.ron +++ b/assets/common/abilities/custom/wendigomagic/frostbomb.ron @@ -7,7 +7,7 @@ BasicRanged( radius: 5.0, min_falloff: 0.5, ), - projectile_body: Object(BoltFire), // TODO: Get ice projectile model + projectile_body: Object(BoltIcicle), /*projectile_light: Some(LightEmitter { col: (1.0, 0.75, 0.11).into(), ..Default::default() diff --git a/assets/common/entity/wild/aggressive/antlion.ron b/assets/common/entity/wild/aggressive/antlion.ron new file mode 100644 index 0000000000..d338fb4387 --- /dev/null +++ b/assets/common/entity/wild/aggressive/antlion.ron @@ -0,0 +1,11 @@ +EntityConfig ( + name: Automatic, + body: RandomWith("antlion"), + alignment: Alignment(Enemy), + + loot: LootTable("common.loot_tables.creature.arthropod.carapace"), + + hands: Uninit, + + meta: [], +) diff --git a/assets/common/entity/wild/aggressive/black_widow.ron b/assets/common/entity/wild/aggressive/black_widow.ron new file mode 100644 index 0000000000..8793ac463a --- /dev/null +++ b/assets/common/entity/wild/aggressive/black_widow.ron @@ -0,0 +1,11 @@ +EntityConfig ( + name: Automatic, + body: RandomWith("black_widow"), + alignment: Alignment(Enemy), + + loot: LootTable("common.loot_tables.creature.arthropod.venom"), + + hands: Uninit, + + meta: [], +) diff --git a/assets/common/entity/wild/aggressive/cave_spider.ron b/assets/common/entity/wild/aggressive/cave_spider.ron new file mode 100644 index 0000000000..12f9863f4c --- /dev/null +++ b/assets/common/entity/wild/aggressive/cave_spider.ron @@ -0,0 +1,11 @@ +EntityConfig ( + name: Automatic, + body: RandomWith("cave_spider"), + alignment: Alignment(Enemy), + + loot: LootTable("common.loot_tables.creature.arthropod.web"), + + hands: Uninit, + + meta: [], +) diff --git a/assets/common/entity/wild/aggressive/horn_beetle.ron b/assets/common/entity/wild/aggressive/horn_beetle.ron new file mode 100644 index 0000000000..4c17803994 --- /dev/null +++ b/assets/common/entity/wild/aggressive/horn_beetle.ron @@ -0,0 +1,11 @@ +EntityConfig ( + name: Automatic, + body: RandomWith("horn_beetle"), + alignment: Alignment(Enemy), + + loot: LootTable("common.loot_tables.creature.arthropod.carapace"), + + hands: Uninit, + + meta: [], +) diff --git a/assets/common/entity/wild/aggressive/stag_beetle.ron b/assets/common/entity/wild/aggressive/stag_beetle.ron new file mode 100644 index 0000000000..9db9753cac --- /dev/null +++ b/assets/common/entity/wild/aggressive/stag_beetle.ron @@ -0,0 +1,11 @@ +EntityConfig ( + name: Automatic, + body: RandomWith("stag_beetle"), + alignment: Alignment(Enemy), + + loot: LootTable("common.loot_tables.creature.arthropod.carapace"), + + hands: Uninit, + + meta: [], +) diff --git a/assets/common/entity/wild/aggressive/tarantula.ron b/assets/common/entity/wild/aggressive/tarantula.ron new file mode 100644 index 0000000000..61675f6f9e --- /dev/null +++ b/assets/common/entity/wild/aggressive/tarantula.ron @@ -0,0 +1,11 @@ +EntityConfig ( + name: Automatic, + body: RandomWith("tarantula"), + alignment: Alignment(Enemy), + + loot: LootTable("common.loot_tables.creature.arthropod.web"), + + hands: Uninit, + + meta: [], +) diff --git a/assets/common/entity/wild/aggressive/weevil.ron b/assets/common/entity/wild/aggressive/weevil.ron new file mode 100644 index 0000000000..3adbedcd36 --- /dev/null +++ b/assets/common/entity/wild/aggressive/weevil.ron @@ -0,0 +1,11 @@ +EntityConfig ( + name: Automatic, + body: RandomWith("weevil"), + alignment: Alignment(Enemy), + + loot: LootTable("common.loot_tables.creature.arthropod.leaf"), + + hands: Uninit, + + meta: [], +) diff --git a/assets/common/entity/wild/peaceful/crawler_molten.ron b/assets/common/entity/wild/peaceful/crawler_molten.ron new file mode 100644 index 0000000000..fe56090e89 --- /dev/null +++ b/assets/common/entity/wild/peaceful/crawler_molten.ron @@ -0,0 +1,11 @@ +EntityConfig ( + name: Automatic, + body: RandomWith("crawler_molten"), + alignment: Alignment(Wild), + + loot: LootTable("common.loot_tables.creature.arthropod.ooze"), + + hands: Uninit, + + meta: [], +) diff --git a/assets/common/entity/wild/peaceful/crawler_moss.ron b/assets/common/entity/wild/peaceful/crawler_moss.ron new file mode 100644 index 0000000000..bc164b86a2 --- /dev/null +++ b/assets/common/entity/wild/peaceful/crawler_moss.ron @@ -0,0 +1,11 @@ +EntityConfig ( + name: Automatic, + body: RandomWith("crawler_moss"), + alignment: Alignment(Wild), + + loot: LootTable("common.loot_tables.creature.arthropod.ooze"), + + hands: Uninit, + + meta: [], +) diff --git a/assets/common/entity/wild/peaceful/crawler_sand.ron b/assets/common/entity/wild/peaceful/crawler_sand.ron new file mode 100644 index 0000000000..a47674a217 --- /dev/null +++ b/assets/common/entity/wild/peaceful/crawler_sand.ron @@ -0,0 +1,11 @@ +EntityConfig ( + name: Automatic, + body: RandomWith("crawler_sand"), + alignment: Alignment(Wild), + + loot: LootTable("common.loot_tables.creature.arthropod.ooze"), + + hands: Uninit, + + meta: [], +) diff --git a/assets/common/entity/wild/peaceful/leaf_beetle.ron b/assets/common/entity/wild/peaceful/leaf_beetle.ron new file mode 100644 index 0000000000..ec0f28c6c4 --- /dev/null +++ b/assets/common/entity/wild/peaceful/leaf_beetle.ron @@ -0,0 +1,11 @@ +EntityConfig ( + name: Automatic, + body: RandomWith("leaf_beetle"), + alignment: Alignment(Wild), + + loot: LootTable("common.loot_tables.creature.arthropod.leaf"), + + hands: Uninit, + + meta: [], +) diff --git a/assets/common/items/npc_armor/arthropod/generic.ron b/assets/common/items/npc_armor/arthropod/generic.ron new file mode 100644 index 0000000000..1b1628492d --- /dev/null +++ b/assets/common/items/npc_armor/arthropod/generic.ron @@ -0,0 +1,13 @@ +ItemDef( + name: "Arthropod Armor", + description: "Worn by arthropods.", + kind: Armor(( + kind: Chest("Arthropod"), + stats: ( + 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_weapons/unique/arthropodbasic.ron b/assets/common/items/npc_weapons/unique/arthropodbasic.ron new file mode 100644 index 0000000000..d3626cbcbb --- /dev/null +++ b/assets/common/items/npc_weapons/unique/arthropodbasic.ron @@ -0,0 +1,21 @@ +ItemDef( + name: "Arthropod Basic", + description: "testing123", + kind: Tool(( + kind: Natural, + hands: Two, + stats: Direct(( + equip_time_secs: 0.01, + power: 1.0, + effect_power: 1.0, + speed: 1.0, + crit_chance: 0.1, + range: 1.0, + energy_efficiency: 1.0, + buff_strength: 1.0, + )), + )), + quality: Low, + tags: [], + ability_spec: Some(Custom("Arthropod Basic")), +) \ No newline at end of file diff --git a/assets/common/items/npc_weapons/unique/arthropodcharge.ron b/assets/common/items/npc_weapons/unique/arthropodcharge.ron new file mode 100644 index 0000000000..fdea93f1df --- /dev/null +++ b/assets/common/items/npc_weapons/unique/arthropodcharge.ron @@ -0,0 +1,21 @@ +ItemDef( + name: "Arthropod Charge", + description: "testing123", + kind: Tool(( + kind: Natural, + hands: Two, + stats: Direct(( + equip_time_secs: 0.01, + power: 1.0, + effect_power: 1.0, + speed: 1.0, + crit_chance: 0.1, + range: 1.0, + energy_efficiency: 1.0, + buff_strength: 1.0, + )), + )), + quality: Low, + tags: [], + ability_spec: Some(Custom("Arthropod Charge")), +) \ No newline at end of file diff --git a/assets/common/items/npc_weapons/unique/arthropodleap.ron b/assets/common/items/npc_weapons/unique/arthropodleap.ron new file mode 100644 index 0000000000..243a455abd --- /dev/null +++ b/assets/common/items/npc_weapons/unique/arthropodleap.ron @@ -0,0 +1,21 @@ +ItemDef( + name: "Arthropod Leap", + description: "testing123", + kind: Tool(( + kind: Natural, + hands: Two, + stats: Direct(( + equip_time_secs: 0.01, + power: 1.0, + effect_power: 1.0, + speed: 1.0, + crit_chance: 0.1, + range: 1.0, + energy_efficiency: 1.0, + buff_strength: 1.0, + )), + )), + quality: Low, + tags: [], + ability_spec: Some(Custom("Arthropod Leap")), +) \ No newline at end of file diff --git a/assets/common/items/npc_weapons/unique/arthropodranged.ron b/assets/common/items/npc_weapons/unique/arthropodranged.ron new file mode 100644 index 0000000000..00e6cee476 --- /dev/null +++ b/assets/common/items/npc_weapons/unique/arthropodranged.ron @@ -0,0 +1,21 @@ +ItemDef( + name: "Arthropod Ranged", + description: "testing123", + kind: Tool(( + kind: Natural, + hands: Two, + stats: Direct(( + equip_time_secs: 0.01, + power: 1.0, + effect_power: 1.0, + speed: 1.0, + crit_chance: 0.1, + range: 1.0, + energy_efficiency: 1.0, + buff_strength: 1.0, + )), + )), + quality: Low, + tags: [], + ability_spec: Some(Custom("Arthropod Ranged")), +) \ No newline at end of file diff --git a/assets/common/loot_tables/creature/arthropod/carapace.ron b/assets/common/loot_tables/creature/arthropod/carapace.ron new file mode 100644 index 0000000000..e926817db9 --- /dev/null +++ b/assets/common/loot_tables/creature/arthropod/carapace.ron @@ -0,0 +1,3 @@ +[ + (1.0, ItemQuantity("common.items.crafting_ing.hide.carapace", 1, 3)), +] \ No newline at end of file diff --git a/assets/common/loot_tables/creature/arthropod/leaf.ron b/assets/common/loot_tables/creature/arthropod/leaf.ron new file mode 100644 index 0000000000..e749a8e587 --- /dev/null +++ b/assets/common/loot_tables/creature/arthropod/leaf.ron @@ -0,0 +1,5 @@ +[ + (1.0, ItemQuantity("common.items.flowers.plant_fiber", 1, 3)), + (0.5, ItemQuantity("common.items.crafting_ing.twigs", 1, 3)), + (0.5, ItemQuantity("common.items.crafting_ing.animal_misc.viscous_ooze", 1, 1)), +] \ No newline at end of file diff --git a/assets/common/loot_tables/creature/arthropod/ooze.ron b/assets/common/loot_tables/creature/arthropod/ooze.ron new file mode 100644 index 0000000000..041a94de30 --- /dev/null +++ b/assets/common/loot_tables/creature/arthropod/ooze.ron @@ -0,0 +1,4 @@ +[ + (1.0, ItemQuantity("common.items.crafting_ing.sticky_thread", 1, 3)), + (0.5, ItemQuantity("common.items.crafting_ing.animal_misc.viscous_ooze", 1, 1)), +] \ No newline at end of file diff --git a/assets/common/loot_tables/creature/arthropod/venom.ron b/assets/common/loot_tables/creature/arthropod/venom.ron new file mode 100644 index 0000000000..d3831e8702 --- /dev/null +++ b/assets/common/loot_tables/creature/arthropod/venom.ron @@ -0,0 +1,4 @@ +[ + (1.0, ItemQuantity("common.items.crafting_ing.sticky_thread", 1, 3)), + (0.5, ItemQuantity("common.items.crafting_ing.animal_misc.venom_sac", 1, 1)), +] \ No newline at end of file diff --git a/assets/common/loot_tables/creature/arthropod/web.ron b/assets/common/loot_tables/creature/arthropod/web.ron new file mode 100644 index 0000000000..7f292f293f --- /dev/null +++ b/assets/common/loot_tables/creature/arthropod/web.ron @@ -0,0 +1,3 @@ +[ + (1.0, ItemQuantity("common.items.crafting_ing.sticky_thread", 1, 3)), +] \ No newline at end of file diff --git a/assets/common/npc_names.ron b/assets/common/npc_names.ron index a68091e6b1..7168fca7d2 100644 --- a/assets/common/npc_names.ron +++ b/assets/common/npc_names.ron @@ -1207,5 +1207,59 @@ generic: "Deadwood" ), ) - ) + ), + arthropod: ( + body: ( + keyword: "arthropod", + names_0: [ + "Shelob" + ] + ), + species: ( + tarantula: ( + keyword: "tarantula", + generic: "Tarantula" + ), + black_widow: ( + keyword: "black_widow", + generic: "Blackwidow" + ), + antlion: ( + keyword: "antlion", + generic: "Antlion" + ), + horn_beetle: ( + keyword: "horn_beetle", + generic: "Horn Beetle" + ), + leaf_beetle: ( + keyword: "leaf_beetle", + generic: "Leaf Beetle" + ), + stag_beetle: ( + keyword: "stag_beetle", + generic: "Stag Beetle" + ), + weevil: ( + keyword: "weevil", + generic: "Weevil" + ), + cave_spider: ( + keyword: "cave_spider", + generic: "Cave Spider" + ), + crawler_molten: ( + keyword: "crawler_molten", + generic: "Molten Crawler" + ), + crawler_moss: ( + keyword: "crawler_moss", + generic: "Moss Crawler" + ), + crawler_sand: ( + keyword: "crawler_sand", + generic: "Sand Crawler" + ), + ) + ), ) diff --git a/assets/voxygen/element/de_buffs/debuff_poisoned_0.png b/assets/voxygen/element/de_buffs/debuff_poisoned_0.png new file mode 100644 index 0000000000..40610ad467 --- /dev/null +++ b/assets/voxygen/element/de_buffs/debuff_poisoned_0.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:373bc89a28a59852efea275b234cdb47388eb7daead2232871fc9811899c2fa9 +size 309 diff --git a/assets/voxygen/voxel/arthropod_central_manifest.ron b/assets/voxygen/voxel/arthropod_central_manifest.ron new file mode 100644 index 0000000000..5848158a16 --- /dev/null +++ b/assets/voxygen/voxel/arthropod_central_manifest.ron @@ -0,0 +1,222 @@ +({ + (Tarantula, Male): ( + head: ( + offset: (-4.5, 0.0, -2.5), + central: ("npc.tarantula.male.head"), + ), + chest: ( + offset: (-5.5, -7.0, -4.0), + central: ("npc.tarantula.male.chest"), + ), + ), + (Tarantula, Female): ( + head: ( + offset: (-4.5, 0.0, -2.5), + central: ("npc.tarantula.male.head"), + ), + chest: ( + offset: (-5.5, -7.0, -4.0), + central: ("npc.tarantula.male.chest"), + ), + ), + (Blackwidow, Male): ( + head: ( + offset: (-4.5, 0.0, -3.0), + central: ("npc.black_widow.male.head"), + ), + chest: ( + offset: (-4.5, -7.5, -6.0), + central: ("npc.black_widow.male.chest"), + ), + ), + (Blackwidow, Female): ( + head: ( + offset: (-4.5, 0.0, -3.0), + central: ("npc.black_widow.male.head"), + ), + chest: ( + offset: (-4.5, -7.5, -6.0), + central: ("npc.black_widow.male.chest"), + ), + ), + (Antlion, Male): ( + head: ( + offset: (-6.5, 0.0, -5.5), + central: ("npc.antlion.male.head"), + ), + chest: ( + offset: (-5.5, -7.5, -5.5), + central: ("npc.antlion.male.chest"), + ), + ), + (Antlion, Female): ( + head: ( + offset: (-6.5, 0.0, -5.5), + central: ("npc.antlion.male.head"), + ), + chest: ( + offset: (-5.5, -7.5, -5.5), + central: ("npc.antlion.male.chest"), + ), + ), + (Hornbeetle, Male): ( + head: ( + offset: (-5.5, 0.0, -7.5), + central: ("npc.horn_beetle.male.head"), + ), + chest: ( + offset: (-4.5, -6.0, -3.5), + central: ("npc.horn_beetle.male.chest"), + ), + ), + (Hornbeetle, Female): ( + head: ( + offset: (-5.5, 0.0, -7.5), + central: ("npc.horn_beetle.male.head"), + ), + chest: ( + offset: (-4.5, -6.0, -3.5), + central: ("npc.horn_beetle.male.chest"), + ), + ), + (Leafbeetle, Male): ( + head: ( + offset: (-5.5, 0.0, -3.0), + central: ("npc.leaf_beetle.male.head"), + ), + chest: ( + offset: (-4.5, -5.0, -3.0), + central: ("npc.leaf_beetle.male.chest"), + ), + ), + (Leafbeetle, Female): ( + head: ( + offset: (-5.5, 0.0, -3.0), + central: ("npc.leaf_beetle.male.head"), + ), + chest: ( + offset: (-4.5, -5.0, -3.0), + central: ("npc.leaf_beetle.male.chest"), + ), + ), + (Stagbeetle, Male): ( + head: ( + offset: (-8.5, 0.0, -4.5), + central: ("npc.stag_beetle.male.head"), + ), + chest: ( + offset: (-4.5, -6.0, -3.5), + central: ("npc.stag_beetle.male.chest"), + ), + ), + (Stagbeetle, Female): ( + head: ( + offset: (-8.5, 0.0, -4.5), + central: ("npc.stag_beetle.male.head"), + ), + chest: ( + offset: (-4.5, -6.0, -3.5), + central: ("npc.stag_beetle.male.chest"), + ), + ), + (Weevil, Male): ( + head: ( + offset: (-4.5, 0.0, -3.0), + central: ("npc.weevil.male.head"), + ), + chest: ( + offset: (-4.5, -5.0, -3.0), + central: ("npc.weevil.male.chest"), + ), + ), + (Weevil, Female): ( + head: ( + offset: (-4.5, 0.0, -3.0), + central: ("npc.weevil.male.head"), + ), + chest: ( + offset: (-4.5, -5.0, -3.0), + central: ("npc.weevil.male.chest"), + ), + ), + (Cavespider, Male): ( + head: ( + offset: (-4.5, 0.0, -2.5), + central: ("npc.cave_spider.male.head"), + ), + chest: ( + offset: (-5.5, -7.0, -4.0), + central: ("npc.cave_spider.male.chest"), + ), + ), + (Cavespider, Female): ( + head: ( + offset: (-4.5, 0.0, -2.5), + central: ("npc.cave_spider.male.head"), + ), + chest: ( + offset: (-5.5, -7.0, -4.0), + central: ("npc.cave_spider.male.chest"), + ), + ), + (Moltencrawler, Male): ( + head: ( + offset: (-7.5, 0.0, -4.0), + central: ("npc.crawler_molten.male.head"), + ), + chest: ( + offset: (-4.5, -5.0, -5.0), + central: ("npc.crawler_molten.male.chest"), + ), + ), + (Moltencrawler, Female): ( + head: ( + offset: (-7.5, 0.0, -4.0), + central: ("npc.crawler_molten.male.head"), + ), + chest: ( + offset: (-4.5, -5.0, -5.0), + central: ("npc.crawler_molten.male.chest"), + ), + ), + (Mosscrawler, Male): ( + head: ( + offset: (-5.5, 0.0, -4.0), + central: ("npc.crawler_moss.male.head"), + ), + chest: ( + offset: (-3.5, -5.0, -5.5), + central: ("npc.crawler_moss.male.chest"), + ), + ), + (Mosscrawler, Female): ( + head: ( + offset: (-5.5, 0.0, -4.0), + central: ("npc.crawler_moss.male.head"), + ), + chest: ( + offset: (-3.5, -5.0, -5.5), + central: ("npc.crawler_moss.male.chest"), + ), + ), + (Sandcrawler, Male): ( + head: ( + offset: (-5.5, 0.0, -4.0), + central: ("npc.crawler_sand.male.head"), + ), + chest: ( + offset: (-3.5, -5.0, -5.0), + central: ("npc.crawler_sand.male.chest"), + ), + ), + (Sandcrawler, Female): ( + head: ( + offset: (-5.5, 0.0, -4.0), + central: ("npc.crawler_sand.male.head"), + ), + chest: ( + offset: (-3.5, -5.0, -5.0), + central: ("npc.crawler_sand.male.chest"), + ), + ), +}) diff --git a/assets/voxygen/voxel/arthropod_lateral_manifest.ron b/assets/voxygen/voxel/arthropod_lateral_manifest.ron new file mode 100644 index 0000000000..ce0faddc2a --- /dev/null +++ b/assets/voxygen/voxel/arthropod_lateral_manifest.ron @@ -0,0 +1,1278 @@ +({ + (Tarantula, Male): ( + mandible_l: ( + offset: (-1.0, 0.0, -4.0), + lateral: ("npc.tarantula.male.mandible_r"), + ), + mandible_r: ( + offset: (-1.0, 0.0, -4.0), + lateral: ("npc.tarantula.male.mandible_r"), + ), + wing_fl: ( + offset: (-6.0, -4.5, -8.0), + lateral: ("armor.empty"), + ), + wing_fr: ( + offset: (0.0, -4.5, -8.0), + lateral: ("armor.empty"), + ), + wing_bl: ( + offset: (-11.0, -1.0, -8.0), + lateral: ("armor.empty"), + ), + wing_br: ( + offset: (-11.0, -1.0, -8.0), + lateral: ("armor.empty"), + ), + leg_fl: ( + offset: (-1.5, 0.0, -4.5), + lateral: ("npc.tarantula.male.leg_fr"), + ), + leg_fr: ( + offset: (-1.5, 0.0, -4.5), + lateral: ("npc.tarantula.male.leg_fr"), + ), + leg_fcl: ( + offset: (-12.0, -1.5, -4.5), + lateral: ("npc.tarantula.male.leg_fcr"), + ), + leg_fcr: ( + offset: (0.0, -1.5, -4.5), + lateral: ("npc.tarantula.male.leg_fcr"), + ), + leg_bcl: ( + offset: (-13.0, -1.5, -4.5), + lateral: ("npc.tarantula.male.leg_bcr"), + ), + leg_bcr: ( + offset: (0.0, -1.5, -4.5), + lateral: ("npc.tarantula.male.leg_bcr"), + ), + leg_bl: ( + offset: (-12.0, -1.5, -4.5), + lateral: ("npc.tarantula.male.leg_br"), + ), + leg_br: ( + offset: (0.0, -1.5, -4.5), + lateral: ("npc.tarantula.male.leg_br"), + ), + ), + (Tarantula, Female): ( + mandible_l: ( + offset: (-1.0, 0.0, -4.0), + lateral: ("npc.tarantula.male.mandible_r"), + ), + mandible_r: ( + offset: (-1.0, 0.0, -4.0), + lateral: ("npc.tarantula.male.mandible_r"), + ), + wing_fl: ( + offset: (-6.0, -4.5, -8.0), + lateral: ("armor.empty"), + ), + wing_fr: ( + offset: (0.0, -4.5, -8.0), + lateral: ("armor.empty"), + ), + wing_bl: ( + offset: (-11.0, -1.0, -8.0), + lateral: ("armor.empty"), + ), + wing_br: ( + offset: (-11.0, -1.0, -8.0), + lateral: ("armor.empty"), + ), + leg_fl: ( + offset: (-1.5, 0.0, -4.5), + lateral: ("npc.tarantula.male.leg_fr"), + ), + leg_fr: ( + offset: (-1.5, 0.0, -4.5), + lateral: ("npc.tarantula.male.leg_fr"), + ), + leg_fcl: ( + offset: (-12.0, -1.5, -4.5), + lateral: ("npc.tarantula.male.leg_fcr"), + ), + leg_fcr: ( + offset: (0.0, -1.5, -4.5), + lateral: ("npc.tarantula.male.leg_fcr"), + ), + leg_bcl: ( + offset: (-13.0, -1.5, -4.5), + lateral: ("npc.tarantula.male.leg_bcr"), + ), + leg_bcr: ( + offset: (0.0, -1.5, -4.5), + lateral: ("npc.tarantula.male.leg_bcr"), + ), + leg_bl: ( + offset: (-12.0, -1.5, -4.5), + lateral: ("npc.tarantula.male.leg_br"), + ), + leg_br: ( + offset: (0.0, -1.5, -4.5), + lateral: ("npc.tarantula.male.leg_br"), + ), + ), + (Blackwidow, Male): ( + mandible_l: ( + offset: (0.0, 0.0, -3.0), + lateral: ("npc.black_widow.male.mandible_r"), + ), + mandible_r: ( + offset: (-2.0, 0.0, -3.0), + lateral: ("npc.black_widow.male.mandible_r"), + ), + wing_fl: ( + offset: (-6.0, -4.5, -8.0), + lateral: ("armor.empty"), + ), + wing_fr: ( + offset: (0.0, -4.5, -8.0), + lateral: ("armor.empty"), + ), + wing_bl: ( + offset: (-11.0, -1.0, -8.0), + lateral: ("armor.empty"), + ), + wing_br: ( + offset: (-11.0, -1.0, -8.0), + lateral: ("armor.empty"), + ), + leg_fl: ( + offset: (-0.5, -0.0, -4.0), + lateral: ("npc.black_widow.male.leg_fr"), + ), + leg_fr: ( + offset: (-0.5, -0.0, -4.0), + lateral: ("npc.black_widow.male.leg_fr"), + ), + leg_fcl: ( + offset: (-12.0, -0.5, -4.5), + lateral: ("npc.black_widow.male.leg_fcr"), + ), + leg_fcr: ( + offset: (0.0, -0.5, -4.5), + lateral: ("npc.black_widow.male.leg_fcr"), + ), + leg_bcl: ( + offset: (-15.0, -0.5, -4.5), + lateral: ("npc.black_widow.male.leg_bcr"), + ), + leg_bcr: ( + offset: (0.0, -0.5, -4.5), + lateral: ("npc.black_widow.male.leg_bcr"), + ), + leg_bl: ( + offset: (-12.0, -0.5, -4.5), + lateral: ("npc.black_widow.male.leg_br"), + ), + leg_br: ( + offset: (0.0, -0.5, -4.5), + lateral: ("npc.black_widow.male.leg_br"), + ), + ), + (Blackwidow, Female): ( + mandible_l: ( + offset: (0.0, 0.0, -3.0), + lateral: ("npc.black_widow.male.mandible_r"), + ), + mandible_r: ( + offset: (-2.0, 0.0, -3.0), + lateral: ("npc.black_widow.male.mandible_r"), + ), + wing_fl: ( + offset: (-6.0, -4.5, -8.0), + lateral: ("armor.empty"), + ), + wing_fr: ( + offset: (0.0, -4.5, -8.0), + lateral: ("armor.empty"), + ), + wing_bl: ( + offset: (-11.0, -1.0, -8.0), + lateral: ("armor.empty"), + ), + wing_br: ( + offset: (-11.0, -1.0, -8.0), + lateral: ("armor.empty"), + ), + leg_fl: ( + offset: (-0.5, -0.0, -4.0), + lateral: ("npc.black_widow.male.leg_fr"), + ), + leg_fr: ( + offset: (-0.5, -0.0, -4.0), + lateral: ("npc.black_widow.male.leg_fr"), + ), + leg_fcl: ( + offset: (-12.0, -0.5, -4.5), + lateral: ("npc.black_widow.male.leg_fcr"), + ), + leg_fcr: ( + offset: (0.0, -0.5, -4.5), + lateral: ("npc.black_widow.male.leg_fcr"), + ), + leg_bcl: ( + offset: (-15.0, -0.5, -4.5), + lateral: ("npc.black_widow.male.leg_bcr"), + ), + leg_bcr: ( + offset: (0.0, -0.5, -4.5), + lateral: ("npc.black_widow.male.leg_bcr"), + ), + leg_bl: ( + offset: (-12.0, -0.5, -4.5), + lateral: ("npc.black_widow.male.leg_br"), + ), + leg_br: ( + offset: (0.0, -0.5, -4.5), + lateral: ("npc.black_widow.male.leg_br"), + ), + ), + (Antlion, Male): ( + mandible_l: ( + offset: (0.0, 0.0, -1.0), + lateral: ("npc.antlion.male.mandible_r"), + ), + mandible_r: ( + offset: (-7.0, 0.0, -1.0), + lateral: ("npc.antlion.male.mandible_r"), + ), + wing_fl: ( + offset: (-6.0, -4.5, -8.0), + lateral: ("armor.empty"), + ), + wing_fr: ( + offset: (0.0, -4.5, -8.0), + lateral: ("armor.empty"), + ), + wing_bl: ( + offset: (-11.0, -1.0, -8.0), + lateral: ("armor.empty"), + ), + wing_br: ( + offset: (-11.0, -1.0, -8.0), + lateral: ("armor.empty"), + ), + leg_fl: ( + offset: (-0.5, 0.0, -4.5), + lateral: ("npc.antlion.male.leg_fr"), + ), + leg_fr: ( + offset: (-0.5, 0.0, -4.5), + lateral: ("npc.antlion.male.leg_fr"), + ), + leg_fcl: ( + offset: (-17.0, -0.5, -4.5), + lateral: ("npc.antlion.male.leg_fcr"), + ), + leg_fcr: ( + offset: (0.0, -0.5, -4.5), + lateral: ("npc.antlion.male.leg_fcr"), + ), + leg_bcl: ( + offset: (-0.5, -18.0, -4.5), + lateral: ("npc.antlion.male.leg_bcr"), + ), + leg_bcr: ( + offset: (-0.5, -18.0, -4.5), + lateral: ("npc.antlion.male.leg_bcr"), + ), + leg_bl: ( + offset: (-12.0, -1.5, -4.5), + lateral: ("armor.empty"), + ), + leg_br: ( + offset: (0.0, -1.5, -4.5), + lateral: ("armor.empty"), + ), + ), + (Antlion, Female): ( + mandible_l: ( + offset: (0.0, 0.0, -1.0), + lateral: ("npc.antlion.male.mandible_r"), + ), + mandible_r: ( + offset: (-7.0, 0.0, -1.0), + lateral: ("npc.antlion.male.mandible_r"), + ), + wing_fl: ( + offset: (-6.0, -4.5, -8.0), + lateral: ("armor.empty"), + ), + wing_fr: ( + offset: (0.0, -4.5, -8.0), + lateral: ("armor.empty"), + ), + wing_bl: ( + offset: (-11.0, -1.0, -8.0), + lateral: ("armor.empty"), + ), + wing_br: ( + offset: (-11.0, -1.0, -8.0), + lateral: ("armor.empty"), + ), + leg_fl: ( + offset: (-0.5, 0.0, -4.5), + lateral: ("npc.antlion.male.leg_fr"), + ), + leg_fr: ( + offset: (-0.5, 0.0, -4.5), + lateral: ("npc.antlion.male.leg_fr"), + ), + leg_fcl: ( + offset: (-17.0, -0.5, -4.5), + lateral: ("npc.antlion.male.leg_fcr"), + ), + leg_fcr: ( + offset: (0.0, -0.5, -4.5), + lateral: ("npc.antlion.male.leg_fcr"), + ), + leg_bcl: ( + offset: (-0.5, -18.0, -4.5), + lateral: ("npc.antlion.male.leg_bcr"), + ), + leg_bcr: ( + offset: (-0.5, -18.0, -4.5), + lateral: ("npc.antlion.male.leg_bcr"), + ), + leg_bl: ( + offset: (-12.0, -1.5, -4.5), + lateral: ("armor.empty"), + ), + leg_br: ( + offset: (0.0, -1.5, -4.5), + lateral: ("armor.empty"), + ), + ), + (Hornbeetle, Male): ( + mandible_l: ( + offset: (-1.0, 0.0, -4.0), + lateral: ("armor.empty"), + ), + mandible_r: ( + offset: (-1.0, 0.0, -4.0), + lateral: ("armor.empty"), + ), + wing_fl: ( + offset: (-0.0, -12.0, -3.5), + lateral: ("npc.horn_beetle.male.wing_fr"), + ), + wing_fr: ( + offset: (-5.0, -12.0, -3.5), + lateral: ("npc.horn_beetle.male.wing_fr"), + ), + wing_bl: ( + offset: (-0.0, -12.0, -0.5), + lateral: ("npc.horn_beetle.male.wing_br"), + ), + wing_br: ( + offset: (-4.0, -12.0, -0.5), + lateral: ("npc.horn_beetle.male.wing_br"), + ), + leg_fl: ( + offset: (-1.5, 0.0, -4.5), + lateral: ("npc.horn_beetle.male.leg_fr"), + ), + leg_fr: ( + offset: (-1.5, 0.0, -4.5), + lateral: ("npc.horn_beetle.male.leg_fr"), + ), + leg_fcl: ( + offset: (-12.0, -1.5, -4.5), + lateral: ("npc.horn_beetle.male.leg_fcr"), + ), + leg_fcr: ( + offset: (0.0, -1.5, -4.5), + lateral: ("npc.horn_beetle.male.leg_fcr"), + ), + leg_bcl: ( + offset: (-1.5, -14.0, -4.5), + lateral: ("npc.horn_beetle.male.leg_bcr"), + ), + leg_bcr: ( + offset: (-1.5, -14.0, -4.5), + lateral: ("npc.horn_beetle.male.leg_bcr"), + ), + leg_bl: ( + offset: (-12.0, -1.5, -4.5), + lateral: ("armor.empty"), + ), + leg_br: ( + offset: (0.0, -1.5, -4.5), + lateral: ("armor.empty"), + ), + ), + (Hornbeetle, Female): ( + mandible_l: ( + offset: (-1.0, 0.0, -4.0), + lateral: ("armor.empty"), + ), + mandible_r: ( + offset: (-1.0, 0.0, -4.0), + lateral: ("armor.empty"), + ), + wing_fl: ( + offset: (-0.0, -12.0, -3.5), + lateral: ("npc.horn_beetle.male.wing_fr"), + ), + wing_fr: ( + offset: (-5.0, -12.0, -3.5), + lateral: ("npc.horn_beetle.male.wing_fr"), + ), + wing_bl: ( + offset: (-0.0, -12.0, -0.5), + lateral: ("npc.horn_beetle.male.wing_br"), + ), + wing_br: ( + offset: (-4.0, -12.0, -0.5), + lateral: ("npc.horn_beetle.male.wing_br"), + ), + leg_fl: ( + offset: (-1.5, 0.0, -4.5), + lateral: ("npc.horn_beetle.male.leg_fr"), + ), + leg_fr: ( + offset: (-1.5, 0.0, -4.5), + lateral: ("npc.horn_beetle.male.leg_fr"), + ), + leg_fcl: ( + offset: (-12.0, -1.5, -4.5), + lateral: ("npc.horn_beetle.male.leg_fcr"), + ), + leg_fcr: ( + offset: (0.0, -1.5, -4.5), + lateral: ("npc.horn_beetle.male.leg_fcr"), + ), + leg_bcl: ( + offset: (-1.5, -14.0, -4.5), + lateral: ("npc.horn_beetle.male.leg_bcr"), + ), + leg_bcr: ( + offset: (-1.5, -14.0, -4.5), + lateral: ("npc.horn_beetle.male.leg_bcr"), + ), + leg_bl: ( + offset: (-12.0, -1.5, -4.5), + lateral: ("armor.empty"), + ), + leg_br: ( + offset: (0.0, -1.5, -4.5), + lateral: ("armor.empty"), + ), + ), + (Leafbeetle, Male): ( + mandible_l: ( + offset: (-1.0, 0.0, -4.0), + lateral: ("armor.empty"), + ), + mandible_r: ( + offset: (-1.0, 0.0, -4.0), + lateral: ("armor.empty"), + ), + wing_fl: ( + offset: (-7.0, -14.0, -4.0), + lateral: ("npc.leaf_beetle.male.wing_fr"), + ), + wing_fr: ( + offset: (-0.0, -14.0, -4.0), + lateral: ("npc.leaf_beetle.male.wing_fr"), + ), + wing_bl: ( + offset: (-4.0, -8.0, -0.5), + lateral: ("npc.leaf_beetle.male.wing_br"), + ), + wing_br: ( + offset: (-0.0, -8.0, -0.5), + lateral: ("npc.leaf_beetle.male.wing_br"), + ), + leg_fl: ( + offset: (-1.5, 0.0, -5.0), + lateral: ("npc.leaf_beetle.male.leg_fr"), + ), + leg_fr: ( + offset: (-1.5, 0.0, -5.0), + lateral: ("npc.leaf_beetle.male.leg_fr"), + ), + leg_fcl: ( + offset: (-9.0, -1.5, -4.5), + lateral: ("npc.leaf_beetle.male.leg_fcr"), + ), + leg_fcr: ( + offset: (-0.0, -1.5, -4.5), + lateral: ("npc.leaf_beetle.male.leg_fcr"), + ), + leg_bcl: ( + offset: (-1.5, -11.0, -3.5), + lateral: ("npc.leaf_beetle.male.leg_bcr"), + ), + leg_bcr: ( + offset: (-1.5, -11.0, -3.5), + lateral: ("npc.leaf_beetle.male.leg_bcr"), + ), + leg_bl: ( + offset: (-12.0, -1.5, -4.5), + lateral: ("armor.empty"), + ), + leg_br: ( + offset: (0.0, -1.5, -4.5), + lateral: ("armor.empty"), + ), + ), + (Leafbeetle, Female): ( + mandible_l: ( + offset: (-1.0, 0.0, -4.0), + lateral: ("armor.empty"), + ), + mandible_r: ( + offset: (-1.0, 0.0, -4.0), + lateral: ("armor.empty"), + ), + wing_fl: ( + offset: (-7.0, -14.0, -4.0), + lateral: ("npc.leaf_beetle.male.wing_fr"), + ), + wing_fr: ( + offset: (-0.0, -14.0, -4.0), + lateral: ("npc.leaf_beetle.male.wing_fr"), + ), + wing_bl: ( + offset: (-4.0, -8.0, -0.5), + lateral: ("npc.leaf_beetle.male.wing_br"), + ), + wing_br: ( + offset: (-0.0, -8.0, -0.5), + lateral: ("npc.leaf_beetle.male.wing_br"), + ), + leg_fl: ( + offset: (-1.5, 0.0, -5.0), + lateral: ("npc.leaf_beetle.male.leg_fr"), + ), + leg_fr: ( + offset: (-1.5, 0.0, -5.0), + lateral: ("npc.leaf_beetle.male.leg_fr"), + ), + leg_fcl: ( + offset: (-9.0, -1.5, -4.5), + lateral: ("npc.leaf_beetle.male.leg_fcr"), + ), + leg_fcr: ( + offset: (-0.0, -1.5, -4.5), + lateral: ("npc.leaf_beetle.male.leg_fcr"), + ), + leg_bcl: ( + offset: (-1.5, -11.0, -3.5), + lateral: ("npc.leaf_beetle.male.leg_bcr"), + ), + leg_bcr: ( + offset: (-1.5, -11.0, -3.5), + lateral: ("npc.leaf_beetle.male.leg_bcr"), + ), + leg_bl: ( + offset: (-12.0, -1.5, -4.5), + lateral: ("armor.empty"), + ), + leg_br: ( + offset: (0.0, -1.5, -4.5), + lateral: ("armor.empty"), + ), + ), + (Stagbeetle, Male): ( + mandible_l: ( + offset: (-7.0, -0.0, -1.5), + lateral: ("npc.stag_beetle.male.mandible_r"), + ), + mandible_r: ( + offset: (-0.0, -0.0, -1.5), + lateral: ("npc.stag_beetle.male.mandible_r"), + ), + wing_fl: ( + offset: (-5.0, -13.0, -4.0), + lateral: ("npc.stag_beetle.male.wing_fr"), + ), + wing_fr: ( + offset: (-0.0, -13.0, -4.0), + lateral: ("npc.stag_beetle.male.wing_fr"), + ), + wing_bl: ( + offset: (-4.0, -12.0, -0.5), + lateral: ("npc.stag_beetle.male.wing_br"), + ), + wing_br: ( + offset: (-0.0, -12.0, -0.5), + lateral: ("npc.stag_beetle.male.wing_br"), + ), + leg_fl: ( + offset: (-1.5, 0.0, -4.5), + lateral: ("npc.stag_beetle.male.leg_fr"), + ), + leg_fr: ( + offset: (-1.5, 0.0, -4.5), + lateral: ("npc.stag_beetle.male.leg_fr"), + ), + leg_fcl: ( + offset: (-12.0, -1.5, -4.5), + lateral: ("npc.stag_beetle.male.leg_fcr"), + ), + leg_fcr: ( + offset: (-0.0, -1.5, -4.5), + lateral: ("npc.stag_beetle.male.leg_fcr"), + ), + leg_bcl: ( + offset: (-1.5, -14.0, -4.5), + lateral: ("npc.stag_beetle.male.leg_bcr"), + ), + leg_bcr: ( + offset: (-1.5, -14.0, -4.5), + lateral: ("npc.stag_beetle.male.leg_bcr"), + ), + leg_bl: ( + offset: (-12.0, -1.5, -4.5), + lateral: ("armor.empty"), + ), + leg_br: ( + offset: (0.0, -1.5, -4.5), + lateral: ("armor.empty"), + ), + ), + (Stagbeetle, Female): ( + mandible_l: ( + offset: (-7.0, -0.0, -1.5), + lateral: ("npc.stag_beetle.male.mandible_r"), + ), + mandible_r: ( + offset: (-0.0, -0.0, -1.5), + lateral: ("npc.stag_beetle.male.mandible_r"), + ), + wing_fl: ( + offset: (-5.0, -13.0, -4.0), + lateral: ("npc.stag_beetle.male.wing_fr"), + ), + wing_fr: ( + offset: (-0.0, -13.0, -4.0), + lateral: ("npc.stag_beetle.male.wing_fr"), + ), + wing_bl: ( + offset: (-4.0, -12.0, -0.5), + lateral: ("npc.stag_beetle.male.wing_br"), + ), + wing_br: ( + offset: (-0.0, -12.0, -0.5), + lateral: ("npc.stag_beetle.male.wing_br"), + ), + leg_fl: ( + offset: (-1.5, 0.0, -4.5), + lateral: ("npc.stag_beetle.male.leg_fr"), + ), + leg_fr: ( + offset: (-1.5, 0.0, -4.5), + lateral: ("npc.stag_beetle.male.leg_fr"), + ), + leg_fcl: ( + offset: (-12.0, -1.5, -4.5), + lateral: ("npc.stag_beetle.male.leg_fcr"), + ), + leg_fcr: ( + offset: (-0.0, -1.5, -4.5), + lateral: ("npc.stag_beetle.male.leg_fcr"), + ), + leg_bcl: ( + offset: (-1.5, -14.0, -4.5), + lateral: ("npc.stag_beetle.male.leg_bcr"), + ), + leg_bcr: ( + offset: (-1.5, -14.0, -4.5), + lateral: ("npc.stag_beetle.male.leg_bcr"), + ), + leg_bl: ( + offset: (-12.0, -1.5, -4.5), + lateral: ("armor.empty"), + ), + leg_br: ( + offset: (0.0, -1.5, -4.5), + lateral: ("armor.empty"), + ), + ), + (Weevil, Male): ( + mandible_l: ( + offset: (-1.0, 0.0, -4.0), + lateral: ("armor.empty"), + ), + mandible_r: ( + offset: (-1.0, 0.0, -4.0), + lateral: ("armor.empty"), + ), + wing_fl: ( + offset: (-5.0, -11.0, -4.0), + lateral: ("npc.weevil.male.wing_fr"), + ), + wing_fr: ( + offset: (-0.0, -11.0, -4.0), + lateral: ("npc.weevil.male.wing_fr"), + ), + wing_bl: ( + offset: (-4.0, -8.0, -0.5), + lateral: ("npc.weevil.male.wing_br"), + ), + wing_br: ( + offset: (-0.0, -8.0, -0.5), + lateral: ("npc.weevil.male.wing_br"), + ), + leg_fl: ( + offset: (-1.5, 0.0, -4.0), + lateral: ("npc.weevil.male.leg_fr"), + ), + leg_fr: ( + offset: (-1.5, 0.0, -4.0), + lateral: ("npc.weevil.male.leg_fr"), + ), + leg_fcl: ( + offset: (-9.0, -1.5, -4.0), + lateral: ("npc.weevil.male.leg_fcr"), + ), + leg_fcr: ( + offset: (0.0, -1.5, -4.0), + lateral: ("npc.weevil.male.leg_fcr"), + ), + leg_bcl: ( + offset: (-1.5, -11.0, -3.5), + lateral: ("npc.weevil.male.leg_bcr"), + ), + leg_bcr: ( + offset: (-1.5, -11.0, -3.5), + lateral: ("npc.weevil.male.leg_bcr"), + ), + leg_bl: ( + offset: (-12.0, -1.5, -4.5), + lateral: ("armor.empty"), + ), + leg_br: ( + offset: (0.0, -1.5, -4.5), + lateral: ("armor.empty"), + ), + ), + (Weevil, Female): ( + mandible_l: ( + offset: (-1.0, 0.0, -4.0), + lateral: ("armor.empty"), + ), + mandible_r: ( + offset: (-1.0, 0.0, -4.0), + lateral: ("armor.empty"), + ), + wing_fl: ( + offset: (-5.0, -11.0, -4.0), + lateral: ("npc.weevil.male.wing_fr"), + ), + wing_fr: ( + offset: (-0.0, -11.0, -4.0), + lateral: ("npc.weevil.male.wing_fr"), + ), + wing_bl: ( + offset: (-4.0, -8.0, -0.5), + lateral: ("npc.weevil.male.wing_br"), + ), + wing_br: ( + offset: (-0.0, -8.0, -0.5), + lateral: ("npc.weevil.male.wing_br"), + ), + leg_fl: ( + offset: (-1.5, 0.0, -4.0), + lateral: ("npc.weevil.male.leg_fr"), + ), + leg_fr: ( + offset: (-1.5, 0.0, -4.0), + lateral: ("npc.weevil.male.leg_fr"), + ), + leg_fcl: ( + offset: (-9.0, -1.5, -4.0), + lateral: ("npc.weevil.male.leg_fcr"), + ), + leg_fcr: ( + offset: (0.0, -1.5, -4.0), + lateral: ("npc.weevil.male.leg_fcr"), + ), + leg_bcl: ( + offset: (-1.5, -11.0, -3.5), + lateral: ("npc.weevil.male.leg_bcr"), + ), + leg_bcr: ( + offset: (-1.5, -11.0, -3.5), + lateral: ("npc.weevil.male.leg_bcr"), + ), + leg_bl: ( + offset: (-12.0, -1.5, -4.5), + lateral: ("armor.empty"), + ), + leg_br: ( + offset: (0.0, -1.5, -4.5), + lateral: ("armor.empty"), + ), + ), + (Cavespider, Male): ( + mandible_l: ( + offset: (0.0, 0.0, -3.0), + lateral: ("npc.cave_spider.male.mandible_r"), + ), + mandible_r: ( + offset: (-2.0, 0.0, -3.0), + lateral: ("npc.cave_spider.male.mandible_r"), + ), + wing_fl: ( + offset: (-6.0, -4.5, -8.0), + lateral: ("armor.empty"), + ), + wing_fr: ( + offset: (0.0, -4.5, -8.0), + lateral: ("armor.empty"), + ), + wing_bl: ( + offset: (-11.0, -1.0, -8.0), + lateral: ("armor.empty"), + ), + wing_br: ( + offset: (-11.0, -1.0, -8.0), + lateral: ("armor.empty"), + ), + leg_fl: ( + offset: (-0.5, -0.0, -4.0), + lateral: ("npc.cave_spider.male.leg_fr"), + ), + leg_fr: ( + offset: (-0.5, -0.0, -4.5), + lateral: ("npc.cave_spider.male.leg_fr"), + ), + leg_fcl: ( + offset: (-11.0, -0.5, -4.5), + lateral: ("npc.cave_spider.male.leg_fcr"), + ), + leg_fcr: ( + offset: (0.0, -0.5, -4.5), + lateral: ("npc.cave_spider.male.leg_fcr"), + ), + leg_bcl: ( + offset: (-14.0, -0.5, -4.5), + lateral: ("npc.cave_spider.male.leg_bcr"), + ), + leg_bcr: ( + offset: (0.0, -0.5, -4.5), + lateral: ("npc.cave_spider.male.leg_bcr"), + ), + leg_bl: ( + offset: (-11.0, -0.5, -4.5), + lateral: ("npc.cave_spider.male.leg_br"), + ), + leg_br: ( + offset: (0.0, -0.5, -4.5), + lateral: ("npc.cave_spider.male.leg_br"), + ), + ), + (Cavespider, Female): ( + mandible_l: ( + offset: (0.0, 0.0, -3.0), + lateral: ("npc.cave_spider.male.mandible_r"), + ), + mandible_r: ( + offset: (-2.0, 0.0, -3.0), + lateral: ("npc.cave_spider.male.mandible_r"), + ), + wing_fl: ( + offset: (-6.0, -4.5, -8.0), + lateral: ("armor.empty"), + ), + wing_fr: ( + offset: (0.0, -4.5, -8.0), + lateral: ("armor.empty"), + ), + wing_bl: ( + offset: (-11.0, -1.0, -8.0), + lateral: ("armor.empty"), + ), + wing_br: ( + offset: (-11.0, -1.0, -8.0), + lateral: ("armor.empty"), + ), + leg_fl: ( + offset: (-0.5, -0.0, -4.0), + lateral: ("npc.cave_spider.male.leg_fr"), + ), + leg_fr: ( + offset: (-0.5, -0.0, -4.5), + lateral: ("npc.cave_spider.male.leg_fr"), + ), + leg_fcl: ( + offset: (-11.0, -0.5, -4.5), + lateral: ("npc.cave_spider.male.leg_fcr"), + ), + leg_fcr: ( + offset: (0.0, -0.5, -4.5), + lateral: ("npc.cave_spider.male.leg_fcr"), + ), + leg_bcl: ( + offset: (-14.0, -0.5, -4.5), + lateral: ("npc.cave_spider.male.leg_bcr"), + ), + leg_bcr: ( + offset: (0.0, -0.5, -4.5), + lateral: ("npc.cave_spider.male.leg_bcr"), + ), + leg_bl: ( + offset: (-11.0, -0.5, -4.5), + lateral: ("npc.cave_spider.male.leg_br"), + ), + leg_br: ( + offset: (0.0, -0.5, -4.5), + lateral: ("npc.cave_spider.male.leg_br"), + ), + ), + (Moltencrawler, Male): ( + mandible_l: ( + offset: (0.0, 0.0, -3.0), + lateral: ("armor.empty"), + ), + mandible_r: ( + offset: (-2.0, 0.0, -3.0), + lateral: ("armor.empty"), + ), + wing_fl: ( + offset: (-6.0, -4.5, -8.0), + lateral: ("armor.empty"), + ), + wing_fr: ( + offset: (0.0, -4.5, -8.0), + lateral: ("armor.empty"), + ), + wing_bl: ( + offset: (-11.0, -1.0, -8.0), + lateral: ("armor.empty"), + ), + wing_br: ( + offset: (-11.0, -1.0, -8.0), + lateral: ("armor.empty"), + ), + leg_fl: ( + offset: (-3.0, -1.0, -3.0), + lateral: ("npc.crawler_molten.male.leg_fr"), + ), + leg_fr: ( + offset: (-0.0, -1.0, -3.0), + lateral: ("npc.crawler_molten.male.leg_fr"), + ), + leg_fcl: ( + offset: (-3.0, -1.0, -3.0), + lateral: ("npc.crawler_molten.male.leg_fcr"), + ), + leg_fcr: ( + offset: (-0.0, -1.0, -3.0), + lateral: ("npc.crawler_molten.male.leg_fcr"), + ), + leg_bcl: ( + offset: (-3.0, -1.0, -3.0), + lateral: ("npc.crawler_molten.male.leg_bcr"), + ), + leg_bcr: ( + offset: (-0.0, -1.0, -3.0), + lateral: ("npc.crawler_molten.male.leg_bcr"), + ), + leg_bl: ( + offset: (-11.0, -0.5, -4.5), + lateral: ("armor.empty"), + ), + leg_br: ( + offset: (0.0, -0.5, -4.5), + lateral: ("armor.empty"), + ), + ), + (Moltencrawler, Female): ( + mandible_l: ( + offset: (0.0, 0.0, -3.0), + lateral: ("armor.empty"), + ), + mandible_r: ( + offset: (-2.0, 0.0, -3.0), + lateral: ("armor.empty"), + ), + wing_fl: ( + offset: (-6.0, -4.5, -8.0), + lateral: ("armor.empty"), + ), + wing_fr: ( + offset: (0.0, -4.5, -8.0), + lateral: ("armor.empty"), + ), + wing_bl: ( + offset: (-11.0, -1.0, -8.0), + lateral: ("armor.empty"), + ), + wing_br: ( + offset: (-11.0, -1.0, -8.0), + lateral: ("armor.empty"), + ), + leg_fl: ( + offset: (-3.0, -1.0, -3.0), + lateral: ("npc.crawler_molten.male.leg_fr"), + ), + leg_fr: ( + offset: (-0.0, -1.0, -3.0), + lateral: ("npc.crawler_molten.male.leg_fr"), + ), + leg_fcl: ( + offset: (-3.0, -1.0, -3.0), + lateral: ("npc.crawler_molten.male.leg_fcr"), + ), + leg_fcr: ( + offset: (-0.0, -1.0, -3.0), + lateral: ("npc.crawler_molten.male.leg_fcr"), + ), + leg_bcl: ( + offset: (-3.0, -1.0, -3.0), + lateral: ("npc.crawler_molten.male.leg_bcr"), + ), + leg_bcr: ( + offset: (-0.0, -1.0, -3.0), + lateral: ("npc.crawler_molten.male.leg_bcr"), + ), + leg_bl: ( + offset: (-11.0, -0.5, -4.5), + lateral: ("armor.empty"), + ), + leg_br: ( + offset: (0.0, -0.5, -4.5), + lateral: ("armor.empty"), + ), + ), + (Mosscrawler, Male): ( + mandible_l: ( + offset: (0.0, 0.0, -3.0), + lateral: ("armor.empty"), + ), + mandible_r: ( + offset: (-2.0, 0.0, -3.0), + lateral: ("armor.empty"), + ), + wing_fl: ( + offset: (-6.0, -4.5, -8.0), + lateral: ("armor.empty"), + ), + wing_fr: ( + offset: (0.0, -4.5, -8.0), + lateral: ("armor.empty"), + ), + wing_bl: ( + offset: (-11.0, -1.0, -8.0), + lateral: ("armor.empty"), + ), + wing_br: ( + offset: (-11.0, -1.0, -8.0), + lateral: ("armor.empty"), + ), + leg_fl: ( + offset: (-3.0, -1.0, -3.0), + lateral: ("npc.crawler_moss.male.leg_fr"), + ), + leg_fr: ( + offset: (-0.0, -1.0, -3.0), + lateral: ("npc.crawler_moss.male.leg_fr"), + ), + leg_fcl: ( + offset: (-3.0, -1.0, -3.0), + lateral: ("npc.crawler_moss.male.leg_fcr"), + ), + leg_fcr: ( + offset: (-0.0, -1.0, -3.0), + lateral: ("npc.crawler_moss.male.leg_fcr"), + ), + leg_bcl: ( + offset: (-3.0, -1.0, -3.0), + lateral: ("npc.crawler_moss.male.leg_bcr"), + ), + leg_bcr: ( + offset: (-0.0, -1.0, -3.0), + lateral: ("npc.crawler_moss.male.leg_bcr"), + ), + leg_bl: ( + offset: (-11.0, -0.5, -4.5), + lateral: ("armor.empty"), + ), + leg_br: ( + offset: (0.0, -0.5, -4.5), + lateral: ("armor.empty"), + ), + ), + (Mosscrawler, Female): ( + mandible_l: ( + offset: (0.0, 0.0, -3.0), + lateral: ("armor.empty"), + ), + mandible_r: ( + offset: (-2.0, 0.0, -3.0), + lateral: ("armor.empty"), + ), + wing_fl: ( + offset: (-6.0, -4.5, -8.0), + lateral: ("armor.empty"), + ), + wing_fr: ( + offset: (0.0, -4.5, -8.0), + lateral: ("armor.empty"), + ), + wing_bl: ( + offset: (-11.0, -1.0, -8.0), + lateral: ("armor.empty"), + ), + wing_br: ( + offset: (-11.0, -1.0, -8.0), + lateral: ("armor.empty"), + ), + leg_fl: ( + offset: (-3.0, -1.0, -3.0), + lateral: ("npc.crawler_moss.male.leg_fr"), + ), + leg_fr: ( + offset: (-0.0, -1.0, -3.0), + lateral: ("npc.crawler_moss.male.leg_fr"), + ), + leg_fcl: ( + offset: (-3.0, -1.0, -3.0), + lateral: ("npc.crawler_moss.male.leg_fcr"), + ), + leg_fcr: ( + offset: (-0.0, -1.0, -3.0), + lateral: ("npc.crawler_moss.male.leg_fcr"), + ), + leg_bcl: ( + offset: (-3.0, -1.0, -3.0), + lateral: ("npc.crawler_moss.male.leg_bcr"), + ), + leg_bcr: ( + offset: (-0.0, -1.0, -3.0), + lateral: ("npc.crawler_moss.male.leg_bcr"), + ), + leg_bl: ( + offset: (-11.0, -0.5, -4.5), + lateral: ("armor.empty"), + ), + leg_br: ( + offset: (0.0, -0.5, -4.5), + lateral: ("armor.empty"), + ), + ), + (Sandcrawler, Male): ( + mandible_l: ( + offset: (0.0, 0.0, -3.0), + lateral: ("armor.empty"), + ), + mandible_r: ( + offset: (-2.0, 0.0, -3.0), + lateral: ("armor.empty"), + ), + wing_fl: ( + offset: (-6.0, -4.5, -8.0), + lateral: ("armor.empty"), + ), + wing_fr: ( + offset: (0.0, -4.5, -8.0), + lateral: ("armor.empty"), + ), + wing_bl: ( + offset: (-11.0, -1.0, -8.0), + lateral: ("armor.empty"), + ), + wing_br: ( + offset: (-11.0, -1.0, -8.0), + lateral: ("armor.empty"), + ), + leg_fl: ( + offset: (-3.0, -1.0, -3.0), + lateral: ("npc.crawler_sand.male.leg_fr"), + ), + leg_fr: ( + offset: (-0.0, -1.0, -3.0), + lateral: ("npc.crawler_sand.male.leg_fr"), + ), + leg_fcl: ( + offset: (-3.0, -1.0, -3.0), + lateral: ("npc.crawler_sand.male.leg_fcr"), + ), + leg_fcr: ( + offset: (-0.0, -1.0, -3.0), + lateral: ("npc.crawler_sand.male.leg_fcr"), + ), + leg_bcl: ( + offset: (-3.0, -1.0, -3.0), + lateral: ("npc.crawler_sand.male.leg_bcr"), + ), + leg_bcr: ( + offset: (-0.0, -1.0, -3.0), + lateral: ("npc.crawler_sand.male.leg_bcr"), + ), + leg_bl: ( + offset: (-11.0, -0.5, -4.5), + lateral: ("armor.empty"), + ), + leg_br: ( + offset: (0.0, -0.5, -4.5), + lateral: ("armor.empty"), + ), + ), + (Sandcrawler, Female): ( + mandible_l: ( + offset: (0.0, 0.0, -3.0), + lateral: ("armor.empty"), + ), + mandible_r: ( + offset: (-2.0, 0.0, -3.0), + lateral: ("armor.empty"), + ), + wing_fl: ( + offset: (-6.0, -4.5, -8.0), + lateral: ("armor.empty"), + ), + wing_fr: ( + offset: (0.0, -4.5, -8.0), + lateral: ("armor.empty"), + ), + wing_bl: ( + offset: (-11.0, -1.0, -8.0), + lateral: ("armor.empty"), + ), + wing_br: ( + offset: (-11.0, -1.0, -8.0), + lateral: ("armor.empty"), + ), + leg_fl: ( + offset: (-3.0, -1.0, -3.0), + lateral: ("npc.crawler_sand.male.leg_fr"), + ), + leg_fr: ( + offset: (-0.0, -1.0, -3.0), + lateral: ("npc.crawler_sand.male.leg_fr"), + ), + leg_fcl: ( + offset: (-3.0, -1.0, -3.0), + lateral: ("npc.crawler_sand.male.leg_fcr"), + ), + leg_fcr: ( + offset: (-0.0, -1.0, -3.0), + lateral: ("npc.crawler_sand.male.leg_fcr"), + ), + leg_bcl: ( + offset: (-3.0, -1.0, -3.0), + lateral: ("npc.crawler_sand.male.leg_bcr"), + ), + leg_bcr: ( + offset: (-0.0, -1.0, -3.0), + lateral: ("npc.crawler_sand.male.leg_bcr"), + ), + leg_bl: ( + offset: (-11.0, -0.5, -4.5), + lateral: ("armor.empty"), + ), + leg_br: ( + offset: (0.0, -0.5, -4.5), + lateral: ("armor.empty"), + ), + ), +}) diff --git a/assets/voxygen/voxel/npc/antlion/male/chest.vox b/assets/voxygen/voxel/npc/antlion/male/chest.vox new file mode 100644 index 0000000000..55a51d4174 --- /dev/null +++ b/assets/voxygen/voxel/npc/antlion/male/chest.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bf5804cd2fcde8bacdbfce5d3ea0d5e46241a3f9a888cb7272dc55afd6edc9ef +size 3648 diff --git a/assets/voxygen/voxel/npc/antlion/male/head.vox b/assets/voxygen/voxel/npc/antlion/male/head.vox new file mode 100644 index 0000000000..1876ade27f --- /dev/null +++ b/assets/voxygen/voxel/npc/antlion/male/head.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1b18d80acdd21fa493588506a05a9f171af2c1d317100b91389db9ea7d88ad53 +size 2884 diff --git a/assets/voxygen/voxel/npc/antlion/male/leg_bcr.vox b/assets/voxygen/voxel/npc/antlion/male/leg_bcr.vox new file mode 100644 index 0000000000..6a675b4f30 --- /dev/null +++ b/assets/voxygen/voxel/npc/antlion/male/leg_bcr.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e5f226c164c11dd198ffa7353fb50f3d18715b58c3c994223abe43120e1e4847 +size 1480 diff --git a/assets/voxygen/voxel/npc/antlion/male/leg_fcr.vox b/assets/voxygen/voxel/npc/antlion/male/leg_fcr.vox new file mode 100644 index 0000000000..99180b1445 --- /dev/null +++ b/assets/voxygen/voxel/npc/antlion/male/leg_fcr.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a261f542e984eca014a8f48836e1e04b8fcd8e227f76adea73d5c24b334c9504 +size 1300 diff --git a/assets/voxygen/voxel/npc/antlion/male/leg_fr.vox b/assets/voxygen/voxel/npc/antlion/male/leg_fr.vox new file mode 100644 index 0000000000..ea0f4bce09 --- /dev/null +++ b/assets/voxygen/voxel/npc/antlion/male/leg_fr.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:14e1960f80b99da34b047419fb93e20b69e50703e51197c2f11ab26743e7d645 +size 1212 diff --git a/assets/voxygen/voxel/npc/antlion/male/mandible_r.vox b/assets/voxygen/voxel/npc/antlion/male/mandible_r.vox new file mode 100644 index 0000000000..d3413754f5 --- /dev/null +++ b/assets/voxygen/voxel/npc/antlion/male/mandible_r.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:61afeec9a9daad0b289c21a10aec11a1bbab2affb968182ed3e871bed14e9c85 +size 1464 diff --git a/assets/voxygen/voxel/npc/black_widow/male/chest.vox b/assets/voxygen/voxel/npc/black_widow/male/chest.vox new file mode 100644 index 0000000000..dab78b4d61 --- /dev/null +++ b/assets/voxygen/voxel/npc/black_widow/male/chest.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:446d01e2a9fbbb3f207988f67f242c86499b0d44f32853c2cc8a56138bfe7e02 +size 3520 diff --git a/assets/voxygen/voxel/npc/black_widow/male/head.vox b/assets/voxygen/voxel/npc/black_widow/male/head.vox new file mode 100644 index 0000000000..fd99eb394b --- /dev/null +++ b/assets/voxygen/voxel/npc/black_widow/male/head.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:02c142e7eb2b390d7955a4d373632f54c1fa95a9b7bf1061188fb0a84495780d +size 2016 diff --git a/assets/voxygen/voxel/npc/black_widow/male/leg_bcr.vox b/assets/voxygen/voxel/npc/black_widow/male/leg_bcr.vox new file mode 100644 index 0000000000..ac96ee5d0a --- /dev/null +++ b/assets/voxygen/voxel/npc/black_widow/male/leg_bcr.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2944655042fdd6b73e732470b6b830c6776ce32f106da513a545300966c60d8f +size 1272 diff --git a/assets/voxygen/voxel/npc/black_widow/male/leg_br.vox b/assets/voxygen/voxel/npc/black_widow/male/leg_br.vox new file mode 100644 index 0000000000..8aa3f4ba9e --- /dev/null +++ b/assets/voxygen/voxel/npc/black_widow/male/leg_br.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:284a92865a26e2243ad96b9a7f7bea6cbbeabc70cf100cc6612a9bdef03f3e87 +size 1264 diff --git a/assets/voxygen/voxel/npc/black_widow/male/leg_fcr.vox b/assets/voxygen/voxel/npc/black_widow/male/leg_fcr.vox new file mode 100644 index 0000000000..8aa3f4ba9e --- /dev/null +++ b/assets/voxygen/voxel/npc/black_widow/male/leg_fcr.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:284a92865a26e2243ad96b9a7f7bea6cbbeabc70cf100cc6612a9bdef03f3e87 +size 1264 diff --git a/assets/voxygen/voxel/npc/black_widow/male/leg_fr.vox b/assets/voxygen/voxel/npc/black_widow/male/leg_fr.vox new file mode 100644 index 0000000000..5d792f3bac --- /dev/null +++ b/assets/voxygen/voxel/npc/black_widow/male/leg_fr.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7bed9ecabbddd5f6088297965216e271f75eadff1e8ac160cde21cf3efe7f9d1 +size 1224 diff --git a/assets/voxygen/voxel/npc/black_widow/male/mandible_r.vox b/assets/voxygen/voxel/npc/black_widow/male/mandible_r.vox new file mode 100644 index 0000000000..063b86e19a --- /dev/null +++ b/assets/voxygen/voxel/npc/black_widow/male/mandible_r.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:71b8d07526d6be20d5701c5b481d228e70384dcdf9e96c5b890a26f60f4cb3d7 +size 1124 diff --git a/assets/voxygen/voxel/npc/cave_spider/male/chest.vox b/assets/voxygen/voxel/npc/cave_spider/male/chest.vox new file mode 100644 index 0000000000..c6cb35817b --- /dev/null +++ b/assets/voxygen/voxel/npc/cave_spider/male/chest.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7dd5443dbdc336d2c924dff4da2e8920986ce5dbbf6a7f01d0370f84d3dc4808 +size 3580 diff --git a/assets/voxygen/voxel/npc/cave_spider/male/head.vox b/assets/voxygen/voxel/npc/cave_spider/male/head.vox new file mode 100644 index 0000000000..e1995a15a8 --- /dev/null +++ b/assets/voxygen/voxel/npc/cave_spider/male/head.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ad1e84586991e827dedfffd69b8ae5405748a823abfd85b5e4cdf7706e2cc6ee +size 2000 diff --git a/assets/voxygen/voxel/npc/cave_spider/male/leg_bcr.vox b/assets/voxygen/voxel/npc/cave_spider/male/leg_bcr.vox new file mode 100644 index 0000000000..e21453e993 --- /dev/null +++ b/assets/voxygen/voxel/npc/cave_spider/male/leg_bcr.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:18b322bafbdb2a5dbc664020a2f97588b831fd52aac22e1ad0e8e4239b5d299e +size 1256 diff --git a/assets/voxygen/voxel/npc/cave_spider/male/leg_br.vox b/assets/voxygen/voxel/npc/cave_spider/male/leg_br.vox new file mode 100644 index 0000000000..0e7f090fb1 --- /dev/null +++ b/assets/voxygen/voxel/npc/cave_spider/male/leg_br.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2ba80fc1c95eca3d512ebfcf7fd70f000918192a366e71e25e5c9dfa63d2c64d +size 1240 diff --git a/assets/voxygen/voxel/npc/cave_spider/male/leg_fcr.vox b/assets/voxygen/voxel/npc/cave_spider/male/leg_fcr.vox new file mode 100644 index 0000000000..0e7f090fb1 --- /dev/null +++ b/assets/voxygen/voxel/npc/cave_spider/male/leg_fcr.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2ba80fc1c95eca3d512ebfcf7fd70f000918192a366e71e25e5c9dfa63d2c64d +size 1240 diff --git a/assets/voxygen/voxel/npc/cave_spider/male/leg_fr.vox b/assets/voxygen/voxel/npc/cave_spider/male/leg_fr.vox new file mode 100644 index 0000000000..7b38b2f18d --- /dev/null +++ b/assets/voxygen/voxel/npc/cave_spider/male/leg_fr.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7def4d2f8c99fb1e5dae951f11cbc88d848edca0f7cd118459accd71f6a7da36 +size 1212 diff --git a/assets/voxygen/voxel/npc/cave_spider/male/mandible_r.vox b/assets/voxygen/voxel/npc/cave_spider/male/mandible_r.vox new file mode 100644 index 0000000000..7c68c9bf39 --- /dev/null +++ b/assets/voxygen/voxel/npc/cave_spider/male/mandible_r.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:48b355cf9781e1839801ea7eb6edc808f3d80dee84ed73522ce16bba545d8a6b +size 1124 diff --git a/assets/voxygen/voxel/npc/crawler_molten/male/chest.vox b/assets/voxygen/voxel/npc/crawler_molten/male/chest.vox new file mode 100644 index 0000000000..667a49b7fd --- /dev/null +++ b/assets/voxygen/voxel/npc/crawler_molten/male/chest.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8f671f9375eeb002d7ce09b7845656200c306c266a5fde71a79b1eba3661d1f0 +size 2240 diff --git a/assets/voxygen/voxel/npc/crawler_molten/male/head.vox b/assets/voxygen/voxel/npc/crawler_molten/male/head.vox new file mode 100644 index 0000000000..293d8b7e46 --- /dev/null +++ b/assets/voxygen/voxel/npc/crawler_molten/male/head.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ae2e0dca69fcf516b4e46372bcfe4394aaa8160f2020ee5976a94a9e8691ca50 +size 5472 diff --git a/assets/voxygen/voxel/npc/crawler_molten/male/leg_bcr.vox b/assets/voxygen/voxel/npc/crawler_molten/male/leg_bcr.vox new file mode 100644 index 0000000000..5fb89afd3c --- /dev/null +++ b/assets/voxygen/voxel/npc/crawler_molten/male/leg_bcr.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b674456de84508d06d1d53106c7777bd3b1a1a9fb805bdd88719f6b1128eac04 +size 1152 diff --git a/assets/voxygen/voxel/npc/crawler_molten/male/leg_fcr.vox b/assets/voxygen/voxel/npc/crawler_molten/male/leg_fcr.vox new file mode 100644 index 0000000000..58307aa16c --- /dev/null +++ b/assets/voxygen/voxel/npc/crawler_molten/male/leg_fcr.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:632202a342888143d7d4f5ef7ac41fbffadc5e599b84db9e5b54d71d44ab20e1 +size 1152 diff --git a/assets/voxygen/voxel/npc/crawler_molten/male/leg_fr.vox b/assets/voxygen/voxel/npc/crawler_molten/male/leg_fr.vox new file mode 100644 index 0000000000..97ebca5014 --- /dev/null +++ b/assets/voxygen/voxel/npc/crawler_molten/male/leg_fr.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:00fb63918bdd5df4d3fe7b6c7f4a04b6e17d504fc2c7021fd115f08f18c4c92e +size 1152 diff --git a/assets/voxygen/voxel/npc/crawler_moss/male/chest.vox b/assets/voxygen/voxel/npc/crawler_moss/male/chest.vox new file mode 100644 index 0000000000..860c78f9e0 --- /dev/null +++ b/assets/voxygen/voxel/npc/crawler_moss/male/chest.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:086091c20c4158a2a9e4cd58fe48cbc5bcba021aeec3ed424c5b0fe535ba4c5e +size 2068 diff --git a/assets/voxygen/voxel/npc/crawler_moss/male/head.vox b/assets/voxygen/voxel/npc/crawler_moss/male/head.vox new file mode 100644 index 0000000000..332335ae44 --- /dev/null +++ b/assets/voxygen/voxel/npc/crawler_moss/male/head.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:69fbc3d67e1556f4f0aec08f674f1f81d1b0f062e2d8a3091f39c21a6ebf2b7a +size 4904 diff --git a/assets/voxygen/voxel/npc/crawler_moss/male/leg_bcr.vox b/assets/voxygen/voxel/npc/crawler_moss/male/leg_bcr.vox new file mode 100644 index 0000000000..24f01c3b13 --- /dev/null +++ b/assets/voxygen/voxel/npc/crawler_moss/male/leg_bcr.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5141d701cced23b122d80de99cb4fac75b0e7e4d586648e9c234993063dc905e +size 1152 diff --git a/assets/voxygen/voxel/npc/crawler_moss/male/leg_fcr.vox b/assets/voxygen/voxel/npc/crawler_moss/male/leg_fcr.vox new file mode 100644 index 0000000000..24f01c3b13 --- /dev/null +++ b/assets/voxygen/voxel/npc/crawler_moss/male/leg_fcr.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5141d701cced23b122d80de99cb4fac75b0e7e4d586648e9c234993063dc905e +size 1152 diff --git a/assets/voxygen/voxel/npc/crawler_moss/male/leg_fr.vox b/assets/voxygen/voxel/npc/crawler_moss/male/leg_fr.vox new file mode 100644 index 0000000000..24f01c3b13 --- /dev/null +++ b/assets/voxygen/voxel/npc/crawler_moss/male/leg_fr.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5141d701cced23b122d80de99cb4fac75b0e7e4d586648e9c234993063dc905e +size 1152 diff --git a/assets/voxygen/voxel/npc/crawler_sand/male/chest.vox b/assets/voxygen/voxel/npc/crawler_sand/male/chest.vox new file mode 100644 index 0000000000..46ddc39ccf --- /dev/null +++ b/assets/voxygen/voxel/npc/crawler_sand/male/chest.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6960895dcd9e49e74fa578c990a5f4ffed7204e0000178f9018ebfcc277b387d +size 2076 diff --git a/assets/voxygen/voxel/npc/crawler_sand/male/head.vox b/assets/voxygen/voxel/npc/crawler_sand/male/head.vox new file mode 100644 index 0000000000..9442417b76 --- /dev/null +++ b/assets/voxygen/voxel/npc/crawler_sand/male/head.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b60744ef84710f7f685b3792bd39ab5e49fd8900302b4a6a28dcf4b318dac249 +size 4964 diff --git a/assets/voxygen/voxel/npc/crawler_sand/male/leg_bcr.vox b/assets/voxygen/voxel/npc/crawler_sand/male/leg_bcr.vox new file mode 100644 index 0000000000..723345bc1a --- /dev/null +++ b/assets/voxygen/voxel/npc/crawler_sand/male/leg_bcr.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5e9f0b35d167edc84acd2124de3cc5207411c2df04b0ba6caa2649b81313ae89 +size 1152 diff --git a/assets/voxygen/voxel/npc/crawler_sand/male/leg_fcr.vox b/assets/voxygen/voxel/npc/crawler_sand/male/leg_fcr.vox new file mode 100644 index 0000000000..723345bc1a --- /dev/null +++ b/assets/voxygen/voxel/npc/crawler_sand/male/leg_fcr.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5e9f0b35d167edc84acd2124de3cc5207411c2df04b0ba6caa2649b81313ae89 +size 1152 diff --git a/assets/voxygen/voxel/npc/crawler_sand/male/leg_fr.vox b/assets/voxygen/voxel/npc/crawler_sand/male/leg_fr.vox new file mode 100644 index 0000000000..723345bc1a --- /dev/null +++ b/assets/voxygen/voxel/npc/crawler_sand/male/leg_fr.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5e9f0b35d167edc84acd2124de3cc5207411c2df04b0ba6caa2649b81313ae89 +size 1152 diff --git a/assets/voxygen/voxel/npc/horn_beetle/male/chest.vox b/assets/voxygen/voxel/npc/horn_beetle/male/chest.vox new file mode 100644 index 0000000000..d61b9604b8 --- /dev/null +++ b/assets/voxygen/voxel/npc/horn_beetle/male/chest.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:624fd39bf4968094b7ad296ee2129bc0eddf65f158fd9e2fd99f2f175785e49b +size 3008 diff --git a/assets/voxygen/voxel/npc/horn_beetle/male/head.vox b/assets/voxygen/voxel/npc/horn_beetle/male/head.vox new file mode 100644 index 0000000000..69ae867e23 --- /dev/null +++ b/assets/voxygen/voxel/npc/horn_beetle/male/head.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:664ac672f706c54bd549fedb1cfdffddf83eb076d74a79a7f60fed44ed69b662 +size 3944 diff --git a/assets/voxygen/voxel/npc/horn_beetle/male/leg_bcr.vox b/assets/voxygen/voxel/npc/horn_beetle/male/leg_bcr.vox new file mode 100644 index 0000000000..84b882be5d --- /dev/null +++ b/assets/voxygen/voxel/npc/horn_beetle/male/leg_bcr.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1f25b41528044ebc4967ebaee3542478620a247b6ffda58378854c342269860c +size 1312 diff --git a/assets/voxygen/voxel/npc/horn_beetle/male/leg_fcr.vox b/assets/voxygen/voxel/npc/horn_beetle/male/leg_fcr.vox new file mode 100644 index 0000000000..8cfde35478 --- /dev/null +++ b/assets/voxygen/voxel/npc/horn_beetle/male/leg_fcr.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9736650b485ce02434b6eae1fc7925ecfa45b6922a7c8b740a5cb5be75837c0f +size 1288 diff --git a/assets/voxygen/voxel/npc/horn_beetle/male/leg_fr.vox b/assets/voxygen/voxel/npc/horn_beetle/male/leg_fr.vox new file mode 100644 index 0000000000..554def1eee --- /dev/null +++ b/assets/voxygen/voxel/npc/horn_beetle/male/leg_fr.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2d742cf754151535d9fbb9504104656c7316c0c51ba5c41b1940d63ab075a925 +size 1232 diff --git a/assets/voxygen/voxel/npc/horn_beetle/male/wing_br.vox b/assets/voxygen/voxel/npc/horn_beetle/male/wing_br.vox new file mode 100644 index 0000000000..8826b9158e --- /dev/null +++ b/assets/voxygen/voxel/npc/horn_beetle/male/wing_br.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7e84b755043d1c24c3e8f12a3f01bd0267ce89510a5dbfb29a3517e62c0fb881 +size 1268 diff --git a/assets/voxygen/voxel/npc/horn_beetle/male/wing_fr.vox b/assets/voxygen/voxel/npc/horn_beetle/male/wing_fr.vox new file mode 100644 index 0000000000..da8b6fd627 --- /dev/null +++ b/assets/voxygen/voxel/npc/horn_beetle/male/wing_fr.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c43ad3afecbbbc1e7b51642150f93d8e58d17a2c972032fcef7802b88bf11803 +size 1460 diff --git a/assets/voxygen/voxel/npc/leaf_beetle/male/chest.vox b/assets/voxygen/voxel/npc/leaf_beetle/male/chest.vox new file mode 100644 index 0000000000..852c7f7fbd --- /dev/null +++ b/assets/voxygen/voxel/npc/leaf_beetle/male/chest.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:50e0f7649948212ee1e2ef140858d73c86c6f89d38026f85afd1f012c6d9caf1 +size 2224 diff --git a/assets/voxygen/voxel/npc/leaf_beetle/male/head.vox b/assets/voxygen/voxel/npc/leaf_beetle/male/head.vox new file mode 100644 index 0000000000..5bf967a020 --- /dev/null +++ b/assets/voxygen/voxel/npc/leaf_beetle/male/head.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3c80f8353608b92fa2f736ac69be0c2ddbec5b4874bdd3b5797263e828d7839e +size 2208 diff --git a/assets/voxygen/voxel/npc/leaf_beetle/male/leg_bcr.vox b/assets/voxygen/voxel/npc/leaf_beetle/male/leg_bcr.vox new file mode 100644 index 0000000000..cd72fd3e20 --- /dev/null +++ b/assets/voxygen/voxel/npc/leaf_beetle/male/leg_bcr.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0a92740406b54cb3bc7c33625a8cc6f3d9c13bdc5bbdf9f19dac34518afab2eb +size 1212 diff --git a/assets/voxygen/voxel/npc/leaf_beetle/male/leg_fcr.vox b/assets/voxygen/voxel/npc/leaf_beetle/male/leg_fcr.vox new file mode 100644 index 0000000000..e8c4c33a1d --- /dev/null +++ b/assets/voxygen/voxel/npc/leaf_beetle/male/leg_fcr.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f33e48e4811ea4198995521ebe9ba380d971e9af398dd218024b645377c1474a +size 1192 diff --git a/assets/voxygen/voxel/npc/leaf_beetle/male/leg_fr.vox b/assets/voxygen/voxel/npc/leaf_beetle/male/leg_fr.vox new file mode 100644 index 0000000000..69a76d145e --- /dev/null +++ b/assets/voxygen/voxel/npc/leaf_beetle/male/leg_fr.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:395a38334958d7f9ef8a8059960bdc5cc2c7cbd78294573c99cb206a2aac21e1 +size 1180 diff --git a/assets/voxygen/voxel/npc/leaf_beetle/male/wing_br.vox b/assets/voxygen/voxel/npc/leaf_beetle/male/wing_br.vox new file mode 100644 index 0000000000..7e389a3cd5 --- /dev/null +++ b/assets/voxygen/voxel/npc/leaf_beetle/male/wing_br.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0e0e1add21e5fb17abd3b7f0c1773e30e9b084bba85cffe9f4ec93cac072f385 +size 1204 diff --git a/assets/voxygen/voxel/npc/leaf_beetle/male/wing_fr.vox b/assets/voxygen/voxel/npc/leaf_beetle/male/wing_fr.vox new file mode 100644 index 0000000000..8f86f644ed --- /dev/null +++ b/assets/voxygen/voxel/npc/leaf_beetle/male/wing_fr.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:85a698fd238468e057bcbbe5c4797b4a59efb0df46528e0de01157ad1088be7c +size 1436 diff --git a/assets/voxygen/voxel/npc/stag_beetle/male/chest.vox b/assets/voxygen/voxel/npc/stag_beetle/male/chest.vox new file mode 100644 index 0000000000..34fa19ae70 --- /dev/null +++ b/assets/voxygen/voxel/npc/stag_beetle/male/chest.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7acee9642213815b17a1146a269ab8369d5306ea41db7e9c38d46edb737a2590 +size 3008 diff --git a/assets/voxygen/voxel/npc/stag_beetle/male/head.vox b/assets/voxygen/voxel/npc/stag_beetle/male/head.vox new file mode 100644 index 0000000000..6a233ead5b --- /dev/null +++ b/assets/voxygen/voxel/npc/stag_beetle/male/head.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6c0c085b7d7ccd874eb0ffc3959ca78a25e3fdb72f12f87abe1f3b9fcbab54f9 +size 3380 diff --git a/assets/voxygen/voxel/npc/stag_beetle/male/leg_bcr.vox b/assets/voxygen/voxel/npc/stag_beetle/male/leg_bcr.vox new file mode 100644 index 0000000000..6ff9a20ec4 --- /dev/null +++ b/assets/voxygen/voxel/npc/stag_beetle/male/leg_bcr.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:71e52664ca88d8cae13fe081a71c7da827525c49ce2414786f4ea6820fedb18b +size 1312 diff --git a/assets/voxygen/voxel/npc/stag_beetle/male/leg_fcr.vox b/assets/voxygen/voxel/npc/stag_beetle/male/leg_fcr.vox new file mode 100644 index 0000000000..e9900bba48 --- /dev/null +++ b/assets/voxygen/voxel/npc/stag_beetle/male/leg_fcr.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8c210e79b430001b6339f07f58dc44bb97ee04689c8bf7599fcfe546908c3f82 +size 1288 diff --git a/assets/voxygen/voxel/npc/stag_beetle/male/leg_fr.vox b/assets/voxygen/voxel/npc/stag_beetle/male/leg_fr.vox new file mode 100644 index 0000000000..767d4315f1 --- /dev/null +++ b/assets/voxygen/voxel/npc/stag_beetle/male/leg_fr.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:861aa2fc23bebbc1fd2f2ad7bc714310e73723df86f876a8145ad9e8e7109000 +size 1232 diff --git a/assets/voxygen/voxel/npc/stag_beetle/male/mandible_r.vox b/assets/voxygen/voxel/npc/stag_beetle/male/mandible_r.vox new file mode 100644 index 0000000000..acdca41429 --- /dev/null +++ b/assets/voxygen/voxel/npc/stag_beetle/male/mandible_r.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ced6c71166b5fee99d917c2bb6d948c7db0c23ff66eb158eb5ab85f816e5dd10 +size 1424 diff --git a/assets/voxygen/voxel/npc/stag_beetle/male/wing_br.vox b/assets/voxygen/voxel/npc/stag_beetle/male/wing_br.vox new file mode 100644 index 0000000000..d23c821a87 --- /dev/null +++ b/assets/voxygen/voxel/npc/stag_beetle/male/wing_br.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:678f0ede6e5aef15ec95a9509e3d87cf14a890f1cca9256dc30a29f3a1742a88 +size 1268 diff --git a/assets/voxygen/voxel/npc/stag_beetle/male/wing_fr.vox b/assets/voxygen/voxel/npc/stag_beetle/male/wing_fr.vox new file mode 100644 index 0000000000..ec70cc9b89 --- /dev/null +++ b/assets/voxygen/voxel/npc/stag_beetle/male/wing_fr.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8446377716e722c62945b9c17f39dd4a8c02ba64289d1ae0ecaf4d0508374b9b +size 1432 diff --git a/assets/voxygen/voxel/npc/tarantula/male/chest.vox b/assets/voxygen/voxel/npc/tarantula/male/chest.vox new file mode 100644 index 0000000000..653b332053 --- /dev/null +++ b/assets/voxygen/voxel/npc/tarantula/male/chest.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:04fd3ca76b86c65a1df18ad0088f49690a6051b6ec7d60bd890d806d18988945 +size 3372 diff --git a/assets/voxygen/voxel/npc/tarantula/male/head.vox b/assets/voxygen/voxel/npc/tarantula/male/head.vox new file mode 100644 index 0000000000..3c2739a862 --- /dev/null +++ b/assets/voxygen/voxel/npc/tarantula/male/head.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:61d9a9445d42f6963b95639bb64aa5c533eb7ebb3a42dc6399850d1a78253a0a +size 1984 diff --git a/assets/voxygen/voxel/npc/tarantula/male/leg_bcr.vox b/assets/voxygen/voxel/npc/tarantula/male/leg_bcr.vox new file mode 100644 index 0000000000..e19d999527 --- /dev/null +++ b/assets/voxygen/voxel/npc/tarantula/male/leg_bcr.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fd893fc11649061cbb01e937b47f25c2214264584558eceaae08e425784ef960 +size 1320 diff --git a/assets/voxygen/voxel/npc/tarantula/male/leg_br.vox b/assets/voxygen/voxel/npc/tarantula/male/leg_br.vox new file mode 100644 index 0000000000..ce7462322e --- /dev/null +++ b/assets/voxygen/voxel/npc/tarantula/male/leg_br.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:dac9debd60b28714180a20635161dd712461863c73688a028bc6b11212a1ee75 +size 1312 diff --git a/assets/voxygen/voxel/npc/tarantula/male/leg_fcr.vox b/assets/voxygen/voxel/npc/tarantula/male/leg_fcr.vox new file mode 100644 index 0000000000..ce7462322e --- /dev/null +++ b/assets/voxygen/voxel/npc/tarantula/male/leg_fcr.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:dac9debd60b28714180a20635161dd712461863c73688a028bc6b11212a1ee75 +size 1312 diff --git a/assets/voxygen/voxel/npc/tarantula/male/leg_fr.vox b/assets/voxygen/voxel/npc/tarantula/male/leg_fr.vox new file mode 100644 index 0000000000..a1445b1554 --- /dev/null +++ b/assets/voxygen/voxel/npc/tarantula/male/leg_fr.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4952034713aa257e0f37e7068df5eb67183f9cfd777d50650cc742a211ca34fd +size 1268 diff --git a/assets/voxygen/voxel/npc/tarantula/male/mandible_r.vox b/assets/voxygen/voxel/npc/tarantula/male/mandible_r.vox new file mode 100644 index 0000000000..96138446da --- /dev/null +++ b/assets/voxygen/voxel/npc/tarantula/male/mandible_r.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cccc9cd008a8e57d89aa55603b7c03f1ca83fdf9c8f468f1c5d2dc548cf8621d +size 1148 diff --git a/assets/voxygen/voxel/npc/weevil/male/chest.vox b/assets/voxygen/voxel/npc/weevil/male/chest.vox new file mode 100644 index 0000000000..f09ebfc7b5 --- /dev/null +++ b/assets/voxygen/voxel/npc/weevil/male/chest.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d8e6c0f7141103054eba3b7540b8a60a3446e5518a66227c67757bea16f0be28 +size 2224 diff --git a/assets/voxygen/voxel/npc/weevil/male/head.vox b/assets/voxygen/voxel/npc/weevil/male/head.vox new file mode 100644 index 0000000000..0fe41e3175 --- /dev/null +++ b/assets/voxygen/voxel/npc/weevil/male/head.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:85c5e6b905c9ceff51bd6b488186b756a4a5e1d02410c90834dafb0a4e57e320 +size 2256 diff --git a/assets/voxygen/voxel/npc/weevil/male/leg_bcr.vox b/assets/voxygen/voxel/npc/weevil/male/leg_bcr.vox new file mode 100644 index 0000000000..9898026993 --- /dev/null +++ b/assets/voxygen/voxel/npc/weevil/male/leg_bcr.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c0ee3e3ae44187b1af5f6d0be66cd4d33755d382c5ea9b34cb4d2390b543f349 +size 1212 diff --git a/assets/voxygen/voxel/npc/weevil/male/leg_fcr.vox b/assets/voxygen/voxel/npc/weevil/male/leg_fcr.vox new file mode 100644 index 0000000000..4fc709fa4f --- /dev/null +++ b/assets/voxygen/voxel/npc/weevil/male/leg_fcr.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:53527d29399d4f3b037f807d5150a63fbb4999294d937d87b72c57e992fd6cf2 +size 1192 diff --git a/assets/voxygen/voxel/npc/weevil/male/leg_fr.vox b/assets/voxygen/voxel/npc/weevil/male/leg_fr.vox new file mode 100644 index 0000000000..8845d9afe7 --- /dev/null +++ b/assets/voxygen/voxel/npc/weevil/male/leg_fr.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1aec2c68d05fe463379b6c89ec5635ffdd5ab1ac6eda946950517f085ad80977 +size 1180 diff --git a/assets/voxygen/voxel/npc/weevil/male/wing_br.vox b/assets/voxygen/voxel/npc/weevil/male/wing_br.vox new file mode 100644 index 0000000000..0124b89e54 --- /dev/null +++ b/assets/voxygen/voxel/npc/weevil/male/wing_br.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9e6f44307ba6a16bcde45c2160e8b53afad45742271e1707fd2ce46ef3c6a402 +size 1204 diff --git a/assets/voxygen/voxel/npc/weevil/male/wing_fr.vox b/assets/voxygen/voxel/npc/weevil/male/wing_fr.vox new file mode 100644 index 0000000000..04e8e4d4fd --- /dev/null +++ b/assets/voxygen/voxel/npc/weevil/male/wing_fr.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:440dc4d1a4836d0651e36a614503ca3263a22187d837e4dcd594307ec15bb7fa +size 1360 diff --git a/assets/voxygen/voxel/object_manifest.ron b/assets/voxygen/voxel/object_manifest.ron index 9bb9166282..1eed2f2f8e 100644 --- a/assets/voxygen/voxel/object_manifest.ron +++ b/assets/voxygen/voxel/object_manifest.ron @@ -799,4 +799,24 @@ central: ("armor.empty"), ) ), + BoltIcicle: ( + bone0: ( + offset: (-2.5, -6.0, -2.5), + central: ("weapon.projectile.icicle-bolt"), + ), + bone1: ( + offset: (0.0, 0.0, 0.0), + central: ("armor.empty"), + ) + ), + SpitPoison: ( + bone0: ( + offset: (-3.0, -5.0, -3.0), + central: ("weapon.projectile.poison-spit"), + ), + bone1: ( + offset: (0.0, 0.0, 0.0), + central: ("armor.empty"), + ) + ), }) diff --git a/assets/voxygen/voxel/sprite/misc/ensnaring_web.vox b/assets/voxygen/voxel/sprite/misc/ensnaring_web.vox new file mode 100644 index 0000000000..6be405d3d3 --- /dev/null +++ b/assets/voxygen/voxel/sprite/misc/ensnaring_web.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:53244cb395f8cc42b83abb036e8541409fbd55c8118076ffd567b5a0c84a3a79 +size 1908 diff --git a/assets/voxygen/voxel/sprite_manifest.ron b/assets/voxygen/voxel/sprite_manifest.ron index 25aa9b6ff0..6abd0b08e3 100644 --- a/assets/voxygen/voxel/sprite_manifest.ron +++ b/assets/voxygen/voxel/sprite_manifest.ron @@ -3691,6 +3691,16 @@ Bomb: Some(( lod_axes: (0.5, 0.5, 0.5), ), ], + wind_sway: 0.6, +)), +EnsnaringWeb: Some(( + variations: [ + ( + model: "voxygen.voxel.sprite.misc.ensnaring_web", + offset: (-5.0, -6.5, 0.0), + lod_axes: (0.0, 0.0, 0.0), + ), + ], wind_sway: 0.0, )), ) diff --git a/assets/voxygen/voxel/weapon/projectile/icicle-bolt.vox b/assets/voxygen/voxel/weapon/projectile/icicle-bolt.vox new file mode 100644 index 0000000000..6600a24517 --- /dev/null +++ b/assets/voxygen/voxel/weapon/projectile/icicle-bolt.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:487aa5c592f37d4dbc4fd705900ccbb6efcb3e08596ca8ac6a817b0c864f954e +size 1400 diff --git a/assets/voxygen/voxel/weapon/projectile/poison-spit.vox b/assets/voxygen/voxel/weapon/projectile/poison-spit.vox new file mode 100644 index 0000000000..d6e7193c7c --- /dev/null +++ b/assets/voxygen/voxel/weapon/projectile/poison-spit.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c2da2e885ab9725d18c20e513cae4d9d069a3cde4690fa860b0de1fb82f82b98 +size 1764 diff --git a/assets/world/wildlife/spawn/desert/hot.ron b/assets/world/wildlife/spawn/desert/hot.ron index 1f56298d9e..f0b031a76f 100644 --- a/assets/world/wildlife/spawn/desert/hot.ron +++ b/assets/world/wildlife/spawn/desert/hot.ron @@ -4,10 +4,13 @@ SpawnEntry ( rules: [ Pack( groups: [ - (1, (1, 1, "common.entity.wild.peaceful.camel")), - (1, (1, 1, "common.entity.wild.peaceful.sand_hare")), - (1, (1, 1, "common.entity.wild.peaceful.sand_salamander")), - (1, (1, 1, "common.entity.wild.peaceful.gecko")), + // Casual + (2, (1, 1, "common.entity.wild.peaceful.camel")), + (2, (1, 1, "common.entity.wild.peaceful.sand_hare")), + (2, (1, 1, "common.entity.wild.peaceful.sand_salamander")), + (2, (1, 1, "common.entity.wild.peaceful.gecko")), + // Rare + (1, (1, 1, "common.entity.wild.peaceful.crawler_sand")), ], is_underwater: false, day_period: [Morning, Noon, Evening], diff --git a/assets/world/wildlife/spawn/desert/wasteland.ron b/assets/world/wildlife/spawn/desert/wasteland.ron index 7d06c2d2a4..40ff714ac6 100644 --- a/assets/world/wildlife/spawn/desert/wasteland.ron +++ b/assets/world/wildlife/spawn/desert/wasteland.ron @@ -5,14 +5,16 @@ SpawnEntry ( Pack( groups: [ // Casual - (100, (1, 1, "common.entity.wild.aggressive.bonerattler")), + (110, (1, 1, "common.entity.wild.aggressive.bonerattler")), (100, (1, 1, "common.entity.wild.aggressive.sand_raptor")), (100, (1, 1, "common.entity.wild.aggressive.sandshark")), + (100, (1, 1, "common.entity.wild.aggressive.antlion")), // Rare (20, (1, 1, "common.entity.wild.aggressive.lavadrake")), (20, (1, 1, "common.entity.wild.aggressive.ntouka")), (20, (1, 1, "common.entity.wild.aggressive.archaeos")), (20, (1, 1, "common.entity.wild.aggressive.ngoubou")), + (20, (1, 1, "common.entity.wild.aggressive.tarantula")), // Ultra_rare (1, (1, 1, "common.entity.wild.aggressive.roshwalr_boss")), ], diff --git a/assets/world/wildlife/spawn/jungle/rainforest_area.ron b/assets/world/wildlife/spawn/jungle/rainforest_area.ron index d25f2a6109..e335f734fd 100644 --- a/assets/world/wildlife/spawn/jungle/rainforest_area.ron +++ b/assets/world/wildlife/spawn/jungle/rainforest_area.ron @@ -10,6 +10,9 @@ SpawnEntry ( // Rare (1, (1, 1, "common.entity.wild.peaceful.tortoise")), (1, (1, 1, "common.entity.wild.aggressive.monitor")), + (1, (1, 1, "common.entity.wild.aggressive.horn_beetle")), + (1, (1, 1, "common.entity.wild.aggressive.stag_beetle")), + (1, (1, 1, "common.entity.wild.peaceful.crawler_moss")), ], is_underwater: false, day_period: [Morning, Noon, Evening], diff --git a/assets/world/wildlife/spawn/temperate/rainforest.ron b/assets/world/wildlife/spawn/temperate/rainforest.ron index c60b19cf5e..78d5790834 100644 --- a/assets/world/wildlife/spawn/temperate/rainforest.ron +++ b/assets/world/wildlife/spawn/temperate/rainforest.ron @@ -30,6 +30,7 @@ SpawnEntry ( (2, (1, 1, "common.entity.wild.peaceful.turtle")), (2, (1, 1, "common.entity.wild.peaceful.hirdrasil")), (2, (1, 1, "common.entity.wild.peaceful.truffler")), + (2, (1, 1, "common.entity.wild.peaceful.leaf_beetle")), ], is_underwater: false, day_period: [Morning, Noon, Evening], diff --git a/assets/world/wildlife/spawn/temperate/wood.ron b/assets/world/wildlife/spawn/temperate/wood.ron index 510ab327a3..e518574165 100644 --- a/assets/world/wildlife/spawn/temperate/wood.ron +++ b/assets/world/wildlife/spawn/temperate/wood.ron @@ -9,6 +9,7 @@ SpawnEntry ( (1, (1, 1, "common.entity.wild.aggressive.wood_raptor")), (1, (1, 1, "common.entity.wild.aggressive.deadwood")), (1, (1, 1, "common.entity.wild.aggressive.saber")), + (1, (1, 1, "common.entity.wild.aggressive.weevil")), ], is_underwater: false, day_period: [Night, Morning, Noon, Evening], diff --git a/common/src/cmd.rs b/common/src/cmd.rs index 02c78b683c..8e76d5515e 100644 --- a/common/src/cmd.rs +++ b/common/src/cmd.rs @@ -172,6 +172,7 @@ lazy_static! { theropod, dragon, golem, + arthropod, ); souls @@ -205,6 +206,7 @@ lazy_static! { BuffKind::Frozen => "frozen", BuffKind::Wet => "wet", BuffKind::Ensnared => "ensnared", + BuffKind::Poisoned => "poisoned", }; let mut buff_parser = HashMap::new(); BuffKind::iter().for_each(|kind| {buff_parser.insert(string_from_buff(kind).to_string(), kind);}); diff --git a/common/src/comp/agent.rs b/common/src/comp/agent.rs index f092092a17..a69b000612 100644 --- a/common/src/comp/agent.rs +++ b/common/src/comp/agent.rs @@ -1,7 +1,7 @@ use crate::{ comp::{ - biped_small, bird_medium, humanoid, quadruped_low, quadruped_medium, quadruped_small, ship, - Body, UtteranceKind, + arthropod, biped_small, bird_medium, humanoid, quadruped_low, quadruped_medium, + quadruped_small, ship, Body, UtteranceKind, }, path::Chaser, rtsim::{Memory, MemoryItem, RtSimController, RtSimEvent}, @@ -267,6 +267,19 @@ impl<'a> From<&'a Body> for Psyche { Body::Theropod(_) => 0.0, Body::Ship(_) => 0.0, Body::Dragon(_) => 0.0, + Body::Arthropod(arthropod) => match arthropod.species { + arthropod::Species::Tarantula => 0.0, + arthropod::Species::Blackwidow => 0.0, + arthropod::Species::Antlion => 0.0, + arthropod::Species::Hornbeetle => 0.1, + arthropod::Species::Leafbeetle => 0.1, + arthropod::Species::Stagbeetle => 0.1, + arthropod::Species::Weevil => 0.0, + arthropod::Species::Cavespider => 0.0, + arthropod::Species::Moltencrawler => 0.2, + arthropod::Species::Mosscrawler => 0.2, + arthropod::Species::Sandcrawler => 0.2, + }, }, sight_dist: 40.0, listen_dist: 30.0, diff --git a/common/src/comp/body.rs b/common/src/comp/body.rs index 33b7cb5b89..475c5adc67 100644 --- a/common/src/comp/body.rs +++ b/common/src/comp/body.rs @@ -1,3 +1,4 @@ +pub mod arthropod; pub mod biped_large; pub mod biped_small; pub mod bird_large; @@ -48,6 +49,7 @@ make_case_elim!( Theropod(body: theropod::Body) = 12, QuadrupedLow(body: quadruped_low::Body) = 13, Ship(body: ship::Body) = 14, + Arthropod(body: arthropod::Body) = 15, } ); @@ -85,6 +87,7 @@ pub struct AllBodies { pub theropod: BodyData>, pub quadruped_low: BodyData>, pub ship: BodyData, + pub arthropod: BodyData>, } /// Can only retrieve body metadata by direct index. @@ -107,6 +110,7 @@ impl core::ops::Index for AllBodies &self.theropod.body, NpcKind::Reddragon => &self.dragon.body, NpcKind::Crocodile => &self.quadruped_low.body, + NpcKind::Tarantula => &self.arthropod.body, } } } @@ -132,6 +136,7 @@ impl<'a, BodyMeta, SpeciesMeta> core::ops::Index<&'a Body> for AllBodies &self.golem.body, Body::Theropod(_) => &self.theropod.body, Body::QuadrupedLow(_) => &self.quadruped_low.body, + Body::Arthropod(_) => &self.arthropod.body, Body::Ship(_) => &self.ship.body, } } @@ -290,6 +295,7 @@ impl Body { theropod::Species::Yale => 1_000.0, }, Body::Ship(ship) => ship.mass().0, + Body::Arthropod(_) => 200.0, }; Mass(m) } @@ -396,6 +402,19 @@ impl Body { theropod::Species::Woodraptor => Vec3::new(2.0, 3.0, 2.6), theropod::Species::Yale => Vec3::new(1.5, 3.2, 4.0), }, + Body::Arthropod(body) => match body.species { + arthropod::Species::Tarantula => Vec3::new(4.0, 4.0, 1.8), + arthropod::Species::Blackwidow => Vec3::new(4.0, 4.0, 2.0), + arthropod::Species::Antlion => Vec3::new(4.0, 4.0, 2.2), + arthropod::Species::Hornbeetle => Vec3::new(3.2, 3.2, 1.3), + arthropod::Species::Leafbeetle => Vec3::new(3.2, 3.2, 1.3), + arthropod::Species::Stagbeetle => Vec3::new(3.2, 3.2, 1.3), + arthropod::Species::Weevil => Vec3::new(3.2, 3.2, 1.6), + arthropod::Species::Cavespider => Vec3::new(4.0, 4.0, 1.4), + arthropod::Species::Moltencrawler => Vec3::new(3.2, 4.0, 1.5), + arthropod::Species::Mosscrawler => Vec3::new(3.2, 4.0, 1.4), + arthropod::Species::Sandcrawler => Vec3::new(3.2, 4.0, 1.4), + }, } } @@ -640,6 +659,20 @@ impl Body { quadruped_low::Species::Deadwood => 120, _ => 70, }, + Body::Arthropod(arthropod) => match arthropod.species { + arthropod::Species::Tarantula => 120, + arthropod::Species::Blackwidow => 120, + arthropod::Species::Antlion => 80, + arthropod::Species::Hornbeetle => 90, + arthropod::Species::Leafbeetle => 90, + arthropod::Species::Stagbeetle => 90, + arthropod::Species::Weevil => 80, + arthropod::Species::Cavespider => 60, + arthropod::Species::Moltencrawler => 80, + arthropod::Species::Mosscrawler => 80, + arthropod::Species::Sandcrawler => 80, + _ => 70, + }, Body::Ship(_) => 1000, } } @@ -668,10 +701,13 @@ impl Body { | bird_large::Species::Cockatrice | bird_large::Species::FlameWyvern ), + Body::Arthropod(b) => matches!(b.species, arthropod::Species::Moltencrawler), _ => false, }, - BuffKind::Ensnared => { - matches!(self, Body::BipedLarge(b) if matches!(b.species, biped_large::Species::Harvester)) + BuffKind::Ensnared => match self { + Body::BipedLarge(b) => matches!(b.species, biped_large::Species::Harvester), + Body::Arthropod(_) => true, + _ => false, }, _ => false, } diff --git a/common/src/comp/body/arthropod.rs b/common/src/comp/body/arthropod.rs new file mode 100644 index 0000000000..021a80b288 --- /dev/null +++ b/common/src/comp/body/arthropod.rs @@ -0,0 +1,108 @@ +use rand::{seq::SliceRandom, thread_rng}; +use serde::{Deserialize, Serialize}; + +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] +pub struct Body { + pub species: Species, + pub body_type: BodyType, +} + +impl Body { + pub fn random() -> Self { + let mut rng = thread_rng(); + let species = *(&ALL_SPECIES).choose(&mut rng).unwrap(); + Self::random_with(&mut rng, &species) + } + + #[inline] + pub fn random_with(rng: &mut impl rand::Rng, &species: &Species) -> Self { + let body_type = *(&ALL_BODY_TYPES).choose(rng).unwrap(); + Self { species, body_type } + } +} + +impl From for super::Body { + fn from(body: Body) -> Self { super::Body::Arthropod(body) } +} + +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] +#[repr(u32)] +pub enum Species { + Tarantula = 0, + Blackwidow = 1, + Antlion = 2, + Hornbeetle = 3, + Leafbeetle = 4, + Stagbeetle = 5, + Weevil = 6, + Cavespider = 7, + Moltencrawler = 8, + Mosscrawler = 9, + Sandcrawler = 10, +} + +/// Data representing per-species generic data. +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct AllSpecies { + pub tarantula: SpeciesMeta, + pub black_widow: SpeciesMeta, + pub antlion: SpeciesMeta, + pub horn_beetle: SpeciesMeta, + pub leaf_beetle: SpeciesMeta, + pub stag_beetle: SpeciesMeta, + pub weevil: SpeciesMeta, + pub cave_spider: SpeciesMeta, + pub crawler_molten: SpeciesMeta, + pub crawler_moss: SpeciesMeta, + pub crawler_sand: SpeciesMeta, +} + +impl<'a, SpeciesMeta> core::ops::Index<&'a Species> for AllSpecies { + type Output = SpeciesMeta; + + #[inline] + fn index(&self, &index: &'a Species) -> &Self::Output { + match index { + Species::Tarantula => &self.tarantula, + Species::Blackwidow => &self.black_widow, + Species::Antlion => &self.antlion, + Species::Hornbeetle => &self.horn_beetle, + Species::Leafbeetle => &self.leaf_beetle, + Species::Stagbeetle => &self.stag_beetle, + Species::Weevil => &self.weevil, + Species::Cavespider => &self.cave_spider, + Species::Moltencrawler => &self.crawler_molten, + Species::Mosscrawler => &self.crawler_moss, + Species::Sandcrawler => &self.crawler_sand, + } + } +} + +pub const ALL_SPECIES: [Species; 11] = [ + Species::Tarantula, + Species::Blackwidow, + Species::Antlion, + Species::Hornbeetle, + Species::Leafbeetle, + Species::Stagbeetle, + Species::Weevil, + Species::Cavespider, + Species::Moltencrawler, + Species::Mosscrawler, + Species::Sandcrawler, +]; + +impl<'a, SpeciesMeta: 'a> IntoIterator for &'a AllSpecies { + type IntoIter = std::iter::Copied>; + type Item = Species; + + fn into_iter(self) -> Self::IntoIter { ALL_SPECIES.iter().copied() } +} + +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] +#[repr(u32)] +pub enum BodyType { + Female = 0, + Male = 1, +} +pub const ALL_BODY_TYPES: [BodyType; 2] = [BodyType::Female, BodyType::Male]; diff --git a/common/src/comp/body/object.rs b/common/src/comp/body/object.rs index 950aeab136..3b61fcb144 100644 --- a/common/src/comp/body/object.rs +++ b/common/src/comp/body/object.rs @@ -92,6 +92,8 @@ make_case_elim!( Apple = 77, Hive = 78, Coconut = 79, + SpitPoison = 80, + BoltIcicle = 81, } ); @@ -272,6 +274,8 @@ impl Body { Body::Apple => "apple", Body::Hive => "hive", Body::Coconut => "coconut", + Body::SpitPoison => "spit_poison", + Body::BoltIcicle => "bolt_icicle", } } @@ -310,7 +314,11 @@ impl Body { Body::BedBlue => 50.0, Body::Bedroll => 3.0, Body::Bench => 100.0, - Body::BoltFire | Body::BoltFireBig | Body::BoltNature => 1.0, + Body::BoltFire + | Body::BoltFireBig + | Body::BoltNature + | Body::BoltIcicle + | Body::SpitPoison => 1.0, Body::Bomb => { 0.5 * IRON_DENSITY * std::f32::consts::PI / 6.0 * self.dimensions().x.powi(3) }, diff --git a/common/src/comp/buff.rs b/common/src/comp/buff.rs index b224710692..69d4f06d36 100644 --- a/common/src/comp/buff.rs +++ b/common/src/comp/buff.rs @@ -74,6 +74,9 @@ pub enum BuffKind { /// Strength scales the movement speed debuff non-linearly. 0.5 is 50% /// speed, 1.0 is 33% speed. Ensnared, + /// Drain stamina to a creature over time + /// Strength should be the energy per second of the debuff + Poisoned, } #[cfg(not(target_arch = "wasm32"))] @@ -96,7 +99,8 @@ impl BuffKind { | BuffKind::Crippled | BuffKind::Frozen | BuffKind::Wet - | BuffKind::Ensnared => false, + | BuffKind::Ensnared + | BuffKind::Poisoned => false, } } @@ -144,6 +148,12 @@ pub enum BuffEffect { accumulated: f32, kind: ModifierKind, }, + /// Periodically consume entity energy + EnergyChangeOverTime { + rate: f32, + accumulated: f32, + kind: ModifierKind, + }, /// Changes maximum health by a certain amount MaxHealthModifier { value: f32, kind: ModifierKind }, /// Changes maximum energy by a certain amount @@ -292,6 +302,14 @@ impl Buff { }], data.duration, ), + BuffKind::Poisoned => ( + vec![BuffEffect::EnergyChangeOverTime { + rate: -data.strength, + accumulated: 0.0, + kind: ModifierKind::Additive, + }], + data.duration, + ), BuffKind::Crippled => ( vec![ BuffEffect::MovementSpeed(1.0 - nn_scaling(data.strength)), diff --git a/common/src/comp/fluid_dynamics.rs b/common/src/comp/fluid_dynamics.rs index 1f6e2960ba..212e4ae198 100644 --- a/common/src/comp/fluid_dynamics.rs +++ b/common/src/comp/fluid_dynamics.rs @@ -229,7 +229,8 @@ impl Body { Body::Theropod(_) | Body::QuadrupedMedium(_) | Body::QuadrupedSmall(_) - | Body::QuadrupedLow(_) => { + | Body::QuadrupedLow(_) + | Body::Arthropod(_) => { let dim = self.dimensions().map(|a| a * 0.5); let cd: f32 = if matches!(self, Body::QuadrupedLow(_)) { 0.7 diff --git a/common/src/comp/inventory/loadout_builder.rs b/common/src/comp/inventory/loadout_builder.rs index 39110bb48c..890d62c3d7 100644 --- a/common/src/comp/inventory/loadout_builder.rs +++ b/common/src/comp/inventory/loadout_builder.rs @@ -3,7 +3,7 @@ use crate::{ assets::{self, AssetExt}, comp::{ - biped_large, biped_small, bird_large, golem, + arthropod, biped_large, biped_small, bird_large, golem, inventory::{ loadout::Loadout, slot::{ArmorSlot, EquipSlot}, @@ -265,6 +265,22 @@ fn default_main_tool(body: &Body) -> Item { "common.items.npc_weapons.unique.theropodbasic", )), }, + Body::Arthropod(arthropod) => match arthropod.species { + arthropod::Species::Hornbeetle + | arthropod::Species::Stagbeetle + | arthropod::Species::Antlion => Some(Item::new_from_asset_expect( + "common.items.npc_weapons.unique.arthropodcharge", + )), + arthropod::Species::Cavespider | arthropod::Species::Blackwidow => Some( + Item::new_from_asset_expect("common.items.npc_weapons.unique.arthropodranged"), + ), + arthropod::Species::Weevil | arthropod::Species::Tarantula => Some( + Item::new_from_asset_expect("common.items.npc_weapons.unique.arthropodleap"), + ), + _ => Some(Item::new_from_asset_expect( + "common.items.npc_weapons.unique.arthropodbasic", + )), + }, Body::BipedLarge(biped_large) => match (biped_large.species, biped_large.body_type) { (biped_large::Species::Occultsaurok, _) => Some(Item::new_from_asset_expect( "common.items.npc_weapons.staff.saurok_staff", @@ -471,6 +487,7 @@ impl LoadoutBuilder { | theropod::Species::Odonto => Some("common.items.npc_armor.theropod.rugged"), _ => None, }, + Body::Arthropod(_) => Some("common.items.npc_armor.arthropod.generic"), _ => None, }; @@ -752,6 +769,7 @@ mod tests { theropod: Theropod, dragon: Dragon, golem: Golem, + arthropod: Arthropod, ); } diff --git a/common/src/comp/mod.rs b/common/src/comp/mod.rs index eccf554684..5d45365138 100644 --- a/common/src/comp/mod.rs +++ b/common/src/comp/mod.rs @@ -59,9 +59,9 @@ pub use self::{ aura::{Aura, AuraChange, AuraKind, Auras}, beam::{Beam, BeamSegment}, body::{ - biped_large, biped_small, bird_large, bird_medium, dragon, fish_medium, fish_small, golem, - humanoid, object, quadruped_low, quadruped_medium, quadruped_small, ship, theropod, - AllBodies, Body, BodyData, + arthropod, biped_large, biped_small, bird_large, bird_medium, dragon, fish_medium, + fish_small, golem, humanoid, object, quadruped_low, quadruped_medium, quadruped_small, + ship, theropod, AllBodies, Body, BodyData, }, buff::{ Buff, BuffCategory, BuffChange, BuffData, BuffEffect, BuffId, BuffKind, BuffSource, Buffs, diff --git a/common/src/comp/projectile.rs b/common/src/comp/projectile.rs index b4e4f7f493..ec43e0aaa1 100644 --- a/common/src/comp/projectile.rs +++ b/common/src/comp/projectile.rs @@ -61,6 +61,11 @@ pub enum ProjectileConstructor { radius: f32, min_falloff: f32, }, + Poisonball { + damage: f32, + radius: f32, + min_falloff: f32, + }, NecroticSphere { damage: f32, radius: f32, @@ -223,6 +228,52 @@ impl ProjectileConstructor { is_point: true, } }, + Poisonball { + damage, + radius, + min_falloff, + } => { + let buff = AttackEffect::new( + Some(GroupTarget::OutOfGroup), + CombatEffect::Buff(CombatBuff { + kind: BuffKind::Poisoned, + dur_secs: 5.0, + strength: CombatBuffStrength::DamageFraction(0.2 * buff_strength), + chance: 1.0, + }), + ) + .with_requirement(CombatRequirement::AnyDamage); + let damage = AttackDamage::new( + Damage { + source: DamageSource::Explosion, + kind: DamageKind::Energy, + value: damage, + }, + Some(GroupTarget::OutOfGroup), + ); + let attack = Attack::default() + .with_damage(damage) + .with_crit(crit_chance, crit_mult) + .with_effect(buff); + let explosion = Explosion { + effects: vec![ + RadiusEffect::Attack(attack), + RadiusEffect::TerrainDestruction(5.0), + ], + radius, + reagent: Some(Reagent::Purple), + min_falloff, + }; + Projectile { + hit_solid: vec![Effect::Explode(explosion.clone()), Effect::Vanish], + hit_entity: vec![Effect::Explode(explosion), Effect::Vanish], + time_left: Duration::from_secs(10), + owner, + ignore_group: true, + is_sticky: true, + is_point: true, + } + }, NecroticSphere { damage, radius, @@ -432,6 +483,14 @@ impl ProjectileConstructor { *damage *= power; *radius *= range; }, + Poisonball { + ref mut damage, + ref mut radius, + .. + } => { + *damage *= power; + *radius *= range; + }, NecroticSphere { ref mut damage, ref mut radius, diff --git a/common/src/generation.rs b/common/src/generation.rs index 4837baa7a1..757eaf720f 100644 --- a/common/src/generation.rs +++ b/common/src/generation.rs @@ -406,6 +406,7 @@ impl EntityInfo { Body::QuadrupedLow(body) => Some(get_npc_name(&npc_names.quadruped_low, body.species)), Body::Golem(body) => Some(get_npc_name(&npc_names.golem, body.species)), Body::BipedLarge(body) => Some(get_npc_name(&npc_names.biped_large, body.species)), + Body::Arthropod(body) => Some(get_npc_name(&npc_names.arthropod, body.species)), _ => None, }; self.name = name.map(str::to_owned); diff --git a/common/src/npc.rs b/common/src/npc.rs index 5712c33696..1985d7f113 100644 --- a/common/src/npc.rs +++ b/common/src/npc.rs @@ -22,9 +22,10 @@ pub enum NpcKind { StoneGolem, Reddragon, Crocodile, + Tarantula, } -pub const ALL_NPCS: [NpcKind; 13] = [ +pub const ALL_NPCS: [NpcKind; 14] = [ NpcKind::Humanoid, NpcKind::Wolf, NpcKind::Pig, @@ -38,6 +39,7 @@ pub const ALL_NPCS: [NpcKind; 13] = [ NpcKind::StoneGolem, NpcKind::Reddragon, NpcKind::Crocodile, + NpcKind::Tarantula, ]; /// Body-specific NPC name metadata. @@ -133,6 +135,7 @@ pub fn kind_to_body(kind: NpcKind) -> Body { NpcKind::StoneGolem => comp::golem::Body::random().into(), NpcKind::Reddragon => comp::dragon::Body::random().into(), NpcKind::Crocodile => comp::quadruped_low::Body::random().into(), + NpcKind::Tarantula => comp::arthropod::Body::random().into(), } } @@ -303,6 +306,14 @@ impl NpcBody { comp::quadruped_low::Body::random_with, ) }) + .or_else(|| { + parse( + s, + NpcKind::Tarantula, + &npc_names.arthropod, + comp::arthropod::Body::random_with, + ) + }) .ok_or(()) } } diff --git a/common/src/states/utils.rs b/common/src/states/utils.rs index 9d0612290a..49a2baedb3 100644 --- a/common/src/states/utils.rs +++ b/common/src/states/utils.rs @@ -2,7 +2,7 @@ use crate::{ astar::Astar, combat, comp::{ - biped_large, biped_small, + arthropod, biped_large, biped_small, character_state::OutputEvents, inventory::slot::{EquipSlot, Slot}, item::{Hands, ItemKind, Tool, ToolKind}, @@ -129,6 +129,19 @@ impl Body { quadruped_low::Species::Deadwood => 140.0, }, Body::Ship(_) => 0.0, + Body::Arthropod(arthropod) => match arthropod.species { + arthropod::Species::Tarantula => 135.0, + arthropod::Species::Blackwidow => 110.0, + arthropod::Species::Antlion => 120.0, + arthropod::Species::Hornbeetle => 80.0, + arthropod::Species::Leafbeetle => 80.0, + arthropod::Species::Stagbeetle => 80.0, + arthropod::Species::Weevil => 110.0, + arthropod::Species::Cavespider => 110.0, + arthropod::Species::Moltencrawler => 70.0, + arthropod::Species::Mosscrawler => 70.0, + arthropod::Species::Sandcrawler => 70.0, + }, } } @@ -186,6 +199,7 @@ impl Body { }, Body::Ship(ship) if ship.has_water_thrust() => 0.1, Body::Ship(_) => 0.035, + Body::Arthropod(_) => 3.5, } } @@ -214,6 +228,7 @@ impl Body { Body::QuadrupedSmall(_) => Some(300.0 * self.mass().0), Body::Ship(ship) if ship.has_water_thrust() => Some(3500.0 * self.mass().0), Body::Ship(_) => None, + Body::Arthropod(_) => Some(300.0 * self.mass().0), } } @@ -242,6 +257,7 @@ impl Body { | theropod::Species::Woodraptor => Some(0.4 * self.mass().0), _ => None, }, + Body::Arthropod(_) => Some(2.0 * self.mass().0), _ => Some(0.4 * self.mass().0), } .map(|f| f * GRAVITY) diff --git a/common/src/terrain/block.rs b/common/src/terrain/block.rs index c367a8c05b..ea515a8cd1 100644 --- a/common/src/terrain/block.rs +++ b/common/src/terrain/block.rs @@ -268,7 +268,7 @@ impl Block { | SpriteKind::SpinningWheel | SpriteKind::DismantlingBench | SpriteKind::TanningRack => None, - SpriteKind::EnsnaringVines => Some(0.1), + SpriteKind::EnsnaringVines | SpriteKind::EnsnaringWeb => Some(0.1), _ => Some(0.25), }), } diff --git a/common/src/terrain/sprite.rs b/common/src/terrain/sprite.rs index e6fdd6c28a..dbd42ceccc 100644 --- a/common/src/terrain/sprite.rs +++ b/common/src/terrain/sprite.rs @@ -190,6 +190,7 @@ make_case_elim!( Bomb = 0xA3, ChristmasOrnament = 0xA4, ChristmasWreath = 0xA5, + EnsnaringWeb = 0xA6, } ); @@ -278,7 +279,9 @@ impl SpriteKind { | SpriteKind::Tin | SpriteKind::Silver | SpriteKind::Gold => 0.6, - SpriteKind::EnsnaringVines | SpriteKind::CavernLillypadBlue => 0.1, + SpriteKind::EnsnaringVines + | SpriteKind::CavernLillypadBlue + | SpriteKind::EnsnaringWeb => 0.1, SpriteKind::LillyPads => 0.1, _ => return None, }) diff --git a/common/systems/src/buff.rs b/common/systems/src/buff.rs index 4bd3516a7b..fc09b09df4 100644 --- a/common/systems/src/buff.rs +++ b/common/systems/src/buff.rs @@ -7,7 +7,8 @@ use common::{ Buffs, }, fluid_dynamics::{Fluid, LiquidKind}, - Group, Health, HealthChange, Inventory, LightEmitter, ModifierKind, PhysicsState, Stats, + Energy, Group, Health, HealthChange, Inventory, LightEmitter, ModifierKind, PhysicsState, + Stats, }, event::{EventBus, ServerEvent}, resources::{DeltaTime, Time}, @@ -30,6 +31,7 @@ pub struct ReadData<'a> { server_bus: Read<'a, EventBus>, inventories: ReadStorage<'a, Inventory>, healths: ReadStorage<'a, Health>, + energies: ReadStorage<'a, Energy>, physics_states: ReadStorage<'a, PhysicsState>, groups: ReadStorage<'a, Group>, uid_allocator: Read<'a, UidAllocator>, @@ -79,11 +81,12 @@ impl<'a> System<'a> for Sys { light_emitters.remove(entity); } } - for (entity, mut buff_comp, mut stat, health, physics_state) in ( + for (entity, mut buff_comp, mut stat, health, energy, physics_state) in ( &read_data.entities, &mut buffs, &mut stats, &read_data.healths, + &read_data.energies, read_data.physics_states.maybe(), ) .join() @@ -92,7 +95,7 @@ impl<'a> System<'a> for Sys { if let Some(physics_state) = physics_state { if matches!( physics_state.on_ground.and_then(|b| b.get_sprite()), - Some(SpriteKind::EnsnaringVines) + Some(SpriteKind::EnsnaringVines) | Some(SpriteKind::EnsnaringWeb) ) { // If on ensnaring vines, apply ensnared debuff server_emitter.emit(ServerEvent::Buff { @@ -237,6 +240,30 @@ impl<'a> System<'a> for Sys { *accumulated = 0.0; }; }, + BuffEffect::EnergyChangeOverTime { + rate, + accumulated, + kind, + } => { + *accumulated += *rate * dt; + // Apply energy change only once per second, per energy, or + // when a buff is removed + if accumulated.abs() > rate.abs().min(10.0) + || buff.time.map_or(false, |dur| dur == Duration::default()) + { + let amount = match *kind { + ModifierKind::Additive => *accumulated, + ModifierKind::Fractional => { + energy.maximum() as f32 * *accumulated + }, + }; + server_emitter.emit(ServerEvent::EnergyChange { + entity, + change: amount, + }); + *accumulated = 0.0; + }; + }, BuffEffect::MaxHealthModifier { value, kind } => match kind { ModifierKind::Additive => { stat.max_health_modifiers.add_mod += *value; diff --git a/server/src/sys/agent.rs b/server/src/sys/agent.rs index 418287de3f..2bfba94eda 100644 --- a/server/src/sys/agent.rs +++ b/server/src/sys/agent.rs @@ -1692,6 +1692,10 @@ impl<'a> AgentData<'a> { "Quad Low Quick" => Tactic::QuadLowQuick, "Quad Low Basic" => Tactic::QuadLowBasic, "Theropod Basic" | "Theropod Bird" => Tactic::Theropod, + "Arthropod Basic" => Tactic::ArthropodBasic, + "Arthropod Charge" => Tactic::ArthropodCharge, + "Arthropod Ranged" => Tactic::ArthropodRanged, + "Arthropod Leap" => Tactic::ArthropodLeap, "Theropod Charge" => Tactic::CircleCharge { radius: 6, circle_time: 1, @@ -1968,6 +1972,35 @@ impl<'a> AgentData<'a> { Tactic::Theropod => { self.handle_theropod_attack(agent, controller, &attack_data, tgt_data, read_data) }, + Tactic::ArthropodBasic => self.handle_arthropod_basic_attack( + agent, + controller, + &attack_data, + tgt_data, + read_data, + ), + Tactic::ArthropodCharge => self.handle_arthropod_charge_attack( + agent, + controller, + &attack_data, + tgt_data, + read_data, + ), + Tactic::ArthropodLeap => self.handle_arthropod_leap_attack( + agent, + controller, + &attack_data, + tgt_data, + read_data, + rng, + ), + Tactic::ArthropodRanged => self.handle_arthropod_ranged_attack( + agent, + controller, + &attack_data, + tgt_data, + read_data, + ), Tactic::Turret => { self.handle_turret_attack(agent, controller, &attack_data, tgt_data, read_data) }, diff --git a/server/src/sys/agent/attack.rs b/server/src/sys/agent/attack.rs index 936b467a17..9e3fc0e1aa 100644 --- a/server/src/sys/agent/attack.rs +++ b/server/src/sys/agent/attack.rs @@ -1681,6 +1681,202 @@ impl<'a> AgentData<'a> { self.path_toward_target(agent, controller, tgt_data, read_data, true, false, None); } + pub fn handle_arthropod_basic_attack( + &self, + agent: &mut Agent, + controller: &mut Controller, + attack_data: &AttackData, + tgt_data: &TargetData, + read_data: &ReadData, + ) { + agent.action_state.timer += read_data.dt.0; + if agent.action_state.timer > 7.0 + && attack_data.dist_sqrd < (2.0 * attack_data.min_attack_dist).powi(2) + { + controller.inputs.move_dir = Vec2::zero(); + controller + .actions + .push(ControlAction::basic_input(InputKind::Secondary)); + // Reset timer + if matches!(self.char_state, CharacterState::SpriteSummon(c) if matches!(c.stage_section, StageSection::Recover)) + { + agent.action_state.timer = 0.0; + } + } else if attack_data.angle < 90.0 + && attack_data.dist_sqrd < (1.5 * attack_data.min_attack_dist).powi(2) + { + controller.inputs.move_dir = Vec2::zero(); + controller + .actions + .push(ControlAction::basic_input(InputKind::Primary)); + } else { + self.path_toward_target(agent, controller, tgt_data, read_data, false, false, None); + } + } + + pub fn handle_arthropod_ranged_attack( + &self, + agent: &mut Agent, + controller: &mut Controller, + attack_data: &AttackData, + tgt_data: &TargetData, + read_data: &ReadData, + ) { + agent.action_state.timer += read_data.dt.0; + if agent.action_state.timer > 6.0 + && attack_data.dist_sqrd < (2.0 * attack_data.min_attack_dist).powi(2) + { + controller.inputs.move_dir = Vec2::zero(); + controller + .actions + .push(ControlAction::basic_input(InputKind::Secondary)); + // Reset timer + if matches!(self.char_state, CharacterState::SpriteSummon(c) if matches!(c.stage_section, StageSection::Recover)) + { + agent.action_state.timer = 0.0; + } + } else if attack_data.dist_sqrd < (3.0 * attack_data.min_attack_dist).powi(2) + && attack_data.angle < 90.0 + { + controller.inputs.move_dir = (tgt_data.pos.0 - self.pos.0) + .xy() + .try_normalized() + .unwrap_or_else(Vec2::unit_y); + controller + .actions + .push(ControlAction::basic_input(InputKind::Primary)); + } else if attack_data.dist_sqrd < MAX_PATH_DIST.powi(2) { + 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 attack_data.angle < 15.0 + && can_see_tgt( + &*read_data.terrain, + self.pos, + tgt_data.pos, + attack_data.dist_sqrd, + ) + { + if agent.action_state.timer > 5.0 { + agent.action_state.timer = 0.0; + } else if agent.action_state.timer > 2.5 { + controller.inputs.move_dir = (tgt_data.pos.0 - self.pos.0) + .xy() + .rotated_z(1.75 * PI) + .try_normalized() + .unwrap_or_else(Vec2::zero) + * speed; + agent.action_state.timer += read_data.dt.0; + } else { + controller.inputs.move_dir = (tgt_data.pos.0 - self.pos.0) + .xy() + .rotated_z(0.25 * PI) + .try_normalized() + .unwrap_or_else(Vec2::zero) + * speed; + agent.action_state.timer += read_data.dt.0; + } + controller + .actions + .push(ControlAction::basic_input(InputKind::Ability(0))); + self.jump_if(controller, bearing.z > 1.5); + controller.inputs.move_z = bearing.z; + } else { + controller.inputs.move_dir = + bearing.xy().try_normalized().unwrap_or_else(Vec2::zero) * speed; + self.jump_if(controller, bearing.z > 1.5); + controller.inputs.move_z = bearing.z; + } + } else { + agent.target = None; + } + } else { + self.path_toward_target(agent, controller, tgt_data, read_data, false, false, None); + } + } + + pub fn handle_arthropod_leap_attack( + &self, + agent: &mut Agent, + controller: &mut Controller, + attack_data: &AttackData, + tgt_data: &TargetData, + read_data: &ReadData, + rng: &mut impl Rng, + ) { + agent.action_state.timer += read_data.dt.0; + if agent.action_state.timer > 12.0 + && attack_data.dist_sqrd < (1.5 * attack_data.min_attack_dist).powi(2) + { + controller.inputs.move_dir = Vec2::zero(); + controller + .actions + .push(ControlAction::basic_input(InputKind::Secondary)); + // Reset timer + if matches!(self.char_state, CharacterState::SpriteSummon(c) if matches!(c.stage_section, StageSection::Recover)) + { + agent.action_state.timer = 0.0; + } + } else if attack_data.angle < 90.0 + && attack_data.dist_sqrd < (1.5 * attack_data.min_attack_dist).powi(2) + { + controller.inputs.move_dir = Vec2::zero(); + controller + .actions + .push(ControlAction::basic_input(InputKind::Primary)); + } else if rng.gen_bool(0.01) + && attack_data.angle < 15.0 + && attack_data.dist_sqrd < (6.0 * attack_data.min_attack_dist).powi(2) + { + controller + .actions + .push(ControlAction::basic_input(InputKind::Ability(0))); + } else { + self.path_toward_target(agent, controller, tgt_data, read_data, false, false, None); + } + } + + pub fn handle_arthropod_charge_attack( + &self, + agent: &mut Agent, + controller: &mut Controller, + attack_data: &AttackData, + tgt_data: &TargetData, + read_data: &ReadData, + ) { + agent.action_state.timer += read_data.dt.0; + if matches!(self.char_state, CharacterState::DashMelee(c) if !matches!(c.stage_section, StageSection::Recover)) + { + // If already charging, keep charging if not in recover + controller + .actions + .push(ControlAction::basic_input(InputKind::Secondary)); + } else if attack_data.dist_sqrd > (5.0 * attack_data.min_attack_dist).powi(2) { + // Charges at target if they are far enough away + if attack_data.angle < 60.0 { + controller + .actions + .push(ControlAction::basic_input(InputKind::Secondary)); + } + } else if attack_data.angle < 90.0 + && attack_data.dist_sqrd < (1.5 * attack_data.min_attack_dist).powi(2) + { + controller.inputs.move_dir = Vec2::zero(); + controller + .actions + .push(ControlAction::basic_input(InputKind::Primary)); + } else { + self.path_toward_target(agent, controller, tgt_data, read_data, false, false, None); + } + } + pub fn handle_minotaur_attack( &self, agent: &mut Agent, diff --git a/server/src/sys/agent/data.rs b/server/src/sys/agent/data.rs index 141b344588..3b60ebe1a9 100644 --- a/server/src/sys/agent/data.rs +++ b/server/src/sys/agent/data.rs @@ -93,6 +93,10 @@ pub enum Tactic { BirdLargeBreathe, BirdLargeFire, BirdLargeBasic, + ArthropodCharge, + ArthropodBasic, + ArthropodRanged, + ArthropodLeap, Minotaur, ClayGolem, TidalWarrior, diff --git a/voxygen/anim/src/arthropod/alpha.rs b/voxygen/anim/src/arthropod/alpha.rs new file mode 100644 index 0000000000..c1a2743ca9 --- /dev/null +++ b/voxygen/anim/src/arthropod/alpha.rs @@ -0,0 +1,152 @@ +use std::f32::consts::PI; + +use super::{ + super::{vek::*, Animation}, + ArthropodSkeleton, SkeletonAttr, +}; +use common::states::utils::StageSection; + +pub struct AlphaAnimation; + +impl Animation for AlphaAnimation { + type Dependency<'a> = (f32, f32, Option, f32); + type Skeleton = ArthropodSkeleton; + + #[cfg(feature = "use-dyn-lib")] + const UPDATE_FN: &'static [u8] = b"arthropod_alpha\0"; + + #[cfg_attr(feature = "be-dyn-lib", export_name = "arthropod_alpha")] + fn update_skeleton_inner<'a>( + skeleton: &Self::Skeleton, + (_velocity, global_time, stage_section, timer): Self::Dependency<'a>, + anim_time: f32, + _rate: &mut f32, + s_a: &SkeletonAttr, + ) -> Self::Skeleton { + let mut next = (*skeleton).clone(); + + let (movement1, movement2, movement3) = match stage_section { + Some(StageSection::Buildup) => (anim_time.powi(2), 0.0, 0.0), + Some(StageSection::Action) => (1.0, anim_time.powi(4), 0.0), + Some(StageSection::Recover) => (1.0, 1.0, anim_time), + _ => (0.0, 0.0, 0.0), + }; + let pullback = 1.0 - movement3; + let subtract = global_time - timer; + let check = subtract - subtract.trunc(); + let mirror = (check - 0.5).signum(); + let movement1abs = movement1 * pullback; + let movement2abs = movement2 * pullback; + let movement3abs = movement3 * pullback; + + if s_a.snapper { + next.chest.scale = Vec3::one() / s_a.scaler; + + next.head.position = Vec3::new(0.0, s_a.head.0, s_a.head.1); + next.head.orientation = Quaternion::rotation_x( + movement1abs * -0.2 + movement2abs * 0.4 + movement3abs * 0.8, + ) * Quaternion::rotation_y( + movement1abs * -0.1 + movement2abs * 0.2 + movement3abs * 0.2, + ); + + next.chest.position = Vec3::new(0.0, s_a.chest.0, s_a.chest.1); + + next.mandible_l.position = Vec3::new(-s_a.mandible.0, s_a.mandible.1, s_a.mandible.2); + next.mandible_r.position = Vec3::new(s_a.mandible.0, s_a.mandible.1, s_a.mandible.2); + next.mandible_l.orientation = Quaternion::rotation_z( + movement1abs * 0.7 + movement2abs * -1.0 + movement3abs * 0.8, + ); + next.mandible_r.orientation = Quaternion::rotation_z( + movement1abs * -0.7 + movement2abs * 1.0 + movement3abs * -0.8, + ); + + next.wing_fl.position = Vec3::new(-s_a.wing_f.0, s_a.wing_f.1, s_a.wing_f.2); + next.wing_fr.position = Vec3::new(s_a.wing_f.0, s_a.wing_f.1, s_a.wing_f.2); + next.wing_fl.orientation = + Quaternion::rotation_x(movement1abs * -0.5 + movement2abs * 0.5) + * Quaternion::rotation_y(movement1abs * 0.2 + movement2abs * -0.2) + * Quaternion::rotation_z(movement1abs * -0.2 + movement2abs * 0.2); + next.wing_fr.orientation = + Quaternion::rotation_x(movement1abs * -0.5 + movement2abs * 0.5) + * Quaternion::rotation_y(movement1abs * -0.2 + movement2abs * 0.2) + * Quaternion::rotation_z(movement1abs * 0.2 + movement2abs * -0.2); + + next.wing_bl.position = Vec3::new(-s_a.wing_b.0, s_a.wing_b.1, s_a.wing_b.2); + next.wing_br.position = Vec3::new(s_a.wing_b.0, s_a.wing_b.1, s_a.wing_b.2); + next.wing_bl.orientation = + Quaternion::rotation_x(movement1abs * -0.3 + movement2abs * 0.3) + * Quaternion::rotation_y(movement1abs * 0.2 + movement2abs * -0.2); + next.wing_br.orientation = + Quaternion::rotation_x(movement1abs * -0.3 + movement2abs * 0.3) + * Quaternion::rotation_y(movement1abs * -0.2 + movement2abs * 0.2); + + next.leg_fl.position = Vec3::new(-s_a.leg_f.0, s_a.leg_f.1, s_a.leg_f.2); + next.leg_fr.position = Vec3::new(s_a.leg_f.0, s_a.leg_f.1, s_a.leg_f.2); + + next.leg_fcl.position = Vec3::new(-s_a.leg_fc.0, s_a.leg_fc.1, s_a.leg_fc.2); + next.leg_fcr.position = Vec3::new(s_a.leg_fc.0, s_a.leg_fc.1, s_a.leg_fc.2); + + next.leg_bcl.position = Vec3::new(-s_a.leg_bc.0, s_a.leg_bc.1, s_a.leg_bc.2); + next.leg_bcr.position = Vec3::new(s_a.leg_bc.0, s_a.leg_bc.1, s_a.leg_bc.2); + + next.leg_bl.position = Vec3::new(-s_a.leg_b.0, s_a.leg_b.1, s_a.leg_b.2); + next.leg_br.position = Vec3::new(s_a.leg_b.0, s_a.leg_b.1, s_a.leg_b.2); + } else { + next.chest.scale = Vec3::one() / s_a.scaler; + next.chest.orientation = Quaternion::rotation_x(movement2abs * 0.3) + * Quaternion::rotation_z((movement1abs * 4.0 * PI).sin() * 0.02); + + next.head.position = Vec3::new(0.0, s_a.head.0, s_a.head.1); + next.head.orientation = + Quaternion::rotation_x( + movement1abs * 0.5 + movement2abs * -1.5 + movement3abs * 0.8, + ) * Quaternion::rotation_y( + mirror * movement1abs * -0.2 + mirror * movement2abs * 0.2, + ) * Quaternion::rotation_z((movement1abs * 4.0 * PI).sin() * 0.02); + + next.chest.position = Vec3::new(0.0, s_a.chest.0, s_a.chest.1); + + next.mandible_l.position = Vec3::new(-s_a.mandible.0, s_a.mandible.1, s_a.mandible.2); + next.mandible_r.position = Vec3::new(s_a.mandible.0, s_a.mandible.1, s_a.mandible.2); + next.mandible_l.orientation = Quaternion::rotation_x( + movement1abs * 0.5 + movement2abs * -1.5 + movement3abs * 0.8, + ) * Quaternion::rotation_z( + movement1abs * 0.5 + movement2abs * -0.6 + movement3abs * 0.8, + ); + next.mandible_r.orientation = Quaternion::rotation_x( + movement1abs * 0.5 + movement2abs * -1.5 + movement3abs * 0.8, + ) * Quaternion::rotation_z( + movement1abs * -0.5 + movement2abs * 0.6 + movement3abs * -0.8, + ); + + next.wing_fl.position = Vec3::new(-s_a.wing_f.0, s_a.wing_f.1, s_a.wing_f.2); + next.wing_fr.position = Vec3::new(s_a.wing_f.0, s_a.wing_f.1, s_a.wing_f.2); + + next.wing_bl.position = Vec3::new(-s_a.wing_b.0, s_a.wing_b.1, s_a.wing_b.2); + next.wing_br.position = Vec3::new(s_a.wing_b.0, s_a.wing_b.1, s_a.wing_b.2); + + next.leg_fl.position = Vec3::new(-s_a.leg_f.0, s_a.leg_f.1, s_a.leg_f.2); + next.leg_fr.position = Vec3::new(s_a.leg_f.0, s_a.leg_f.1, s_a.leg_f.2); + next.leg_fl.orientation = Quaternion::rotation_z( + s_a.leg_ori.0 + movement1abs * 0.4 + movement2abs * -0.4 + movement3abs * 0.8, + ) * Quaternion::rotation_x( + movement1abs * 1.0 + movement2abs * -1.8 + movement3abs * 0.8, + ); + next.leg_fr.orientation = Quaternion::rotation_z( + -s_a.leg_ori.0 + movement1abs * -0.4 + movement2abs * 0.4 + movement3abs * -0.8, + ) * Quaternion::rotation_x( + movement1abs * 1.0 + movement2abs * -1.8 + movement3abs * 0.8, + ); + + next.leg_fcl.position = Vec3::new(-s_a.leg_fc.0, s_a.leg_fc.1, s_a.leg_fc.2); + next.leg_fcr.position = Vec3::new(s_a.leg_fc.0, s_a.leg_fc.1, s_a.leg_fc.2); + + next.leg_bcl.position = Vec3::new(-s_a.leg_bc.0, s_a.leg_bc.1, s_a.leg_bc.2); + next.leg_bcr.position = Vec3::new(s_a.leg_bc.0, s_a.leg_bc.1, s_a.leg_bc.2); + + next.leg_bl.position = Vec3::new(-s_a.leg_b.0, s_a.leg_b.1, s_a.leg_b.2); + next.leg_br.position = Vec3::new(s_a.leg_b.0, s_a.leg_b.1, s_a.leg_b.2); + } + next + } +} diff --git a/voxygen/anim/src/arthropod/dash.rs b/voxygen/anim/src/arthropod/dash.rs new file mode 100644 index 0000000000..8aaadea4dd --- /dev/null +++ b/voxygen/anim/src/arthropod/dash.rs @@ -0,0 +1,74 @@ +use super::{super::Animation, ArthropodSkeleton, SkeletonAttr}; +//use std::{f32::consts::PI, ops::Mul}; +use super::super::vek::*; +use common::states::utils::StageSection; +use std::f32::consts::PI; + +pub struct DashAnimation; + +impl Animation for DashAnimation { + type Dependency<'a> = (f32, f32, Option, f32); + type Skeleton = ArthropodSkeleton; + + #[cfg(feature = "use-dyn-lib")] + const UPDATE_FN: &'static [u8] = b"arthropod_dash\0"; + + #[cfg_attr(feature = "be-dyn-lib", export_name = "arthropod_dash")] + fn update_skeleton_inner<'a>( + skeleton: &Self::Skeleton, + (_velocity, _global_time, stage_section, _timer): Self::Dependency<'a>, + anim_time: f32, + _rate: &mut f32, + s_a: &SkeletonAttr, + ) -> Self::Skeleton { + let mut next = (*skeleton).clone(); + + let (movement1base, chargemovementbase, movement2base, movement3) = match stage_section { + Some(StageSection::Buildup) => (anim_time.powi(4), 0.0, 0.0, 0.0), + Some(StageSection::Charge) => (1.0, 1.0, 0.0, 0.0), + Some(StageSection::Action) => (1.0, 1.0, anim_time.powi(6), 0.0), + Some(StageSection::Recover) => (1.0, 1.0, 1.0, anim_time), + _ => (0.0, 0.0, 0.0, 0.0), + }; + let pullback = 1.0 - movement3; + let movement1abs = movement1base * pullback; + let movement2abs = movement2base * pullback; + let shortalt = (anim_time * 200.0 + PI * 0.25).sin() * chargemovementbase * pullback; + + next.chest.scale = Vec3::one(); + + next.head.position = Vec3::new(0.0, s_a.head.0, s_a.head.1); + next.head.orientation = Quaternion::rotation_x(movement1abs * -0.4 + movement2abs * 1.4); + + next.chest.position = Vec3::new(0.0, s_a.chest.0, s_a.chest.1); + + next.mandible_l.position = Vec3::new(-s_a.mandible.0, s_a.mandible.1, s_a.mandible.2); + next.mandible_r.position = Vec3::new(s_a.mandible.0, s_a.mandible.1, s_a.mandible.2); + next.mandible_l.orientation = + Quaternion::rotation_z(movement1abs * 0.5 + movement2abs * -0.7); + next.mandible_r.orientation = + Quaternion::rotation_z(movement1abs * -0.5 + movement2abs * 0.7); + + next.wing_fl.position = Vec3::new(-s_a.wing_f.0, s_a.wing_f.1, s_a.wing_f.2); + next.wing_fr.position = Vec3::new(s_a.wing_f.0, s_a.wing_f.1, s_a.wing_f.2); + next.wing_fl.orientation = + Quaternion::rotation_x(movement1abs * -0.4 + shortalt * 0.2 + movement2abs * -0.6) + * Quaternion::rotation_y(movement1abs * -0.5 + movement2abs * -0.1) + * Quaternion::rotation_z(movement1abs * -0.2); + next.wing_fr.orientation = + Quaternion::rotation_x(movement1abs * -0.4 + shortalt * 0.2 + movement2abs * -0.6) + * Quaternion::rotation_y(movement1abs * 0.5 + movement2abs * 0.1) + * Quaternion::rotation_z(movement1abs * 0.2); + + next.wing_bl.position = Vec3::new(-s_a.wing_b.0, s_a.wing_b.1, s_a.wing_b.2); + next.wing_br.position = Vec3::new(s_a.wing_b.0, s_a.wing_b.1, s_a.wing_b.2); + next.wing_bl.orientation = + Quaternion::rotation_x(movement1abs * -0.2 + shortalt * 0.2 + movement2abs * -0.6) + * Quaternion::rotation_y(movement1abs * -0.4 + movement2abs * -0.1); + next.wing_br.orientation = + Quaternion::rotation_x(movement1abs * -0.2 + shortalt * 0.2 + movement2abs * -0.6) + * Quaternion::rotation_y(movement1abs * 0.4 + movement2abs * 0.1); + + next + } +} diff --git a/voxygen/anim/src/arthropod/idle.rs b/voxygen/anim/src/arthropod/idle.rs new file mode 100644 index 0000000000..506e3c2c10 --- /dev/null +++ b/voxygen/anim/src/arthropod/idle.rs @@ -0,0 +1,64 @@ +use super::{ + super::{vek::*, Animation}, + ArthropodSkeleton, SkeletonAttr, +}; + +pub struct IdleAnimation; + +impl Animation for IdleAnimation { + type Dependency<'a> = f32; + type Skeleton = ArthropodSkeleton; + + #[cfg(feature = "use-dyn-lib")] + const UPDATE_FN: &'static [u8] = b"arthropod_idle\0"; + + #[cfg_attr(feature = "be-dyn-lib", export_name = "arthropod_idle")] + fn update_skeleton_inner<'a>( + skeleton: &Self::Skeleton, + _global_time: Self::Dependency<'a>, + _anim_time: f32, + _rate: &mut f32, + s_a: &SkeletonAttr, + ) -> Self::Skeleton { + let mut next = (*skeleton).clone(); + + next.chest.scale = Vec3::one() / s_a.scaler; + next.wing_bl.scale = Vec3::one() * 0.98; + next.wing_br.scale = Vec3::one() * 0.98; + + next.head.position = Vec3::new(0.0, s_a.head.0, s_a.head.1); + + next.chest.position = Vec3::new(0.0, s_a.chest.0, s_a.chest.1); + + next.mandible_l.position = Vec3::new(-s_a.mandible.0, s_a.mandible.1, s_a.mandible.2); + next.mandible_r.position = Vec3::new(s_a.mandible.0, s_a.mandible.1, s_a.mandible.2); + + next.wing_fl.position = Vec3::new(-s_a.wing_f.0, s_a.wing_f.1, s_a.wing_f.2); + next.wing_fr.position = Vec3::new(s_a.wing_f.0, s_a.wing_f.1, s_a.wing_f.2); + + next.wing_bl.position = Vec3::new(-s_a.wing_b.0, s_a.wing_b.1, s_a.wing_b.2); + next.wing_br.position = Vec3::new(s_a.wing_b.0, s_a.wing_b.1, s_a.wing_b.2); + + next.leg_fl.position = Vec3::new(-s_a.leg_f.0, s_a.leg_f.1, s_a.leg_f.2); + next.leg_fr.position = Vec3::new(s_a.leg_f.0, s_a.leg_f.1, s_a.leg_f.2); + next.leg_fl.orientation = Quaternion::rotation_z(s_a.leg_ori.0); + next.leg_fr.orientation = Quaternion::rotation_z(-s_a.leg_ori.0); + + next.leg_fcl.position = Vec3::new(-s_a.leg_fc.0, s_a.leg_fc.1, s_a.leg_fc.2); + next.leg_fcr.position = Vec3::new(s_a.leg_fc.0, s_a.leg_fc.1, s_a.leg_fc.2); + next.leg_fcl.orientation = Quaternion::rotation_z(s_a.leg_ori.1); + next.leg_fcr.orientation = Quaternion::rotation_z(-s_a.leg_ori.1); + + next.leg_bcl.position = Vec3::new(-s_a.leg_bc.0, s_a.leg_bc.1, s_a.leg_bc.2); + next.leg_bcr.position = Vec3::new(s_a.leg_bc.0, s_a.leg_bc.1, s_a.leg_bc.2); + next.leg_bcl.orientation = Quaternion::rotation_z(s_a.leg_ori.2); + next.leg_bcr.orientation = Quaternion::rotation_z(-s_a.leg_ori.2); + + next.leg_bl.position = Vec3::new(-s_a.leg_b.0, s_a.leg_b.1, s_a.leg_b.2); + next.leg_br.position = Vec3::new(s_a.leg_b.0, s_a.leg_b.1, s_a.leg_b.2); + next.leg_bl.orientation = Quaternion::rotation_z(s_a.leg_ori.3); + next.leg_br.orientation = Quaternion::rotation_z(-s_a.leg_ori.3); + + next + } +} diff --git a/voxygen/anim/src/arthropod/jump.rs b/voxygen/anim/src/arthropod/jump.rs new file mode 100644 index 0000000000..9bc8b61b9f --- /dev/null +++ b/voxygen/anim/src/arthropod/jump.rs @@ -0,0 +1,72 @@ +use super::{ + super::{vek::*, Animation}, + ArthropodSkeleton, SkeletonAttr, +}; + +pub struct JumpAnimation; + +impl Animation for JumpAnimation { + type Dependency<'a> = (f32, Vec3, Vec3, f32, Vec3); + type Skeleton = ArthropodSkeleton; + + #[cfg(feature = "use-dyn-lib")] + const UPDATE_FN: &'static [u8] = b"arthropod_jump\0"; + + #[cfg_attr(feature = "be-dyn-lib", export_name = "arthropod_jump")] + fn update_skeleton_inner<'a>( + skeleton: &Self::Skeleton, + (_velocity, _orientation, _last_ori, _global_time, _avg_vel): Self::Dependency<'a>, + _anim_time: f32, + _rate: &mut f32, + s_a: &SkeletonAttr, + ) -> Self::Skeleton { + let mut next = (*skeleton).clone(); + + next.chest.scale = Vec3::one() / s_a.scaler; + next.wing_bl.scale = Vec3::one() * 0.98; + next.wing_br.scale = Vec3::one() * 0.98; + + next.head.position = Vec3::new(0.0, s_a.head.0, s_a.head.1); + + next.chest.position = Vec3::new(0.0, s_a.chest.0, s_a.chest.1); + + next.mandible_l.position = Vec3::new(-s_a.mandible.0, s_a.mandible.1, s_a.mandible.2); + next.mandible_r.position = Vec3::new(s_a.mandible.0, s_a.mandible.1, s_a.mandible.2); + + next.wing_fl.position = Vec3::new(-s_a.wing_f.0, s_a.wing_f.1, s_a.wing_f.2); + next.wing_fr.position = Vec3::new(s_a.wing_f.0, s_a.wing_f.1, s_a.wing_f.2); + + next.wing_bl.position = Vec3::new(-s_a.wing_b.0, s_a.wing_b.1, s_a.wing_b.2); + next.wing_br.position = Vec3::new(s_a.wing_b.0, s_a.wing_b.1, s_a.wing_b.2); + + next.leg_fl.position = Vec3::new(-s_a.leg_f.0, s_a.leg_f.1, s_a.leg_f.2); + next.leg_fr.position = Vec3::new(s_a.leg_f.0, s_a.leg_f.1, s_a.leg_f.2); + next.leg_fl.orientation = + Quaternion::rotation_z(s_a.leg_ori.0) * Quaternion::rotation_y(0.6); + next.leg_fr.orientation = + Quaternion::rotation_z(-s_a.leg_ori.0) * Quaternion::rotation_y(-0.6); + + next.leg_fcl.position = Vec3::new(-s_a.leg_fc.0, s_a.leg_fc.1, s_a.leg_fc.2); + next.leg_fcr.position = Vec3::new(s_a.leg_fc.0, s_a.leg_fc.1, s_a.leg_fc.2); + next.leg_fcl.orientation = + Quaternion::rotation_z(s_a.leg_ori.1) * Quaternion::rotation_y(0.6); + next.leg_fcr.orientation = + Quaternion::rotation_z(-s_a.leg_ori.1) * Quaternion::rotation_y(-0.6); + + next.leg_bcl.position = Vec3::new(-s_a.leg_bc.0, s_a.leg_bc.1, s_a.leg_bc.2); + next.leg_bcr.position = Vec3::new(s_a.leg_bc.0, s_a.leg_bc.1, s_a.leg_bc.2); + next.leg_bcl.orientation = + Quaternion::rotation_z(s_a.leg_ori.2) * Quaternion::rotation_y(0.6); + next.leg_bcr.orientation = + Quaternion::rotation_z(-s_a.leg_ori.2) * Quaternion::rotation_y(-0.6); + + next.leg_bl.position = Vec3::new(-s_a.leg_b.0, s_a.leg_b.1, s_a.leg_b.2); + next.leg_br.position = Vec3::new(s_a.leg_b.0, s_a.leg_b.1, s_a.leg_b.2); + next.leg_bl.orientation = + Quaternion::rotation_z(s_a.leg_ori.3) * Quaternion::rotation_y(0.6); + next.leg_br.orientation = + Quaternion::rotation_z(-s_a.leg_ori.3) * Quaternion::rotation_y(-0.6); + + next + } +} diff --git a/voxygen/anim/src/arthropod/leapmelee.rs b/voxygen/anim/src/arthropod/leapmelee.rs new file mode 100644 index 0000000000..989f5a1bba --- /dev/null +++ b/voxygen/anim/src/arthropod/leapmelee.rs @@ -0,0 +1,129 @@ +use std::f32::consts::PI; + +use super::{ + super::{vek::*, Animation}, + ArthropodSkeleton, SkeletonAttr, +}; +use common::states::utils::StageSection; + +pub struct LeapMeleeAnimation; + +impl Animation for LeapMeleeAnimation { + type Dependency<'a> = (f32, f32, Option, f32); + type Skeleton = ArthropodSkeleton; + + #[cfg(feature = "use-dyn-lib")] + const UPDATE_FN: &'static [u8] = b"arthropod_leapmelee\0"; + + #[cfg_attr(feature = "be-dyn-lib", export_name = "arthropod_leapmelee")] + fn update_skeleton_inner<'a>( + skeleton: &Self::Skeleton, + (_velocity, global_time, stage_section, _timer): Self::Dependency<'a>, + anim_time: f32, + _rate: &mut f32, + s_a: &SkeletonAttr, + ) -> Self::Skeleton { + let mut next = (*skeleton).clone(); + //let speed = (Vec2::::from(velocity).magnitude()).min(24.0); + + let (movement1base, movement2base, movement3base, movement4) = match stage_section { + Some(StageSection::Buildup) => (anim_time, 0.0, 0.0, 0.0), + Some(StageSection::Movement) => (1.0, anim_time.powf(0.1), 0.0, 0.0), + Some(StageSection::Action) => (1.0, 1.0, anim_time.powf(0.1), 0.0), + Some(StageSection::Recover) => (0.0, 1.0, 1.0, anim_time.powi(4)), + _ => (0.0, 0.0, 0.0, 0.0), + }; + let pullback = 1.0 - movement4; + let early_pullback = 1.0 - movement3base; + let movement1abs = movement1base * pullback; + let movement2abs = movement2base * pullback; + let movement3abs = movement3base * pullback; + + let shortalt = (global_time * 80.0).sin() * movement2base * early_pullback; + + next.chest.scale = Vec3::one() / s_a.scaler; + + next.head.position = Vec3::new(0.0, s_a.head.0, s_a.head.1); + next.head.orientation = + Quaternion::rotation_x(movement1abs * -0.2 + movement2abs * 0.4 + movement3abs * -1.0) + * Quaternion::rotation_z((movement1abs * 4.0 * PI).sin() * 0.08); + + next.chest.position = Vec3::new(0.0, s_a.chest.0, s_a.chest.1 + movement1abs * -2.0); + next.chest.orientation = Quaternion::rotation_x(movement2abs * 0.3) + * Quaternion::rotation_z((movement1abs * 4.0 * PI).sin() * 0.08); + + next.mandible_l.position = Vec3::new(-s_a.mandible.0, s_a.mandible.1, s_a.mandible.2); + next.mandible_r.position = Vec3::new(s_a.mandible.0, s_a.mandible.1, s_a.mandible.2); + next.mandible_l.orientation = Quaternion::rotation_x( + (movement1abs * 4.0 * PI).sin() * 0.08 + movement2abs * 0.3 + movement3abs * -0.4, + ); + next.mandible_r.orientation = Quaternion::rotation_x( + (movement1abs * 4.0 * PI).sin() * 0.08 + movement2abs * 0.3 + movement3abs * -0.4, + ); + + next.wing_fl.position = Vec3::new(-s_a.wing_f.0, s_a.wing_f.1, s_a.wing_f.2); + next.wing_fr.position = Vec3::new(s_a.wing_f.0, s_a.wing_f.1, s_a.wing_f.2); + + next.wing_bl.position = Vec3::new(-s_a.wing_b.0, s_a.wing_b.1, s_a.wing_b.2); + next.wing_br.position = Vec3::new(s_a.wing_b.0, s_a.wing_b.1, s_a.wing_b.2); + + next.leg_fl.position = Vec3::new(-s_a.leg_f.0, s_a.leg_f.1, s_a.leg_f.2); + next.leg_fr.position = Vec3::new(s_a.leg_f.0, s_a.leg_f.1, s_a.leg_f.2); + next.leg_fl.orientation = + Quaternion::rotation_x(movement1abs * 0.2 + movement2abs * 0.8 + movement3abs * -1.5) + * Quaternion::rotation_z(s_a.leg_ori.0); + next.leg_fr.orientation = + Quaternion::rotation_x(movement1abs * 0.2 + movement2abs * 0.8 + movement3abs * -1.5) + * Quaternion::rotation_z(-s_a.leg_ori.0); + + next.leg_fcl.position = Vec3::new(-s_a.leg_fc.0, s_a.leg_fc.1, s_a.leg_fc.2); + next.leg_fcr.position = Vec3::new(s_a.leg_fc.0, s_a.leg_fc.1, s_a.leg_fc.2); + next.leg_fcl.orientation = + Quaternion::rotation_y(movement1abs * 0.2 + movement2abs * -1.0 + movement3abs * 0.8) + * Quaternion::rotation_z(s_a.leg_ori.1); + next.leg_fcr.orientation = Quaternion::rotation_y(movement1abs * -0.2 + movement2abs * 1.0) + * Quaternion::rotation_z(-s_a.leg_ori.1); + + next.leg_bcl.position = Vec3::new(-s_a.leg_bc.0, s_a.leg_bc.1, s_a.leg_bc.2); + next.leg_bcr.position = Vec3::new(s_a.leg_bc.0, s_a.leg_bc.1, s_a.leg_bc.2); + next.leg_bcl.orientation = + Quaternion::rotation_y(movement1abs * 0.2 + movement2abs * -1.0 + movement3abs * 0.8) + * Quaternion::rotation_z(s_a.leg_ori.2); + next.leg_bcr.orientation = Quaternion::rotation_y(movement1abs * -0.2 + movement2abs * 1.0) + * Quaternion::rotation_z(-s_a.leg_ori.2); + + next.leg_bl.position = Vec3::new(-s_a.leg_b.0, s_a.leg_b.1, s_a.leg_b.2); + next.leg_br.position = Vec3::new(s_a.leg_b.0, s_a.leg_b.1, s_a.leg_b.2); + next.leg_bl.orientation = + Quaternion::rotation_y(movement1abs * 0.2 + movement2abs * -1.0 + movement3abs * 0.8) + * Quaternion::rotation_z(s_a.leg_ori.3); + next.leg_br.orientation = Quaternion::rotation_y(movement1abs * -0.2 + movement2abs * 1.0) + * Quaternion::rotation_z(-s_a.leg_ori.3); + + next.wing_fl.position = Vec3::new(-s_a.wing_f.0, s_a.wing_f.1, s_a.wing_f.2); + next.wing_fr.position = Vec3::new(s_a.wing_f.0, s_a.wing_f.1, s_a.wing_f.2); + next.wing_fl.orientation = + Quaternion::rotation_x(movement1abs * -0.4 + movement2abs * -0.2) + * Quaternion::rotation_y(movement1abs * 0.5 + movement2abs * 0.1) + * Quaternion::rotation_z(movement1abs * -0.2); + next.wing_fr.orientation = + Quaternion::rotation_x(movement1abs * -0.4 + movement2abs * -0.2) + * Quaternion::rotation_y(movement1abs * -0.5 + movement2abs * -0.1) + * Quaternion::rotation_z(movement1abs * 0.2); + + next.wing_bl.position = Vec3::new(-s_a.wing_b.0, s_a.wing_b.1, s_a.wing_b.2); + next.wing_br.position = Vec3::new(s_a.wing_b.0, s_a.wing_b.1, s_a.wing_b.2); + next.wing_bl.orientation = + Quaternion::rotation_x((movement1abs * -0.2 + movement2abs * -0.6) * early_pullback) + * Quaternion::rotation_y(movement1abs * 0.4 + shortalt * 2.0 + movement2abs * 0.1) + * Quaternion::rotation_z(movement1abs * -1.4); + next.wing_br.orientation = + Quaternion::rotation_x((movement1abs * -0.2 + movement2abs * -0.6) * early_pullback) + * Quaternion::rotation_y( + movement1abs * -0.4 + shortalt * 2.0 + movement2abs * -0.1, + ) + * Quaternion::rotation_z(movement1abs * 1.4); + + next + } +} diff --git a/voxygen/anim/src/arthropod/mod.rs b/voxygen/anim/src/arthropod/mod.rs new file mode 100644 index 0000000000..a0c25c2599 --- /dev/null +++ b/voxygen/anim/src/arthropod/mod.rs @@ -0,0 +1,318 @@ +pub mod alpha; +pub mod dash; +pub mod idle; +pub mod jump; +pub mod leapmelee; +pub mod run; +pub mod shoot; +pub mod stunned; +pub mod summon; + +// Reexports +pub use self::{ + alpha::AlphaAnimation, dash::DashAnimation, idle::IdleAnimation, jump::JumpAnimation, + leapmelee::LeapMeleeAnimation, run::RunAnimation, shoot::ShootAnimation, + stunned::StunnedAnimation, summon::SummonAnimation, +}; + +use super::{make_bone, vek::*, FigureBoneData, Offsets, Skeleton}; +use common::comp::{self}; +use core::convert::TryFrom; + +pub type Body = comp::arthropod::Body; + +skeleton_impls!(struct ArthropodSkeleton { + + head, + + chest, + + mandible_l, + + mandible_r, + + wing_fl, + + wing_fr, + + wing_bl, + + wing_br, + + leg_fl, + + leg_fr, + + leg_fcl, + + leg_fcr, + + leg_bcl, + + leg_bcr, + + leg_bl, + + leg_br, +}); + +impl Skeleton for ArthropodSkeleton { + type Attr = SkeletonAttr; + type Body = Body; + + const BONE_COUNT: usize = 16; + #[cfg(feature = "use-dyn-lib")] + const COMPUTE_FN: &'static [u8] = b"arthropod_compute_s\0"; + + #[cfg_attr(feature = "be-dyn-lib", export_name = "arthropod_compute_s")] + + fn compute_matrices_inner( + &self, + base_mat: Mat4, + buf: &mut [FigureBoneData; super::MAX_BONE_COUNT], + body: Self::Body, + ) -> Offsets { + let base_mat = base_mat * Mat4::scaling_3d(SkeletonAttr::from(&body).scaler / 6.0); + + let chest_mat = base_mat * Mat4::::from(self.chest); + let head_mat = chest_mat * Mat4::::from(self.head); + let mandible_l_mat = head_mat * Mat4::::from(self.mandible_l); + let mandible_r_mat = head_mat * Mat4::::from(self.mandible_r); + let wing_fl_mat = chest_mat * Mat4::::from(self.wing_fl); + let wing_fr_mat = chest_mat * Mat4::::from(self.wing_fr); + let wing_bl_mat = chest_mat * Mat4::::from(self.wing_bl); + let wing_br_mat = chest_mat * Mat4::::from(self.wing_br); + let leg_fl_mat = chest_mat * Mat4::::from(self.leg_fl); + let leg_fr_mat = chest_mat * Mat4::::from(self.leg_fr); + let leg_fcl_mat = chest_mat * Mat4::::from(self.leg_fcl); + let leg_fcr_mat = chest_mat * Mat4::::from(self.leg_fcr); + let leg_bcl_mat = chest_mat * Mat4::::from(self.leg_bcl); + let leg_bcr_mat = chest_mat * Mat4::::from(self.leg_bcr); + let leg_bl_mat = chest_mat * Mat4::::from(self.leg_bl); + let leg_br_mat = chest_mat * Mat4::::from(self.leg_br); + + *(<&mut [_; Self::BONE_COUNT]>::try_from(&mut buf[0..Self::BONE_COUNT]).unwrap()) = [ + make_bone(head_mat), + make_bone(chest_mat), + make_bone(mandible_l_mat), + make_bone(mandible_r_mat), + make_bone(wing_fl_mat), + make_bone(wing_fr_mat), + make_bone(wing_bl_mat), + make_bone(wing_br_mat), + make_bone(leg_fl_mat), + make_bone(leg_fr_mat), + make_bone(leg_fcl_mat), + make_bone(leg_fcr_mat), + make_bone(leg_bcl_mat), + make_bone(leg_bcr_mat), + make_bone(leg_bl_mat), + make_bone(leg_br_mat), + ]; + + // TODO: mount points + //use comp::arthropod::Species::*; + let (mount_bone_mat, mount_bone_ori) = (chest_mat, self.chest.orientation); + // Offset from the mounted bone's origin. + // Note: This could be its own bone if we need to animate it independently. + let mount_position = (mount_bone_mat * Vec4::from_point(mount_point(&body))) + .homogenized() + .xyz(); + // NOTE: We apply the ori from base_mat externally so we don't need to worry + // about it here for now. + let mount_orientation = mount_bone_ori; + + Offsets { + lantern: None, + mount_bone: Transform { + position: mount_position, + orientation: mount_orientation, + scale: Vec3::one(), + }, + } + } +} + +pub struct SkeletonAttr { + head: (f32, f32), + chest: (f32, f32), + mandible: (f32, f32, f32), + wing_f: (f32, f32, f32), + wing_b: (f32, f32, f32), + leg_f: (f32, f32, f32), + leg_fc: (f32, f32, f32), + leg_bc: (f32, f32, f32), + leg_b: (f32, f32, f32), + scaler: f32, + leg_ori: (f32, f32, f32, f32), + snapper: bool, +} + +impl<'a> std::convert::TryFrom<&'a comp::Body> for SkeletonAttr { + type Error = (); + + fn try_from(body: &'a comp::Body) -> Result { + match body { + comp::Body::Arthropod(body) => Ok(SkeletonAttr::from(body)), + _ => Err(()), + } + } +} + +impl Default for SkeletonAttr { + fn default() -> Self { + Self { + head: (0.0, 0.0), + chest: (0.0, 0.0), + mandible: (0.0, 0.0, 0.0), + wing_f: (0.0, 0.0, 0.0), + wing_b: (0.0, 0.0, 0.0), + leg_f: (0.0, 0.0, 0.0), + leg_fc: (0.0, 0.0, 0.0), + leg_bc: (0.0, 0.0, 0.0), + leg_b: (0.0, 0.0, 0.0), + scaler: 0.0, + leg_ori: (0.0, 0.0, 0.0, 0.0), + snapper: false, + } + } +} + +impl<'a> From<&'a Body> for SkeletonAttr { + fn from(body: &'a Body) -> Self { + use comp::arthropod::Species::*; + Self { + head: match (body.species, body.body_type) { + (Tarantula, _) => (6.0, 0.5), + (Blackwidow, _) => (5.5, -3.0), + (Antlion, _) => (4.5, 0.0), + (Hornbeetle, _) => (5.0, 3.0), + (Leafbeetle, _) => (4.0, 0.0), + (Stagbeetle, _) => (5.0, -1.0), + (Weevil, _) => (4.0, 0.0), + (Cavespider, _) => (6.0, 0.5), + (Moltencrawler, _) => (4.0, -1.0), + (Mosscrawler, _) => (4.0, -1.5), + (Sandcrawler, _) => (4.0, -1.0), + }, + chest: match (body.species, body.body_type) { + (Tarantula, _) => (-5.0, 6.0), + (Blackwidow, _) => (-5.0, 10.0), + (Antlion, _) => (-5.0, 8.5), + (Hornbeetle, _) => (-5.0, 7.5), + (Leafbeetle, _) => (-5.0, 6.0), + (Stagbeetle, _) => (-5.0, 6.5), + (Weevil, _) => (-5.0, 6.0), + (Cavespider, _) => (-5.0, 7.0), + (Moltencrawler, _) => (-7.0, 6.0), + (Mosscrawler, _) => (-7.0, 6.5), + (Sandcrawler, _) => (-7.0, 6.0), + }, + mandible: match (body.species, body.body_type) { + (Tarantula, _) => (1.5, 7.0, -0.5), + (Blackwidow, _) => (2.5, 8.0, 0.0), + (Antlion, _) => (8.5, 9.0, -3.5), + (Hornbeetle, _) => (1.5, 7.0, -0.5), + (Leafbeetle, _) => (1.5, 7.0, -0.5), + (Stagbeetle, _) => (1.5, 10.0, 1.0), + (Weevil, _) => (1.5, 7.0, -0.5), + (Cavespider, _) => (2.5, 8.0, -0.5), + (Moltencrawler, _) => (2.5, 8.0, 0.0), + (Mosscrawler, _) => (2.5, 8.0, 0.0), + (Sandcrawler, _) => (2.5, 8.0, 0.0), + }, + wing_f: match (body.species, body.body_type) { + (Tarantula, _) => (3.0, 0.0, -4.0), + (Blackwidow, _) => (3.0, 0.0, -4.0), + (Antlion, _) => (3.0, 0.0, -4.0), + (Hornbeetle, _) => (5.5, 5.0, 3.0), + (Leafbeetle, _) => (0.5, 5.0, 3.0), + (Stagbeetle, _) => (0.5, 6.0, 4.5), + (Weevil, _) => (0.5, 5.0, 3.0), + (Cavespider, _) => (3.0, 0.0, -4.0), + (Moltencrawler, _) => (3.0, 0.0, -4.0), + (Mosscrawler, _) => (3.0, 0.0, -4.0), + (Sandcrawler, _) => (3.0, 0.0, -4.0), + }, + wing_b: match (body.species, body.body_type) { + (Tarantula, _) => (3.0, 0.0, -4.0), + (Blackwidow, _) => (3.0, 0.0, -4.0), + (Antlion, _) => (3.0, 0.0, -4.0), + (Hornbeetle, _) => (4.0, 6.0, 2.0), + (Leafbeetle, _) => (0.5, 4.0, 2.0), + (Stagbeetle, _) => (0.5, 6.0, 3.0), + (Weevil, _) => (0.5, 4.0, 1.5), + (Cavespider, _) => (3.0, 0.0, -4.0), + (Moltencrawler, _) => (3.0, 0.0, -4.0), + (Mosscrawler, _) => (3.0, 0.0, -4.0), + (Sandcrawler, _) => (3.0, 0.0, -4.0), + }, + leg_f: match (body.species, body.body_type) { + (Tarantula, _) => (4.0, 11.0, -1.5), + (Blackwidow, _) => (4.0, 13.5, -6.0), + (Antlion, _) => (4.0, 11.5, -4.0), + (Hornbeetle, _) => (5.0, 6.0, -3.0), + (Leafbeetle, _) => (5.0, 6.0, -1.0), + (Stagbeetle, _) => (4.5, 6.0, -2.0), + (Weevil, _) => (5.0, 9.0, -2.0), + (Cavespider, _) => (4.0, 13.0, -3.0), + (Moltencrawler, _) => (2.5, 14.0, -3.0), + (Mosscrawler, _) => (1.5, 14.0, -3.5), + (Sandcrawler, _) => (1.5, 14.0, -3.0), + }, + leg_fc: match (body.species, body.body_type) { + (Tarantula, _) => (1.5, 13.5, -1.5), + (Blackwidow, _) => (2.5, 13.0, -5.5), + (Antlion, _) => (1.5, 6.0, -4.0), + (Hornbeetle, _) => (1.5, 7.5, -3.0), + (Leafbeetle, _) => (1.5, 6.5, -1.5), + (Stagbeetle, _) => (1.5, 7.5, -2.0), + (Weevil, _) => (1.5, 8.5, -2.0), + (Cavespider, _) => (2.5, 12.5, -2.5), + (Moltencrawler, _) => (3.5, 11.0, -3.0), + (Mosscrawler, _) => (2.5, 11.0, -3.5), + (Sandcrawler, _) => (2.5, 11.0, -3.0), + }, + leg_bc: match (body.species, body.body_type) { + (Tarantula, _) => (1.5, 10.5, -1.5), + (Blackwidow, _) => (2.5, 10.0, -5.5), + (Antlion, _) => (6.0, 7.5, -4.0), + (Hornbeetle, _) => (5.0, 6.0, -3.0), + (Leafbeetle, _) => (4.5, 5.0, -2.5), + (Stagbeetle, _) => (5.0, 6.0, -2.0), + (Weevil, _) => (6.0, 5.0, -2.5), + (Cavespider, _) => (2.5, 9.5, -2.5), + (Moltencrawler, _) => (2.5, 8.0, -3.0), + (Mosscrawler, _) => (1.5, 8.0, -3.5), + (Sandcrawler, _) => (1.5, 8.0, -3.0), + }, + leg_b: match (body.species, body.body_type) { + (Tarantula, _) => (1.5, 7.5, -1.5), + (Blackwidow, _) => (2.5, 7.0, -5.5), + (Antlion, _) => (1.5, 7.5, -1.5), + (Hornbeetle, _) => (1.5, 7.5, -1.5), + (Leafbeetle, _) => (1.5, 7.5, -1.5), + (Stagbeetle, _) => (1.5, 7.5, -1.5), + (Weevil, _) => (1.5, 7.5, -1.5), + (Cavespider, _) => (2.5, 6.5, -2.5), + (Moltencrawler, _) => (2.5, 7.0, -5.5), + (Mosscrawler, _) => (2.5, 7.0, -5.5), + (Sandcrawler, _) => (2.5, 7.0, -5.5), + }, + scaler: match (body.species, body.body_type) { + (Tarantula, _) => (1.0), + (Blackwidow, _) => (1.0), + (Antlion, _) => (1.0), + (Hornbeetle, _) => (0.8), + (Leafbeetle, _) => (0.8), + (Stagbeetle, _) => (0.8), + (Weevil, _) => (0.8), + (Cavespider, _) => (1.0), + (Moltencrawler, _) => (0.8), + (Mosscrawler, _) => (0.8), + (Sandcrawler, _) => (0.8), + }, + // Z ori (front, front center, back center, center) + leg_ori: match (body.species, body.body_type) { + (Antlion, _) => (0.7, -0.3, -0.4, 0.4), + (_, _) => (0.1, -0.3, 0.0, 0.4), + }, + // Whether or not it used its mandibles for attacks + snapper: match (body.species, body.body_type) { + (Stagbeetle, _) => true, + (Antlion, _) => true, + (_, _) => false, + }, + } + } +} + +fn mount_point(_body: &Body) -> Vec3 { + // TODO: mount points + //use comp::arthropod::{BodyType::*, Species::*}; + (0.0, -6.0, 6.0).into() +} diff --git a/voxygen/anim/src/arthropod/run.rs b/voxygen/anim/src/arthropod/run.rs new file mode 100644 index 0000000000..6ca2b347b2 --- /dev/null +++ b/voxygen/anim/src/arthropod/run.rs @@ -0,0 +1,104 @@ +use super::{ + super::{vek::*, Animation}, + ArthropodSkeleton, SkeletonAttr, +}; +use std::f32::consts::PI; + +pub struct RunAnimation; + +impl Animation for RunAnimation { + type Dependency<'a> = (Vec3, Vec3, Vec3, f32, Vec3, f32); + type Skeleton = ArthropodSkeleton; + + #[cfg(feature = "use-dyn-lib")] + const UPDATE_FN: &'static [u8] = b"arthropod_run\0"; + + #[cfg_attr(feature = "be-dyn-lib", export_name = "arthropod_run")] + fn update_skeleton_inner<'a>( + skeleton: &Self::Skeleton, + (velocity, _orientation, _last_ori, _global_time, avg_vel, acc_vel): Self::Dependency<'a>, + anim_time: f32, + rate: &mut f32, + s_a: &SkeletonAttr, + ) -> Self::Skeleton { + let mut next = (*skeleton).clone(); + let speed = (Vec2::::from(velocity).magnitude()).min(22.0); + *rate = 1.0; + + let speednorm = speed / 13.0; + + let mixed_vel = (acc_vel + anim_time * 6.0) * 0.8; //sets run frequency using speed, with anim_time setting a floor + + //create a mix between a sine and a square wave + //(controllable with ratio variable) + let ratio = 0.1; + let wave1 = (mixed_vel).sin(); + let wave2 = (mixed_vel - PI / 2.0).sin(); + let wave3 = (mixed_vel + PI / 2.0).sin(); + let wave4 = (mixed_vel + PI).sin(); + let foot1 = wave1.abs().powf(ratio) * wave1.signum(); + let foot2 = wave2.abs().powf(ratio) * wave2.signum(); + let foot3 = wave3.abs().powf(ratio) * wave3.signum(); + let foot4 = wave4.abs().powf(ratio) * wave4.signum(); + + let x_tilt = avg_vel.z.atan2(avg_vel.xy().magnitude()) * speednorm; + + next.chest.scale = Vec3::one() / s_a.scaler; + next.wing_bl.scale = Vec3::one() * 0.98; + next.wing_br.scale = Vec3::one() * 0.98; + + next.head.position = Vec3::new(0.0, s_a.head.0, s_a.head.1); + next.head.orientation = Quaternion::rotation_x((mixed_vel).sin() * 0.1) + * Quaternion::rotation_y((mixed_vel).sin().min(0.0) * 0.08) + * Quaternion::rotation_z((mixed_vel + PI * 1.5).sin() * 0.08); + + next.chest.position = Vec3::new(0.0, s_a.chest.0, s_a.chest.1 + x_tilt); + next.chest.orientation = Quaternion::rotation_x((mixed_vel).sin().max(0.0) * 0.06 + x_tilt) + * Quaternion::rotation_z((mixed_vel + PI / 2.0).sin() * 0.06); + + next.mandible_l.position = Vec3::new(-s_a.mandible.0, s_a.mandible.1, s_a.mandible.2); + next.mandible_r.position = Vec3::new(s_a.mandible.0, s_a.mandible.1, s_a.mandible.2); + + next.wing_fl.position = Vec3::new(-s_a.wing_f.0, s_a.wing_f.1, s_a.wing_f.2); + next.wing_fr.position = Vec3::new(s_a.wing_f.0, s_a.wing_f.1, s_a.wing_f.2); + + next.wing_bl.position = Vec3::new(-s_a.wing_b.0, s_a.wing_b.1, s_a.wing_b.2); + next.wing_br.position = Vec3::new(s_a.wing_b.0, s_a.wing_b.1, s_a.wing_b.2); + + next.leg_fl.position = Vec3::new(-s_a.leg_f.0, s_a.leg_f.1, s_a.leg_f.2); + next.leg_fr.position = Vec3::new(s_a.leg_f.0, s_a.leg_f.1, s_a.leg_f.2); + next.leg_fl.orientation = Quaternion::rotation_x(foot4.max(0.0) * 0.7) + * Quaternion::rotation_z(s_a.leg_ori.0 + foot2 * 0.4); + next.leg_fr.orientation = Quaternion::rotation_x(foot1.max(0.0) * 0.7) + * Quaternion::rotation_z(-s_a.leg_ori.0 - foot3 * 0.4); + + next.leg_fcl.position = Vec3::new(-s_a.leg_fc.0, s_a.leg_fc.1, s_a.leg_fc.2); + next.leg_fcr.position = Vec3::new(s_a.leg_fc.0, s_a.leg_fc.1, s_a.leg_fc.2); + next.leg_fcl.orientation = Quaternion::rotation_x(foot4 * 0.2) + * Quaternion::rotation_y(foot1.max(0.0) * 0.7) + * Quaternion::rotation_z(s_a.leg_ori.1 + foot3 * 0.2); + next.leg_fcr.orientation = Quaternion::rotation_x(foot1 * 0.2) + * Quaternion::rotation_y(foot1.min(0.0) * 0.7) + * Quaternion::rotation_z(-s_a.leg_ori.1 - foot2 * 0.2); + + next.leg_bcl.position = Vec3::new(-s_a.leg_bc.0, s_a.leg_bc.1, s_a.leg_bc.2); + next.leg_bcr.position = Vec3::new(s_a.leg_bc.0, s_a.leg_bc.1, s_a.leg_bc.2); + next.leg_bcl.orientation = Quaternion::rotation_x(foot4 * 0.2) + * Quaternion::rotation_y(foot4.max(0.0) * 0.7) + * Quaternion::rotation_z(s_a.leg_ori.2 + foot2 * 0.3); + next.leg_bcr.orientation = Quaternion::rotation_x(foot1 * 0.2) + * Quaternion::rotation_y(foot4.min(0.0) * 0.7) + * Quaternion::rotation_z(-s_a.leg_ori.2 - foot3 * 0.3); + + next.leg_bl.position = Vec3::new(-s_a.leg_b.0, s_a.leg_b.1, s_a.leg_b.2); + next.leg_br.position = Vec3::new(s_a.leg_b.0, s_a.leg_b.1, s_a.leg_b.2); + next.leg_bl.orientation = Quaternion::rotation_x(foot4 * 0.2) + * Quaternion::rotation_y(foot1.max(0.0) * 0.7) + * Quaternion::rotation_z(s_a.leg_ori.3 + foot3 * 0.2); + next.leg_br.orientation = Quaternion::rotation_x(foot1 * 0.2) + * Quaternion::rotation_y(foot1.min(0.0) * 0.7) + * Quaternion::rotation_z(-s_a.leg_ori.3 - foot2 * 0.2); + + next + } +} diff --git a/voxygen/anim/src/arthropod/shoot.rs b/voxygen/anim/src/arthropod/shoot.rs new file mode 100644 index 0000000000..ecf4fc95e6 --- /dev/null +++ b/voxygen/anim/src/arthropod/shoot.rs @@ -0,0 +1,81 @@ +use super::{ + super::{vek::*, Animation}, + ArthropodSkeleton, SkeletonAttr, +}; +use common::states::utils::StageSection; + +pub struct ShootAnimation; + +impl Animation for ShootAnimation { + type Dependency<'a> = (f32, f32, Option, f32); + type Skeleton = ArthropodSkeleton; + + #[cfg(feature = "use-dyn-lib")] + const UPDATE_FN: &'static [u8] = b"arthropod_shoot\0"; + + #[cfg_attr(feature = "be-dyn-lib", export_name = "arthropod_shoot")] + fn update_skeleton_inner<'a>( + skeleton: &Self::Skeleton, + (_velocity, _global_time, stage_section, _timer): Self::Dependency<'a>, + anim_time: f32, + _rate: &mut f32, + s_a: &SkeletonAttr, + ) -> Self::Skeleton { + let mut next = (*skeleton).clone(); + + let (movement1, movement2, twitch) = match stage_section { + Some(StageSection::Buildup) => (anim_time.powf(0.25), 0.0, (anim_time * 30.0).sin()), + Some(StageSection::Recover) => (1.0, anim_time, 1.0), + _ => (0.0, 0.0, 0.0), + }; + let pullback = 1.0 - movement2; + let movement1abs = movement1 * pullback; + + next.chest.scale = Vec3::one() / s_a.scaler; + next.chest.orientation = Quaternion::rotation_x(0.0) * Quaternion::rotation_z(0.0); + + next.head.position = Vec3::new(0.0, s_a.head.0, s_a.head.1); + next.head.orientation = Quaternion::rotation_x(movement1abs * 0.35 + twitch * -0.02) + * Quaternion::rotation_y(0.0); + + next.chest.position = Vec3::new(0.0, s_a.chest.0, s_a.chest.1); + + next.mandible_l.position = Vec3::new(-s_a.mandible.0, s_a.mandible.1, s_a.mandible.2); + next.mandible_r.position = Vec3::new(s_a.mandible.0, s_a.mandible.1, s_a.mandible.2); + next.mandible_l.orientation = Quaternion::rotation_x(movement1abs * 0.5 + twitch * 0.2) + * Quaternion::rotation_y(movement1abs * 0.5) + * Quaternion::rotation_z(movement1abs * 0.5); + next.mandible_r.orientation = Quaternion::rotation_x(movement1abs * 0.5 + twitch * 0.2) + * Quaternion::rotation_y(movement1abs * -0.5) + * Quaternion::rotation_z(movement1abs * -0.5); + + next.wing_fl.position = Vec3::new(-s_a.wing_f.0, s_a.wing_f.1, s_a.wing_f.2); + next.wing_fr.position = Vec3::new(s_a.wing_f.0, s_a.wing_f.1, s_a.wing_f.2); + + next.wing_bl.position = Vec3::new(-s_a.wing_b.0, s_a.wing_b.1, s_a.wing_b.2); + next.wing_br.position = Vec3::new(s_a.wing_b.0, s_a.wing_b.1, s_a.wing_b.2); + + next.leg_fl.position = Vec3::new(-s_a.leg_f.0, s_a.leg_f.1, s_a.leg_f.2); + next.leg_fr.position = Vec3::new(s_a.leg_f.0, s_a.leg_f.1, s_a.leg_f.2); + next.leg_fl.orientation = Quaternion::rotation_z(s_a.leg_ori.0 + movement1abs * 0.4) + * Quaternion::rotation_x(movement1abs * 1.0); + next.leg_fr.orientation = Quaternion::rotation_z(-s_a.leg_ori.0 + movement1abs * -0.4) + * Quaternion::rotation_x(movement1abs * 1.0); + + next.leg_fcl.orientation = Quaternion::rotation_z(s_a.leg_ori.1 + movement1abs * 0.2) + * Quaternion::rotation_y(movement1abs * 0.5); + next.leg_fcr.orientation = Quaternion::rotation_z(-s_a.leg_ori.1 + movement1abs * -0.2) + * Quaternion::rotation_y(movement1abs * -0.5); + + next.leg_fcl.position = Vec3::new(-s_a.leg_fc.0, s_a.leg_fc.1, s_a.leg_fc.2); + next.leg_fcr.position = Vec3::new(s_a.leg_fc.0, s_a.leg_fc.1, s_a.leg_fc.2); + + next.leg_bcl.position = Vec3::new(-s_a.leg_bc.0, s_a.leg_bc.1, s_a.leg_bc.2); + next.leg_bcr.position = Vec3::new(s_a.leg_bc.0, s_a.leg_bc.1, s_a.leg_bc.2); + + next.leg_bl.position = Vec3::new(-s_a.leg_b.0, s_a.leg_b.1, s_a.leg_b.2); + next.leg_br.position = Vec3::new(s_a.leg_b.0, s_a.leg_b.1, s_a.leg_b.2); + + next + } +} diff --git a/voxygen/anim/src/arthropod/stunned.rs b/voxygen/anim/src/arthropod/stunned.rs new file mode 100644 index 0000000000..8900e102d3 --- /dev/null +++ b/voxygen/anim/src/arthropod/stunned.rs @@ -0,0 +1,86 @@ +use super::{ + super::{vek::*, Animation}, + ArthropodSkeleton, SkeletonAttr, +}; +use common::states::utils::StageSection; + +pub struct StunnedAnimation; + +impl Animation for StunnedAnimation { + type Dependency<'a> = (f32, f32, Option, f32); + type Skeleton = ArthropodSkeleton; + + #[cfg(feature = "use-dyn-lib")] + const UPDATE_FN: &'static [u8] = b"arthropod_stunned\0"; + + #[cfg_attr(feature = "be-dyn-lib", export_name = "arthropod_stunned")] + fn update_skeleton_inner<'a>( + skeleton: &Self::Skeleton, + (_velocity, global_time, stage_section, timer): Self::Dependency<'a>, + anim_time: f32, + _rate: &mut f32, + s_a: &SkeletonAttr, + ) -> Self::Skeleton { + let mut next = (*skeleton).clone(); + + let (_movement1base, movement2, twitch) = match stage_section { + Some(StageSection::Buildup) => (anim_time.powf(0.1), 0.0, anim_time), + Some(StageSection::Recover) => (1.0, anim_time.powf(4.0), 1.0), + _ => (0.0, 0.0, 0.0), + }; + + let pullback = 1.0 - movement2; + + let subtract = global_time - timer; + let check = subtract - subtract.trunc(); + let mirror = (check - 0.5).signum(); + let twitch1 = mirror * (twitch * 20.0).cos() * pullback; + let twitch2 = mirror * (twitch * 20.0).sin() * pullback; + + next.chest.scale = Vec3::one() / s_a.scaler; + + next.head.position = Vec3::new(0.0, s_a.head.0, s_a.head.1); + next.head.orientation = Quaternion::rotation_z(twitch2 * 0.6); + + next.chest.position = Vec3::new(0.0, s_a.chest.0, s_a.chest.1); + + next.mandible_l.position = Vec3::new(-s_a.mandible.0, s_a.mandible.1, s_a.mandible.2); + next.mandible_r.position = Vec3::new(s_a.mandible.0, s_a.mandible.1, s_a.mandible.2); + + next.wing_fl.position = Vec3::new(-s_a.wing_f.0, s_a.wing_f.1, s_a.wing_f.2); + next.wing_fr.position = Vec3::new(s_a.wing_f.0, s_a.wing_f.1, s_a.wing_f.2); + + next.wing_bl.position = Vec3::new(-s_a.wing_b.0, s_a.wing_b.1, s_a.wing_b.2); + next.wing_br.position = Vec3::new(s_a.wing_b.0, s_a.wing_b.1, s_a.wing_b.2); + + next.leg_fl.position = Vec3::new(-s_a.leg_f.0, s_a.leg_f.1, s_a.leg_f.2); + next.leg_fr.position = Vec3::new(s_a.leg_f.0, s_a.leg_f.1, s_a.leg_f.2); + next.leg_fl.orientation = + Quaternion::rotation_z(s_a.leg_ori.0) * Quaternion::rotation_x(twitch1 * 0.8 + 0.4); + next.leg_fr.orientation = + Quaternion::rotation_z(-s_a.leg_ori.0) * Quaternion::rotation_x(-twitch1 * 0.8 - 0.4); + + next.leg_fcl.position = Vec3::new(-s_a.leg_fc.0, s_a.leg_fc.1, s_a.leg_fc.2); + next.leg_fcr.position = Vec3::new(s_a.leg_fc.0, s_a.leg_fc.1, s_a.leg_fc.2); + next.leg_fcl.orientation = + Quaternion::rotation_z(s_a.leg_ori.1) * Quaternion::rotation_y(twitch2 * 0.8 + 0.4); + next.leg_fcr.orientation = + Quaternion::rotation_z(-s_a.leg_ori.1) * Quaternion::rotation_y(-twitch2 * 0.8 - 0.4); + + next.leg_bcl.position = Vec3::new(-s_a.leg_bc.0, s_a.leg_bc.1, s_a.leg_bc.2); + next.leg_bcr.position = Vec3::new(s_a.leg_bc.0, s_a.leg_bc.1, s_a.leg_bc.2); + next.leg_bcl.orientation = + Quaternion::rotation_z(s_a.leg_ori.2) * Quaternion::rotation_y(twitch1 * 0.8 + 0.4); + next.leg_bcr.orientation = + Quaternion::rotation_z(-s_a.leg_ori.2) * Quaternion::rotation_y(-twitch1 * 0.8 - 0.4); + + next.leg_bl.position = Vec3::new(-s_a.leg_b.0, s_a.leg_b.1, s_a.leg_b.2); + next.leg_br.position = Vec3::new(s_a.leg_b.0, s_a.leg_b.1, s_a.leg_b.2); + next.leg_bl.orientation = + Quaternion::rotation_z(s_a.leg_ori.3) * Quaternion::rotation_y(twitch2 * 0.8 + 0.4); + next.leg_br.orientation = + Quaternion::rotation_z(-s_a.leg_ori.3) * Quaternion::rotation_y(-twitch2 * 0.8 - 0.4); + + next + } +} diff --git a/voxygen/anim/src/arthropod/summon.rs b/voxygen/anim/src/arthropod/summon.rs new file mode 100644 index 0000000000..789baf53ec --- /dev/null +++ b/voxygen/anim/src/arthropod/summon.rs @@ -0,0 +1,107 @@ +use std::f32::consts::PI; + +use super::{ + super::{vek::*, Animation}, + ArthropodSkeleton, SkeletonAttr, +}; +use common::states::utils::StageSection; + +pub struct SummonAnimation; + +impl Animation for SummonAnimation { + type Dependency<'a> = (f32, f32, Option, f32); + type Skeleton = ArthropodSkeleton; + + #[cfg(feature = "use-dyn-lib")] + const UPDATE_FN: &'static [u8] = b"arthropod_summon\0"; + + #[cfg_attr(feature = "be-dyn-lib", export_name = "arthropod_summon")] + fn update_skeleton_inner<'a>( + skeleton: &Self::Skeleton, + (_velocity, global_time, stage_section, timer): Self::Dependency<'a>, + anim_time: f32, + _rate: &mut f32, + s_a: &SkeletonAttr, + ) -> Self::Skeleton { + let mut next = (*skeleton).clone(); + + let (movement1, movement2, movement3) = match stage_section { + Some(StageSection::Buildup) => (anim_time.powi(2), 0.0, 0.0), + Some(StageSection::Action) => (1.0, anim_time.powi(4), 0.0), + Some(StageSection::Recover) => (1.0, 1.0, anim_time), + _ => (0.0, 0.0, 0.0), + }; + let pullback = 1.0 - movement3; + let subtract = global_time - timer; + let check = subtract - subtract.trunc(); + let mirror = (check - 0.5).signum(); + let movement1abs = movement1 * pullback; + let movement2abs = movement2 * pullback; + let movement3abs = movement3 * pullback; + + next.chest.scale = Vec3::one() / s_a.scaler; + next.chest.orientation = Quaternion::rotation_x(movement2abs * 0.3) + * Quaternion::rotation_z((movement1abs * 4.0 * PI).sin() * 0.02); + + next.head.position = Vec3::new( + 0.0, + s_a.head.0 + movement1abs * 3.0, + s_a.head.1 + movement1abs * -3.0, + ); + next.head.orientation = + Quaternion::rotation_x(movement1abs * 1.5 + movement2abs * -1.5 + movement3abs * 0.8) + * Quaternion::rotation_y( + mirror * movement1abs * -0.2 + mirror * movement2abs * 0.2, + ) + * Quaternion::rotation_z((movement1abs * 4.0 * PI).sin() * 0.02); + + next.chest.position = Vec3::new( + 0.0, + s_a.chest.0, + s_a.chest.1 + movement1abs * 7.0 + movement2abs * -2.0, + ); + next.chest.orientation = Quaternion::rotation_x(movement1abs * -1.0 + movement2abs * 0.2); + next.mandible_l.position = Vec3::new(-s_a.mandible.0, s_a.mandible.1, s_a.mandible.2); + next.mandible_r.position = Vec3::new(s_a.mandible.0, s_a.mandible.1, s_a.mandible.2); + next.mandible_l.orientation = + Quaternion::rotation_x(movement1abs * 0.5 + movement2abs * -1.5 + movement3abs * 0.8) + * Quaternion::rotation_z( + movement1abs * 0.5 + movement2abs * -0.6 + movement3abs * 0.8, + ); + next.mandible_r.orientation = + Quaternion::rotation_x(movement1abs * 0.5 + movement2abs * -1.5 + movement3abs * 0.8) + * Quaternion::rotation_z( + movement1abs * -0.5 + movement2abs * 0.6 + movement3abs * -0.8, + ); + + next.leg_fl.position = Vec3::new(-s_a.leg_f.0, s_a.leg_f.1, s_a.leg_f.2); + next.leg_fr.position = Vec3::new(s_a.leg_f.0, s_a.leg_f.1, s_a.leg_f.2); + next.leg_fl.orientation = Quaternion::rotation_x(movement1abs * 1.0 + movement2abs * 0.2) + * Quaternion::rotation_z(movement1abs * -0.2 + movement2abs * -0.2); + next.leg_fr.orientation = Quaternion::rotation_x(movement1abs * 1.0 + movement2abs * 0.2) + * Quaternion::rotation_x(movement1abs * 0.2 + movement2abs * 0.2); + + next.leg_fcl.position = Vec3::new(-s_a.leg_fc.0, s_a.leg_fc.1, s_a.leg_fc.2); + next.leg_fcr.position = Vec3::new(s_a.leg_fc.0, s_a.leg_fc.1, s_a.leg_fc.2); + + next.leg_fcl.orientation = Quaternion::rotation_x(movement1abs * 1.3 + movement2abs * 0.3) + * Quaternion::rotation_z(movement1abs * -0.5 + movement2abs * -0.2); + next.leg_fcr.orientation = Quaternion::rotation_x(movement1abs * 1.3 + movement2abs * 0.3) + * Quaternion::rotation_z(movement1abs * 0.5 + movement2abs * -0.2); + + next.leg_bcl.position = Vec3::new(-s_a.leg_bc.0, s_a.leg_bc.1, s_a.leg_bc.2); + next.leg_bcr.position = Vec3::new(s_a.leg_bc.0, s_a.leg_bc.1, s_a.leg_bc.2); + + next.leg_bcl.orientation = Quaternion::rotation_x(movement1abs * 0.5 + movement2abs * 0.2); + next.leg_bcr.orientation = Quaternion::rotation_x(movement1abs * 0.5 + movement2abs * 0.2); + + next.leg_bl.position = Vec3::new(-s_a.leg_b.0, s_a.leg_b.1, s_a.leg_b.2); + next.leg_br.position = Vec3::new(s_a.leg_b.0, s_a.leg_b.1, s_a.leg_b.2); + + next.leg_bl.orientation = Quaternion::rotation_x(movement1abs * -0.5 + movement2abs * -0.2) + * Quaternion::rotation_z(movement1abs * 0.8); + next.leg_br.orientation = Quaternion::rotation_x(movement1abs * -0.5 + movement2abs * -0.2) + * Quaternion::rotation_z(movement1abs * -0.8); + next + } +} diff --git a/voxygen/anim/src/lib.rs b/voxygen/anim/src/lib.rs index dfe3ac86d2..f60ca96751 100644 --- a/voxygen/anim/src/lib.rs +++ b/voxygen/anim/src/lib.rs @@ -47,6 +47,7 @@ macro_rules! skeleton_impls { } } +pub mod arthropod; pub mod biped_large; pub mod biped_small; pub mod bird_large; diff --git a/voxygen/egui/src/lib.rs b/voxygen/egui/src/lib.rs index 8c80955a42..d1233d462c 100644 --- a/voxygen/egui/src/lib.rs +++ b/voxygen/egui/src/lib.rs @@ -716,6 +716,7 @@ fn body_species(body: &Body) -> String { Body::Golem(body) => format!("{:?}", body.species), Body::Theropod(body) => format!("{:?}", body.species), Body::QuadrupedLow(body) => format!("{:?}", body.species), + Body::Arthropod(body) => format!("{:?}", body.species), Body::Ship(body) => format!("{:?}", body), } } diff --git a/voxygen/src/hud/chat.rs b/voxygen/src/hud/chat.rs index c4d8f176df..be9e25ef1c 100644 --- a/voxygen/src/hud/chat.rs +++ b/voxygen/src/hud/chat.rs @@ -768,6 +768,7 @@ fn insert_killing_buff(buff: BuffKind, localized_strings: &Localization, templat BuffKind::Cursed => localized_strings.get("hud.outcome.curse"), BuffKind::Crippled => localized_strings.get("hud.outcome.crippled"), BuffKind::Frozen => localized_strings.get("hud.outcome.frozen"), + BuffKind::Poisoned => localized_strings.get("hud.outcome.poisoned"), BuffKind::Regeneration | BuffKind::Saturation | BuffKind::Potion diff --git a/voxygen/src/hud/img_ids.rs b/voxygen/src/hud/img_ids.rs index 0d795e563f..e214322c07 100644 --- a/voxygen/src/hud/img_ids.rs +++ b/voxygen/src/hud/img_ids.rs @@ -618,6 +618,7 @@ image_ids! { debuff_frozen_0: "voxygen.element.de_buffs.debuff_frozen_0", debuff_wet_0: "voxygen.element.de_buffs.debuff_wet_0", debuff_ensnared_0: "voxygen.element.de_buffs.debuff_ensnared_0", + debuff_poisoned_0: "voxygen.element.de_buffs.debuff_poisoned_0", // Animation Frames // Buff Frame diff --git a/voxygen/src/hud/mod.rs b/voxygen/src/hud/mod.rs index 175bcd88e0..6322d7c486 100644 --- a/voxygen/src/hud/mod.rs +++ b/voxygen/src/hud/mod.rs @@ -4257,6 +4257,7 @@ pub fn get_buff_image(buff: BuffKind, imgs: &Imgs) -> conrod_core::image::Id { BuffKind::Frozen { .. } => imgs.debuff_frozen_0, BuffKind::Wet { .. } => imgs.debuff_wet_0, BuffKind::Ensnared { .. } => imgs.debuff_ensnared_0, + BuffKind::Poisoned { .. } => imgs.debuff_poisoned_0, } } @@ -4280,6 +4281,7 @@ pub fn get_buff_title(buff: BuffKind, localized_strings: &Localization) -> &str BuffKind::Frozen { .. } => localized_strings.get("buff.title.frozen"), BuffKind::Wet { .. } => localized_strings.get("buff.title.wet"), BuffKind::Ensnared { .. } => localized_strings.get("buff.title.ensnared"), + BuffKind::Poisoned { .. } => localized_strings.get("buff.title.poisoned"), } } @@ -4315,6 +4317,7 @@ pub fn get_buff_desc(buff: BuffKind, data: BuffData, localized_strings: &Localiz BuffKind::Frozen { .. } => Cow::Borrowed(localized_strings.get("buff.desc.frozen")), BuffKind::Wet { .. } => Cow::Borrowed(localized_strings.get("buff.desc.wet")), BuffKind::Ensnared { .. } => Cow::Borrowed(localized_strings.get("buff.desc.ensnared")), + BuffKind::Poisoned { .. } => Cow::Borrowed(localized_strings.get("buff.desc.poisoned")), } } diff --git a/voxygen/src/hud/util.rs b/voxygen/src/hud/util.rs index aa38d674c3..a2d2bef185 100644 --- a/voxygen/src/hud/util.rs +++ b/voxygen/src/hud/util.rs @@ -172,7 +172,8 @@ pub fn consumable_desc(effects: &[Effect], i18n: &Localization) -> Vec { | BuffKind::Frenzied | BuffKind::Frozen | BuffKind::Wet - | BuffKind::Ensnared => "".to_owned(), + | BuffKind::Ensnared + | BuffKind::Poisoned => "".to_owned(), }; write!(&mut description, "{}", buff_desc).unwrap(); @@ -197,7 +198,8 @@ pub fn consumable_desc(effects: &[Effect], i18n: &Localization) -> Vec { | BuffKind::Frenzied | BuffKind::Frozen | BuffKind::Wet - | BuffKind::Ensnared => "".to_owned(), + | BuffKind::Ensnared + | BuffKind::Poisoned => "".to_owned(), } } else if let BuffKind::Saturation | BuffKind::Regeneration = buff.kind { i18n.get("buff.text.every_second").to_string() diff --git a/voxygen/src/scene/figure/load.rs b/voxygen/src/scene/figure/load.rs index 084eb5b301..684a279cd7 100644 --- a/voxygen/src/scene/figure/load.rs +++ b/voxygen/src/scene/figure/load.rs @@ -2,6 +2,7 @@ use super::cache::{FigureKey, ToolKey}; use common::{ assets::{self, AssetExt, AssetHandle, DotVoxAsset, ReloadWatcher, Ron}, comp::{ + arthropod::{self, BodyType as ABodyType, Species as ASpecies}, biped_large::{self, BodyType as BLBodyType, Species as BLSpecies}, biped_small, bird_large::{self, BodyType as BLABodyType, Species as BLASpecies}, @@ -2151,6 +2152,384 @@ impl TheropodLateralSpec { (lateral, Vec3::from(spec.foot_r.offset)) } } + +//// +#[derive(Deserialize)] +struct ArthropodCentralSpec(HashMap<(ASpecies, ABodyType), SidedACentralVoxSpec>); + +#[derive(Deserialize)] +struct SidedACentralVoxSpec { + head: ArthropodCentralSubSpec, + chest: ArthropodCentralSubSpec, +} +#[derive(Deserialize)] +struct ArthropodCentralSubSpec { + offset: [f32; 3], // Should be relative to initial origin + central: VoxSimple, +} +#[derive(Deserialize)] +struct ArthropodLateralSpec(HashMap<(ASpecies, ABodyType), SidedALateralVoxSpec>); + +#[derive(Deserialize)] +struct SidedALateralVoxSpec { + mandible_l: ArthropodLateralSubSpec, + mandible_r: ArthropodLateralSubSpec, + wing_fl: ArthropodLateralSubSpec, + wing_fr: ArthropodLateralSubSpec, + wing_bl: ArthropodLateralSubSpec, + wing_br: ArthropodLateralSubSpec, + leg_fl: ArthropodLateralSubSpec, + leg_fr: ArthropodLateralSubSpec, + leg_fcl: ArthropodLateralSubSpec, + leg_fcr: ArthropodLateralSubSpec, + leg_bcl: ArthropodLateralSubSpec, + leg_bcr: ArthropodLateralSubSpec, + leg_bl: ArthropodLateralSubSpec, + leg_br: ArthropodLateralSubSpec, +} +#[derive(Deserialize)] +struct ArthropodLateralSubSpec { + offset: [f32; 3], // Should be relative to initial origin + lateral: VoxSimple, +} +make_vox_spec!( + arthropod::Body, + struct ArthropodSpec { + central: ArthropodCentralSpec = "voxygen.voxel.Arthropod_central_manifest", + lateral: ArthropodLateralSpec = "voxygen.voxel.Arthropod_lateral_manifest", + }, + |FigureKey { body, .. }, spec| { + [ + Some(spec.central.read().0.mesh_head( + body.species, + body.body_type, + )), + Some(spec.central.read().0.mesh_chest( + body.species, + body.body_type, + )), + Some(spec.lateral.read().0.mesh_mandible_l( + body.species, + body.body_type, + )), + Some(spec.lateral.read().0.mesh_mandible_r( + body.species, + body.body_type, + )), + Some(spec.lateral.read().0.mesh_wing_fl( + body.species, + body.body_type, + )), + Some(spec.lateral.read().0.mesh_wing_fr( + body.species, + body.body_type, + )), + Some(spec.lateral.read().0.mesh_wing_bl( + body.species, + body.body_type, + )), + Some(spec.lateral.read().0.mesh_wing_br( + body.species, + body.body_type, + )), + Some(spec.lateral.read().0.mesh_leg_fl( + body.species, + body.body_type, + )), + Some(spec.lateral.read().0.mesh_leg_fr( + body.species, + body.body_type, + )), + Some(spec.lateral.read().0.mesh_leg_fcl( + body.species, + body.body_type, + )), + Some(spec.lateral.read().0.mesh_leg_fcr( + body.species, + body.body_type, + )), + Some(spec.lateral.read().0.mesh_leg_bcl( + body.species, + body.body_type, + )), + Some(spec.lateral.read().0.mesh_leg_bcr( + body.species, + body.body_type, + )), + Some(spec.lateral.read().0.mesh_leg_bl( + body.species, + body.body_type, + )), + Some(spec.lateral.read().0.mesh_leg_br( + body.species, + body.body_type, + )), + ] + }, +); + +impl ArthropodCentralSpec { + fn mesh_head(&self, species: ASpecies, body_type: ABodyType) -> BoneMeshes { + let spec = match self.0.get(&(species, body_type)) { + Some(spec) => spec, + None => { + error!( + "No head specification exists for the combination of {:?} and {:?}", + species, body_type + ); + return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5)); + }, + }; + let central = graceful_load_segment(&spec.head.central.0); + + (central, Vec3::from(spec.head.offset)) + } + + fn mesh_chest(&self, species: ASpecies, body_type: ABodyType) -> BoneMeshes { + let spec = match self.0.get(&(species, body_type)) { + Some(spec) => spec, + None => { + error!( + "No chest specification exists for the combination of {:?} and {:?}", + species, body_type + ); + return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5)); + }, + }; + let central = graceful_load_segment(&spec.chest.central.0); + + (central, Vec3::from(spec.chest.offset)) + } +} +impl ArthropodLateralSpec { + fn mesh_mandible_l(&self, species: ASpecies, body_type: ABodyType) -> BoneMeshes { + let spec = match self.0.get(&(species, body_type)) { + Some(spec) => spec, + None => { + error!( + "No left mandible specification exists for the combination of {:?} and {:?}", + species, body_type + ); + return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5)); + }, + }; + let lateral = graceful_load_segment_flipped(&spec.mandible_l.lateral.0, true); + + (lateral, Vec3::from(spec.mandible_l.offset)) + } + + fn mesh_mandible_r(&self, species: ASpecies, body_type: ABodyType) -> BoneMeshes { + let spec = match self.0.get(&(species, body_type)) { + Some(spec) => spec, + None => { + error!( + "No right mandible specification exists for the combination of {:?} and {:?}", + species, body_type + ); + return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5)); + }, + }; + let lateral = graceful_load_segment(&spec.mandible_r.lateral.0); + + (lateral, Vec3::from(spec.mandible_r.offset)) + } + + fn mesh_wing_fl(&self, species: ASpecies, body_type: ABodyType) -> BoneMeshes { + let spec = match self.0.get(&(species, body_type)) { + Some(spec) => spec, + None => { + error!( + "No front left wing specification exists for the combination of {:?} and {:?}", + species, body_type + ); + return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5)); + }, + }; + let lateral = graceful_load_segment_flipped(&spec.wing_fl.lateral.0, true); + + (lateral, Vec3::from(spec.wing_fl.offset)) + } + + fn mesh_wing_fr(&self, species: ASpecies, body_type: ABodyType) -> BoneMeshes { + let spec = match self.0.get(&(species, body_type)) { + Some(spec) => spec, + None => { + error!( + "No front right wing specification exists for the combination of {:?} and {:?}", + species, body_type + ); + return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5)); + }, + }; + let lateral = graceful_load_segment(&spec.wing_fr.lateral.0); + + (lateral, Vec3::from(spec.wing_fr.offset)) + } + + fn mesh_wing_bl(&self, species: ASpecies, body_type: ABodyType) -> BoneMeshes { + let spec = match self.0.get(&(species, body_type)) { + Some(spec) => spec, + None => { + error!( + "No back left wing specification exists for the combination of {:?} and {:?}", + species, body_type + ); + return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5)); + }, + }; + let lateral = graceful_load_segment_flipped(&spec.wing_bl.lateral.0, true); + + (lateral, Vec3::from(spec.wing_bl.offset)) + } + + fn mesh_wing_br(&self, species: ASpecies, body_type: ABodyType) -> BoneMeshes { + let spec = match self.0.get(&(species, body_type)) { + Some(spec) => spec, + None => { + error!( + "No back right wing specification exists for the combination of {:?} and {:?}", + species, body_type + ); + return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5)); + }, + }; + let lateral = graceful_load_segment(&spec.wing_br.lateral.0); + + (lateral, Vec3::from(spec.wing_br.offset)) + } + + fn mesh_leg_fl(&self, species: ASpecies, body_type: ABodyType) -> BoneMeshes { + let spec = match self.0.get(&(species, body_type)) { + Some(spec) => spec, + None => { + error!( + "No front left leg specification exists for the combination of {:?} and {:?}", + species, body_type + ); + return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5)); + }, + }; + let lateral = graceful_load_segment_flipped(&spec.leg_fl.lateral.0, true); + + (lateral, Vec3::from(spec.leg_fl.offset)) + } + + fn mesh_leg_fr(&self, species: ASpecies, body_type: ABodyType) -> BoneMeshes { + let spec = match self.0.get(&(species, body_type)) { + Some(spec) => spec, + None => { + error!( + "No front right leg specification exists for the combination of {:?} and {:?}", + species, body_type + ); + return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5)); + }, + }; + let lateral = graceful_load_segment(&spec.leg_fr.lateral.0); + + (lateral, Vec3::from(spec.leg_fr.offset)) + } + + fn mesh_leg_fcl(&self, species: ASpecies, body_type: ABodyType) -> BoneMeshes { + let spec = match self.0.get(&(species, body_type)) { + Some(spec) => spec, + None => { + error!( + "No front center left leg specification exists for the combination of {:?} \ + and {:?}", + species, body_type + ); + return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5)); + }, + }; + let lateral = graceful_load_segment_flipped(&spec.leg_fcl.lateral.0, true); + + (lateral, Vec3::from(spec.leg_fcl.offset)) + } + + fn mesh_leg_fcr(&self, species: ASpecies, body_type: ABodyType) -> BoneMeshes { + let spec = match self.0.get(&(species, body_type)) { + Some(spec) => spec, + None => { + error!( + "No front center right leg specification exists for the combination of {:?} \ + and {:?}", + species, body_type + ); + return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5)); + }, + }; + let lateral = graceful_load_segment(&spec.leg_fcr.lateral.0); + + (lateral, Vec3::from(spec.leg_fcr.offset)) + } + + fn mesh_leg_bcl(&self, species: ASpecies, body_type: ABodyType) -> BoneMeshes { + let spec = match self.0.get(&(species, body_type)) { + Some(spec) => spec, + None => { + error!( + "No back center left leg specification exists for the combination of {:?} and \ + {:?}", + species, body_type + ); + return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5)); + }, + }; + let lateral = graceful_load_segment_flipped(&spec.leg_bcl.lateral.0, true); + + (lateral, Vec3::from(spec.leg_bcl.offset)) + } + + fn mesh_leg_bcr(&self, species: ASpecies, body_type: ABodyType) -> BoneMeshes { + let spec = match self.0.get(&(species, body_type)) { + Some(spec) => spec, + None => { + error!( + "No back center right leg specification exists for the combination of {:?} \ + and {:?}", + species, body_type + ); + return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5)); + }, + }; + let lateral = graceful_load_segment(&spec.leg_bcr.lateral.0); + + (lateral, Vec3::from(spec.leg_bcr.offset)) + } + + fn mesh_leg_bl(&self, species: ASpecies, body_type: ABodyType) -> BoneMeshes { + let spec = match self.0.get(&(species, body_type)) { + Some(spec) => spec, + None => { + error!( + "No back left leg specification exists for the combination of {:?} and {:?}", + species, body_type + ); + return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5)); + }, + }; + let lateral = graceful_load_segment_flipped(&spec.leg_bl.lateral.0, true); + + (lateral, Vec3::from(spec.leg_bl.offset)) + } + + fn mesh_leg_br(&self, species: ASpecies, body_type: ABodyType) -> BoneMeshes { + let spec = match self.0.get(&(species, body_type)) { + Some(spec) => spec, + None => { + error!( + "No back right leg specification exists for the combination of {:?} and {:?}", + species, body_type + ); + return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5)); + }, + }; + let lateral = graceful_load_segment(&spec.leg_br.lateral.0); + + (lateral, Vec3::from(spec.leg_br.offset)) + } +} //// #[derive(Deserialize)] struct FishMediumCentralSpec(HashMap<(FMSpecies, FMBodyType), SidedFMCentralVoxSpec>); diff --git a/voxygen/src/scene/figure/mod.rs b/voxygen/src/scene/figure/mod.rs index 46bfce12a0..6277149f8c 100644 --- a/voxygen/src/scene/figure/mod.rs +++ b/voxygen/src/scene/figure/mod.rs @@ -21,7 +21,7 @@ use crate::{ }, }; use anim::{ - biped_large::BipedLargeSkeleton, biped_small::BipedSmallSkeleton, + arthropod::ArthropodSkeleton, biped_large::BipedLargeSkeleton, biped_small::BipedSmallSkeleton, bird_large::BirdLargeSkeleton, bird_medium::BirdMediumSkeleton, character::CharacterSkeleton, dragon::DragonSkeleton, fish_medium::FishMediumSkeleton, fish_small::FishSmallSkeleton, golem::GolemSkeleton, object::ObjectSkeleton, quadruped_low::QuadrupedLowSkeleton, @@ -119,6 +119,7 @@ struct FigureMgrStates { object_states: HashMap>, ship_states: HashMap>, volume_states: HashMap>, + arthropod_states: HashMap>, } impl FigureMgrStates { @@ -140,6 +141,7 @@ impl FigureMgrStates { object_states: HashMap::new(), ship_states: HashMap::new(), volume_states: HashMap::new(), + arthropod_states: HashMap::new(), } } @@ -207,6 +209,10 @@ impl FigureMgrStates { self.volume_states.get_mut(entity).map(DerefMut::deref_mut) } }, + Body::Arthropod(_) => self + .arthropod_states + .get_mut(entity) + .map(DerefMut::deref_mut), } } @@ -237,6 +243,7 @@ impl FigureMgrStates { self.volume_states.remove(entity).map(|e| e.meta) } }, + Body::Arthropod(_) => self.arthropod_states.remove(entity).map(|e| e.meta), } } @@ -258,6 +265,7 @@ impl FigureMgrStates { self.object_states.retain(|k, v| f(k, &mut *v)); self.ship_states.retain(|k, v| f(k, &mut *v)); self.volume_states.retain(|k, v| f(k, &mut *v)); + self.arthropod_states.retain(|k, v| f(k, &mut *v)); } fn count(&self) -> usize { @@ -278,6 +286,7 @@ impl FigureMgrStates { + self.object_states.len() + self.ship_states.len() + self.volume_states.len() + + self.arthropod_states.len() } fn count_visible(&self) -> usize { @@ -350,6 +359,11 @@ impl FigureMgrStates { .iter() .filter(|(_, c)| c.visible()) .count() + + self + .arthropod_states + .iter() + .filter(|(_, c)| c.visible()) + .count() + self.ship_states.iter().filter(|(_, c)| c.visible()).count() + self .volume_states @@ -377,6 +391,7 @@ pub struct FigureMgr { ship_model_cache: FigureModelCache, golem_model_cache: FigureModelCache, volume_model_cache: FigureModelCache, + arthropod_model_cache: FigureModelCache, states: FigureMgrStates, } @@ -400,6 +415,7 @@ impl FigureMgr { ship_model_cache: FigureModelCache::new(), golem_model_cache: FigureModelCache::new(), volume_model_cache: FigureModelCache::new(), + arthropod_model_cache: FigureModelCache::new(), states: FigureMgrStates::default(), } } @@ -433,6 +449,7 @@ impl FigureMgr { self.ship_model_cache.clean(&mut self.col_lights, tick); self.golem_model_cache.clean(&mut self.col_lights, tick); self.volume_model_cache.clean(&mut self.col_lights, tick); + self.arthropod_model_cache.clean(&mut self.col_lights, tick); } pub fn update_lighting(&mut self, scene_data: &SceneData) { @@ -3425,6 +3442,296 @@ impl FigureMgr { body, ); }, + Body::Arthropod(body) => { + let (model, skeleton_attr) = self.arthropod_model_cache.get_or_create_model( + renderer, + &mut self.col_lights, + body, + inventory, + (), + tick, + player_camera_mode, + player_character_state, + &slow_jobs, + ); + + let state = self + .states + .arthropod_states + .entry(entity) + .or_insert_with(|| { + FigureState::new(renderer, ArthropodSkeleton::default(), body) + }); + + // Average velocity relative to the current ground + let rel_avg_vel = state.avg_vel - physics.ground_vel; + + let (character, last_character) = match (character, last_character) { + (Some(c), Some(l)) => (c, l), + _ => continue, + }; + + if !character.same_variant(&last_character.0) { + state.state_time = 0.0; + } + + let target_base = match ( + physics.on_ground.is_some(), + rel_vel.magnitude_squared() > MOVING_THRESHOLD_SQR, // Moving + physics.in_liquid().is_some(), // In water + ) { + // Standing + (true, false, false) => anim::arthropod::IdleAnimation::update_skeleton( + &ArthropodSkeleton::default(), + time, + state.state_time, + &mut state_animation_rate, + skeleton_attr, + ), + // Running + (true, true, false) => anim::arthropod::RunAnimation::update_skeleton( + &ArthropodSkeleton::default(), + ( + rel_vel, + // TODO: Update to use the quaternion. + ori * anim::vek::Vec3::::unit_y(), + state.last_ori * anim::vek::Vec3::::unit_y(), + time, + rel_avg_vel, + state.acc_vel, + ), + state.state_time, + &mut state_animation_rate, + skeleton_attr, + ), + // In air + (false, _, false) => anim::arthropod::JumpAnimation::update_skeleton( + &ArthropodSkeleton::default(), + ( + rel_vel.magnitude(), + // TODO: Update to use the quaternion. + ori * anim::vek::Vec3::::unit_y(), + state.last_ori * anim::vek::Vec3::::unit_y(), + time, + rel_avg_vel, + ), + state.state_time, + &mut state_animation_rate, + skeleton_attr, + ), + _ => anim::arthropod::IdleAnimation::update_skeleton( + &ArthropodSkeleton::default(), + time, + state.state_time, + &mut state_animation_rate, + skeleton_attr, + ), + }; + let target_bones = match &character { + CharacterState::ComboMelee(s) => { + let stage_index = (s.stage - 1) as usize; + let stage_time = s.timer.as_secs_f32(); + let stage_progress = + if let Some(stage) = s.static_data.stage_data.get(stage_index) { + match s.stage_section { + StageSection::Buildup => { + stage_time / stage.base_buildup_duration.as_secs_f32() + }, + StageSection::Action => { + stage_time / stage.base_swing_duration.as_secs_f32() + }, + StageSection::Recover => { + stage_time / stage.base_recover_duration.as_secs_f32() + }, + _ => 0.0, + } + } else { + 0.0 + }; + match s.stage { + 1 => anim::arthropod::AlphaAnimation::update_skeleton( + &target_base, + ( + rel_vel.magnitude(), + time, + Some(s.stage_section), + state.state_time, + ), + stage_progress, + &mut state_animation_rate, + skeleton_attr, + ), + _ => anim::arthropod::AlphaAnimation::update_skeleton( + &target_base, + ( + rel_vel.magnitude(), + time, + Some(s.stage_section), + state.state_time, + ), + stage_progress, + &mut state_animation_rate, + skeleton_attr, + ), + } + }, + CharacterState::LeapMelee(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::Movement => { + stage_time / s.static_data.movement_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::arthropod::LeapMeleeAnimation::update_skeleton( + &target_base, + ( + rel_vel.magnitude(), + time, + Some(s.stage_section), + state.state_time, + ), + stage_progress, + &mut state_animation_rate, + skeleton_attr, + ) + }, + CharacterState::SpriteSummon(s) => { + let stage_time = s.timer.as_secs_f32(); + let stage_progress = match s.stage_section { + StageSection::Buildup => { + stage_time / s.static_data.buildup_duration.as_secs_f32() + }, + StageSection::Action => { + stage_time / s.static_data.cast_duration.as_secs_f32() + }, + StageSection::Recover => { + stage_time / s.static_data.recover_duration.as_secs_f32() + }, + _ => 0.0, + }; + anim::arthropod::SummonAnimation::update_skeleton( + &target_base, + ( + rel_vel.magnitude(), + time, + Some(s.stage_section), + state.state_time, + ), + stage_progress, + &mut state_animation_rate, + skeleton_attr, + ) + }, + CharacterState::DashMelee(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::Charge => { + stage_time / s.static_data.charge_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::arthropod::DashAnimation::update_skeleton( + &target_base, + ( + rel_vel.magnitude(), + time, + Some(s.stage_section), + state.state_time, + ), + stage_progress, + &mut state_animation_rate, + skeleton_attr, + ) + }, + CharacterState::BasicRanged(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::Recover => { + stage_time / s.static_data.recover_duration.as_secs_f32() + }, + _ => 0.0, + }; + anim::arthropod::ShootAnimation::update_skeleton( + &target_base, + ( + rel_vel.magnitude(), + time, + Some(s.stage_section), + state.state_time, + ), + stage_progress, + &mut state_animation_rate, + skeleton_attr, + ) + }, + CharacterState::Stunned(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::Recover => { + stage_time / s.static_data.recover_duration.as_secs_f32() + }, + _ => 0.0, + }; + match s.static_data.poise_state { + PoiseState::Normal + | PoiseState::Interrupted + | PoiseState::Stunned + | PoiseState::Dazed + | PoiseState::KnockedDown => { + anim::arthropod::StunnedAnimation::update_skeleton( + &target_base, + ( + rel_vel.magnitude(), + time, + Some(s.stage_section), + state.state_time, + ), + stage_progress, + &mut state_animation_rate, + skeleton_attr, + ) + }, + } + }, + // TODO! + _ => target_base, + }; + + state.skeleton = anim::vek::Lerp::lerp(&state.skeleton, &target_bones, dt_lerp); + state.update( + renderer, + &mut update_buf, + &common_params, + state_animation_rate, + model, + body, + ); + }, Body::BirdLarge(body) => { let (model, skeleton_attr) = self.bird_large_model_cache.get_or_create_model( renderer, @@ -5142,6 +5449,7 @@ impl FigureMgr { ship_model_cache, golem_model_cache, volume_model_cache, + arthropod_model_cache, states: FigureMgrStates { character_states, @@ -5160,6 +5468,7 @@ impl FigureMgr { object_states, ship_states, volume_states, + arthropod_states, }, } = self; let col_lights = &*col_lights_; @@ -5372,6 +5681,22 @@ impl FigureMgr { ), ) }), + Body::Arthropod(body) => arthropod_states + .get(&entity) + .filter(|state| filter_state(*state)) + .map(move |state| { + ( + state.bound(), + arthropod_model_cache.get_model( + col_lights, + body, + inventory, + tick, + player_camera_mode, + character_state, + ), + ) + }), Body::Object(body) => object_states .get(&entity) .filter(|state| filter_state(*state)) diff --git a/world/src/layer/mod.rs b/world/src/layer/mod.rs index 63c277e4c6..de74db054d 100644 --- a/world/src/layer/mod.rs +++ b/world/src/layer/mod.rs @@ -466,15 +466,19 @@ pub fn apply_caves_supplement<'a>( _ => "common.entity.wild.aggressive.batfox", } } else if cave_depth < 120.0 { - match dynamic_rng.gen_range(0..3) { + match dynamic_rng.gen_range(0..6) { 0 => "common.entity.wild.aggressive.rocksnapper", 1 => "common.entity.wild.aggressive.cave_salamander", + 2 => "common.entity.wild.aggressive.cave_spider", + 3 => "common.entity.wild.aggressive.antlion", + 4 => "common.entity.wild.peaceful.crawler_molten", _ => "common.entity.wild.aggressive.asp", } } else if cave_depth < 190.0 { - match dynamic_rng.gen_range(0..3) { + match dynamic_rng.gen_range(0..4) { 0 => "common.entity.wild.aggressive.rocksnapper", 1 => "common.entity.wild.aggressive.lavadrake", + 2 => "common.entity.wild.aggressive.black_widow", _ => "common.entity.wild.aggressive.basilisk", } } else {