use crate::script;
use crate::script::{Argument, Event, Offset, Requirement, Script};
use std::f32;
use std::iter::Iterator;
use std::slice;
pub mod variable_ast;
use variable_ast::VariableAst;
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct ScriptAst {
pub block: Block,
pub offset: i32,
}
impl ScriptAst {
pub fn new(script: &Script) -> ScriptAst {
let block = if let ProcessedBlock::Finished(events) =
process_block(&mut script.events.iter().peekable())
{
events
} else {
error!("A block in the script did not terminate.");
Block { events: vec![] }
};
ScriptAst {
block,
offset: script.offset,
}
}
}
#[rustfmt::skip]
fn process_block(events: &mut std::iter::Peekable<slice::Iter<Event>>) -> ProcessedBlock {
let mut event_asts = vec!();
while let Some(event) = events.next() {
let args = &event.arguments;
use crate::script::Argument::*;
let event_ast = match (event.namespace, event.code, args.first(), args.get(1), args.get(2)) {
(0x00, 0x01, Some(Scalar(v0)), None, None) => EventAst::SyncWait (*v0),
(0x00, 0x02, None, None, None) => EventAst::Nop,
(0x00, 0x02, Some(Scalar(v0)), None, None) => EventAst::AsyncWait (*v0),
(0x00, 0x04, Some(Value(v0)), None, None) => { let iterations = if *v0 == -1 {
Iterations::Infinite
} else {
Iterations::Finite (*v0)
};
match process_block(events) {
ProcessedBlock::EndForLoop (block) => EventAst::ForLoop (ForLoop { iterations, block }),
_ => {
error!("ForLoop did not terminate");
EventAst::Unknown (event.clone())
}
}
}
(0x00, 0x05, None, None, None) => { return ProcessedBlock::EndForLoop (Block { events: event_asts })
}
(0x00, 0x07, Some(Offset(v0)), None, None) => EventAst::Subroutine (v0.clone()),
(0x00, 0x07, Some(Value (v0)), None, None) => EventAst::Subroutine (script::Offset { offset: *v0, origin: -1 }),
(0x00, 0x08, None, None, None) => EventAst::Return,
(0x00, 0x09, Some(Offset(v0)), None, None) => EventAst::Goto (v0.clone()),
(0x00, 0x09, Some(Value (v0)), None, None) => EventAst::Goto (script::Offset { offset: *v0, origin: -1 }),
(0x00, 0x0A, Some(Requirement { ty, flip }), v1, v2) => { if let Some(test) = Expression::from_args(ty, *flip, v1, v2, args.get(3)) {
match process_block(events) {
ProcessedBlock::EndIf { then_branch } => {
EventAst::IfStatement (IfStatement { test, then_branch, else_branch: None })
}
ProcessedBlock::EndIfAndElse { then_branch, else_branch } => {
EventAst::IfStatement (IfStatement { test, then_branch, else_branch })
}
_ => {
error!("IfStatement did not terminate");
EventAst::Unknown (event.clone())
}
}
} else {
EventAst::Unknown (event.clone())
}
}
(0x00, 0x0E, None, None, None) => { match process_block(events) {
ProcessedBlock::EndIf { then_branch: else_branch } => {
let then_branch = Block { events: event_asts };
let else_branch = Some(Box::new(else_branch));
return ProcessedBlock::EndIfAndElse { then_branch, else_branch }
}
_ => {
error!("IfStatement did not terminate");
EventAst::Unknown (event.clone())
}
}
}
(0x00, 0x0B, Some(Requirement { ty, flip }), v1, v2) => { if let Some(test) = Expression::from_args(ty, *flip, v1, v2, args.get(3)) {
EventAst::IfStatementAnd (test)
} else {
EventAst::Unknown (event.clone())
}
}
(0x00, 0x0C, Some(Requirement { ty, flip }), v1, v2) => { if let Some(test) = Expression::from_args(ty, *flip, v1, v2, args.get(3)) {
EventAst::IfStatementOr (test)
} else {
EventAst::Unknown (event.clone())
}
}
(0x00, 0x0D, Some(Requirement { ty, flip }), v1, v2) => { if let Some(test) = Expression::from_args(ty, *flip, v1, v2, args.get(3)) {
let event = match process_block(events) {
ProcessedBlock::EndIf { then_branch } => {
EventAst::IfStatement (IfStatement { test, then_branch, else_branch: None })
}
ProcessedBlock::EndIfAndElse { then_branch, else_branch } => {
EventAst::IfStatement (IfStatement { test, then_branch, else_branch })
}
_ => {
error!("IfStatement did not terminate");
return ProcessedBlock::Finished (Block { events: event_asts });
}
};
let else_branch = Some(Box::new(Block { events: vec!(event) }));
let then_branch = Block { events: event_asts };
return ProcessedBlock::EndIfAndElse { then_branch, else_branch };
} else {
EventAst::Unknown (event.clone())
}
}
(0x00, 0x0F, None, None, None) => { return ProcessedBlock::EndIf { then_branch: Block { events: event_asts } } }
(0x00, 0x10, Some(Value(v0)), Some(Value(v1)), None) => EventAst::Switch (*v0, *v1),
(0x00, 0x11, Some(Value(v0)), None, None) => EventAst::Case (*v0),
(0x00, 0x11, None, None, None) => EventAst::DefaultCase,
(0x00, 0x13, None, None, None) => EventAst::EndSwitch,
(0x01, 0x01, None, None, None) => EventAst::LoopRest,
(0x0D, 0x00, Some(Value(v0)), Some(Offset(v1)), None) => EventAst::CallEveryFrame { thread_id: *v0, offset: v1.clone() },
(0x0D, 0x01, Some(Value(v0)), None, None) => EventAst::RemoveCallEveryFrame { thread_id: *v0 },
(0x0D, 0x05, Some(Value(v0)), Some(Offset(v1)), None) => EventAst::IndependentSubroutine { thread_id: *v0, offset: v1.clone() },
(0x0D, 0x06, Some(Value(v0)), None, None) => EventAst::RemoveIndependentSubroutine { thread_id: *v0 },
(0x0D, 0x07, Some(Value(v0)), Some(Value(v1)), None) => EventAst::SetIndependentSubroutineThreadType { thread_id: *v0, thread_type: *v1 },
(0x02, 0x00, Some(Value(v0)), Some(Value(v1)), Some(Requirement { ty, flip })) => {
if let Some(test) = Expression::from_args(ty, *flip, args.get(3), args.get(4), args.get(5)) {
EventAst::CreateInterrupt (Interrupt { interrupt_id: Some(*v0), action: *v1, test })
} else {
EventAst::Unknown (event.clone())
}
}
(0x02, 0x01, Some(Value(v0)), Some(Requirement { ty, flip }), v2) => {
if let Some(test) = Expression::from_args(ty, *flip, v2, args.get(3), args.get(4)) {
EventAst::CreateInterrupt (Interrupt { interrupt_id: None, action: *v0, test })
} else {
EventAst::Unknown (event.clone())
}
}
(0x02, 0x04, Some(Requirement { ty, flip }), v1, v2) => {
if let Some(test) = Expression::from_args(ty, *flip, v1, v2, args.get(3)) {
EventAst::PreviousInterruptAddRequirement { test }
}
else {
EventAst::Unknown (event.clone())
}
}
(0x02, 0x05, Some(Value(v0)), Some(Value(v1)), Some(Requirement { ty, flip })) => {
if let Some(test) = Expression::from_args(ty, *flip, args.get(3), args.get(4), args.get(5)) {
EventAst::InterruptAddRequirement { interrupt_type: InterruptType::new(*v0), interrupt_id: *v1, test }
} else {
EventAst::Unknown (event.clone())
}
}
(0x02, 0x06, Some(Value(v0)), None, None) => EventAst::EnableInterrupt (*v0),
(0x02, 0x08, Some(Value(v0)), None, None) => EventAst::DisableInterrupt (*v0),
(0x02, 0x09, Some(Value(v0)), Some(Value(v1)), None) => EventAst::ToggleInterrupt { interrupt_type: InterruptType::new(*v0), interrupt_id: *v1 },
(0x02, 0x0A, Some(Value(v0)), None, None) => EventAst::EnableInterruptGroup (InterruptType::new(*v0)),
(0x02, 0x0B, Some(Value(v0)), None, None) => EventAst::DisableInterruptGroup (InterruptType::new(*v0)),
(0x02, 0x0C, Some(Value(v0)), None, None) => EventAst::ClearInterruptGroup (InterruptType::new(*v0)),
(0x64, 0x00, None, None, None) => EventAst::AllowInterrupts,
(0x64, 0x01, None, None, None) => EventAst::DisallowInterrupts,
(0x04, 0x00, Some(Value(v0)), None, None) => EventAst::ChangeSubactionRestartFrame (*v0),
(0x04, 0x00, Some(Value(v0)), Some(Bool(v1)), None) => if *v1 { EventAst::ChangeSubaction (*v0) } else { EventAst::ChangeSubactionRestartFrame (*v0) }
(0x04, 0x06, Some(Scalar(v0)), None, None) => EventAst::SetAnimationFrame (*v0),
(0x04, 0x07, Some(Scalar(v0)), None, None) => EventAst::FrameSpeedModifier { multiplier: *v0, unk: 0 },
(0x04, 0x07, Some(Scalar(v0)), Some(Value(v1)), None) => EventAst::FrameSpeedModifier { multiplier: *v0, unk: *v1 },
(0x04, 0x14, Some(Scalar(v0)), None, None) => EventAst::SetAnimationAndTimerFrame (*v0),
(0x0c, 0x23, Some(Value(v0)), Some(Value(v1)), None) => EventAst::TimeManipulation (*v0, *v1),
(0x0e, 0x00, Some(Value(v0)), None, None) => EventAst::SetAirGround (*v0),
(0x08, 0x00, Some(Value(v0)), None, None) => EventAst::SetEdgeSlide (EdgeSlide::new(*v0)),
(0x05, 0x00, None, None, None) => EventAst::ReverseDirection,
(0x06, 0x04, None, None, None) => EventAst::DeleteAllHitBoxes,
(0x06, 0x00, Some(Value(v0)), Some(v1), Some(Value(v2))) => {
match (args.get(3), args.get(4), args.get(5), args.get(6), args.get(7), args.get(8), args.get(9), args.get(10), args.get(11), args.get(12)) {
(Some(Value(v3)), Some(Value(v4)), Some(Scalar(v5)), Some(Scalar(v6)), Some(Scalar(v7)), Some(Scalar(v8)), Some(Scalar(v9)), Some(Scalar(v10)), Some(Scalar(v11)), Some(Value(v12))) => {
let damage = match v1 {
Value(constant) => Some(FloatValue::Constant (*constant as f32)),
Variable(variable) => Some(FloatValue::Variable (VariableAst::new(variable))),
_ => None,
};
if let Some(damage) = damage {
let v12u = *v12 as u32;
EventAst::CreateHitBox (HitBoxArguments {
bone_index: (*v0 >> 16) as i16,
set_id: (*v0 >> 8) as u8,
hitbox_id: *v0 as u8,
damage,
trajectory: *v2,
wdsk: (*v3 >> 16) as i16,
kbg: *v3 as i16,
shield_damage: (*v4 >> 16) as i16,
bkb: *v4 as i16,
size: *v5,
x_offset: *v6,
y_offset: *v7,
z_offset: *v8,
tripping_rate: *v9,
hitlag_mult: *v10,
sdi_mult: *v11,
effect: HitBoxEffect::new(*v12 & 0b0000_0000_0000_0000_0000_0000_0001_1111),
unk1: (*v12 & 0b0000_0000_0000_0000_0000_0000_0010_0000) != 0,
sound_level: ((*v12 & 0b0000_0000_0000_0000_0000_0000_1100_0000) >> 6) as u8,
unk2: ((*v12 & 0b0000_0000_0000_0000_0000_0001_0000_0000) != 0),
sound: HitBoxSound::new((*v12 & 0b0000_0000_0000_0000_0011_1110_0000_0000) >> 9),
unk3: ((*v12 & 0b0000_0000_0000_0000_1100_0000_0000_0000) >> 14) as u8,
ground: (*v12 & 0b0000_0000_0000_0001_0000_0000_0000_0000) != 0,
aerial: (*v12 & 0b0000_0000_0000_0010_0000_0000_0000_0000) != 0,
unk4: ((*v12 & 0b0000_0000_0011_1100_0000_0000_0000_0000) >> 18) as u8,
sse_type: HitBoxSseType::new((*v12 & 0b0000_0111_1100_0000_0000_0000_0000_0000) >> 22),
clang: (*v12 & 0b0000_1000_0000_0000_0000_0000_0000_0000) != 0,
unk5: (*v12 & 0b0001_0000_0000_0000_0000_0000_0000_0000) != 0,
direct: (*v12 & 0b0010_0000_0000_0000_0000_0000_0000_0000) != 0,
unk6: ((v12u & 0b1100_0000_0000_0000_0000_0000_0000_0000) >> 30) as u8,
})
} else {
EventAst::Unknown (event.clone())
}
}
_ => EventAst::Unknown (event.clone())
}
}
(0x06, 0x2B, Some(Value(v0)), Some(Value(v1)), Some(Value(v2))) => {
match (args.get(3), args.get(4), args.get(5), args.get(6), args.get(7), args.get(8), args.get(9), args.get(10), args.get(11), args.get(12)) {
(Some(Value(v3)), Some(Value(v4)), Some(Scalar(v5)), Some(Scalar(v6)), Some(Scalar(v7)), Some(Scalar(v8)), Some(Scalar(v9)), Some(Scalar(v10)), Some(Scalar(v11)), Some(Value(v12))) => {
let v12u = *v12 as u32;
EventAst::ThrownHitBox (HitBoxArguments {
bone_index: (*v0 >> 16) as i16,
set_id: (*v0 >> 8) as u8,
hitbox_id: *v0 as u8,
damage: FloatValue::Constant (*v1 as f32),
trajectory: *v2,
wdsk: (*v3 >> 16) as i16,
kbg: *v3 as i16,
shield_damage: (*v4 >> 16) as i16,
bkb: *v4 as i16,
size: *v5,
x_offset: *v6,
y_offset: *v7,
z_offset: *v8,
tripping_rate: *v9,
hitlag_mult: *v10,
sdi_mult: *v11,
effect: HitBoxEffect::new(*v12 & 0b0000_0000_0000_0000_0000_0000_0001_1111),
unk1: (*v12 & 0b0000_0000_0000_0000_0000_0000_0010_0000) != 0,
sound_level: ((*v12 & 0b0000_0000_0000_0000_0000_0000_1100_0000) >> 6) as u8,
unk2: ((*v12 & 0b0000_0000_0000_0000_0000_0001_0000_0000) != 0),
sound: HitBoxSound::new((*v12 & 0b0000_0000_0000_0000_0011_1110_0000_0000) >> 9),
unk3: ((*v12 & 0b0000_0000_0000_0000_1100_0000_0000_0000) >> 14) as u8,
ground: (*v12 & 0b0000_0000_0000_0001_0000_0000_0000_0000) != 0,
aerial: (*v12 & 0b0000_0000_0000_0010_0000_0000_0000_0000) != 0,
unk4: ((*v12 & 0b0000_0000_0011_1100_0000_0000_0000_0000) >> 18) as u8,
sse_type: HitBoxSseType::new((*v12 & 0b0000_0111_1100_0000_0000_0000_0000_0000) >> 22),
clang: (*v12 & 0b0000_1000_0000_0000_0000_0000_0000_0000) != 0,
unk5: (*v12 & 0b0001_0000_0000_0000_0000_0000_0000_0000) != 0,
direct: (*v12 & 0b0010_0000_0000_0000_0000_0000_0000_0000) != 0,
unk6: ((v12u & 0b1100_0000_0000_0000_0000_0000_0000_0000) >> 30) as u8,
})
}
_ => EventAst::Unknown (event.clone())
}
}
(0x06, 0x15, Some(Value(v0)), Some(v1), Some(Value(v2))) => {
match (args.get(3), args.get(4), args.get(5), args.get(6), args.get(7), args.get(8), args.get(9), args.get(10), args.get(11), args.get(12), args.get(13), args.get(14)) {
(Some(Value(v3)), Some(Value(v4)), Some(Scalar(v5)), Some(Scalar(v6)), Some(Scalar(v7)), Some(Scalar(v8)), Some(Scalar(v9)), Some(Scalar(v10)), Some(Scalar(v11)), Some(Value(v12)), Some(Value(v13)), Some(Value(v14))) => {
let damage = match v1 {
Value(constant) => Some(FloatValue::Constant (*constant as f32)),
Variable(variable) => Some(FloatValue::Variable (VariableAst::new(variable))),
_ => None,
};
if let Some(damage) = damage {
let v12u = *v12 as u32;
let v14u = *v14 as u32;
EventAst::CreateSpecialHitBox (SpecialHitBoxArguments {
hitbox_args: HitBoxArguments {
bone_index: (*v0 >> 16) as i16,
set_id: (*v0 >> 8) as u8,
hitbox_id: *v0 as u8,
damage,
trajectory: *v2,
wdsk: (*v3 >> 16) as i16,
kbg: *v3 as i16,
shield_damage: (*v4 >> 16) as i16,
bkb: *v4 as i16,
size: *v5,
x_offset: *v6,
y_offset: *v7,
z_offset: *v8,
tripping_rate: *v9,
hitlag_mult: *v10,
sdi_mult: *v11,
effect: HitBoxEffect::new(*v12 & 0b0000_0000_0000_0000_0000_0000_0001_1111),
unk1: (*v12 & 0b0000_0000_0000_0000_0000_0000_0010_0000) != 0,
sound_level: ((*v12 & 0b0000_0000_0000_0000_0000_0000_1100_0000) >> 6) as u8,
unk2: ((*v12 & 0b0000_0000_0000_0000_0000_0001_0000_0000) != 0),
sound: HitBoxSound::new((*v12 & 0b0000_0000_0000_0000_0011_1110_0000_0000) >> 6),
unk3: ((*v12 & 0b0000_0000_0000_0000_1100_0000_0000_0000) >> 14) as u8,
ground: (*v12 & 0b0000_0000_0000_0001_0000_0000_0000_0000) != 0,
aerial: (*v12 & 0b0000_0000_0000_0010_0000_0000_0000_0000) != 0,
unk4: ((*v12 & 0b0000_0000_0011_1100_0000_0000_0000_0000) >> 18) as u8,
sse_type: HitBoxSseType::new((*v12 & 0b0000_0111_1100_0000_0000_0000_0000_0000) >> 22),
clang: (*v12 & 0b0000_1000_0000_0000_0000_0000_0000_0000) != 0,
unk5: (*v12 & 0b0001_0000_0000_0000_0000_0000_0000_0000) != 0,
direct: (*v12 & 0b0010_0000_0000_0000_0000_0000_0000_0000) != 0,
unk6: ((v12u & 0b1100_0000_0000_0000_0000_0000_0000_0000) >> 30) as u8,
},
rehit_rate: *v13,
angle_flipping: AngleFlip::new(*v14 & 0b0000_0000_0000_0000_0000_0000_0000_0111),
unk1: (*v14 & 0b0000_0000_0000_0000_0000_0000_0000_1000) != 0,
stretches_to_bone: (*v14 & 0b0000_0000_0000_0000_0000_0000_0001_0000) != 0,
unk2: (*v14 & 0b0000_0000_0000_0000_0000_0000_0010_0000) != 0,
can_hit1: (*v14 & 0b0000_0000_0000_0000_0000_0000_0100_0000) != 0,
can_hit2: (*v14 & 0b0000_0000_0000_0000_0000_0000_1000_0000) != 0,
can_hit3: (*v14 & 0b0000_0000_0000_0000_0000_0001_0000_0000) != 0,
can_hit4: (*v14 & 0b0000_0000_0000_0000_0000_0010_0000_0000) != 0,
can_hit5: (*v14 & 0b0000_0000_0000_0000_0000_0100_0000_0000) != 0,
can_hit6: (*v14 & 0b0000_0000_0000_0000_0000_1000_0000_0000) != 0,
can_hit7: (*v14 & 0b0000_0000_0000_0000_0001_0000_0000_0000) != 0,
can_hit8: (*v14 & 0b0000_0000_0000_0000_0010_0000_0000_0000) != 0,
can_hit9: (*v14 & 0b0000_0000_0000_0000_0100_0000_0000_0000) != 0,
can_hit10: (*v14 & 0b0000_0000_0000_0000_1000_0000_0000_0000) != 0,
can_hit11: (*v14 & 0b0000_0000_0000_0001_0000_0000_0000_0000) != 0,
can_hit12: (*v14 & 0b0000_0000_0000_0010_0000_0000_0000_0000) != 0,
can_hit13: (*v14 & 0b0000_0000_0000_0100_0000_0000_0000_0000) != 0,
enabled: (*v14 & 0b0000_0000_0000_1000_0000_0000_0000_0000) != 0,
unk3: ((*v14 & 0b0000_0000_0011_0000_0000_0000_0000_0000) >> 20) as u8,
can_be_shielded: (*v14 & 0b0000_0000_0100_0000_0000_0000_0000_0000) != 0,
can_be_reflected: (*v14 & 0b0000_0000_1000_0000_0000_0000_0000_0000) != 0,
can_be_absorbed: (*v14 & 0b0000_0001_0000_0000_0000_0000_0000_0000) != 0,
unk4: ((*v14 & 0b0000_0110_0000_0000_0000_0000_0000_0000) >> 25) as u8,
remain_grabbed: (*v14 & 0b0000_1000_0000_0000_0000_0000_0000_0000) != 0,
ignore_invincibility: (*v14 & 0b0001_0000_0000_0000_0000_0000_0000_0000) != 0,
freeze_frame_disable: (*v14 & 0b0010_0000_0000_0000_0000_0000_0000_0000) != 0,
unk5: (*v14 & 0b0100_0000_0000_0000_0000_0000_0000_0000) != 0,
flinchless: (v14u & 0b1000_0000_0000_0000_0000_0000_0000_0000) != 0,
})
} else {
EventAst::Unknown (event.clone())
}
}
_ => EventAst::Unknown (event.clone())
}
}
(0x06, 0x17, Some(Value(v0)), Some(Value(v1)), Some(Value(v2))) => {
EventAst::DefensiveCollision {
ty: DefensiveCollisionType::new(*v0),
unk: *v1,
direction: DefensiveCollisionDirection::new(*v2),
}
}
(0x06, 0x1B, Some(Value(v0)), Some(Value(v1)), Some(Scalar(v2))) => {
if let (Some(Scalar(v3)), Some(Scalar(v4))) = (args.get(3), args.get(4)) {
EventAst::MoveHitBox (MoveHitBox {
hitbox_id: *v0,
new_bone: *v1,
new_x_offset: *v2,
new_y_offset: *v3,
new_z_offset: *v4,
})
} else {
EventAst::Unknown (event.clone())
}
}
(0x06, 0x01, Some(Value(v0)), Some(Value(v1)), None) => EventAst::ChangeHitBoxDamage { hitbox_id: *v0, new_damage: *v1 },
(0x06, 0x02, Some(Value(v0)), Some(Value(v1)), None) => EventAst::ChangeHitBoxSize { hitbox_id: *v0, new_size: *v1 },
(0x06, 0x03, Some(Value(v0)), None, None) => EventAst::DeleteHitBox (*v0),
(0x06, 0x0A, Some(Value(v0)), Some(Value(v1)), Some(Scalar(v2))) => {
if let (Some(Scalar(v3)), Some(Scalar(v4)), Some(Scalar(v5)), Some(Value(v6)), Some(Value(v7))) =
(args.get(3), args.get(4), args.get(5), args.get(6), args.get(7))
{
let unk = if let Some(Value(value)) = args.get(8) { Some(*value) } else { None };
assert!((0..=0xFF).contains(v0), "grab boxes shouldn't include any extra data with the hitbox_id");
EventAst::CreateGrabBox(GrabBoxArguments {
hitbox_id: *v0,
bone_index: *v1,
size: *v2,
x_offset: *v3,
y_offset: *v4,
z_offset: *v5,
set_action: *v6,
target: GrabTarget::new(*v7),
unk
})
} else {
EventAst::Unknown (event.clone())
}
}
(0x06, 0x0C, Some(Value(v0)), None, None) => EventAst::DeleteGrabBox (*v0),
(0x06, 0x0D, None, None, None) => EventAst::DeleteAllGrabBoxes,
(0x06, 0x0E, Some(Value(v0)), Some(Value(v1)), Some(Value(v2))) => {
match (args.get(3), args.get(4), args.get(5), args.get(6), args.get(7), args.get(8), args.get(9), args.get(10), args.get(11), args.get(12), args.get(13), args.get(14), args.get(15), args.get(16)) {
(Some(Value(v3)), Some(Value(v4)), Some(Value(v5)), Some(Value(v6)), Some(Value(v7)), Some(Scalar(v8)), Some(Scalar(v9)), Some(Scalar(v10)), Some(Value(v11)), Some(Value(v12)), Some(Value(v13)), Some(Bool(v14)), Some(Bool(v15)), Some(Value(v16))) => {
EventAst::SpecifyThrow (SpecifyThrow {
throw_use: ThrowUse::new(*v0),
bone: *v1,
damage: *v2,
trajectory: *v3,
kbg: *v4,
wdsk: *v5,
bkb: *v6,
effect: HitBoxEffect::new(*v7),
unk0: *v8,
unk1: *v9,
unk2: *v10,
unk3: *v11,
sfx: HitBoxSound::new(*v12),
grab_target: GrabTarget::new(*v13),
unk4: *v14,
unk5: *v15,
i_frames: *v16,
})
}
_ => EventAst::Unknown(event.clone())
}
}
(0x06, 0x0F, Some(Value(v0)), Some(Value(v1)), Some(Variable(v2))) => {
if let (Some(Variable(v3)), Some(Variable(v4))) = (args.get(3), args.get(4)) {
EventAst::ApplyThrow (ApplyThrow {
unk0: *v0,
bone: *v1,
unk1: VariableAst::new(v2),
unk2: VariableAst::new(v3),
unk3: VariableAst::new(v4),
})
} else {
EventAst::Unknown(event.clone())
}
}
(0x06, 0x14, Some(Value(v0)), Some(v1), None) => {
let add_damage = match v1 {
Value(constant) => Some(FloatValue::Constant (*constant as f32)),
Variable(variable) => Some(FloatValue::Variable (VariableAst::new(variable))),
_ => None,
};
if let Some(add_damage) = add_damage {
EventAst::AddHitBoxDamage { hitbox_id: *v0, add_damage }
} else {
EventAst::Unknown(event.clone())
}
}
(0x06, 0x14, a, b, c, ) => panic!("{:?} {:?} {:?}", a , b, c),
(0x06, 0x05, Some(Value(v0)), None, None) => EventAst::ChangeHurtBoxStateAll { state: HurtBoxState::new(*v0) },
(0x06, 0x08, Some(Value(v0)), Some(Value(v1)), None) => EventAst::ChangeHurtBoxStateSpecific { bone: *v0, state: HurtBoxState::new(*v1) },
(0x06, 0x06, Some(Value(v0)), None, None) => {
if *v0 != 0 {
error!("Unsual UnchangeHurtBoxStateSpecific argument: All known cases of this event have an argument of 0")
}
EventAst::UnchangeHurtBoxStateSpecific
}
(0x07, 0x00, None, None, None) => EventAst::ControllerClearBuffer,
(0x07, 0x01, None, None, None) => EventAst::ControllerUnk01,
(0x07, 0x02, None, None, None) => EventAst::ControllerUnk02,
(0x07, 0x06, Some(Bool(v0)), None, None) => EventAst::ControllerUnk06 (*v0),
(0x07, 0x06, None, None, None) => EventAst::ControllerUnk0C,
(0x07, 0x07, Some(Value(v0)), Some(Value(v1)), None) => EventAst::Rumble { unk1: *v0, unk2: *v1 },
(0x07, 0x0B, Some(Value(v0)), Some(Value(v1)), None) => EventAst::RumbleLoop { unk1: *v0, unk2: *v1 },
(0x18, 0x00, Some(Value(v0)), None, None) => EventAst::SlopeContourStand { leg_bone_parent: *v0 },
(0x18, 0x01, Some(Value(v0)), Some(Value(v1)), None) => EventAst::SlopeContourFull { hip_n_or_top_n: *v0, trans_bone: *v1 },
(0x10, 0x00, Some(Value(v0)), None, None) => EventAst::GenerateArticle { article_id: *v0, subaction_only: true }, (0x10, 0x00, Some(Value(v0)), Some(Bool(v1)), None) => EventAst::GenerateArticle { article_id: *v0, subaction_only: *v1 },
(0x10, 0x01, Some(Value(v0)), None, None) => EventAst::ArticleEvent (*v0),
(0x10, 0x02, Some(Value(v0)), None, None) => EventAst::ArticleAnimation (*v0),
(0x10, 0x03, Some(Value(v0)), None, None) => EventAst::ArticleRemove (*v0),
(0x10, 0x05, Some(Value(v0)), Some(Bool(v1)), None) => EventAst::ArticleVisibility { article_id: *v0, visibility: *v1 },
(0x0C, 0x06, None, None, None) => EventAst::FinalSmashEnter,
(0x0C, 0x07, None, None, None) => EventAst::FinalSmashExit,
(0x0C, 0x08, None, None, None) => EventAst::TerminateSelf,
(0x0C, 0x09, Some(Value(v0)), None, None) => EventAst::LedgeGrabEnable (LedgeGrabEnable::new(*v0)),
(0x0C, 0x25, Some(Bool(v0)), None, None) => EventAst::TagDisplay (*v0),
(0x1E, 0x00, Some(Value(v0)), Some(Scalar(v1)), None) => EventAst::Armor { armor_type: ArmorType::new(*v0), tolerance: *v1 },
(0x1E, 0x03, Some(Scalar(v0)), None, None) => EventAst::AddDamage (*v0),
(0x05, 0x01, None, None, None) => EventAst::Posture (0x01),
(0x05, 0x02, None, None, None) => EventAst::Posture (0x02),
(0x05, 0x03, None, None, None) => EventAst::Posture (0x03),
(0x05, 0x04, None, None, None) => EventAst::Posture (0x04),
(0x05, 0x07, None, None, None) => EventAst::Posture (0x07),
(0x05, 0x0D, None, None, None) => EventAst::Posture (0x0D),
(0x0E, 0x08, Some(&Scalar(v0)), Some(&Scalar(v1)), Some(&Value(v2))) => {
if let Some(&Value(v3)) = args.get(3) {
EventAst::SetOrAddVelocity (SetOrAddVelocity {
x_vel: v0,
y_vel: v1,
x_set: v2 != 0,
y_set: v3 != 0,
})
} else {
EventAst::Unknown (event.clone())
}
}
(0x0E, 0x08, Some(Scalar(v0)), Some(Scalar(v1)), None) => EventAst::SetVelocity { x_vel: *v0, y_vel: *v1 },
(0x0E, 0x01, Some(Scalar(v0)), Some(Scalar(v1)), None) => EventAst::AddVelocity { x_vel: FloatValue::Constant(*v0), y_vel: FloatValue::Constant(*v1) },
(0x0E, 0x01, Some(Variable(v0)), Some(Scalar(v1)), None) => EventAst::AddVelocity { x_vel: FloatValue::Variable(VariableAst::new(v0)), y_vel: FloatValue::Constant(*v1) },
(0x0E, 0x01, Some(Scalar(v0)), Some(Variable(v1)), None) => EventAst::AddVelocity { x_vel: FloatValue::Constant(*v0), y_vel: FloatValue::Variable(VariableAst::new(v1)) },
(0x0E, 0x01, Some(Variable(v0)), Some(Variable(v1)), None) => EventAst::AddVelocity { x_vel: FloatValue::Variable(VariableAst::new(v0)), y_vel: FloatValue::Variable(VariableAst::new(v1)) },
(0x0E, 0x06, Some(Value(v0)), None, None) => EventAst::DisableMovement (DisableMovement::new(*v0)),
(0x0E, 0x07, Some(Value(v0)), None, None) => EventAst::DisableMovement2 (DisableMovement::new(*v0)),
(0x0E, 0x02, Some(Value(v0)), None, None) => EventAst::ResetVerticalVelocityAndAcceleration (*v0 == 1),
(0x17, 0x00, None, None, None) => EventAst::NormalizePhysics,
(0x0A, 0x00, Some(Value(v0)), None, None) => EventAst::SoundEffect1 (*v0),
(0x0A, 0x01, Some(Value(v0)), None, None) => EventAst::SoundEffect2 (*v0),
(0x0A, 0x02, Some(Value(v0)), None, None) => EventAst::SoundEffectTransient (*v0),
(0x0A, 0x03, Some(Value(v0)), None, None) => EventAst::SoundEffectStop (*v0),
(0x0A, 0x05, Some(Value(v0)), None, None) => EventAst::SoundEffectVictory (*v0),
(0x0A, 0x07, Some(Value(v0)), None, None) => EventAst::SoundEffectUnk (*v0),
(0x0A, 0x09, Some(Value(v0)), None, None) => EventAst::SoundEffectOther1 (*v0),
(0x0A, 0x0A, Some(Value(v0)), None, None) => EventAst::SoundEffectOther2 (*v0),
(0x0C, 0x0B, None, None, None) => EventAst::SoundVoiceLow,
(0x0C, 0x19, None, None, None) => EventAst::SoundVoiceDamage,
(0x0C, 0x1D, None, None, None) => EventAst::SoundVoiceOttotto,
(0x0C, 0x1F, None, None, None) => EventAst::SoundVoiceEating,
(0x12, 0x00, Some(Value(v0)), Some(Variable(v1)), None) => EventAst::IntVariableSet { value: *v0, variable: VariableAst::new(v1) },
(0x12, 0x01, Some(Value(v0)), Some(Variable(v1)), None) => EventAst::IntVariableAdd { value: *v0, variable: VariableAst::new(v1) },
(0x12, 0x02, Some(Value(v0)), Some(Variable(v1)), None) => EventAst::IntVariableSubtract { value: *v0, variable: VariableAst::new(v1) },
(0x12, 0x03, Some(Variable(v0)), None, None) => EventAst::IntVariableIncrement { variable: VariableAst::new(v0) },
(0x12, 0x04, Some(Variable(v0)), None, None) => EventAst::IntVariableDecrement { variable: VariableAst::new(v0) },
(0x12, 0x06, Some(Scalar(v0)), Some(Variable(v1)), None) => EventAst::FloatVariableSet { value: FloatValue::Constant(*v0), variable: VariableAst::new(v1) },
(0x12, 0x06, Some(Variable(v0)), Some(Variable(v1)), None) => EventAst::FloatVariableSet { value: FloatValue::Variable(VariableAst::new(v0)), variable: VariableAst::new(v1) },
(0x12, 0x07, Some(Scalar(v0)), Some(Variable(v1)), None) => EventAst::FloatVariableAdd { value: FloatValue::Constant(*v0), variable: VariableAst::new(v1) },
(0x12, 0x07, Some(Variable(v0)), Some(Variable(v1)), None) => EventAst::FloatVariableAdd { value: FloatValue::Variable(VariableAst::new(v0)), variable: VariableAst::new(v1) },
(0x12, 0x08, Some(Scalar(v0)), Some(Variable(v1)), None) => EventAst::FloatVariableSubtract { value: FloatValue::Constant(*v0), variable: VariableAst::new(v1) },
(0x12, 0x08, Some(Variable(v0)), Some(Variable(v1)), None) => EventAst::FloatVariableSubtract { value: FloatValue::Variable(VariableAst::new(v0)), variable: VariableAst::new(v1) },
(0x12, 0x0F, Some(Scalar(v0)), Some(Variable(v1)), None) => EventAst::FloatVariableMultiply { value: FloatValue::Constant(*v0), variable: VariableAst::new(v1) },
(0x12, 0x0F, Some(Variable(v0)), Some(Variable(v1)), None) => EventAst::FloatVariableMultiply { value: FloatValue::Variable(VariableAst::new(v0)), variable: VariableAst::new(v1) },
(0x12, 0x10, Some(Scalar(v0)), Some(Variable(v1)), None) => EventAst::FloatVariableDivide { value: FloatValue::Constant(*v0), variable: VariableAst::new(v1) },
(0x12, 0x10, Some(Variable(v0)), Some(Variable(v1)), None) => EventAst::FloatVariableDivide { value: FloatValue::Variable(VariableAst::new(v0)), variable: VariableAst::new(v1) },
(0x12, 0x0A, Some(Variable(v0)), None, None) => EventAst::BoolVariableSetTrue { variable: VariableAst::new(v0) },
(0x12, 0x0B, Some(Variable(v0)), None, None) => EventAst::BoolVariableSetFalse { variable: VariableAst::new(v0) },
(0x0B, 0x00, Some(&Value(v0)), Some(&Value(v1)), None) => EventAst::ModelChanger { reference: 0, switch_index: v0, bone_group_index: v1 },
(0x0B, 0x01, Some(&Value(v0)), Some(&Value(v1)), None) => EventAst::ModelChanger { reference: 1, switch_index: v0, bone_group_index: v1 },
(0x11, 0x1A, Some(&Value(v0)), Some(&Value(v1)), Some(&Scalar(v2))) |
(0x11, 0x1B, Some(&Value(v0)), Some(&Value(v1)), Some(&Scalar(v2))) => {
match (args.get(3), args.get(4), args.get(5), args.get(6), args.get(7), args.get(8), args.get(9), args.get(10), args.get(11), args.get(12), args.get(13), args.get(14), args.get(15)) {
(Some(&Scalar(v3)), Some(&Scalar(v4)), Some(&Scalar(v5)), Some(&Scalar(v6)), Some(&Scalar(v7)), Some(&Scalar(v8)), Some(&Scalar(v9)), Some(&Scalar(v10)), Some(&Scalar(v11)), Some(&Scalar(v12)), Some(&Scalar(v13)), Some(&Scalar(v14)), Some(&Bool(v15))) => {
EventAst::GraphicEffect (GraphicEffect {
graphic: v0,
bone: v1,
x_offset: v4,
y_offset: v3,
z_offset: v2,
x_rotation: v7,
y_rotation: v6,
z_rotation: v5,
scale: v8,
random_x_offset: v11,
random_y_offset: v10,
random_z_offset: v9,
random_x_rotation: v14,
random_y_rotation: v13,
random_z_rotation: v12,
terminate_with_animation: v15
})
}
_ => EventAst::Unknown (event.clone())
}
}
(0x11, 0x00, Some(&Value(v0)), Some(&Value(v1)), Some(&Scalar(v2))) => {
if let (Some(&Scalar(v3)), Some(&Scalar(v4)), Some(&Scalar(v5)), Some(&Scalar(v6)), Some(&Scalar(v7)), Some(&Scalar(v8)), Some(&Scalar(v9)), Some(&Scalar(v10)), Some(&Scalar(v11)), Some(&Scalar(v12)), Some(&Scalar(v13)), Some(&Scalar(v14)), Some(&Bool(v15))) =
(args.get(3), args.get(4), args.get(5), args.get(6), args.get(7), args.get(8), args.get(9), args.get(10), args.get(11), args.get(12), args.get(13), args.get(14), args.get(15))
{
EventAst::ExternalGraphicEffect (ExternalGraphicEffect {
file: (v0 >> 16) as i16,
graphic: v0 as i16,
bone: v1,
x_offset: v4,
y_offset: v3,
z_offset: v2,
x_rotation: v7,
y_rotation: v6,
z_rotation: v5,
scale: v8,
randomize: Some(ExternalGraphicEffectRandomize {
random_x_offset: v11,
random_y_offset: v10,
random_z_offset: v9,
random_x_rotation: v14,
random_y_rotation: v13,
random_z_rotation: v12,
}),
terminate_with_animation: v15,
})
} else {
EventAst::Unknown (event.clone())
}
}
(0x11, 0x01, Some(&Value(v0)), Some(&Value(v1)), Some(&Scalar(v2))) |
(0x11, 0x02, Some(&Value(v0)), Some(&Value(v1)), Some(&Scalar(v2))) => {
if let (Some(&Scalar(v3)), Some(&Scalar(v4)), Some(&Scalar(v5)), Some(&Scalar(v6)), Some(&Scalar(v7)), Some(&Scalar(v8)), Some(&Bool(v9))) =
(args.get(3), args.get(4), args.get(5), args.get(6), args.get(7), args.get(8), args.get(9))
{
EventAst::ExternalGraphicEffect (ExternalGraphicEffect {
file: (v0 >> 16) as i16,
graphic: v0 as i16,
bone: v1,
x_offset: v4,
y_offset: v3,
z_offset: v2,
x_rotation: v7,
y_rotation: v6,
z_rotation: v5,
scale: v8,
terminate_with_animation: v9,
randomize: None,
})
} else {
EventAst::Unknown (event.clone())
}
}
(0x11, 0x17, Some(&Value(v0)), Some(&Value(v1)), Some(&Value(v2))) => {
match (args.get(3), args.get(4), args.get(5), args.get(6)) {
(Some(&Value(v3)), Some(&Value(v4)), Some(&Value(v5)), Some(&Value(v6))) => {
EventAst::LimitedScreenTint (LimitedScreenTint {
transition_in_time: v0,
red: v1,
green: v2,
blue: v3,
alpha: v4,
frame_count: v5,
transition_out_time: v6,
})
}
(Some(&Value(v3)), Some(&Value(v4)), Some(&Value(v5)), None) => {
EventAst::UnlimitedScreenTint (UnlimitedScreenTint {
tint_id: v0,
transition_in_time: v1,
red: v2,
green: v3,
blue: v4,
alpha: v5,
})
}
_ => EventAst::Unknown (event.clone())
}
}
(0x11, 0x18, Some(&Value(v0)), Some(&Value(v1)), None) => EventAst::EndUnlimitedScreenTint { tint_id: v0, transition_out_time: v1 },
(0x11, 0x03, Some(&Value(v0)), Some(&Value(v1)), Some(&Value(v2))) => {
if let (Some(&Scalar(v3)), Some(&Scalar(v4)), Some(&Scalar(v5)), Some(&Value(v6)), Some(&Scalar(v7)), Some(&Scalar(v8)), Some(&Scalar(v9)), Some(&Bool(v10)), Some(&Value(v11)), Some(&Value(v12)), Some(&Scalar(v13)), Some(&Scalar(v14)), Some(&Scalar(v15)), Some(&Scalar(v16)), Some(&Scalar(v17)), Some(&Scalar(v18)), Some(&Scalar(v19))) =
(args.get(3), args.get(4), args.get(5), args.get(6), args.get(7), args.get(8), args.get(9), args.get(10), args.get(11), args.get(12), args.get(13), args.get(14), args.get(15), args.get(16), args.get(17), args.get(18), args.get(19))
{
EventAst::SwordGlow (SwordGlow {
color: v0,
blur_length: v1,
point1_bone: v2,
point1_x_offset: v3,
point1_y_offset: v4,
point1_z_offset: v5,
point2_bone: v6,
point2_x_offset: v7,
point2_y_offset: v8,
point2_z_offset: v9,
delete_after_subaction: v10,
graphic_id: v11,
bone_id: v12,
x_offset: v13,
y_offset: v14,
z_offset: v15,
x_rotation: v16,
y_rotation: v17,
z_rotation: v18,
glow_length: v19,
})
} else {
EventAst::Unknown (event.clone())
}
}
(0x11, 0x05, Some(&Value(v0)), None, None) => EventAst::DeleteSwordGlow { fade_time: v0 },
(0x14, 0x07, Some(&Value(v0)), Some(&Scalar(v1)), Some(&Scalar(v2))) => {
match (args.get(3), args.get(4), args.get(5), args.get(6), args.get(7), args.get(8), args.get(9)) {
(Some(&Scalar(v3)), Some(&Scalar(v4)), Some(&Scalar(v5)), Some(&Scalar(v6)), Some(&Scalar(v7)), Some(&Scalar(v8)), Some(&Value(v9))) => {
EventAst::AestheticWindEffect (AestheticWindEffect {
unk1: v0,
unk2: v1,
stength: v2,
speed: v3,
size: v4,
unk3: v5,
unk4: v6,
unk5: v7,
unk6: v8,
unk7: v8,
unk8: v9,
})
}
_ => EventAst::Unknown (event.clone())
}
}
(0x14, 0x04, Some(&Value(v0)), None, None) => EventAst::EndAestheticWindEffect { unk: v0 },
(0x1A, 0x00, Some(&Value(v0)), None, None) => EventAst::ScreenShake { magnitude: v0 },
(0x1A, 0x04, Some(&Value(v0)), Some(&Value(v1)), Some(&Scalar(v2))) => {
if let (Some(&Scalar(v3)), Some(&Scalar(v4))) = (args.get(3), args.get(4)) {
EventAst::CameraCloseup (CameraCloseup {
zoom_time: v0,
unk: v1,
distance: v2,
x_angle: v3,
y_angle: v4,
})
} else {
EventAst::Unknown (event.clone())
}
}
(0x1A, 0x08, None, None, None) => EventAst::CameraNormal,
(0x21, 0x00, None, None, None) => EventAst::RemoveFlashEffect,
(0x21, 0x01, Some(&Value(v0)), Some(&Value(v1)), Some(&Value(v2))) => {
if let Some(&Value(v3)) = args.get(3) {
EventAst::FlashEffectOverlay { red: v0, green: v1, blue: v2, alpha: v3 }
} else {
EventAst::Unknown (event.clone())
}
}
(0x21, 0x02, Some(&Value(v0)), Some(&Value(v1)), Some(&Value(v2))) => {
if let (Some(&Value(v3)), Some(&Value(v4))) = (args.get(3), args.get(4)) {
EventAst::SetColorOfFlashEffectOverlay { transition_time: v0, red: v1, green: v2, blue: v3, alpha: v4 }
} else {
EventAst::Unknown (event.clone())
}
}
(0x21, 0x05, Some(&Value(v0)), Some(&Value(v1)), Some(&Value(v2))) => {
if let (Some(&Value(v3)), Some(&Scalar(v4)), Some(&Scalar(v5))) = (args.get(3), args.get(4), args.get(5)) {
EventAst::FlashEffectLight { red: v0, green: v1, blue: v2, alpha: v3, light_source_x: v4, light_source_y: v5 }
} else {
EventAst::Unknown (event.clone())
}
}
(0x21, 0x07, Some(&Value(v0)), Some(&Value(v1)), Some(&Value(v2))) => {
if let (Some(&Value(v3)), Some(&Value(v4))) = (args.get(3), args.get(4)) {
EventAst::SetColorOfFlashEffectLight { transition_time: v0, red: v1, green: v2, blue: v3, alpha: v4 }
} else {
EventAst::Unknown (event.clone())
}
}
(0x1F, 0x00, Some(&Value(v0)), None, None) => EventAst::ItemPickup { unk1: v0, unk2: None, unk3: None, unk4: None },
(0x1F, 0x00, Some(&Value(v0)), Some(&Value(v1)), None) => EventAst::ItemPickup { unk1: v0, unk2: Some(v1), unk3: None, unk4: None },
(0x1F, 0x00, Some(&Value(v0)), Some(&Value(v1)), Some(&Value(v2))) =>
if let Some(&Value(v3)) = args.get(3) {
EventAst::ItemPickup { unk1: v0, unk2: Some(v1), unk3: Some(v2), unk4: Some(v3) }
} else {
EventAst::Unknown (event.clone())
},
(0x1F, 0x01, Some(Variable(v0)), Some(Variable(v1)), Some(Variable(v2))) =>
if let (Some(Variable(v3)), Some(Variable(v4))) = (args.get(3), args.get(4)) {
EventAst::ItemThrow { unk1: VariableAst::new(v0), unk2: VariableAst::new(v1), unk3: VariableAst::new(v2), unk4: Some(VariableAst::new(v3)), unk5: Some(VariableAst::new(v4)) }
} else {
EventAst::Unknown (event.clone())
},
(0x1F, 0x0E, Some(Variable(v0)), Some(Variable(v1)), Some(Variable(v2)))
=> EventAst::ItemThrow { unk1: VariableAst::new(v0), unk2: VariableAst::new(v1), unk3: VariableAst::new(v2), unk4: None, unk5: None },
(0x1F, 0x01, Some(Scalar(v0)), Some(Scalar(v1)), Some(Variable(v2))) =>
EventAst::ItemThrow2 { unk1: *v0, unk2: *v1, unk3: VariableAst::new(v2) },
(0x1F, 0x02, None, None, None) => EventAst::ItemDrop,
(0x1F, 0x03, Some(Value(v0)), None, None) => EventAst::ItemConsume { unk: *v0 },
(0x1F, 0x04, Some(Value(v0)), Some(Scalar(v1)), None) => EventAst::ItemSetProperty { unk1: *v0, unk2: *v1 },
(0x1F, 0x05, None, None, None) => EventAst::FireWeapon,
(0x1F, 0x06, None, None, None) => EventAst::FireProjectile,
(0x1F, 0x07, Some(Value(v0)), None, None) => EventAst::Item1F { unk: *v0 },
(0x1F, 0x08, Some(Value(v0)), None, None) => EventAst::ItemCreate { unk: *v0 },
(0x1F, 0x09, Some(Bool(v0)), None, None) => EventAst::ItemVisibility (*v0),
(0x1F, 0x0A, None, None, None) => EventAst::ItemDelete,
(0x1F, 0x0C, Some(Value(v0)), None, None) => EventAst::BeamSwordTrail { unk: *v0 },
_ => EventAst::Unknown (event.clone())
};
event_asts.push(event_ast);
}
ProcessedBlock::Finished(Block { events: event_asts })
}
impl Expression {
fn from_args(
requirement: &Requirement,
flip: bool,
v1: Option<&Argument>,
v2: Option<&Argument>,
v3: Option<&Argument>,
) -> Option<Expression> {
let test = match (v1, v2, v3) {
(None, None, None) => Expression::Nullary(requirement.clone()),
(Some(v1), None, None) => {
let value = Box::new(match v1 {
Argument::Scalar(v1) => Expression::Scalar(*v1),
Argument::Variable(v1) => Expression::Variable(VariableAst::new(v1)),
Argument::Value(v1) => Expression::Value(*v1),
_ => {
error!("Unhandled expression case: value: {:?}", v1);
return None;
}
});
Expression::Unary(UnaryExpression {
requirement: requirement.clone(),
value,
})
}
(Some(v1), Some(Argument::Value(v2)), Some(v3)) => {
let left = Box::new(match v1 {
Argument::Scalar(v1) => Expression::Scalar(*v1),
Argument::Variable(v1) => Expression::Variable(VariableAst::new(v1)),
Argument::Value(v1) => Expression::Value(*v1),
_ => {
error!("Unhandled expression case: left");
return None;
}
});
let right = Box::new(match v3 {
Argument::Scalar(v3) => Expression::Scalar(*v3),
Argument::Variable(v3) => Expression::Variable(VariableAst::new(v3)),
Argument::Value(v3) => Expression::Value(*v3),
_ => {
error!("Unhandled expression case: right");
return None;
}
});
match requirement {
script::Requirement::Comparison => Expression::Binary(BinaryExpression {
left,
right,
operator: ComparisonOperator::from_arg(*v2),
}),
script::Requirement::Always => Expression::Nullary(requirement.clone()),
_ => {
error!(
"Unhandled expression case: comparison v0: {:?} v1: {:?} v2: {:?}: v3: {:?}",
requirement, v1, v2, v3
);
return None;
}
}
}
(v1, v2, v3) => {
error!("Unhandled expression case: {:?} {:?} {:?}", v1, v2, v3);
return None;
}
};
Some(if flip {
Expression::Not(Box::new(test))
} else {
test
})
}
}
enum ProcessedBlock {
Finished(Block),
EndForLoop(Block),
EndIf {
then_branch: Block,
},
EndIfAndElse {
then_branch: Block,
else_branch: Option<Box<Block>>,
},
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub enum EventAst {
SyncWait(f32),
Nop,
AsyncWait(f32),
ForLoop(ForLoop),
Subroutine(Offset),
Return,
Goto(Offset),
IfStatement(IfStatement),
IfStatementAnd(Expression),
IfStatementOr(Expression),
Switch(i32, i32),
Case(i32),
DefaultCase,
EndSwitch,
LoopRest,
CallEveryFrame { thread_id: i32, offset: Offset },
RemoveCallEveryFrame { thread_id: i32 },
IndependentSubroutine { thread_id: i32, offset: Offset },
RemoveIndependentSubroutine { thread_id: i32 },
SetIndependentSubroutineThreadType { thread_id: i32, thread_type: i32 },
EnableInterrupt(i32),
DisableInterrupt(i32),
ToggleInterrupt {
interrupt_type: InterruptType,
interrupt_id: i32,
},
EnableInterruptGroup(InterruptType),
DisableInterruptGroup(InterruptType),
ClearInterruptGroup(InterruptType),
CreateInterrupt(Interrupt),
PreviousInterruptAddRequirement { test: Expression },
InterruptAddRequirement {
interrupt_type: InterruptType,
interrupt_id: i32,
test: Expression,
},
AllowInterrupts,
DisallowInterrupts,
ChangeSubaction(i32),
ChangeSubactionRestartFrame(i32),
SetAnimationFrame(f32),
FrameSpeedModifier { multiplier: f32, unk: i32 },
SetAnimationAndTimerFrame(f32),
TimeManipulation(i32, i32),
SetAirGround(i32),
SetEdgeSlide(EdgeSlide),
ReverseDirection,
CreateHitBox(HitBoxArguments), ThrownHitBox(HitBoxArguments),
DeleteAllHitBoxes, CreateSpecialHitBox(SpecialHitBoxArguments), DefensiveCollision {
ty: DefensiveCollisionType,
unk: i32,
direction: DefensiveCollisionDirection,
},
MoveHitBox(MoveHitBox),
ChangeHitBoxDamage { hitbox_id: i32, new_damage: i32 },
ChangeHitBoxSize { hitbox_id: i32, new_size: i32 },
DeleteHitBox(i32),
CreateGrabBox(GrabBoxArguments),
DeleteGrabBox(i32),
DeleteAllGrabBoxes,
SpecifyThrow(SpecifyThrow),
ApplyThrow(ApplyThrow),
AddHitBoxDamage {
hitbox_id: i32,
add_damage: FloatValue,
},
ChangeHurtBoxStateAll { state: HurtBoxState },
ChangeHurtBoxStateSpecific { bone: i32, state: HurtBoxState },
UnchangeHurtBoxStateSpecific,
ControllerClearBuffer,
ControllerUnk01,
ControllerUnk02,
ControllerUnk06(bool),
ControllerUnk0C,
Rumble { unk1: i32, unk2: i32 },
RumbleLoop { unk1: i32, unk2: i32 },
SlopeContourStand { leg_bone_parent: i32 },
SlopeContourFull {
hip_n_or_top_n: i32,
trans_bone: i32,
},
GenerateArticle {
article_id: i32,
subaction_only: bool,
},
ArticleEvent(i32),
ArticleAnimation(i32),
ArticleRemove(i32),
ArticleVisibility { article_id: i32, visibility: bool },
FinalSmashEnter,
FinalSmashExit,
TerminateSelf,
LedgeGrabEnable(LedgeGrabEnable),
TagDisplay(bool),
Armor {
armor_type: ArmorType,
tolerance: f32,
},
AddDamage(f32),
Posture(i32),
SetOrAddVelocity(SetOrAddVelocity),
SetVelocity { x_vel: f32, y_vel: f32 },
AddVelocity {
x_vel: FloatValue,
y_vel: FloatValue,
},
DisableMovement(DisableMovement),
DisableMovement2(DisableMovement),
ResetVerticalVelocityAndAcceleration(bool),
NormalizePhysics,
SoundEffect1(i32),
SoundEffect2(i32),
SoundEffectTransient(i32),
SoundEffectStop(i32),
SoundEffectVictory(i32),
SoundEffectUnk(i32),
SoundEffectOther1(i32),
SoundEffectOther2(i32),
SoundVoiceLow,
SoundVoiceDamage,
SoundVoiceOttotto,
SoundVoiceEating,
IntVariableSet { value: i32, variable: VariableAst },
IntVariableAdd { value: i32, variable: VariableAst },
IntVariableSubtract { value: i32, variable: VariableAst },
IntVariableIncrement { variable: VariableAst },
IntVariableDecrement { variable: VariableAst },
FloatVariableSet {
value: FloatValue,
variable: VariableAst,
},
FloatVariableAdd {
value: FloatValue,
variable: VariableAst,
},
FloatVariableSubtract {
value: FloatValue,
variable: VariableAst,
},
FloatVariableMultiply {
value: FloatValue,
variable: VariableAst,
},
FloatVariableDivide {
value: FloatValue,
variable: VariableAst,
},
BoolVariableSetTrue { variable: VariableAst },
BoolVariableSetFalse { variable: VariableAst },
ModelChanger {
reference: u8,
switch_index: i32,
bone_group_index: i32,
},
GraphicEffect(GraphicEffect),
ExternalGraphicEffect(ExternalGraphicEffect),
LimitedScreenTint(LimitedScreenTint),
UnlimitedScreenTint(UnlimitedScreenTint),
EndUnlimitedScreenTint {
tint_id: i32,
transition_out_time: i32,
},
SwordGlow(SwordGlow),
DeleteSwordGlow { fade_time: i32 },
AestheticWindEffect(AestheticWindEffect),
EndAestheticWindEffect { unk: i32 },
ScreenShake { magnitude: i32 },
CameraCloseup(CameraCloseup),
CameraNormal,
RemoveFlashEffect,
FlashEffectOverlay {
red: i32,
green: i32,
blue: i32,
alpha: i32,
},
SetColorOfFlashEffectOverlay {
transition_time: i32,
red: i32,
green: i32,
blue: i32,
alpha: i32,
},
FlashEffectLight {
red: i32,
green: i32,
blue: i32,
alpha: i32,
light_source_x: f32,
light_source_y: f32,
},
SetColorOfFlashEffectLight {
transition_time: i32,
red: i32,
green: i32,
blue: i32,
alpha: i32,
},
ItemPickup {
unk1: i32,
unk2: Option<i32>,
unk3: Option<i32>,
unk4: Option<i32>,
},
ItemThrow {
unk1: VariableAst,
unk2: VariableAst,
unk3: VariableAst,
unk4: Option<VariableAst>,
unk5: Option<VariableAst>,
},
ItemThrow2 {
unk1: f32,
unk2: f32,
unk3: VariableAst,
},
ItemDrop,
ItemConsume { unk: i32 },
ItemSetProperty { unk1: i32, unk2: f32 },
FireWeapon,
FireProjectile,
Item1F { unk: i32 },
ItemCreate { unk: i32 },
ItemVisibility(bool),
ItemDelete,
BeamSwordTrail { unk: i32 },
Unknown(Event),
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub enum FloatValue {
Variable(VariableAst),
Constant(f32),
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct Block {
pub events: Vec<EventAst>,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct ForLoop {
pub iterations: Iterations,
pub block: Block,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub enum Iterations {
Finite(i32),
Infinite,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct IfStatement {
pub test: Expression,
pub then_branch: Block,
pub else_branch: Option<Box<Block>>,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub enum Expression {
Nullary(Requirement),
Unary(UnaryExpression),
Binary(BinaryExpression),
Not(Box<Expression>),
Variable(VariableAst),
Value(i32),
Scalar(f32),
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct BinaryExpression {
pub left: Box<Expression>,
pub right: Box<Expression>,
pub operator: ComparisonOperator,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct UnaryExpression {
pub requirement: Requirement,
pub value: Box<Expression>,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub enum ComparisonOperator {
LessThan,
LessThanOrEqual,
Equal,
NotEqual,
GreaterThanOrEqual,
GreaterThan,
And,
Or,
UnknownArg(i32),
}
impl ComparisonOperator {
fn from_arg(value: i32) -> ComparisonOperator {
match value {
0 => ComparisonOperator::LessThan,
1 => ComparisonOperator::LessThanOrEqual,
2 => ComparisonOperator::Equal,
3 => ComparisonOperator::NotEqual,
4 => ComparisonOperator::GreaterThanOrEqual,
5 => ComparisonOperator::GreaterThan,
v => ComparisonOperator::UnknownArg(v),
}
}
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub enum EdgeSlide {
SlideOff,
StayOn,
Airbourne,
Unknown(i32),
}
impl EdgeSlide {
fn new(value: i32) -> EdgeSlide {
match value {
0 => EdgeSlide::SlideOff,
1 => EdgeSlide::StayOn,
5 => EdgeSlide::Airbourne,
v => EdgeSlide::Unknown(v),
}
}
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub enum HurtBoxState {
Normal,
Invincible,
IntangibleFlashing,
IntangibleNoFlashing,
IntangibleQuickFlashing,
Unknown(i32),
}
impl HurtBoxState {
fn new(value: i32) -> HurtBoxState {
match value {
0 => HurtBoxState::Normal,
1 => HurtBoxState::Invincible,
2 => HurtBoxState::IntangibleFlashing,
3 => HurtBoxState::IntangibleNoFlashing,
4 => HurtBoxState::IntangibleQuickFlashing,
v => HurtBoxState::Unknown(v),
}
}
pub fn is_normal(&self) -> bool {
matches!(self, HurtBoxState::Normal)
}
pub fn is_invincible(&self) -> bool {
matches!(self, HurtBoxState::Invincible)
}
pub fn is_intangible(&self) -> bool {
matches!(
self,
HurtBoxState::IntangibleFlashing
| HurtBoxState::IntangibleNoFlashing
| HurtBoxState::IntangibleQuickFlashing
)
}
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
pub enum AngleFlip {
AttackerPosition,
MovementDir,
LeftDir,
AttackerDir,
AttackerDirReverse,
HitboxPosition,
FaceZaxis,
Unknown(i32),
}
impl AngleFlip {
fn new(value: i32) -> AngleFlip {
match value {
0 => AngleFlip::AttackerPosition,
1 => AngleFlip::MovementDir,
2 => AngleFlip::LeftDir,
3 => AngleFlip::AttackerDir,
4 => AngleFlip::AttackerDirReverse,
5 => AngleFlip::HitboxPosition,
6 | 7 => AngleFlip::FaceZaxis,
v => AngleFlip::Unknown(v),
}
}
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
pub enum HitBoxEffect {
Normal,
None,
Slash,
Electric,
Freezing,
Flame,
Coin,
Reverse,
Trip,
Sleep,
Bury,
Stun,
Flower,
Grass,
Water,
Darkness,
Paralyze,
Aura,
Plunge,
Down,
Flinchless,
Unknown(i32),
}
impl HitBoxEffect {
fn new(value: i32) -> HitBoxEffect {
match value {
00 => HitBoxEffect::Normal,
01 => HitBoxEffect::None,
02 => HitBoxEffect::Slash,
03 => HitBoxEffect::Electric,
04 => HitBoxEffect::Freezing,
05 => HitBoxEffect::Flame,
06 => HitBoxEffect::Coin,
07 => HitBoxEffect::Reverse,
08 => HitBoxEffect::Trip,
09 => HitBoxEffect::Sleep,
11 => HitBoxEffect::Bury,
12 => HitBoxEffect::Stun,
14 => HitBoxEffect::Flower,
17 => HitBoxEffect::Grass,
18 => HitBoxEffect::Water,
19 => HitBoxEffect::Darkness,
20 => HitBoxEffect::Paralyze,
21 => HitBoxEffect::Aura,
22 => HitBoxEffect::Plunge,
23 => HitBoxEffect::Down,
24 => HitBoxEffect::Flinchless,
v => HitBoxEffect::Unknown(v),
}
}
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
pub enum HitBoxSound {
Unique,
Punch,
Kick,
Slash,
Coin,
HomeRunBat,
Paper,
Shock,
Burn,
Splash,
Explosion,
Thud,
Slam,
Thwomp,
MagicZap,
Shell,
Slap,
Pan,
Club,
Racket,
Aura,
NessBat,
Unknown(i32),
}
impl HitBoxSound {
fn new(value: i32) -> HitBoxSound {
match value {
00 => HitBoxSound::Unique,
01 => HitBoxSound::Punch,
02 => HitBoxSound::Kick,
03 => HitBoxSound::Slash,
04 => HitBoxSound::Coin,
05 => HitBoxSound::HomeRunBat,
06 => HitBoxSound::Paper,
07 => HitBoxSound::Shock,
08 => HitBoxSound::Burn,
09 => HitBoxSound::Splash,
11 => HitBoxSound::Explosion,
13 => HitBoxSound::Thud,
14 => HitBoxSound::Slam,
15 => HitBoxSound::Thwomp,
16 => HitBoxSound::MagicZap,
17 => HitBoxSound::Shell,
18 => HitBoxSound::Slap,
19 => HitBoxSound::Pan,
20 => HitBoxSound::Club,
21 => HitBoxSound::Racket,
22 => HitBoxSound::Aura,
27 => HitBoxSound::NessBat,
_ => HitBoxSound::Unknown(value),
}
}
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
pub enum HitBoxSseType {
None,
Head,
Body,
Butt,
Hand,
Elbow,
Foot,
Knee,
Throwing,
Weapon,
Sword,
Hammer,
Explosive,
Spin,
Bite,
Magic,
Pk,
Bow,
NessBat,
Umbrella,
Pimin,
Water,
Whip,
Tail,
Energy,
Unknown(i32),
}
impl HitBoxSseType {
fn new(value: i32) -> HitBoxSseType {
match value {
00 => HitBoxSseType::None,
01 => HitBoxSseType::Head,
02 => HitBoxSseType::Body,
03 => HitBoxSseType::Butt,
04 => HitBoxSseType::Hand,
05 => HitBoxSseType::Elbow,
06 => HitBoxSseType::Foot,
07 => HitBoxSseType::Knee,
08 => HitBoxSseType::Throwing,
09 => HitBoxSseType::Weapon,
10 => HitBoxSseType::Sword,
11 => HitBoxSseType::Hammer,
12 => HitBoxSseType::Explosive,
13 => HitBoxSseType::Spin,
14 => HitBoxSseType::Bite,
15 => HitBoxSseType::Magic,
16 => HitBoxSseType::Pk,
17 => HitBoxSseType::Bow,
19 => HitBoxSseType::NessBat,
20 => HitBoxSseType::Umbrella,
21 => HitBoxSseType::Pimin,
22 => HitBoxSseType::Water,
23 => HitBoxSseType::Whip,
24 => HitBoxSseType::Tail,
25 => HitBoxSseType::Energy,
_ => HitBoxSseType::Unknown(value),
}
}
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct HitBoxArguments {
pub bone_index: i16,
pub hitbox_id: u8,
pub set_id: u8,
pub damage: FloatValue,
pub trajectory: i32,
pub wdsk: i16,
pub kbg: i16,
pub shield_damage: i16,
pub bkb: i16,
pub size: f32,
pub x_offset: f32,
pub y_offset: f32,
pub z_offset: f32,
pub tripping_rate: f32,
pub hitlag_mult: f32,
pub sdi_mult: f32,
pub effect: HitBoxEffect,
pub unk1: bool,
pub sound_level: u8,
pub unk2: bool,
pub sound: HitBoxSound,
pub unk3: u8,
pub ground: bool,
pub aerial: bool,
pub unk4: u8,
pub sse_type: HitBoxSseType,
pub clang: bool,
pub unk5: bool,
pub direct: bool,
pub unk6: u8,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct SpecialHitBoxArguments {
pub hitbox_args: HitBoxArguments,
pub rehit_rate: i32,
pub angle_flipping: AngleFlip,
pub unk1: bool,
pub stretches_to_bone: bool,
pub unk2: bool,
pub can_hit1: bool,
pub can_hit2: bool,
pub can_hit3: bool,
pub can_hit4: bool,
pub can_hit5: bool,
pub can_hit6: bool,
pub can_hit7: bool,
pub can_hit8: bool,
pub can_hit9: bool,
pub can_hit10: bool,
pub can_hit11: bool,
pub can_hit12: bool,
pub can_hit13: bool,
pub enabled: bool,
pub unk3: u8,
pub can_be_shielded: bool,
pub can_be_reflected: bool,
pub can_be_absorbed: bool,
pub unk4: u8,
pub remain_grabbed: bool,
pub ignore_invincibility: bool,
pub freeze_frame_disable: bool,
pub unk5: bool,
pub flinchless: bool,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub enum DefensiveCollisionType {
Block,
Reflect,
Unknown(i32),
}
impl DefensiveCollisionType {
fn new(value: i32) -> Self {
match value {
2 => DefensiveCollisionType::Block,
3 => DefensiveCollisionType::Reflect,
v => DefensiveCollisionType::Unknown(v),
}
}
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub enum DefensiveCollisionDirection {
Front,
FrontAndBack,
Unknown(i32),
}
impl DefensiveCollisionDirection {
fn new(value: i32) -> Self {
match value {
1 => DefensiveCollisionDirection::Front,
2 => DefensiveCollisionDirection::FrontAndBack,
v => DefensiveCollisionDirection::Unknown(v),
}
}
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct MoveHitBox {
pub hitbox_id: i32,
pub new_bone: i32,
pub new_x_offset: f32,
pub new_y_offset: f32,
pub new_z_offset: f32,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct GrabBoxArguments {
pub hitbox_id: i32,
pub bone_index: i32,
pub size: f32,
pub x_offset: f32,
pub y_offset: f32,
pub z_offset: f32,
pub set_action: i32,
pub target: GrabTarget,
pub unk: Option<i32>,
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
pub enum GrabTarget {
None,
GroundedOnly,
AerialOnly,
AerialAndGrounded,
Unknown(i32),
}
impl GrabTarget {
fn new(value: i32) -> GrabTarget {
match value {
0 => GrabTarget::None,
1 => GrabTarget::GroundedOnly,
2 => GrabTarget::AerialOnly,
3 => GrabTarget::AerialAndGrounded,
v => GrabTarget::Unknown(v),
}
}
pub fn grounded(&self) -> bool {
matches!(
self,
GrabTarget::GroundedOnly | GrabTarget::AerialAndGrounded
)
}
pub fn aerial(&self) -> bool {
matches!(self, GrabTarget::AerialOnly | GrabTarget::AerialAndGrounded)
}
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct SpecifyThrow {
pub throw_use: ThrowUse,
pub bone: i32,
pub damage: i32,
pub trajectory: i32,
pub kbg: i32,
pub wdsk: i32,
pub bkb: i32,
pub effect: HitBoxEffect,
pub unk0: f32,
pub unk1: f32,
pub unk2: f32,
pub unk3: i32,
pub sfx: HitBoxSound,
pub grab_target: GrabTarget,
pub unk4: bool,
pub unk5: bool,
pub i_frames: i32,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub enum ThrowUse {
Throw,
GrabInterrupt,
Unknown(i32),
}
impl ThrowUse {
fn new(value: i32) -> ThrowUse {
match value {
0 => ThrowUse::Throw,
1 => ThrowUse::GrabInterrupt,
v => ThrowUse::Unknown(v),
}
}
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct ApplyThrow {
pub unk0: i32,
pub bone: i32,
pub unk1: VariableAst,
pub unk2: VariableAst,
pub unk3: VariableAst,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub enum LedgeGrabEnable {
Disable,
EnableInFront,
EnableInFrontAndBehind,
Unknown(i32),
}
impl LedgeGrabEnable {
fn new(value: i32) -> LedgeGrabEnable {
match value {
0 => LedgeGrabEnable::Disable,
1 => LedgeGrabEnable::EnableInFront,
2 => LedgeGrabEnable::EnableInFrontAndBehind,
v => LedgeGrabEnable::Unknown(v),
}
}
pub fn enabled(&self) -> bool {
match self {
LedgeGrabEnable::EnableInFront => true,
LedgeGrabEnable::EnableInFrontAndBehind => true,
LedgeGrabEnable::Disable => false,
LedgeGrabEnable::Unknown(_) => false,
}
}
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub enum ArmorType {
None,
SuperArmor,
HeavyArmorKnockbackBased,
HeavyArmorDamageBased,
Unknown(i32),
}
impl ArmorType {
fn new(value: i32) -> ArmorType {
match value {
0 => ArmorType::None,
1 => ArmorType::SuperArmor,
2 => ArmorType::HeavyArmorKnockbackBased,
3 => ArmorType::HeavyArmorDamageBased,
v => ArmorType::Unknown(v),
}
}
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct SetOrAddVelocity {
pub x_vel: f32,
pub y_vel: f32,
pub x_set: bool,
pub y_set: bool,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub enum DisableMovement {
Enable,
DisableVertical,
DisableHorizontal,
Unknown(i32),
}
impl DisableMovement {
fn new(value: i32) -> DisableMovement {
match value {
0 => DisableMovement::Enable,
1 => DisableMovement::DisableVertical,
2 => DisableMovement::DisableHorizontal,
v => DisableMovement::Unknown(v),
}
}
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct GraphicEffect {
pub graphic: i32,
pub bone: i32,
pub x_offset: f32,
pub y_offset: f32,
pub z_offset: f32,
pub x_rotation: f32,
pub y_rotation: f32,
pub z_rotation: f32,
pub scale: f32,
pub random_x_offset: f32,
pub random_y_offset: f32,
pub random_z_offset: f32,
pub random_x_rotation: f32,
pub random_y_rotation: f32,
pub random_z_rotation: f32,
pub terminate_with_animation: bool,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct ExternalGraphicEffect {
pub file: i16,
pub graphic: i16,
pub bone: i32,
pub x_offset: f32,
pub y_offset: f32,
pub z_offset: f32,
pub x_rotation: f32,
pub y_rotation: f32,
pub z_rotation: f32,
pub scale: f32,
pub randomize: Option<ExternalGraphicEffectRandomize>,
pub terminate_with_animation: bool,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct ExternalGraphicEffectRandomize {
pub random_x_offset: f32,
pub random_y_offset: f32,
pub random_z_offset: f32,
pub random_x_rotation: f32,
pub random_y_rotation: f32,
pub random_z_rotation: f32,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct LimitedScreenTint {
pub transition_in_time: i32,
pub red: i32,
pub green: i32,
pub blue: i32,
pub alpha: i32,
pub frame_count: i32,
pub transition_out_time: i32,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct UnlimitedScreenTint {
pub tint_id: i32,
pub transition_in_time: i32,
pub red: i32,
pub green: i32,
pub blue: i32,
pub alpha: i32,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct SwordGlow {
pub color: i32,
pub blur_length: i32,
pub point1_bone: i32,
pub point1_x_offset: f32,
pub point1_y_offset: f32,
pub point1_z_offset: f32,
pub point2_bone: i32,
pub point2_x_offset: f32,
pub point2_y_offset: f32,
pub point2_z_offset: f32,
pub delete_after_subaction: bool,
pub graphic_id: i32,
pub bone_id: i32,
pub x_offset: f32,
pub y_offset: f32,
pub z_offset: f32,
pub x_rotation: f32,
pub y_rotation: f32,
pub z_rotation: f32,
pub glow_length: f32,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct AestheticWindEffect {
pub unk1: i32,
pub unk2: f32,
pub stength: f32,
pub speed: f32,
pub size: f32,
pub unk3: f32,
pub unk4: f32,
pub unk5: f32,
pub unk6: f32,
pub unk7: f32,
pub unk8: i32,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct Interrupt {
pub interrupt_id: Option<i32>,
pub action: i32,
pub test: Expression,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub enum InterruptType {
Main,
GroundSpecial,
GroundItem,
GroundCatch,
GroundAttack,
GroundEscape,
GroundGuard,
GroundJump,
GroundOther,
AirLanding,
CliffCatch,
AirSpecial,
AirItemThrow,
AirLasso,
AirDodge,
AirAttack,
AirTreadjump,
AirWalljump,
AirJump,
PassThroughPlat,
Unknown(i32),
}
impl InterruptType {
pub fn new(value: i32) -> Self {
match value {
0x00 => InterruptType::Main,
0x01 => InterruptType::GroundSpecial,
0x02 => InterruptType::GroundItem,
0x03 => InterruptType::GroundCatch,
0x04 => InterruptType::GroundAttack,
0x05 => InterruptType::GroundEscape,
0x06 => InterruptType::GroundGuard,
0x07 => InterruptType::GroundJump,
0x08 => InterruptType::GroundOther,
0x09 => InterruptType::AirLanding,
0x0A => InterruptType::CliffCatch,
0x0B => InterruptType::AirSpecial,
0x0C => InterruptType::AirItemThrow,
0x0D => InterruptType::AirLasso,
0x0E => InterruptType::AirDodge,
0x0F => InterruptType::AirAttack,
0x10 => InterruptType::AirTreadjump,
0x11 => InterruptType::AirWalljump,
0x12 => InterruptType::AirJump,
0x13 => InterruptType::PassThroughPlat,
_ => InterruptType::Unknown(value),
}
}
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct CameraCloseup {
pub zoom_time: i32,
pub unk: i32,
pub distance: f32,
pub x_angle: f32,
pub y_angle: f32,
}