pso2packetlib/protocol/models/
item_attrs.rs

1//! Item attribute related structures.
2use super::character::ClassFlags;
3use crate::{
4    fixed_types::{FixedBytes, FixedVec, VecUSize},
5    protocol::{HelperReadWrite, PacketError, PacketType},
6};
7use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
8
9/// Item attributes found in the `item_parameter.bin` file in the ICE archive from
10/// [`crate::protocol::Packet::LoadItemAttributes`].
11#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
12#[derive(Debug, Clone, PartialEq)]
13pub enum ItemAttributes {
14    /// NA and JP client version.
15    PC(ItemAttributesPC),
16    /// Vita client version.
17    Vita(ItemAttributesVita),
18}
19
20/// Item attributes found in the `item_parameter.bin` file in the ICE archive from
21/// [`crate::protocol::Packet::LoadItemAttributes`] (NA and JP client).
22#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
23#[cfg_attr(feature = "serde", serde(default))]
24#[derive(Debug, Default, Clone, PartialEq, HelperReadWrite)]
25pub struct ItemAttributesPC {
26    pub unk1: u32,
27    pub unk2: u128,
28    /// Attributes for weapons.
29    pub weapons: VecUSize<u16, WeaponAttrs>,
30    /// Attributes for costumes.
31    pub human_costumes: VecUSize<u16, HumanCostume>,
32    /// Attributes for CAST parts.
33    pub cast_parts: VecUSize<u16, CastPart>,
34    /// Attributes for consumables.
35    pub consumables: VecUSize<u16, Consumable>,
36    pub data5: VecUSize<u16, Data5>,
37    /// Attributes for units.
38    pub data6: VecUSize<u16, Unit>,
39    pub data7: VecUSize<u16, Data7>,
40    pub data8: VecUSize<u16, Data8>,
41    pub data9: VecUSize<u16, Data9>,
42    pub data10: VecUSize<u16, Data10>,
43    pub data11: VecUSize<u16, Data11>,
44    pub data12: VecUSize<u16, Data12>,
45    pub data13: VecUSize<u16, Data13>,
46    pub data14: VecUSize<u16, Data14>,
47    pub data15: VecUSize<u16, Data15>,
48    pub data16: VecUSize<u16, Data16>,
49    pub data17: VecUSize<u16, Data17>,
50    pub data18: FixedVec<406, ShortData>,
51    pub data19: VecUSize<u16, Data19>,
52    pub data20: VecUSize<u16, Data20>,
53}
54
55/// Item attributes found in the `item_parameter.bin` file in the ICE archive from
56/// [`crate::protocol::Packet::LoadItemAttributes`] (Vita client).
57#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
58#[cfg_attr(feature = "serde", serde(default))]
59#[derive(Debug, Default, Clone, PartialEq, HelperReadWrite)]
60pub struct ItemAttributesVita {
61    pub unk1: u32,
62    pub unk2: u128,
63    /// Attributes for weapons.
64    pub weapons: VecUSize<u16, WeaponAttrs>,
65    /// Attributes for costumes.
66    pub human_costumes: VecUSize<u16, HumanCostume>,
67    /// Attributes for CAST parts.
68    pub cast_parts: VecUSize<u16, CastPart>,
69    /// Attributes for consumables.
70    pub consumables: VecUSize<u16, Consumable>,
71    pub data5: VecUSize<u16, Data5>,
72    /// Attributes for units.
73    pub data6: VecUSize<u16, Unit>,
74    pub data7: VecUSize<u16, Data7>,
75    pub data8: VecUSize<u16, Data8>,
76    pub data9: VecUSize<u16, Data9>,
77    pub data10: VecUSize<u16, Data10>,
78    pub data11: VecUSize<u16, Data11>,
79    pub data12: VecUSize<u16, Data12>,
80    pub data13: VecUSize<u16, Data13>,
81    pub data14: VecUSize<u16, Data14>,
82    pub data15: VecUSize<u16, Data15>,
83    pub data16: VecUSize<u16, Data16>,
84    pub data17: VecUSize<u16, Data17>,
85    // #[FixedLen(46)] // inside game files
86    pub data18: FixedVec<406, ShortData>,
87    pub data19: VecUSize<u16, Data19Vita>,
88    pub data20: VecUSize<u16, Data20>,
89}
90
91/// Weapon attributes.
92#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
93#[cfg_attr(feature = "serde", serde(default))]
94#[derive(Debug, Default, Clone, PartialEq, HelperReadWrite)]
95pub struct WeaponAttrs {
96    /// Item category.
97    pub id: u16,
98    /// Item ID.
99    pub subid: u16,
100    pub unk1: u8,
101    pub priority: u8,
102    pub unk2: u8,
103    pub priority2: u8,
104    /// Item rarity in stars.
105    pub rarity: u8,
106    pub flags: u16,
107    pub unk3: u8,
108    pub icon_list: u16,
109    pub icon_index: u16,
110    /// Range damage.
111    pub range_dmg: u16,
112    pub unk4: u8,
113    /// Melee damage.
114    pub melee_dmg: u16,
115    pub unk5: u8,
116    pub unk6: u32,
117    /// Force damage and equipable genders.
118    #[cfg_attr(feature = "serde", serde(flatten))]
119    pub gender_force_dmg: GenderDmg,
120    pub unk8: [u8; 4],
121    /// Equipable races.
122    pub race: RaceFlags,
123    pub flags2: u8,
124    /// Equipable classes.
125    pub class: ClassFlags,
126    /// Required stat value.
127    pub req_stat: u16,
128    /// Required stat type.
129    pub req_stat_type: StatType,
130    pub unk9: u8,
131    pub model: u16,
132    pub unk10: u32,
133    pub unk11: u16,
134    pub affix_flag: u16,
135    pub unk12: u16,
136}
137
138/// Costume attributes.
139#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
140#[cfg_attr(feature = "serde", serde(default))]
141#[derive(Debug, Default, Clone, PartialEq, HelperReadWrite)]
142pub struct HumanCostume {
143    /// Item category.
144    pub id: u16,
145    /// Item ID.
146    pub subid: u16,
147    pub unk1: u16,
148    pub unk2: u16,
149    /// Item rarity in stars.
150    pub rarity: u8,
151    pub flags: u16,
152    pub unk3: u8,
153    pub icon_list: u16,
154    pub icon_index: u16,
155    /// Equipable genders.
156    pub gender_flags: GenderFlags,
157    pub color_flags: u8,
158    /// Equipable races.
159    pub race_flags: RaceFlags,
160    pub unk4: u8,
161    pub model: u16,
162    pub unk5: [u16; 3],
163}
164
165/// CAST part attributes.
166#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
167#[cfg_attr(feature = "serde", serde(default))]
168#[derive(Debug, Default, Clone, PartialEq, HelperReadWrite)]
169pub struct CastPart {
170    /// Item category.
171    pub id: u16,
172    /// Item ID.
173    pub subid: u16,
174    pub unk1: u16,
175    pub unk2: u16,
176    /// Item rarity in stars.
177    pub rarity: u8,
178    pub flags: u16,
179    pub unk3: u8,
180    pub icon_list: u16,
181    pub icon_index: u16,
182    pub gender_flags: u8,
183    pub unk4: u8,
184    pub race_flags: u8,
185    pub unk5: u8,
186    pub unk6: u16,
187    pub model: u16,
188}
189
190/// Consumable attributes.
191#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
192#[cfg_attr(feature = "serde", serde(default))]
193#[derive(Debug, Default, Clone, PartialEq, HelperReadWrite)]
194pub struct Consumable {
195    /// Item category.
196    pub id: u16,
197    /// Item ID.
198    pub subid: u16,
199    pub unk1: u16,
200    pub unk2: u16,
201    /// Item rarity in stars.
202    pub rarity: u8,
203    pub flags: u16,
204    pub unk3: u8,
205    pub icon_list: u16,
206    pub icon_index: u16,
207    /// Max item quantity.
208    pub max_qty: u8,
209    pub unk4: [u8; 3],
210    pub unk5: u32,
211}
212
213#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
214#[cfg_attr(feature = "serde", serde(default))]
215#[derive(Debug, Default, Clone, PartialEq, HelperReadWrite)]
216pub struct Data5 {
217    pub id: u16,
218    pub subid: u16,
219    pub unk1: u16,
220    pub unk2: u16,
221    pub unk6: u8,
222    pub unk3: u8,
223    pub unk4: u8,
224    pub unk5: u8,
225    pub icon_list: u16,
226    pub icon_index: u16,
227    pub unk: FixedBytes<0x30>,
228}
229
230/// Unit attributes.
231#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
232#[cfg_attr(feature = "serde", serde(default))]
233#[derive(Debug, Default, Clone, PartialEq, HelperReadWrite)]
234pub struct Unit {
235    /// Item category.
236    pub id: u16,
237    /// Item ID.
238    pub subid: u16,
239    pub unk1: u16,
240    pub unk2: u16,
241    /// Item rarity in stars.
242    pub rarity: u8,
243    pub flags: u16,
244    pub unk3: u8,
245    pub icon_list: u16,
246    pub icon_index: u16,
247    /// Unit stats.
248    #[cfg_attr(feature = "serde", serde(flatten))]
249    pub stats: UnitRes,
250    /// Required stat type.
251    pub req_stat_type: StatType,
252    pub unk4: u8,
253    pub unk5: u8,
254    pub unk6: u16,
255    pub unk7: u16,
256    pub unk8: u16,
257    pub unk9: u16,
258    /// Required stat value.
259    pub req_stat: u16,
260    /// Unit attack values.
261    #[cfg_attr(feature = "serde", serde(flatten))]
262    pub atk: UnitAtk,
263    pub unk10: u8,
264    pub unk11: u8,
265    pub unk12: u8,
266    pub unk13: u16,
267    pub unk14: u32,
268    pub unk15: u32,
269}
270
271#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
272#[cfg_attr(feature = "serde", serde(default))]
273#[derive(Debug, Default, Clone, PartialEq, HelperReadWrite)]
274pub struct Data7 {
275    pub unk: FixedBytes<0x38>,
276}
277
278#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
279#[cfg_attr(feature = "serde", serde(default))]
280#[derive(Debug, Default, Clone, PartialEq, HelperReadWrite)]
281pub struct Data8 {
282    pub unk: FixedBytes<0x10>,
283}
284
285#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
286#[cfg_attr(feature = "serde", serde(default))]
287#[derive(Debug, Default, Clone, PartialEq, HelperReadWrite)]
288pub struct Data9 {
289    pub unk: FixedBytes<0x3C>,
290}
291
292#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
293#[cfg_attr(feature = "serde", serde(default))]
294#[derive(Debug, Default, Clone, PartialEq, HelperReadWrite)]
295pub struct Data10 {
296    pub unk: FixedBytes<0x24>,
297}
298
299#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
300#[cfg_attr(feature = "serde", serde(default))]
301#[derive(Debug, Default, Clone, PartialEq, HelperReadWrite)]
302pub struct Data11 {
303    pub unk: FixedBytes<0x10>,
304}
305
306#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
307#[cfg_attr(feature = "serde", serde(default))]
308#[derive(Debug, Default, Clone, PartialEq, HelperReadWrite)]
309pub struct Data12 {
310    pub unk: FixedBytes<0x24>,
311}
312
313#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
314#[cfg_attr(feature = "serde", serde(default))]
315#[derive(Debug, Default, Clone, PartialEq, HelperReadWrite)]
316pub struct Data13 {
317    pub unk: FixedBytes<0x50>,
318}
319
320#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
321#[cfg_attr(feature = "serde", serde(default))]
322#[derive(Debug, Default, Clone, PartialEq, HelperReadWrite)]
323pub struct Data14 {
324    pub unk: FixedBytes<0x7C>,
325}
326
327#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
328#[cfg_attr(feature = "serde", serde(default))]
329#[derive(Debug, Default, Clone, PartialEq, HelperReadWrite)]
330pub struct Data15 {
331    pub unk: FixedBytes<0x10>,
332}
333
334#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
335#[cfg_attr(feature = "serde", serde(default))]
336#[derive(Debug, Default, Clone, PartialEq, HelperReadWrite)]
337pub struct Data16 {
338    pub unk: FixedBytes<0x12, true>,
339}
340
341#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
342#[cfg_attr(feature = "serde", serde(default))]
343#[derive(Debug, Default, Clone, PartialEq, HelperReadWrite)]
344pub struct Data17 {
345    pub unk: FixedBytes<0x5A, true>,
346}
347
348#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
349#[cfg_attr(feature = "serde", serde(default))]
350#[derive(Debug, Default, Clone, PartialEq, HelperReadWrite)]
351pub struct Data18 {
352    pub unk: FixedBytes<0x8>,
353}
354
355#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
356#[cfg_attr(feature = "serde", serde(default))]
357#[derive(Debug, Clone, PartialEq, HelperReadWrite)]
358pub struct ShortData {
359    pub unk: VecUSize<u16, Data18>,
360}
361
362#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
363#[cfg_attr(feature = "serde", serde(default))]
364#[derive(Debug, Default, Clone, PartialEq, HelperReadWrite)]
365pub struct Data19 {
366    pub unk: FixedBytes<0x54>, //sent by jp server + used by pc
367}
368
369#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
370#[cfg_attr(feature = "serde", serde(default))]
371#[derive(Debug, Default, Clone, PartialEq, HelperReadWrite)]
372pub struct Data19Vita {
373    pub unk: FixedBytes<0x2C>, //inside na/vita client + used by vita
374}
375
376#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
377#[cfg_attr(feature = "serde", serde(default))]
378#[derive(Debug, Default, Clone, PartialEq, HelperReadWrite)]
379pub struct Data20 {
380    pub unk: FixedBytes<0x1C>,
381}
382
383/// Force damage and equipable genders.
384#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
385#[cfg_attr(feature = "serde", serde(default))]
386#[derive(Debug, Default, Clone, PartialEq)]
387pub struct GenderDmg {
388    /// Force damage.
389    pub force_dmg: u16,
390    /// Equipable genders.
391    pub gender: GenderFlags,
392}
393
394/// Unit stats.
395#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
396#[cfg_attr(feature = "serde", serde(default))]
397#[derive(Debug, Default, Clone, PartialEq)]
398pub struct UnitRes {
399    /// TEC resistance.
400    pub tec_res: u8,
401    /// TEC defence.
402    pub tec_def: u16,
403    /// RNG defence.
404    pub rng_def: u16,
405    /// MEL defence.
406    pub mel_def: u16,
407    /// Additional HP.
408    pub hp: u16,
409    /// Additional PP.
410    pub pp: u8,
411    /// Dark resistance.
412    pub dark_res: u8,
413    /// Light resistance.
414    pub light_res: u8,
415    /// Wind resistance.
416    pub wind_res: u8,
417    /// Lightning resistance.
418    pub lightning_res: u8,
419    /// Ice resistance.
420    pub ice_res: u8,
421    /// Fire resistance.
422    pub fire_res: u8,
423    /// RNG resistance.
424    pub rng_res: u8,
425    /// MEL resistance.
426    pub mel_res: u8,
427}
428
429/// Unit attack values.
430#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
431#[cfg_attr(feature = "serde", serde(default))]
432#[derive(Debug, Default, Clone, PartialEq)]
433pub struct UnitAtk {
434    /// Additional MEL attack.
435    pub mel_atk: u16,
436    /// Additional RNG attack.
437    pub rng_atk: u16,
438    /// Additional TEC attack.
439    pub tec_atk: u16,
440    /// Additional DEX.
441    pub dex: u16,
442    pub unk_atk: u8,
443}
444
445bitflags::bitflags! {
446    /// Equipable genders.
447    #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
448    #[cfg_attr(feature = "serde", serde(default))]
449    #[derive(Debug, Default, Clone, PartialEq, HelperReadWrite)]
450    #[BitFlags(u8)]
451    pub struct GenderFlags: u8 {
452        /// Males can equip.
453        const MALE = 1 << 0;
454        /// Females can equip.
455        const FEMALE = 1 << 1;
456    }
457}
458
459bitflags::bitflags! {
460    /// Equipable races.
461    #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
462    #[cfg_attr(feature = "serde", serde(default))]
463    #[derive(Debug, Default, Clone, PartialEq, HelperReadWrite)]
464    #[BitFlags(u8)]
465    pub struct RaceFlags: u8 {
466        /// Humans can equip.
467        const HUMAN = 1 << 0;
468        /// Newmans can equip.
469        const NEWMAN = 1 << 1;
470        /// CASTs can equip.
471        const CAST = 1 << 2;
472        /// Deumans can equip.
473        const DEUMAN = 1 << 3;
474    }
475}
476
477/// Required stat type.
478#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
479#[derive(Debug, Default, Clone, Copy, PartialEq, HelperReadWrite)]
480#[repr(u8)]
481pub enum StatType {
482    /// MEL power.
483    #[default]
484    #[Read_default]
485    MELPwr,
486    /// RNG power.
487    RNGPwr,
488    /// TEC power.
489    TECPwr,
490    /// DEX.
491    DEX,
492    /// MEL defence.
493    MELDef,
494    /// RNG defence.
495    RNGDef,
496    /// TEC defence.
497    TECDef,
498}
499
500// ----------------------------------------------------------------
501// Read/Write implementations
502// ----------------------------------------------------------------
503
504impl ItemAttributes {
505    pub fn read_attrs(
506        reader: &mut (impl std::io::Read + std::io::Seek),
507        packet_type: PacketType,
508    ) -> Result<Self, PacketError> {
509        match packet_type {
510            PacketType::Vita => Ok(Self::Vita(ItemAttributesVita::read(
511                reader,
512                packet_type,
513                0,
514                0,
515            )?)),
516            _ => Ok(Self::PC(ItemAttributesPC::read(reader, packet_type, 0, 0)?)),
517        }
518    }
519    pub fn write_attrs(&self, writer: &mut impl std::io::Write) -> Result<(), PacketError> {
520        match self {
521            ItemAttributes::PC(x) => x.write_attrs(writer),
522            ItemAttributes::Vita(x) => x.write_attrs(writer),
523        }
524    }
525}
526
527impl ItemAttributesPC {
528    pub fn read_attrs(
529        reader: &mut (impl std::io::Read + std::io::Seek),
530    ) -> Result<Self, PacketError> {
531        Self::read(reader, crate::protocol::PacketType::Classic, 0, 0)
532    }
533    pub fn write_attrs(&self, writer: &mut impl std::io::Write) -> Result<(), PacketError> {
534        self.write(writer, crate::protocol::PacketType::Classic, 0, 0)
535    }
536}
537
538impl ItemAttributesVita {
539    pub fn read_attrs(
540        reader: &mut (impl std::io::Read + std::io::Seek),
541    ) -> Result<Self, PacketError> {
542        Self::read(reader, crate::protocol::PacketType::Classic, 0, 0)
543    }
544    pub fn write_attrs(&self, writer: &mut impl std::io::Write) -> Result<(), PacketError> {
545        self.write(writer, crate::protocol::PacketType::Classic, 0, 0)
546    }
547}
548
549impl HelperReadWrite for GenderDmg {
550    fn read(
551        reader: &mut (impl std::io::Read + std::io::Seek),
552        pt: PacketType,
553        _: u32,
554        _: u32,
555    ) -> Result<Self, PacketError> {
556        let bits = reader
557            .read_u16::<LittleEndian>()
558            .map_err(|e| PacketError::ValueError {
559                packet_name: "GenderDmg",
560                error: e,
561            })?;
562        // 14 bits
563        let force_dmg = bits & 0x3FFF;
564        // hacky solution but it works
565        let gender_bits = (bits >> 14) as u8;
566        let mut gender_slice = std::io::Cursor::new(std::slice::from_ref(&gender_bits));
567        let gender = GenderFlags::read(&mut gender_slice, pt, 0, 0).map_err(|e| {
568            PacketError::CompositeFieldError {
569                packet_name: "GenderDmg",
570                field_name: "gender",
571                error: Box::new(e),
572            }
573        })?;
574        Ok(Self { force_dmg, gender })
575    }
576
577    fn write(
578        &self,
579        writer: &mut impl std::io::Write,
580        pt: PacketType,
581        _: u32,
582        _: u32,
583    ) -> Result<(), PacketError> {
584        let mut gender = [0u8];
585        self.gender
586            .write(&mut gender.as_mut_slice(), pt, 0, 0)
587            .map_err(|e| PacketError::CompositeFieldError {
588                packet_name: "GenderDmg",
589                field_name: "gender",
590                error: Box::new(e),
591            })?;
592
593        let mut bits = 0u16;
594        bits |= self.force_dmg & 0x3FFF;
595        bits |= (gender[0] as u16) << 14;
596        writer
597            .write_u16::<LittleEndian>(bits)
598            .map_err(|e| PacketError::ValueError {
599                packet_name: "GenderDmg",
600                error: e,
601            })?;
602        Ok(())
603    }
604}
605
606impl HelperReadWrite for UnitRes {
607    fn read(
608        reader: &mut (impl std::io::Read + std::io::Seek),
609        _: PacketType,
610        _: u32,
611        _: u32,
612    ) -> Result<Self, PacketError> {
613        let mut bytes = [0u8; 16];
614        reader
615            .read_exact(&mut bytes[..0xF])
616            .map_err(|e| PacketError::ValueError {
617                packet_name: "UnitRes",
618                error: e,
619            })?;
620        let mut bits = u128::from_le_bytes(bytes);
621        // 7 bits
622        let tec_res = (bits & 0x7F) as u8;
623        bits >>= 7;
624        // 13 bits
625        let tec_def = (bits & 0x1FFF) as u16;
626        bits >>= 13;
627        let rng_def = (bits & 0x1FFF) as u16;
628        bits >>= 13;
629        let mel_def = (bits & 0x1FFF) as u16;
630        bits >>= 13;
631        // 10 bits
632        let hp = (bits & 0x3FF) as u16;
633        bits >>= 10;
634        // 8 bits
635        let pp = (bits & 0xFF) as u8;
636        bits >>= 8;
637        // 7 bits
638        let dark_res = (bits & 0x7F) as u8;
639        bits >>= 7;
640        let light_res = (bits & 0x7F) as u8;
641        bits >>= 7;
642        let wind_res = (bits & 0x7F) as u8;
643        bits >>= 7;
644        let lightning_res = (bits & 0x7F) as u8;
645        bits >>= 7;
646        let ice_res = (bits & 0x7F) as u8;
647        bits >>= 7;
648        let fire_res = (bits & 0x7F) as u8;
649        bits >>= 7;
650        let rng_res = (bits & 0x7F) as u8;
651        bits >>= 7;
652        let mel_res = (bits & 0x7F) as u8;
653        Ok(Self {
654            tec_res,
655            tec_def,
656            rng_def,
657            mel_def,
658            hp,
659            pp,
660            dark_res,
661            light_res,
662            wind_res,
663            lightning_res,
664            ice_res,
665            fire_res,
666            rng_res,
667            mel_res,
668        })
669    }
670
671    fn write(
672        &self,
673        writer: &mut impl std::io::Write,
674        _: PacketType,
675        _: u32,
676        _: u32,
677    ) -> Result<(), PacketError> {
678        let mut bits = 0u128;
679        bits |= (self.mel_res as u128) & 0x7F;
680        bits <<= 7;
681        bits |= (self.rng_res as u128) & 0x7F;
682        bits <<= 7;
683        bits |= (self.fire_res as u128) & 0x7F;
684        bits <<= 7;
685        bits |= (self.ice_res as u128) & 0x7F;
686        bits <<= 7;
687        bits |= (self.lightning_res as u128) & 0x7F;
688        bits <<= 7;
689        bits |= (self.wind_res as u128) & 0x7F;
690        bits <<= 7;
691        bits |= (self.light_res as u128) & 0x7F;
692        bits <<= 7;
693        bits |= (self.dark_res as u128) & 0x7F;
694        bits <<= 8;
695        bits |= (self.pp as u128) & 0xFF;
696        bits <<= 10;
697        bits |= (self.hp as u128) & 0x3FF;
698        bits <<= 13;
699        bits |= (self.mel_def as u128) & 0x1FFF;
700        bits <<= 13;
701        bits |= (self.rng_def as u128) & 0x1FFF;
702        bits <<= 13;
703        bits |= (self.tec_def as u128) & 0x1FFF;
704        bits <<= 7;
705        bits |= (self.tec_res as u128) & 0x7F;
706        let bytes = bits.to_le_bytes();
707        writer
708            .write_all(&bytes[..0xF])
709            .map_err(|e| PacketError::ValueError {
710                packet_name: "UnitRes",
711                error: e,
712            })?;
713        Ok(())
714    }
715}
716
717impl HelperReadWrite for UnitAtk {
718    fn read(
719        reader: &mut (impl std::io::Read + std::io::Seek),
720        _: PacketType,
721        _: u32,
722        _: u32,
723    ) -> Result<Self, PacketError> {
724        let mut bytes = [0u8; 8];
725        reader
726            .read_exact(&mut bytes[..0x7])
727            .map_err(|e| PacketError::ValueError {
728                packet_name: "UnitAtk",
729                error: e,
730            })?;
731        let mut bits = u64::from_le_bytes(bytes);
732        // 13 bits
733        let mel_atk = (bits & 0x1FFF) as u16;
734        bits >>= 13;
735        let rng_atk = (bits & 0x1FFF) as u16;
736        bits >>= 13;
737        let tec_atk = (bits & 0x1FFF) as u16;
738        bits >>= 13;
739        let dex = (bits & 0x1FFF) as u16;
740        bits >>= 13;
741        let unk_atk = (bits & 0xF) as u8;
742        Ok(Self {
743            mel_atk,
744            rng_atk,
745            tec_atk,
746            dex,
747            unk_atk,
748        })
749    }
750
751    fn write(
752        &self,
753        writer: &mut impl std::io::Write,
754        _: PacketType,
755        _: u32,
756        _: u32,
757    ) -> Result<(), PacketError> {
758        let mut bits = 0u64;
759        bits |= (self.unk_atk as u64) & 0xF;
760        bits <<= 13;
761        bits |= (self.dex as u64) & 0x1FFF;
762        bits <<= 13;
763        bits |= (self.tec_atk as u64) & 0x1FFF;
764        bits <<= 13;
765        bits |= (self.rng_atk as u64) & 0x1FFF;
766        bits <<= 13;
767        bits |= (self.mel_atk as u64) & 0x1FFF;
768        let bytes = bits.to_le_bytes();
769        writer
770            .write_all(&bytes[..0x7])
771            .map_err(|e| PacketError::ValueError {
772                packet_name: "UnitAtk",
773                error: e,
774            })?;
775        Ok(())
776    }
777}
778
779impl Default for ShortData {
780    fn default() -> Self {
781        Self {
782            unk: vec![Default::default()].into(),
783        }
784    }
785}
786
787impl From<Data19Vita> for Data19 {
788    fn from(value: Data19Vita) -> Self {
789        Self {
790            unk: Into::<Vec<_>>::into(value.unk).into(),
791        }
792    }
793}
794
795impl From<Data19> for Data19Vita {
796    fn from(value: Data19) -> Self {
797        Self {
798            unk: Into::<Vec<_>>::into(value.unk).into(),
799        }
800    }
801}
802
803impl From<ItemAttributesPC> for ItemAttributesVita {
804    fn from(value: ItemAttributesPC) -> Self {
805        Self {
806            unk1: value.unk1,
807            unk2: value.unk2,
808            weapons: value.weapons,
809            human_costumes: value.human_costumes,
810            cast_parts: value.cast_parts,
811            consumables: value.consumables,
812            data5: value.data5,
813            data6: value.data6,
814            data7: value.data7,
815            data8: value.data8,
816            data9: value.data9,
817            data10: value.data10,
818            data11: value.data11,
819            data12: value.data12,
820            data13: value.data13,
821            data14: value.data14,
822            data15: value.data15,
823            data16: value.data16,
824            data17: value.data17,
825            data18: value.data18,
826            data19: Into::<Vec<_>>::into(value.data19)
827                .into_iter()
828                .map(|x| x.into())
829                .collect::<Vec<_>>()
830                .into(),
831            data20: value.data20,
832        }
833    }
834}
835
836impl From<ItemAttributesVita> for ItemAttributesPC {
837    fn from(value: ItemAttributesVita) -> Self {
838        Self {
839            unk1: value.unk1,
840            unk2: value.unk2,
841            weapons: value.weapons,
842            human_costumes: value.human_costumes,
843            cast_parts: value.cast_parts,
844            consumables: value.consumables,
845            data5: value.data5,
846            data6: value.data6,
847            data7: value.data7,
848            data8: value.data8,
849            data9: value.data9,
850            data10: value.data10,
851            data11: value.data11,
852            data12: value.data12,
853            data13: value.data13,
854            data14: value.data14,
855            data15: value.data15,
856            data16: value.data16,
857            data17: value.data17,
858            data18: value.data18,
859            data19: Into::<Vec<_>>::into(value.data19)
860                .into_iter()
861                .map(|x| x.into())
862                .collect::<Vec<_>>()
863                .into(),
864            data20: value.data20,
865        }
866    }
867}
868
869impl From<ItemAttributes> for ItemAttributesPC {
870    fn from(value: ItemAttributes) -> Self {
871        match value {
872            ItemAttributes::PC(x) => x,
873            ItemAttributes::Vita(x) => x.into(),
874        }
875    }
876}
877
878impl From<ItemAttributesPC> for ItemAttributes {
879    fn from(value: ItemAttributesPC) -> Self {
880        Self::PC(value)
881    }
882}
883
884impl From<ItemAttributes> for ItemAttributesVita {
885    fn from(value: ItemAttributes) -> Self {
886        match value {
887            ItemAttributes::PC(x) => x.into(),
888            ItemAttributes::Vita(x) => x,
889        }
890    }
891}
892
893impl From<ItemAttributesVita> for ItemAttributes {
894    fn from(value: ItemAttributesVita) -> Self {
895        Self::Vita(value)
896    }
897}