use crate::game::GameFamily;
use binrw::{BinRead, BinWrite};
use std::io::{self, Read, Seek, Write};
#[derive(Debug, Clone, PartialEq, Eq, BinRead, BinWrite)]
#[brw(little)]
pub struct BgEvent {
pub script: u16,
pub event_type: u16,
pub x: i32,
pub z: i32,
pub y: i32,
#[brw(pad_after = 2)]
pub player_facing_dir: u16,
}
#[derive(Debug, Clone, PartialEq, Eq, BinRead, BinWrite)]
#[brw(little)]
pub struct ObjectEvent {
pub local_id: u16,
pub graphics_id: u16,
pub movement_type: u16,
pub trainer_type: u16,
pub hidden_flag: u16,
pub script: u16,
pub dir: i16,
pub data: [u16; 3],
pub movement_range_x: i16,
pub movement_range_z: i16,
pub x: u16,
pub z: u16,
pub y: i32,
}
#[derive(Debug, Clone, PartialEq, Eq, BinRead, BinWrite)]
#[brw(little)]
pub struct WarpEvent {
pub x: u16,
pub z: u16,
pub dest_header_id: u16,
pub dest_warp_id: u16,
pub height: u32,
}
#[derive(Debug, Clone, PartialEq, Eq, BinRead, BinWrite)]
#[brw(little)]
pub struct CoordEvent {
pub script: u16,
pub x: i16,
pub z: i16,
pub width: u16,
pub length: u16,
pub y: u16,
pub value: u16,
pub var: u16,
}
#[binrw::binrw]
#[brw(little)]
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct EventFile {
#[br(temp)]
#[bw(calc = bg_events.len() as u32)]
bg_count: u32,
#[br(count = bg_count)]
pub bg_events: Vec<BgEvent>,
#[br(temp)]
#[bw(calc = object_events.len() as u32)]
object_count: u32,
#[br(count = object_count)]
pub object_events: Vec<ObjectEvent>,
#[br(temp)]
#[bw(calc = warp_events.len() as u32)]
warp_count: u32,
#[br(count = warp_count)]
pub warp_events: Vec<WarpEvent>,
#[br(temp)]
#[bw(calc = coord_events.len() as u32)]
coord_count: u32,
#[br(count = coord_count)]
pub coord_events: Vec<CoordEvent>,
}
impl EventFile {
pub fn from_binary<R: Read + Seek>(reader: &mut R) -> io::Result<Self> {
Self::read_le(reader).map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))
}
pub fn to_binary<W: Write + Seek>(&self, writer: &mut W) -> io::Result<()> {
self.write_le(writer)
.map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))
}
pub fn to_binary_for<W: Write + Seek>(
&self,
writer: &mut W,
family: GameFamily,
) -> io::Result<()> {
if family != GameFamily::HGSS {
for warp in &self.warp_events {
if warp.height != 0 {
return Err(io::Error::new(
io::ErrorKind::InvalidData,
format!(
"warp height must be 0 for {:?}, got {}",
family, warp.height
),
));
}
}
}
self.to_binary(writer)
}
}