diff --git a/assets/common/items/armor/misc/head/exclamation.ron b/assets/common/items/armor/misc/head/exclamation.ron new file mode 100644 index 0000000000..4e7da3c988 --- /dev/null +++ b/assets/common/items/armor/misc/head/exclamation.ron @@ -0,0 +1,17 @@ +ItemDef( + name: "Exclamation hat", + description: "You feel like bestowing quests.", + kind: Armor(( + kind: Head("Exclamation"), + stats: ( + protection: Normal(0.0), + poise_resilience: Normal(0.0), + energy_max: 0, + energy_reward: 0.0, + crit_power: 0.0, + stealth: 0.0, + ), + )), + quality: Common, + tags: [], +) diff --git a/assets/voxygen/item_image_manifest.ron b/assets/voxygen/item_image_manifest.ron index 925bf0e639..303028d56e 100644 --- a/assets/voxygen/item_image_manifest.ron +++ b/assets/voxygen/item_image_manifest.ron @@ -2194,6 +2194,10 @@ "voxel.armor.misc.head.assa_mask-0", (0.0, 0.0, 0.0), (-90.0, 180.0, 0.0), 1.0, ), + Armor(Head("Exclamation")): VoxTrans( + "voxel.armor.misc.head.exclamation", + (0.0, 15.0, 0.0), (-75.0, 135.0, 0.0), 3.0, + ), // Bags Armor(Bag("RedFace")): Png ( "element.items.item_bag_red_face", diff --git a/assets/voxygen/voxel/armor/misc/head/exclamation.vox b/assets/voxygen/voxel/armor/misc/head/exclamation.vox new file mode 100644 index 0000000000..5304297467 --- /dev/null +++ b/assets/voxygen/voxel/armor/misc/head/exclamation.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e6a3369c5a2fc3e75d6ecb07d8e282b877b50f999afb629ac2c6b69359658b8a +size 1208 diff --git a/assets/voxygen/voxel/humanoid_armor_head_manifest.ron b/assets/voxygen/voxel/humanoid_armor_head_manifest.ron new file mode 100644 index 0000000000..6307a9b106 --- /dev/null +++ b/assets/voxygen/voxel/humanoid_armor_head_manifest.ron @@ -0,0 +1,32 @@ +(( + default: ( + vox_spec: ("armor.empty", (0.0, 0.0, 0.0)), + color: None + ), + map: { + (Danari, "Exclamation"): ( + vox_spec: ("armor.misc.head.exclamation", (-10.0, -10.0, 20.0)), + color: None + ), + (Dwarf, "Exclamation"): ( + vox_spec: ("armor.misc.head.exclamation", (-13.0, -10.0, 18.0)), + color: None + ), + (Human, "Exclamation"): ( + vox_spec: ("armor.misc.head.exclamation", (-12.0, -11.0, 18.0)), + color: None + ), + (Orc, "Exclamation"): ( + vox_spec: ("armor.misc.head.exclamation", (-11.0, -12.0, 18.0)), + color: None + ), + (Undead, "Exclamation"): ( + vox_spec: ("armor.misc.head.exclamation", (-14.0, -11.0, 18.0)), + color: None + ), + (Elf, "Exclamation"): ( + vox_spec: ("armor.misc.head.exclamation", (-11.0, -11.0, 18.0)), + color: None + ), + } +)) diff --git a/voxygen/src/scene/figure/cache.rs b/voxygen/src/scene/figure/cache.rs index 0165122045..7f25fd606c 100644 --- a/voxygen/src/scene/figure/cache.rs +++ b/voxygen/src/scene/figure/cache.rs @@ -113,6 +113,7 @@ pub(super) struct CharacterCacheKey { pub glider: Option, pub hand: Option, pub foot: Option, + pub head: Option, } impl CharacterCacheKey { @@ -264,6 +265,17 @@ impl CharacterCacheKey { } else { None }, + head: if let Some(ItemKind::Armor(Armor { + kind: ArmorKind::Head(armor), + .. + })) = inventory + .equipped(EquipSlot::Armor(ArmorSlot::Head)) + .map(|i| i.kind()) + { + Some(armor.clone()) + } else { + None + }, } } } diff --git a/voxygen/src/scene/figure/load.rs b/voxygen/src/scene/figure/load.rs index 34736b6200..dda604e939 100644 --- a/voxygen/src/scene/figure/load.rs +++ b/voxygen/src/scene/figure/load.rs @@ -234,7 +234,12 @@ struct HumHeadSubSpec { struct HumHeadSpec(HashMap<(Species, BodyType), HumHeadSubSpec>); impl HumHeadSpec { - fn mesh_head(&self, body: &Body, color_spec: &HumColorSpec) -> BoneMeshes { + fn mesh_head( + &self, + body: &Body, + color_spec: &HumColorSpec, + helmet: Option<(Segment, Vec3)>, + ) -> BoneMeshes { let spec = match self.0.get(&(body.species, body.body_type)) { Some(spec) => spec, None => { @@ -311,6 +316,7 @@ impl HumHeadSpec { .maybe_add(hair) .maybe_add(beard) .maybe_add(accessory) + .maybe_add(helmet) .unify(); ( @@ -353,7 +359,7 @@ struct HumArmorLanternSpec(ArmorVoxSpecMap); #[derive(Deserialize)] struct HumArmorGliderSpec(ArmorVoxSpecMap); #[derive(Deserialize)] -struct HumArmorHeadSpec(ArmorVoxSpecMap); +struct HumArmorHeadSpec(ArmorVoxSpecMap<(Species, String), ArmorVoxSpec>); #[derive(Deserialize)] struct HumArmorTabardSpec(ArmorVoxSpecMap); @@ -373,9 +379,9 @@ make_vox_spec!( modular_components: HumModularComponentSpec = "voxygen.voxel.humanoid_modular_component_manifest", armor_lantern: HumArmorLanternSpec = "voxygen.voxel.humanoid_lantern_manifest", armor_glider: HumArmorGliderSpec = "voxygen.voxel.humanoid_glider_manifest", + armor_head: HumArmorHeadSpec = "voxygen.voxel.humanoid_armor_head_manifest", // TODO: Add these. - /* armor_head: HumArmorHeadSpec = "voxygen.voxel.humanoid_armor_head_manifest", - tabard: HumArmorTabardSpec = "voxygen.voxel.humanoid_armor_tabard_manifest", */ + /* tabard: HumArmorTabardSpec = "voxygen.voxel.humanoid_armor_tabard_manifest", */ }, |FigureKey { body, extra }, spec| { const DEFAULT_LOADOUT: super::cache::CharacterCacheKey = super::cache::CharacterCacheKey { @@ -385,6 +391,7 @@ make_vox_spec!( glider: None, hand: None, foot: None, + head: None, }; // TODO: This is bad code, maybe this method should return Option<_> @@ -403,6 +410,10 @@ make_vox_spec!( spec.head.read().0.mesh_head( body, color, + spec.armor_head.read().0.load_head( + body, + loadout.head.as_deref() + ), ) }), third_person.map(|loadout| { @@ -957,46 +968,17 @@ impl HumArmorLanternSpec { } } impl HumArmorHeadSpec { - /// FIXME: Either use this, or remove it. - #[allow(dead_code)] - fn mesh_head(&self, body: &Body, color_spec: &HumColorSpec, head: Option<&str>) -> BoneMeshes { - let spec = if let Some(head) = head { - match self.0.map.get(head) { - Some(spec) => spec, - None => { - error!(?head, "No head specification exists"); - return load_mesh("not_found", Vec3::new(-5.0, -3.5, 1.0)); - }, - } - } else { - &self.0.default - }; - - let color = |mat_segment| { - color_spec.color_segment( - mat_segment, - body.species.skin_color(body.skin), - color_spec.hair_color(body.species, body.hair_color), - body.species.eye_color(body.eye_color), - ) - }; - - let bare_head = graceful_load_mat_segment("armor.empty"); - - let mut head_armor = graceful_load_mat_segment(&spec.vox_spec.0); - - if let Some(color) = spec.color { - let head_color = Vec3::from(color); - head_armor = head_armor.map_rgb(|rgb| recolor_grey(rgb, Rgb::from(head_color))); + fn load_head(&self, body: &Body, head: Option<&str>) -> Option<(Segment, Vec3)> { + match self.0.map.get(&(body.species, head?.to_string())) { + Some(spec) => Some(( + graceful_load_segment(&spec.vox_spec.0), + Vec3::::from(spec.vox_spec.1).as_(), + )), + None => { + warn!("No specification for this head: {:?}", head); + None + }, } - - let head = DynaUnionizer::new() - .add(color(bare_head), Vec3::new(0, 0, 0)) - .add(color(head_armor), Vec3::new(0, 0, 0)) - .unify() - .0; - - (head, Vec3::from(spec.vox_spec.1)) } } impl HumArmorTabardSpec { @@ -2516,6 +2498,7 @@ make_vox_spec!( glider: None, hand: None, foot: None, + head: None, }; // TODO: This is bad code, maybe this method should return Option<_> @@ -3544,6 +3527,7 @@ make_vox_spec!( glider: None, hand: None, foot: None, + head: None, }; // TODO: This is bad code, maybe this method should return Option<_>