wolfrpg_map_parser/
page.rs

1pub mod blend_type;
2pub mod event_trigger;
3pub mod condition;
4pub mod move_route;
5pub mod options;
6
7use crate::byte_utils::{as_u32_le, parse_string};
8use crate::command::Command;
9use crate::common::r#move::Move;
10use crate::page::blend_type::BlendType;
11use crate::page::condition::Condition;
12use crate::page::event_trigger::EventTrigger;
13use crate::page::move_route::MoveRoute;
14use crate::page::options::Options;
15#[cfg(feature = "serde")]
16use serde::{Serialize, Deserialize};
17
18const PAGE_SIGNATURE: &[u8] = b"\x79\xff\xff\xff\xff";
19
20/// An event page containing most of the event state.
21///
22/// Each event page describes the behaviour of the event, its appearance and the scripts that it
23/// runs as a collection of [`Command`].
24#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
25#[derive(PartialEq, Clone)]
26#[allow(unused)]
27pub struct Page {
28    icon: String,
29    icon_row: u8,
30    icon_column: u8,
31    icon_opacity: u8,
32    icon_blend: BlendType,
33    event_trigger: EventTrigger,
34    conditions: [Condition; 4],
35    animation_speed: u8,
36    move_speed: u8,
37    move_frequency: u8,
38    move_route: MoveRoute,
39    options: Options,
40    unknown1: u8,
41    moves: Vec<Move>,
42    commands: Vec<Command>,
43    unknown2: u32,
44    shadow_graphic: u8,
45    range_extension_x: u8,
46    range_extension_y: u8,
47}
48
49impl Page {
50    /// Parse raw bytes into a single [`Page`] struct.
51    ///
52    /// Use of this method is highly discouraged unless you know exactly what you are doing.
53    /// Prefer using [`Map::parse`] and then extract what you want from the structure tree.
54    ///
55    /// # Panics
56    /// This function will panic if the given bytes do not represent a valid page structure.
57    ///
58    /// This might be caused by unaligned bytes, corrupt files, incompatible format updates and
59    /// library bugs.
60    /// If you are confident you are doing everything right, feel free to report an issue on [GitHub].
61    ///
62    /// [`Map::parse`]: crate::map::Map::parse
63    /// [GitHub]: https://github.com/G1org1owo/wolfrpg-map-parser/issues
64    pub fn parse(bytes: &[u8]) -> (usize, Self) {
65        let mut offset: usize = 0;
66
67        let signature: &[u8] = &bytes[offset..offset+5];
68        offset += 5;
69
70        if signature != PAGE_SIGNATURE {
71            panic!("Invalid page signature");
72        }
73
74        let (bytes_read, icon): (usize, String) = parse_string(&bytes[offset..]);
75        offset += bytes_read;
76
77        let icon_row: u8 = (bytes[offset] >> 1) - 1;
78        let icon_column: u8 = bytes[offset+1];
79        let icon_opacity: u8 = bytes[offset+2];
80        let icon_blend: BlendType = BlendType::new(bytes[offset+3]);
81        let event_trigger: EventTrigger = EventTrigger::new(bytes[offset+4]);
82        offset += 5;
83
84        let condition1: Condition = Self::parse_condition(&bytes[offset..], 0);
85        let condition2: Condition = Self::parse_condition(&bytes[offset..], 1);
86        let condition3: Condition = Self::parse_condition(&bytes[offset..], 2);
87        let condition4: Condition = Self::parse_condition(&bytes[offset..], 3);
88        offset += 36;
89
90        let animation_speed: u8 = bytes[offset];
91        let move_speed: u8 = bytes[offset+1];
92        let move_frequency: u8 = bytes[offset+2];
93        let move_route: MoveRoute = MoveRoute::new(bytes[offset+3]);
94        let options: Options = Options::new(bytes[offset+4]);
95        let unknown1: u8 = bytes[offset+5];
96        offset += 6;
97
98        let move_count: u32 = as_u32_le(&bytes[offset..offset+4]);
99        offset += 4;
100
101        let (bytes_read, moves): (usize, Vec<Move>) 
102            = Move::parse_multiple(&bytes[offset..], move_count);
103        offset += bytes_read;
104        
105        let command_count: u32 = as_u32_le(&bytes[offset..offset+4]);
106        offset += 4;
107
108        let (bytes_read, commands): (usize, Vec<Command>)
109            = Self::parse_commands(&bytes[offset..], command_count);
110        offset += bytes_read;
111
112        let unknown2: u32 = as_u32_le(&bytes[offset..offset+4]);
113        offset += 4;
114
115        let shadow_graphic: u8 = bytes[offset];
116        let range_extension_x: u8 = bytes[offset+1];
117        let range_extension_y: u8 = bytes[offset+2];
118        offset += 3;
119
120        let page_end: u8 = bytes[offset];
121        offset += 1;
122
123        if page_end != 0x7a {
124            panic!("Expected page end but found {:02x}", page_end);
125        }
126
127        (offset, Self {
128            icon,
129            icon_row,
130            icon_column,
131            icon_opacity,
132            icon_blend,
133            event_trigger,
134            conditions: [condition1, condition2, condition3, condition4],
135            animation_speed,
136            move_speed,
137            move_frequency,
138            move_route,
139            options,
140            unknown1,
141            moves,
142            commands,
143            unknown2,
144            shadow_graphic,
145            range_extension_x,
146            range_extension_y,
147        })
148    }
149
150    fn parse_condition(bytes: &[u8], count: usize) -> Condition {
151        Condition::new(
152            bytes[count],
153            as_u32_le(&bytes[4*(1+count)..4*(2+count)]),
154            as_u32_le(&bytes[4*(5+count)..4*(6+count)]),
155        )
156    }
157
158    fn parse_commands(bytes: &[u8], command_count: u32) -> (usize, Vec<Command>){
159        let mut offset: usize = 0;
160        let mut commands: Vec<Command> = Vec::new();
161
162        let mut i: u32 = 0;
163        while i<command_count {
164            let (bytes_read, commands_read, command): (usize, u32, Command)
165                = Command::parse(&bytes[offset..]);
166            offset += bytes_read;
167            commands.push(command);
168
169            i += commands_read;
170        }
171
172        (offset, commands)
173    }
174
175    /// The filename of the icon sprite sheet used by this page.
176    pub fn icon(&self) -> &str {
177        &self.icon
178    }
179
180    /// Mutable reference accessor for [`Page::icon`].
181    pub fn icon_mut(&mut self) -> &mut String {
182        &mut self.icon
183    }
184
185    /// The row of the selected icon in the selected sprite sheet.
186    pub fn icon_row(&self) -> u8 {
187        self.icon_row
188    }
189
190    /// Mutable reference accessor for [`Page::icon_row`].
191    pub fn icon_row_mut(&mut self) -> &mut u8 {
192        &mut self.icon_row
193    }
194
195    /// The column of the selected icon in the selected sprite sheet.
196    pub fn icon_column(&self) -> u8 {
197        self.icon_column
198    }
199
200    /// Mutable reference accessor for [`Page::icon_column`].
201    pub fn icon_column_mut(&mut self) -> &mut u8 {
202        &mut self.icon_column
203    }
204
205    /// The opacity the icon should have when rendered.
206    pub fn icon_opacity(&self) -> u8 {
207        self.icon_opacity
208    }
209
210    /// Mutable reference accessor for [`Page::icon_opacity`].
211    pub fn icon_opacity_mut(&mut self) -> &mut u8 {
212        &mut self.icon_opacity
213    }
214
215    /// The blend method used for painting the icon onto the background.
216    pub fn icon_blend(&self) -> &BlendType {
217        &self.icon_blend
218    }
219
220    /// Mutable reference accessor for [`Page::icon_blend`].
221    pub fn icon_blend_mut(&mut self) -> &mut BlendType {
222        &mut self.icon_blend
223    }
224
225    /// The condition by which the event is triggered.
226    pub fn event_trigger(&self) -> &EventTrigger {
227        &self.event_trigger
228    }
229
230    /// Mutable reference accessor for [`Page::event_trigger`].
231    pub fn event_trigger_mut(&mut self) -> &mut EventTrigger {
232        &mut self.event_trigger
233    }
234
235    /// The conditions that must be mut for the script to run.
236    pub fn conditions(&self) -> &[Condition; 4] {
237        &self.conditions
238    }
239
240    /// Mutable reference accessor for [`Page::conditions`].
241    pub fn conditions_mut(&mut self) -> &mut [Condition; 4] {
242        &mut self.conditions
243    }
244
245    /// The speed at which the event's animation advance.
246    pub fn animation_speed(&self) -> u8 {
247        self.animation_speed
248    }
249
250    /// Mutable reference accessor for [`Page::animation_speed`].
251    pub fn animation_speed_mut(&mut self) -> &mut u8 {
252        &mut self.animation_speed
253    }
254
255    /// The speed at which the event moves.
256    pub fn move_speed(&self) -> u8 {
257        self.move_speed
258    }
259
260    /// Mutable reference accessor for [`Page::move_speed`].
261    pub fn move_speed_mut(&mut self) -> &mut u8 {
262        &mut self.move_speed
263    }
264
265    /// The frequency at which the event moves.
266    pub fn move_frequency(&self) -> u8 {
267        self.move_frequency
268    }
269
270    /// Mutable reference accessor for [`Page::move_frequency`].
271    pub fn move_frequency_mut(&mut self) -> &mut u8 {
272        &mut self.move_frequency
273    }
274
275    /// How (and whether) the event should move.
276    pub fn move_route(&self) -> &MoveRoute {
277        &self.move_route
278    }
279
280    /// Mutable reference accessor for [`Page::move_route`].
281    pub fn move_route_mut(&mut self) -> &mut MoveRoute {
282        &mut self.move_route
283    }
284
285    /// A set of options that influence the event rendering and behaviour.
286    pub fn options(&self) -> &Options {
287        &self.options
288    }
289
290    /// Mutable reference accessor for [`Page::options`].
291    pub fn options_mut(&mut self) -> &mut Options {
292        &mut self.options
293    }
294
295    /// The pattern the event follows when moving.
296    ///
297    /// This field is only valid if [`Page::move_route`] is `MoveRoute::Custom`, otherwise it's
298    /// empty.
299    pub fn moves(&self) -> &Vec<Move> {
300        &self.moves
301    }
302
303    /// Mutable reference accessor for [`Page::moves`].
304    pub fn moves_mut(&mut self) -> &mut Vec<Move> {
305        &mut self.moves
306    }
307
308    /// The event script, in the form of a [`Command`] collection.
309    pub fn commands(&self) -> &Vec<Command> {
310        &self.commands
311    }
312
313    /// Mutable reference accessor for [`Page::commands`].
314    pub fn commands_mut(&mut self) -> &mut Vec<Command> {
315        &mut self.commands
316    }
317
318    /// The graphic to use for the shadow, if shadow graphics are enabled.
319    pub fn shadow_graphic(&self) -> u8 {
320        self.shadow_graphic
321    }
322
323    /// Mutable reference accessor for [`Page::shadow_graphic`].
324    pub fn shadow_graphic_mut(&mut self) -> &mut u8 {
325        &mut self.shadow_graphic
326    }
327
328    /// How much the trigger area is expanded horizontally.
329    ///
330    /// This field is only valid if [`Page::event_trigger`] is `EventTrigger::ConfirmKey`,
331    /// `EventTrigger::EventTouch` or `EventTrigger::PlayerTouch`
332    pub fn range_extension_x(&self) -> u8 {
333        self.range_extension_x
334    }
335
336    /// Mutable reference accessor for [`Page::range_extension_x`].
337    pub fn range_extension_x_mut(&mut self) -> &mut u8 {
338        &mut self.range_extension_x
339    }
340
341    /// How much the trigger area is expanded horizontally.
342    ///
343    /// This field is only valid if [`Page::event_trigger`] is `EventTrigger::ConfirmKey`,
344    /// `EventTrigger::EventTouch` or `EventTrigger::PlayerTouch`
345    pub fn range_extension_y(&self) -> u8 {
346        self.range_extension_y
347    }
348
349    /// Mutable reference accessor for [`Page::range_extension_y`].
350    pub fn range_extension_y_mut(&mut self) -> &mut u8 {
351        &mut self.range_extension_y
352    }
353}