tf2_enum/
paint.rs

1use crate::{
2    Attribute,
3    AttributeDef,
4    Colored,
5    DescriptionFormat,
6    EffectType,
7    HasItemDefindex,
8    ItemAttribute,
9    TryFromIntAttributeValue,
10};
11use num_enum::{IntoPrimitive, TryFromPrimitive};
12use serde_repr::{Deserialize_repr, Serialize_repr};
13use strum::{Display, EnumCount, EnumIter, EnumString};
14
15/// Paint. `repr` values are mapped to the corresponding hexadecimal color (represented as a u32).
16/// For team paints, this is the color for RED team.
17#[derive(
18    Debug,
19    Clone,
20    Copy,
21    Eq,
22    PartialEq,
23    Ord,
24    PartialOrd,
25    Hash,
26    Display,
27    Serialize_repr,
28    Deserialize_repr,
29    EnumString,
30    EnumIter,
31    EnumCount,
32    TryFromPrimitive,
33    IntoPrimitive,
34)]
35#[repr(u32)]
36#[allow(missing_docs)]
37pub enum Paint {
38    #[strum(serialize = "A Color Similar to Slate")]
39    AColorSimilarToSlate = 0x2F4F4F,
40    #[strum(serialize = "A Deep Commitment to Purple")]
41    ADeepCommitmentToPurple = 0x7D4071,
42    #[strum(serialize = "A Distinctive Lack of Hue")]
43    ADistinctiveLackOfHue = 0x141414,
44    #[strum(serialize = "A Mann's Mint")]
45    AMannsMint = 0xBCDDB3,
46    #[strum(serialize = "After Eight")]
47    AfterEight = 0x2D2D24,
48    #[strum(serialize = "Aged Moustache Grey")]
49    AgedMoustacheGrey = 0x7E7E7E,
50    #[strum(serialize = "An Extraordinary Abundance of Tinge")]
51    AnExtraordinaryAbundanceOfTinge = 0xE6E6E6,
52    #[strum(serialize = "Australium Gold")]
53    AustraliumGold = 0xE7B53B,
54    #[strum(serialize = "Color No. 216-190-216")]
55    ColorNo216190216 = 0xD8BED8,
56    #[strum(serialize = "Dark Salmon Injustice")]
57    DarkSalmonInjustice = 0xE9967A,
58    #[strum(serialize = "Drably Olive")]
59    DrablyOlive = 0x808000,
60    #[strum(serialize = "Indubitably Green")]
61    IndubitablyGreen = 0x729E42,
62    #[strum(serialize = "Mann Co. Orange")]
63    MannCoOrange = 0xCF7336,
64    #[strum(serialize = "Muskelmannbraun")]
65    Muskelmannbraun = 0xA57545,
66    #[strum(serialize = "Noble Hatter's Violet")]
67    NobleHattersViolet = 0x51384A,
68    #[strum(serialize = "Peculiarly Drab Tincture")]
69    PeculiarlyDrabTincture = 0xC5AF91,
70    #[strum(serialize = "Pink as Hell")]
71    PinkAsHell = 0xFF69B4,
72    #[strum(serialize = "Radigan Conagher Brown")]
73    RadiganConagherBrown = 0x694D3A,
74    #[strum(serialize = "The Bitter Taste of Defeat and Lime")]
75    TheBitterTasteOfDefeatAndLime = 0x32CD32,
76    #[strum(serialize = "The Color of a Gentlemann's Business Pants")]
77    TheColorOfAGentlemannsBusinessPants = 0xF0E68C,
78    #[strum(serialize = "Ye Olde Rustic Colour")]
79    YeOldeRusticColour = 0x7C6C57,
80    #[strum(serialize = "Zepheniah's Greed")]
81    ZepheniahsGreed = 0x424F3B,
82    #[strum(serialize = "An Air of Debonair")]
83    AnAirOfDebonair = 0x654740,
84    #[strum(serialize = "Balaclavas Are Forever")]
85    BalaclavasAreForever = 0x3B1F23,
86    #[strum(serialize = "Cream Spirit")]
87    CreamSpirit = 0xC36C2D,
88    #[strum(serialize = "Operator's Overalls")]
89    OperatorsOveralls = 0x483838,
90    #[strum(serialize = "Team Spirit")]
91    TeamSpirit = 0xB8383B,
92    #[strum(serialize = "The Value of Teamwork")]
93    TheValueOfTeamwork = 0x803020,
94    #[strum(serialize = "Waterlogged Lab Coat")]
95    WaterloggedLabCoat = 0xA89A8C,
96}
97
98impl Paint {
99    /// Gets the colors for both teams. The RED team appears first. For non-team-color paints, the
100    /// color will be the same.
101    pub fn colors(&self) -> (u32, u32) {
102        match self {
103            Self::AColorSimilarToSlate => (0x2F4F4F, 0x2F4F4F),
104            Self::ADeepCommitmentToPurple => (0x7D4071, 0x7D4071),
105            Self::ADistinctiveLackOfHue => (0x141414, 0x141414),
106            Self::AMannsMint => (0xBCDDB3, 0xBCDDB3),
107            Self::AfterEight => (0x2D2D24, 0x2D2D24),
108            Self::AgedMoustacheGrey => (0x7E7E7E, 0x7E7E7E),
109            Self::AnExtraordinaryAbundanceOfTinge => (0xE6E6E6, 0xE6E6E6),
110            Self::AustraliumGold => (0xE7B53B, 0xE7B53B),
111            Self::ColorNo216190216 => (0xD8BED8, 0xD8BED8),
112            Self::DarkSalmonInjustice => (0xE9967A, 0xE9967A),
113            Self::DrablyOlive => (0x808000, 0x808000),
114            Self::IndubitablyGreen => (0x729E42, 0x729E42),
115            Self::MannCoOrange => (0xCF7336, 0xCF7336),
116            Self::Muskelmannbraun => (0xA57545, 0xA57545),
117            Self::NobleHattersViolet => (0x51384A, 0x51384A),
118            Self::PeculiarlyDrabTincture => (0xC5AF91, 0xC5AF91),
119            Self::PinkAsHell => (0xFF69B4, 0xFF69B4),
120            Self::RadiganConagherBrown => (0x694D3A, 0x694D3A),
121            Self::TheBitterTasteOfDefeatAndLime => (0x32CD32, 0x32CD32),
122            Self::TheColorOfAGentlemannsBusinessPants => (0xF0E68C, 0xF0E68C),
123            Self::YeOldeRusticColour => (0x7C6C57, 0x7C6C57),
124            Self::ZepheniahsGreed => (0x424F3B, 0x424F3B),
125            Self::AnAirOfDebonair => (0x654740, 0x28394D),
126            Self::BalaclavasAreForever => (0x3B1F23, 0x18233D),
127            Self::CreamSpirit => (0xC36C2D, 0xB88035),
128            Self::OperatorsOveralls => (0x483838, 0x384248),
129            Self::TeamSpirit => (0xB8383B, 0x5885A2),
130            Self::TheValueOfTeamwork => (0x803020, 0x256D8D),
131            Self::WaterloggedLabCoat => (0xA89A8C, 0x839FA3),
132        }
133    }
134    
135    /// Determines if this paint is a team-colored paint.
136    pub fn is_team_paint(&self) -> bool {
137        matches!(
138            self,
139            Self::AnAirOfDebonair |
140            Self::BalaclavasAreForever |
141            Self::CreamSpirit |
142            Self::OperatorsOveralls |
143            Self::TeamSpirit |
144            Self::TheValueOfTeamwork |
145            Self::WaterloggedLabCoat
146        )
147    }
148}
149
150impl Attribute for Paint {
151    const DEFINDEX: u32 = 142;
152    const USES_FLOAT_VALUE: bool = true;
153    /// Represents the "set_item_tint_rgb" attribute.
154    const ATTRIBUTE: AttributeDef = AttributeDef {
155        defindex: 142,
156        name: "set item tint RGB",
157        attribute_class: Some("set_item_tint_rgb"),
158        description_string: Some("Item tint color code: %s1"),
159        description_format: Some(DescriptionFormat::ValueIsAdditive),
160        effect_type: EffectType::Neutral,
161        hidden: true,
162        stored_as_integer: false,
163    };
164    
165    /// Gets the attribute float value.
166    fn attribute_float_value(&self) -> Option<f32> {
167        Some((*self as u32) as f32)
168    }
169}
170
171impl TryFromIntAttributeValue for Paint {}
172
173impl From<Paint> for ItemAttribute {
174    fn from(val: Paint) -> Self {
175        ItemAttribute {
176            defindex: Paint::DEFINDEX,
177            value: val.attribute_value(),
178            float_value: val.attribute_float_value(),
179        }
180    }
181}
182
183impl Colored for Paint {
184    /// Gets the color of the [`Paint`].
185    fn color(&self) -> u32 {
186        u32::from(*self)
187    }
188    
189    /// Converts a hexadecimal color into a [`Paint`].
190    /// 
191    /// # Examples
192    /// ```
193    /// use tf2_enum::{Paint, Colored};
194    /// 
195    /// assert_eq!(Paint::from_color(0x7D4071).unwrap(), Paint::ADeepCommitmentToPurple);
196    /// ```
197    fn from_color(color: u32) -> Option<Self> {
198        Self::try_from(color).ok()
199    }
200}
201
202impl HasItemDefindex for Paint {
203    /// Gets the `defindex` related to this [`Paint`].
204    fn defindex(&self) -> u32 {
205        match self {
206            Self::AColorSimilarToSlate => 5052,
207            Self::ADeepCommitmentToPurple => 5031,
208            Self::ADistinctiveLackOfHue => 5040,
209            Self::AMannsMint => 5076,
210            Self::AfterEight => 5077,
211            Self::AgedMoustacheGrey => 5038,
212            Self::AnExtraordinaryAbundanceOfTinge => 5039,
213            Self::AustraliumGold => 5037,
214            Self::ColorNo216190216 => 5030,
215            Self::DarkSalmonInjustice => 5056,
216            Self::DrablyOlive => 5053,
217            Self::IndubitablyGreen => 5027,
218            Self::MannCoOrange => 5032,
219            Self::Muskelmannbraun => 5033,
220            Self::NobleHattersViolet => 5029,
221            Self::PeculiarlyDrabTincture => 5034,
222            Self::PinkAsHell => 5051,
223            Self::RadiganConagherBrown => 5035,
224            Self::TheBitterTasteOfDefeatAndLime => 5054,
225            Self::TheColorOfAGentlemannsBusinessPants => 5055,
226            Self::YeOldeRusticColour => 5036,
227            Self::ZepheniahsGreed => 5028,
228            Self::AnAirOfDebonair => 5063,
229            Self::BalaclavasAreForever => 5062,
230            Self::CreamSpirit => 5065,
231            Self::OperatorsOveralls => 5060,
232            Self::TeamSpirit => 5046,
233            Self::TheValueOfTeamwork => 5064,
234            Self::WaterloggedLabCoat => 5061,
235        }
236    }
237    
238    /// Converts a `defindex` into its related [`Paint`], if it exists.
239    fn from_defindex(defindex: u32) -> Option<Self> {
240        match defindex {
241            5052 => Some(Self::AColorSimilarToSlate),
242            5031 => Some(Self::ADeepCommitmentToPurple),
243            5040 => Some(Self::ADistinctiveLackOfHue),
244            5076 => Some(Self::AMannsMint),
245            5077 => Some(Self::AfterEight),
246            5038 => Some(Self::AgedMoustacheGrey),
247            5039 => Some(Self::AnExtraordinaryAbundanceOfTinge),
248            5037 => Some(Self::AustraliumGold),
249            5030 => Some(Self::ColorNo216190216),
250            5056 => Some(Self::DarkSalmonInjustice),
251            5053 => Some(Self::DrablyOlive),
252            5027 => Some(Self::IndubitablyGreen),
253            5032 => Some(Self::MannCoOrange),
254            5033 => Some(Self::Muskelmannbraun),
255            5029 => Some(Self::NobleHattersViolet),
256            5034 => Some(Self::PeculiarlyDrabTincture),
257            5051 => Some(Self::PinkAsHell),
258            5035 => Some(Self::RadiganConagherBrown),
259            5054 => Some(Self::TheBitterTasteOfDefeatAndLime),
260            5055 => Some(Self::TheColorOfAGentlemannsBusinessPants),
261            5036 => Some(Self::YeOldeRusticColour),
262            5028 => Some(Self::ZepheniahsGreed),
263            5063 => Some(Self::AnAirOfDebonair),
264            5062 => Some(Self::BalaclavasAreForever),
265            5065 => Some(Self::CreamSpirit),
266            5060 => Some(Self::OperatorsOveralls),
267            5046 => Some(Self::TeamSpirit),
268            5064 => Some(Self::TheValueOfTeamwork),
269            5061 => Some(Self::WaterloggedLabCoat),
270            _ => None,
271        }
272    }
273}
274
275#[cfg(test)]
276mod tests {
277    use super::*;
278    
279    #[test]
280    fn string_conversions() {
281        assert_eq!(Paint::AColorSimilarToSlate.to_string(), "A Color Similar to Slate");
282        assert_eq!(Paint::ADeepCommitmentToPurple.to_string(), "A Deep Commitment to Purple");
283    }
284    
285    #[test]
286    fn converts_to_primitive() {
287        assert_eq!(16738740_u32, Paint::PinkAsHell as u32);
288    }
289    
290    #[test]
291    fn gets_defindex() {
292        assert_eq!(5051_u32, Paint::PinkAsHell.defindex());
293    }
294    
295    #[test]
296    fn displays_as_string() {
297        assert_eq!("Pink as Hell", &format!("{}", Paint::PinkAsHell));
298    }
299    
300    #[test]
301    fn converts_to_hex() {
302        assert_eq!(0xFF69B4, Paint::PinkAsHell.color());
303    }
304    
305    #[test]
306    fn converts_from_hex_str() {
307        assert_eq!(Paint::from_color_str("FF69B4").unwrap(), Paint::PinkAsHell);
308    }
309    
310    #[test]
311    fn converts_from_hex_str_lowercase() {
312        assert_eq!(Paint::from_color_str("ff69b4").unwrap(), Paint::PinkAsHell);
313    }
314    
315    #[test]
316    fn converts_from_hex_str_lowercase_with_pound() {
317        assert_eq!(Paint::from_color_str("#FF69B4").unwrap(), Paint::PinkAsHell);
318    }
319}