wow_dbc/wrath_tables/
creature_sound_data.rs

1use crate::{
2    DbcTable, Indexable,
3};
4use crate::header::{
5    DbcHeader, HEADER_SIZE, parse_header,
6};
7use crate::wrath_tables::footstep_terrain_lookup::FootstepTerrainLookupKey;
8use crate::wrath_tables::sound_entries::SoundEntriesKey;
9use std::io::Write;
10
11#[derive(Debug, Clone, PartialEq, PartialOrd)]
12pub struct CreatureSoundData {
13    pub rows: Vec<CreatureSoundDataRow>,
14}
15
16impl DbcTable for CreatureSoundData {
17    type Row = CreatureSoundDataRow;
18
19    const FILENAME: &'static str = "CreatureSoundData.dbc";
20
21    fn rows(&self) -> &[Self::Row] { &self.rows }
22    fn rows_mut(&mut self) -> &mut [Self::Row] { &mut self.rows }
23
24    fn read(b: &mut impl std::io::Read) -> Result<Self, crate::DbcError> {
25        let mut header = [0_u8; HEADER_SIZE];
26        b.read_exact(&mut header)?;
27        let header = parse_header(&header)?;
28
29        if header.record_size != 152 {
30            return Err(crate::DbcError::InvalidHeader(
31                crate::InvalidHeaderError::RecordSize {
32                    expected: 152,
33                    actual: header.record_size,
34                },
35            ));
36        }
37
38        if header.field_count != 38 {
39            return Err(crate::DbcError::InvalidHeader(
40                crate::InvalidHeaderError::FieldCount {
41                    expected: 38,
42                    actual: header.field_count,
43                },
44            ));
45        }
46
47        let mut r = vec![0_u8; (header.record_count * header.record_size) as usize];
48        b.read_exact(&mut r)?;
49
50        let mut rows = Vec::with_capacity(header.record_count as usize);
51
52        for mut chunk in r.chunks(header.record_size as usize) {
53            let chunk = &mut chunk;
54
55            // id: primary_key (CreatureSoundData) int32
56            let id = CreatureSoundDataKey::new(crate::util::read_i32_le(chunk)?);
57
58            // sound_exertion_id: foreign_key (SoundEntries) int32
59            let sound_exertion_id = SoundEntriesKey::new(crate::util::read_i32_le(chunk)?.into());
60
61            // sound_exertion_critical_id: foreign_key (SoundEntries) int32
62            let sound_exertion_critical_id = SoundEntriesKey::new(crate::util::read_i32_le(chunk)?.into());
63
64            // sound_injury_id: foreign_key (SoundEntries) int32
65            let sound_injury_id = SoundEntriesKey::new(crate::util::read_i32_le(chunk)?.into());
66
67            // sound_injury_critical_id: foreign_key (SoundEntries) int32
68            let sound_injury_critical_id = SoundEntriesKey::new(crate::util::read_i32_le(chunk)?.into());
69
70            // sound_injury_crushing_blow_id: int32
71            let sound_injury_crushing_blow_id = crate::util::read_i32_le(chunk)?;
72
73            // sound_death_id: foreign_key (SoundEntries) int32
74            let sound_death_id = SoundEntriesKey::new(crate::util::read_i32_le(chunk)?.into());
75
76            // sound_stun_id: foreign_key (SoundEntries) int32
77            let sound_stun_id = SoundEntriesKey::new(crate::util::read_i32_le(chunk)?.into());
78
79            // sound_stand_id: foreign_key (SoundEntries) int32
80            let sound_stand_id = SoundEntriesKey::new(crate::util::read_i32_le(chunk)?.into());
81
82            // sound_footstep_id: foreign_key (FootstepTerrainLookup) int32
83            let sound_footstep_id = FootstepTerrainLookupKey::new(crate::util::read_i32_le(chunk)?.into());
84
85            // sound_aggro_id: foreign_key (SoundEntries) int32
86            let sound_aggro_id = SoundEntriesKey::new(crate::util::read_i32_le(chunk)?.into());
87
88            // sound_wing_flap_id: foreign_key (SoundEntries) int32
89            let sound_wing_flap_id = SoundEntriesKey::new(crate::util::read_i32_le(chunk)?.into());
90
91            // sound_wing_glide_id: foreign_key (SoundEntries) int32
92            let sound_wing_glide_id = SoundEntriesKey::new(crate::util::read_i32_le(chunk)?.into());
93
94            // sound_alert_id: foreign_key (SoundEntries) int32
95            let sound_alert_id = SoundEntriesKey::new(crate::util::read_i32_le(chunk)?.into());
96
97            // sound_fidget: int32[5]
98            let sound_fidget = crate::util::read_array_i32::<5>(chunk)?;
99
100            // custom_attack: int32[4]
101            let custom_attack = crate::util::read_array_i32::<4>(chunk)?;
102
103            // n_p_c_sound_id: int32
104            let n_p_c_sound_id = crate::util::read_i32_le(chunk)?;
105
106            // loop_sound_id: foreign_key (SoundEntries) int32
107            let loop_sound_id = SoundEntriesKey::new(crate::util::read_i32_le(chunk)?.into());
108
109            // creature_impact_type: int32
110            let creature_impact_type = crate::util::read_i32_le(chunk)?;
111
112            // sound_jump_start_id: foreign_key (SoundEntries) int32
113            let sound_jump_start_id = SoundEntriesKey::new(crate::util::read_i32_le(chunk)?.into());
114
115            // sound_jump_end_id: foreign_key (SoundEntries) int32
116            let sound_jump_end_id = SoundEntriesKey::new(crate::util::read_i32_le(chunk)?.into());
117
118            // sound_pet_attack_id: foreign_key (SoundEntries) int32
119            let sound_pet_attack_id = SoundEntriesKey::new(crate::util::read_i32_le(chunk)?.into());
120
121            // sound_pet_order_id: foreign_key (SoundEntries) int32
122            let sound_pet_order_id = SoundEntriesKey::new(crate::util::read_i32_le(chunk)?.into());
123
124            // sound_pet_dismiss_id: foreign_key (SoundEntries) int32
125            let sound_pet_dismiss_id = SoundEntriesKey::new(crate::util::read_i32_le(chunk)?.into());
126
127            // fidget_delay_seconds_min: float
128            let fidget_delay_seconds_min = crate::util::read_f32_le(chunk)?;
129
130            // fidget_delay_seconds_max: float
131            let fidget_delay_seconds_max = crate::util::read_f32_le(chunk)?;
132
133            // birth_sound_id: foreign_key (SoundEntries) int32
134            let birth_sound_id = SoundEntriesKey::new(crate::util::read_i32_le(chunk)?.into());
135
136            // spell_cast_directed_sound_id: foreign_key (SoundEntries) int32
137            let spell_cast_directed_sound_id = SoundEntriesKey::new(crate::util::read_i32_le(chunk)?.into());
138
139            // submerge_sound_id: foreign_key (SoundEntries) int32
140            let submerge_sound_id = SoundEntriesKey::new(crate::util::read_i32_le(chunk)?.into());
141
142            // submerged_sound_id: foreign_key (SoundEntries) int32
143            let submerged_sound_id = SoundEntriesKey::new(crate::util::read_i32_le(chunk)?.into());
144
145            // creature_sound_data_id_pet: foreign_key (CreatureSoundData) int32
146            let creature_sound_data_id_pet = CreatureSoundDataKey::new(crate::util::read_i32_le(chunk)?.into());
147
148
149            rows.push(CreatureSoundDataRow {
150                id,
151                sound_exertion_id,
152                sound_exertion_critical_id,
153                sound_injury_id,
154                sound_injury_critical_id,
155                sound_injury_crushing_blow_id,
156                sound_death_id,
157                sound_stun_id,
158                sound_stand_id,
159                sound_footstep_id,
160                sound_aggro_id,
161                sound_wing_flap_id,
162                sound_wing_glide_id,
163                sound_alert_id,
164                sound_fidget,
165                custom_attack,
166                n_p_c_sound_id,
167                loop_sound_id,
168                creature_impact_type,
169                sound_jump_start_id,
170                sound_jump_end_id,
171                sound_pet_attack_id,
172                sound_pet_order_id,
173                sound_pet_dismiss_id,
174                fidget_delay_seconds_min,
175                fidget_delay_seconds_max,
176                birth_sound_id,
177                spell_cast_directed_sound_id,
178                submerge_sound_id,
179                submerged_sound_id,
180                creature_sound_data_id_pet,
181            });
182        }
183
184        Ok(CreatureSoundData { rows, })
185    }
186
187    fn write(&self, b: &mut impl Write) -> Result<(), std::io::Error> {
188        let header = DbcHeader {
189            record_count: self.rows.len() as u32,
190            field_count: 38,
191            record_size: 152,
192            string_block_size: 1,
193        };
194
195        b.write_all(&header.write_header())?;
196
197        for row in &self.rows {
198            // id: primary_key (CreatureSoundData) int32
199            b.write_all(&row.id.id.to_le_bytes())?;
200
201            // sound_exertion_id: foreign_key (SoundEntries) int32
202            b.write_all(&(row.sound_exertion_id.id as i32).to_le_bytes())?;
203
204            // sound_exertion_critical_id: foreign_key (SoundEntries) int32
205            b.write_all(&(row.sound_exertion_critical_id.id as i32).to_le_bytes())?;
206
207            // sound_injury_id: foreign_key (SoundEntries) int32
208            b.write_all(&(row.sound_injury_id.id as i32).to_le_bytes())?;
209
210            // sound_injury_critical_id: foreign_key (SoundEntries) int32
211            b.write_all(&(row.sound_injury_critical_id.id as i32).to_le_bytes())?;
212
213            // sound_injury_crushing_blow_id: int32
214            b.write_all(&row.sound_injury_crushing_blow_id.to_le_bytes())?;
215
216            // sound_death_id: foreign_key (SoundEntries) int32
217            b.write_all(&(row.sound_death_id.id as i32).to_le_bytes())?;
218
219            // sound_stun_id: foreign_key (SoundEntries) int32
220            b.write_all(&(row.sound_stun_id.id as i32).to_le_bytes())?;
221
222            // sound_stand_id: foreign_key (SoundEntries) int32
223            b.write_all(&(row.sound_stand_id.id as i32).to_le_bytes())?;
224
225            // sound_footstep_id: foreign_key (FootstepTerrainLookup) int32
226            b.write_all(&(row.sound_footstep_id.id as i32).to_le_bytes())?;
227
228            // sound_aggro_id: foreign_key (SoundEntries) int32
229            b.write_all(&(row.sound_aggro_id.id as i32).to_le_bytes())?;
230
231            // sound_wing_flap_id: foreign_key (SoundEntries) int32
232            b.write_all(&(row.sound_wing_flap_id.id as i32).to_le_bytes())?;
233
234            // sound_wing_glide_id: foreign_key (SoundEntries) int32
235            b.write_all(&(row.sound_wing_glide_id.id as i32).to_le_bytes())?;
236
237            // sound_alert_id: foreign_key (SoundEntries) int32
238            b.write_all(&(row.sound_alert_id.id as i32).to_le_bytes())?;
239
240            // sound_fidget: int32[5]
241            for i in row.sound_fidget {
242                b.write_all(&i.to_le_bytes())?;
243            }
244
245
246            // custom_attack: int32[4]
247            for i in row.custom_attack {
248                b.write_all(&i.to_le_bytes())?;
249            }
250
251
252            // n_p_c_sound_id: int32
253            b.write_all(&row.n_p_c_sound_id.to_le_bytes())?;
254
255            // loop_sound_id: foreign_key (SoundEntries) int32
256            b.write_all(&(row.loop_sound_id.id as i32).to_le_bytes())?;
257
258            // creature_impact_type: int32
259            b.write_all(&row.creature_impact_type.to_le_bytes())?;
260
261            // sound_jump_start_id: foreign_key (SoundEntries) int32
262            b.write_all(&(row.sound_jump_start_id.id as i32).to_le_bytes())?;
263
264            // sound_jump_end_id: foreign_key (SoundEntries) int32
265            b.write_all(&(row.sound_jump_end_id.id as i32).to_le_bytes())?;
266
267            // sound_pet_attack_id: foreign_key (SoundEntries) int32
268            b.write_all(&(row.sound_pet_attack_id.id as i32).to_le_bytes())?;
269
270            // sound_pet_order_id: foreign_key (SoundEntries) int32
271            b.write_all(&(row.sound_pet_order_id.id as i32).to_le_bytes())?;
272
273            // sound_pet_dismiss_id: foreign_key (SoundEntries) int32
274            b.write_all(&(row.sound_pet_dismiss_id.id as i32).to_le_bytes())?;
275
276            // fidget_delay_seconds_min: float
277            b.write_all(&row.fidget_delay_seconds_min.to_le_bytes())?;
278
279            // fidget_delay_seconds_max: float
280            b.write_all(&row.fidget_delay_seconds_max.to_le_bytes())?;
281
282            // birth_sound_id: foreign_key (SoundEntries) int32
283            b.write_all(&(row.birth_sound_id.id as i32).to_le_bytes())?;
284
285            // spell_cast_directed_sound_id: foreign_key (SoundEntries) int32
286            b.write_all(&(row.spell_cast_directed_sound_id.id as i32).to_le_bytes())?;
287
288            // submerge_sound_id: foreign_key (SoundEntries) int32
289            b.write_all(&(row.submerge_sound_id.id as i32).to_le_bytes())?;
290
291            // submerged_sound_id: foreign_key (SoundEntries) int32
292            b.write_all(&(row.submerged_sound_id.id as i32).to_le_bytes())?;
293
294            // creature_sound_data_id_pet: foreign_key (CreatureSoundData) int32
295            b.write_all(&(row.creature_sound_data_id_pet.id as i32).to_le_bytes())?;
296
297        }
298
299        b.write_all(&[0_u8])?;
300
301        Ok(())
302    }
303
304}
305
306impl Indexable for CreatureSoundData {
307    type PrimaryKey = CreatureSoundDataKey;
308    fn get(&self, key: impl TryInto<Self::PrimaryKey>) -> Option<&Self::Row> {
309        let key = key.try_into().ok()?;
310        self.rows.iter().find(|a| a.id.id == key.id)
311    }
312
313    fn get_mut(&mut self, key: impl TryInto<Self::PrimaryKey>) -> Option<&mut Self::Row> {
314        let key = key.try_into().ok()?;
315        self.rows.iter_mut().find(|a| a.id.id == key.id)
316    }
317}
318
319#[derive(Debug, Clone, Copy, PartialEq, Eq, Ord, PartialOrd, Hash, Default)]
320pub struct CreatureSoundDataKey {
321    pub id: i32
322}
323
324impl CreatureSoundDataKey {
325    pub const fn new(id: i32) -> Self {
326        Self { id }
327    }
328
329}
330
331impl From<u8> for CreatureSoundDataKey {
332    fn from(v: u8) -> Self {
333        Self::new(v.into())
334    }
335}
336
337impl From<u16> for CreatureSoundDataKey {
338    fn from(v: u16) -> Self {
339        Self::new(v.into())
340    }
341}
342
343impl From<i8> for CreatureSoundDataKey {
344    fn from(v: i8) -> Self {
345        Self::new(v.into())
346    }
347}
348
349impl From<i16> for CreatureSoundDataKey {
350    fn from(v: i16) -> Self {
351        Self::new(v.into())
352    }
353}
354
355impl From<i32> for CreatureSoundDataKey {
356    fn from(v: i32) -> Self {
357        Self::new(v)
358    }
359}
360
361impl TryFrom<u32> for CreatureSoundDataKey {
362    type Error = u32;
363    fn try_from(v: u32) -> Result<Self, Self::Error> {
364        Ok(TryInto::<i32>::try_into(v).ok().ok_or(v)?.into())
365    }
366}
367
368impl TryFrom<usize> for CreatureSoundDataKey {
369    type Error = usize;
370    fn try_from(v: usize) -> Result<Self, Self::Error> {
371        Ok(TryInto::<i32>::try_into(v).ok().ok_or(v)?.into())
372    }
373}
374
375impl TryFrom<u64> for CreatureSoundDataKey {
376    type Error = u64;
377    fn try_from(v: u64) -> Result<Self, Self::Error> {
378        Ok(TryInto::<i32>::try_into(v).ok().ok_or(v)?.into())
379    }
380}
381
382impl TryFrom<i64> for CreatureSoundDataKey {
383    type Error = i64;
384    fn try_from(v: i64) -> Result<Self, Self::Error> {
385        Ok(TryInto::<i32>::try_into(v).ok().ok_or(v)?.into())
386    }
387}
388
389impl TryFrom<isize> for CreatureSoundDataKey {
390    type Error = isize;
391    fn try_from(v: isize) -> Result<Self, Self::Error> {
392        Ok(TryInto::<i32>::try_into(v).ok().ok_or(v)?.into())
393    }
394}
395
396#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
397pub struct CreatureSoundDataRow {
398    pub id: CreatureSoundDataKey,
399    pub sound_exertion_id: SoundEntriesKey,
400    pub sound_exertion_critical_id: SoundEntriesKey,
401    pub sound_injury_id: SoundEntriesKey,
402    pub sound_injury_critical_id: SoundEntriesKey,
403    pub sound_injury_crushing_blow_id: i32,
404    pub sound_death_id: SoundEntriesKey,
405    pub sound_stun_id: SoundEntriesKey,
406    pub sound_stand_id: SoundEntriesKey,
407    pub sound_footstep_id: FootstepTerrainLookupKey,
408    pub sound_aggro_id: SoundEntriesKey,
409    pub sound_wing_flap_id: SoundEntriesKey,
410    pub sound_wing_glide_id: SoundEntriesKey,
411    pub sound_alert_id: SoundEntriesKey,
412    pub sound_fidget: [i32; 5],
413    pub custom_attack: [i32; 4],
414    pub n_p_c_sound_id: i32,
415    pub loop_sound_id: SoundEntriesKey,
416    pub creature_impact_type: i32,
417    pub sound_jump_start_id: SoundEntriesKey,
418    pub sound_jump_end_id: SoundEntriesKey,
419    pub sound_pet_attack_id: SoundEntriesKey,
420    pub sound_pet_order_id: SoundEntriesKey,
421    pub sound_pet_dismiss_id: SoundEntriesKey,
422    pub fidget_delay_seconds_min: f32,
423    pub fidget_delay_seconds_max: f32,
424    pub birth_sound_id: SoundEntriesKey,
425    pub spell_cast_directed_sound_id: SoundEntriesKey,
426    pub submerge_sound_id: SoundEntriesKey,
427    pub submerged_sound_id: SoundEntriesKey,
428    pub creature_sound_data_id_pet: CreatureSoundDataKey,
429}
430