From 750859366a3087c72d704c75647ce385d61fb34e Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Thu, 5 Mar 2026 19:52:54 +0000 Subject: [PATCH 001/187] feat: impl Container::push --- crates/ltk_meta/src/property/values/container.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/crates/ltk_meta/src/property/values/container.rs b/crates/ltk_meta/src/property/values/container.rs index 2771f27b..13ff208f 100644 --- a/crates/ltk_meta/src/property/values/container.rs +++ b/crates/ltk_meta/src/property/values/container.rs @@ -108,6 +108,21 @@ macro_rules! define_container_enum { } impl Container { + + pub fn push(&mut self, value: PropertyValueEnum) -> Result<(), Error>{ + let got = value.kind(); + let expected = self.item_kind(); + match (self, value) { + $((Self::$variant{items,..}, PropertyValueEnum::$variant(item)) => { + items.push(item); + Ok(()) + })* + _ => { + Err(Error::MismatchedContainerTypes { got, expected }) + } + } + } + /// Iterator that returns each item as a [`PropertyValueEnum`] for convenience. #[inline(always)] #[must_use] From 1833a701c5b1451c9566c478f5743296e7798ead Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Thu, 5 Mar 2026 19:55:49 +0000 Subject: [PATCH 002/187] feat: impl Map::push --- crates/ltk_meta/src/property/values/map.rs | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/crates/ltk_meta/src/property/values/map.rs b/crates/ltk_meta/src/property/values/map.rs index 03ef2d21..454fa43b 100644 --- a/crates/ltk_meta/src/property/values/map.rs +++ b/crates/ltk_meta/src/property/values/map.rs @@ -65,6 +65,28 @@ impl Map { pub fn into_entries(self) -> Vec<(PropertyValueEnum, PropertyValueEnum)> { self.entries } + + #[inline(always)] + pub fn push( + &mut self, + key: PropertyValueEnum, + value: PropertyValueEnum, + ) -> Result<(), Error> { + if self.key_kind != key.kind() { + return Err(Error::MismatchedContainerTypes { + expected: self.key_kind, + got: key.kind(), + }); + } + if self.value_kind != value.kind() { + return Err(Error::MismatchedContainerTypes { + expected: self.value_kind, + got: value.kind(), + }); + } + self.entries.push((key, value)); + Ok(()) + } } impl Map { From 1f1a49102cc4e381e9a1d069e967ca885fb28fb8 Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Thu, 5 Mar 2026 20:39:36 +0000 Subject: [PATCH 003/187] feat: impl Container::empty/empty_const --- crates/ltk_meta/src/property/values/container.rs | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/crates/ltk_meta/src/property/values/container.rs b/crates/ltk_meta/src/property/values/container.rs index 13ff208f..d019d21b 100644 --- a/crates/ltk_meta/src/property/values/container.rs +++ b/crates/ltk_meta/src/property/values/container.rs @@ -108,6 +108,19 @@ macro_rules! define_container_enum { } impl Container { + pub fn empty(item_kind: Kind) -> Result + where + M: Default + { + match item_kind { + $(Kind::$variant => Ok(Self::$variant { + items: vec![], + meta: M::default(), + }),)* + kind => Err(Error::InvalidNesting(kind)), + + } + } pub fn push(&mut self, value: PropertyValueEnum) -> Result<(), Error>{ let got = value.kind(); @@ -164,7 +177,7 @@ impl Container { Self::from(items) } - pub fn empty() -> Self + pub fn empty_const() -> Self where Self: From>, { From 43c1eef19b9038b9d1d028b338c050efe26e6d16 Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Thu, 5 Mar 2026 20:45:35 +0000 Subject: [PATCH 004/187] feat: impl Optional::empty_const --- crates/ltk_meta/src/property/values/optional.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/crates/ltk_meta/src/property/values/optional.rs b/crates/ltk_meta/src/property/values/optional.rs index b3748b30..81782e7c 100644 --- a/crates/ltk_meta/src/property/values/optional.rs +++ b/crates/ltk_meta/src/property/values/optional.rs @@ -84,6 +84,13 @@ impl Default for Optional { } impl Optional { + pub fn empty_const() -> Self + where + Self: From>, + { + Self::from(None) + } + #[inline(always)] #[must_use] pub fn item_kind(&self) -> Kind { From e56f2479da26782c38fbeb3c95d6979d6d5a2ec6 Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Thu, 5 Mar 2026 20:51:20 +0000 Subject: [PATCH 005/187] fix: tests --- crates/ltk_meta/src/tree/tests.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/ltk_meta/src/tree/tests.rs b/crates/ltk_meta/src/tree/tests.rs index a4594773..520694b4 100644 --- a/crates/ltk_meta/src/tree/tests.rs +++ b/crates/ltk_meta/src/tree/tests.rs @@ -298,7 +298,7 @@ fn test_object_link_property_roundtrip() { fn test_container_empty_roundtrip() { let prop = make_prop( 0x1234, - PropertyValueEnum::Container(values::Container::empty::()), + PropertyValueEnum::Container(values::Container::empty_const::()), ); let result = roundtrip_property(&prop); assert_eq!(prop, result); From be77f2f69f555535d1fe1380dd70babc097e9d64 Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Fri, 6 Mar 2026 20:02:27 +0000 Subject: [PATCH 006/187] feat: add PropertyExt::meta() + meta to Optional --- crates/ltk_meta/src/property/enum.rs | 33 ++++++- .../ltk_meta/src/property/values/container.rs | 9 ++ .../src/property/values/container/iter.rs | 4 +- .../ltk_meta/src/property/values/embedded.rs | 4 + crates/ltk_meta/src/property/values/map.rs | 5 + crates/ltk_meta/src/property/values/none.rs | 5 + .../ltk_meta/src/property/values/optional.rs | 98 +++++++++++++------ .../src/property/values/primitives.rs | 5 + crates/ltk_meta/src/property/values/string.rs | 5 + crates/ltk_meta/src/property/values/struct.rs | 5 + .../property/values/unordered_container.rs | 5 + crates/ltk_meta/src/traits.rs | 4 +- 12 files changed, 145 insertions(+), 37 deletions(-) diff --git a/crates/ltk_meta/src/property/enum.rs b/crates/ltk_meta/src/property/enum.rs index 726ff38b..a7653d78 100644 --- a/crates/ltk_meta/src/property/enum.rs +++ b/crates/ltk_meta/src/property/enum.rs @@ -2,7 +2,7 @@ use enum_dispatch::enum_dispatch; use crate::{ property::{Kind, NoMeta}, - traits::{ReadProperty as _, WriteProperty as _}, + traits::{PropertyExt, ReadProperty as _, WriteProperty as _}, Error, }; use std::io; @@ -50,10 +50,9 @@ macro_rules! create_enum { )] #[cfg_attr(feature = "serde", serde(tag = "kind", content = "value"))] #[derive(Clone, Debug, PartialEq)] - #[enum_dispatch(PropertyExt)] /// The value part of a [`super::BinProperty`]. Holds the type of the value, and the value itself. pub enum PropertyValueEnum { - $( $variant (pub self::$variant), )* + $( $variant (self::$variant), )* } @@ -87,7 +86,35 @@ macro_rules! create_enum { $(Self::$variant(_) => Kind::$variant,)* } } + } + + impl PropertyExt for PropertyValueEnum { + type Meta = M; + fn meta(&self) -> &Self::Meta { + match self { + $(Self::$variant(i) => i.meta(),)* + } + } + fn size(&self, include_header: bool) -> usize { + match self { + $(Self::$variant(i) => i.size(include_header),)* + } + } + fn size_no_header(&self) -> usize { + match self { + $(Self::$variant(i) => i.size_no_header(),)* + } + } + } + + $( + impl From> for PropertyValueEnum { + fn from(other: values::$variant) -> Self { + Self::$variant(other) + } + } + )* }; } diff --git a/crates/ltk_meta/src/property/values/container.rs b/crates/ltk_meta/src/property/values/container.rs index d019d21b..a3e9c7c0 100644 --- a/crates/ltk_meta/src/property/values/container.rs +++ b/crates/ltk_meta/src/property/values/container.rs @@ -42,6 +42,15 @@ macro_rules! define_container_enum { })* } } + + type Meta = M; + fn meta(&self) -> &Self::Meta { + match &self { + $(Self::$variant{meta,..} => { + meta + })* + } + } } $( diff --git a/crates/ltk_meta/src/property/values/container/iter.rs b/crates/ltk_meta/src/property/values/container/iter.rs index fbfbb692..d6b54bf9 100644 --- a/crates/ltk_meta/src/property/values/container/iter.rs +++ b/crates/ltk_meta/src/property/values/container/iter.rs @@ -6,7 +6,7 @@ use crate::{ pub struct ItemsDyn<'a, M>(ItemsDynInner<'a, M>); impl<'a, M> Iterator for ItemsDyn<'a, M> { - type Item = &'a dyn PropertyValueDyn; + type Item = &'a dyn PropertyValueDyn; fn next(&mut self) -> Option { self.0.next() @@ -39,7 +39,7 @@ macro_rules! define_dyn_iter { } impl<'a, M> Iterator for ItemsDynInner<'a, M> { - type Item = &'a dyn PropertyValueDyn; + type Item = &'a dyn PropertyValueDyn; fn next(&mut self) -> Option { match self { diff --git a/crates/ltk_meta/src/property/values/embedded.rs b/crates/ltk_meta/src/property/values/embedded.rs index 958e40a6..e65c4785 100644 --- a/crates/ltk_meta/src/property/values/embedded.rs +++ b/crates/ltk_meta/src/property/values/embedded.rs @@ -21,6 +21,10 @@ impl PropertyExt for Embedded { fn size_no_header(&self) -> usize { self.0.size_no_header() } + type Meta = M; + fn meta(&self) -> &Self::Meta { + self.0.meta() + } } impl ReadProperty for Embedded { diff --git a/crates/ltk_meta/src/property/values/map.rs b/crates/ltk_meta/src/property/values/map.rs index 454fa43b..2e0119b9 100644 --- a/crates/ltk_meta/src/property/values/map.rs +++ b/crates/ltk_meta/src/property/values/map.rs @@ -141,6 +141,11 @@ impl PropertyExt for Map { .map(|(k, v)| k.size_no_header() + v.size_no_header()) .sum::() } + + type Meta = M; + fn meta(&self) -> &Self::Meta { + &self.meta + } } impl ReadProperty for Map { diff --git a/crates/ltk_meta/src/property/values/none.rs b/crates/ltk_meta/src/property/values/none.rs index 0c3a1ff1..e636bfc5 100644 --- a/crates/ltk_meta/src/property/values/none.rs +++ b/crates/ltk_meta/src/property/values/none.rs @@ -19,6 +19,11 @@ impl PropertyExt for None { fn size_no_header(&self) -> usize { 0 } + + type Meta = M; + fn meta(&self) -> &Self::Meta { + &self.meta + } } impl ReadProperty for None { diff --git a/crates/ltk_meta/src/property/values/optional.rs b/crates/ltk_meta/src/property/values/optional.rs index 81782e7c..20e93cd2 100644 --- a/crates/ltk_meta/src/property/values/optional.rs +++ b/crates/ltk_meta/src/property/values/optional.rs @@ -14,7 +14,10 @@ macro_rules! construct_enum { )] #[derive(Clone, PartialEq, Debug)] pub enum Optional { - $($variant(Option>),)* + $($variant{ + value: Option>, + meta: M + },)* } impl Optional { @@ -23,7 +26,7 @@ macro_rules! construct_enum { /// Helper function to create an empty [`Optional`], if the property kind can be stored in one. pub fn empty(kind: Kind) -> Option { Some(match kind { - $(Kind::$variant => Self::$variant(None),)* + $(Kind::$variant => Self::$variant{value: None, meta: M::default()},)* _ => return None }) } @@ -32,15 +35,22 @@ macro_rules! construct_enum { impl PropertyExt for Optional { fn size_no_header(&self) -> usize { 2 + match &self { - $(Self::$variant(inner) => inner.as_ref().map(|i| i.size_no_header()).unwrap_or_default(),)* + $(Self::$variant{value, ..} => value.as_ref().map(|i| i.size_no_header()).unwrap_or_default(),)* } } + type Meta = M; + fn meta(&self) -> &Self::Meta { + match &self { + $(Self::$variant{meta, ..} => meta,)* + } + + } } $( impl From>> for Optional { fn from(other: Option>) -> Self { - Self::$variant(other) + Self::$variant{value: other, meta: M::default()} } } @@ -48,27 +58,50 @@ macro_rules! construct_enum { $( impl From> for Optional { fn from(other: values::$variant) -> Self { - Self::$variant(Some(other)) + Self::$variant{value: Some(other), meta: M::default()} } } )* - impl Optional { - pub fn new(item_kind: Kind, value: Option>) -> Result { + impl Optional { + #[inline(always)] + pub fn new(item_kind: Kind, value: Option>) -> Result where M: Default { + Self::new_with_meta(item_kind, value, M::default()) + } + #[inline(always)] + pub fn new_with_meta(item_kind: Kind, value: Option>, meta: M) -> Result { match item_kind { $(Kind::$variant => match value { - Some(PropertyValueEnum::$variant(inner)) => Ok(Self::$variant(Some(inner))), - None => Ok(Self::$variant(None)), + Some(PropertyValueEnum::$variant(inner)) => Ok(Self::$variant{value: Some(inner), meta}), + None => Ok(Self::$variant{value: None, meta}), Some(value) => Err(Error::MismatchedContainerTypes {expected: item_kind, got: value.kind()}), },)* kind => Err(Error::InvalidNesting(kind)), } } - pub fn into_inner(self) -> Option> { + #[inline(always)] + #[must_use] + pub fn into_parts(self) -> (Option>, M) { + match self { + $(Optional::$variant{ value, meta } => (value.map(PropertyValueEnum::$variant), meta),)* + } + } + + #[inline(always)] + #[must_use] + pub fn is_some(&self) -> bool { + match self { + $(Self::$variant{value,..} => value.is_some(),)* + } + } + + #[inline(always)] + #[must_use] + pub fn is_none(&self) -> bool { match self { - $(Optional::$variant(item) => item.map(PropertyValueEnum::$variant),)* + $(Self::$variant{value,..} => value.is_none(),)* } } } @@ -79,7 +112,10 @@ container_variants!(construct_enum); impl Default for Optional { fn default() -> Self { - Self::None(None) + Self::None { + value: None, + meta: M::default(), + } } } @@ -97,16 +133,11 @@ impl Optional { container_variants!(property_kinds, (self)) } - #[inline(always)] - #[must_use] - pub fn is_some(&self) -> bool { - match_property!(self, inner => inner.is_some()) + pub fn into_inner(self) -> Option> { + self.into_parts().0 } - - #[inline(always)] - #[must_use] - pub fn is_none(&self) -> bool { - match_property!(self, inner => inner.is_none()) + pub fn into_meta(self) -> M { + self.into_parts().1 } } @@ -132,8 +163,8 @@ impl ReadProperty for Optional { match $value { $( Kind::$variant => match is_some { - true => values::$variant::from_reader(reader, legacy).map(Some).map(Self::$variant), - false => Ok(Self::$variant(None)), + true => Ok(values::$variant::from_reader(reader, legacy)?.into()), + false => Ok(Self::empty_const::>()), }, )* kind => { return Err(Error::InvalidNesting(kind)) } @@ -156,14 +187,19 @@ impl WriteProperty for Optional { writer.write_property_kind(self.item_kind())?; writer.write_bool(self.is_some())?; - match_property!( - self, - Some(inner) => { - inner.to_writer(writer, legacy)?; - }, - _ => {} - ); + macro_rules! write_inner { + (($value:expr) + [$( $variant:ident, )*]) => { + match $value { + $( + Self::$variant{value: Some(value),..} => value.to_writer(writer, legacy), + + )* + _ => { Ok(()) } + } + }; + } - Ok(()) + container_variants!(write_inner, (self)) } } diff --git a/crates/ltk_meta/src/property/values/primitives.rs b/crates/ltk_meta/src/property/values/primitives.rs index eb9c30ac..d0db8c31 100644 --- a/crates/ltk_meta/src/property/values/primitives.rs +++ b/crates/ltk_meta/src/property/values/primitives.rs @@ -32,6 +32,11 @@ macro_rules! impl_prim { fn size_no_header(&self) -> usize { core::mem::size_of::<$rust>() } + + type Meta = M; + fn meta(&self) -> &Self::Meta { + &self.meta + } } impl PropertyValueExt for $name { diff --git a/crates/ltk_meta/src/property/values/string.rs b/crates/ltk_meta/src/property/values/string.rs index 7a377919..e0a6294b 100644 --- a/crates/ltk_meta/src/property/values/string.rs +++ b/crates/ltk_meta/src/property/values/string.rs @@ -35,6 +35,11 @@ impl PropertyExt for String { fn size_no_header(&self) -> usize { self.value.len() + 2 } + + type Meta = M; + fn meta(&self) -> &Self::Meta { + &self.meta + } } impl ReadProperty for String { diff --git a/crates/ltk_meta/src/property/values/struct.rs b/crates/ltk_meta/src/property/values/struct.rs index c58d243b..c6376294 100644 --- a/crates/ltk_meta/src/property/values/struct.rs +++ b/crates/ltk_meta/src/property/values/struct.rs @@ -32,6 +32,11 @@ impl PropertyExt for Struct { _ => 10 + self.properties.values().map(|p| p.size()).sum::(), } } + + type Meta = M; + fn meta(&self) -> &Self::Meta { + &self.meta + } } impl ReadProperty for Struct { diff --git a/crates/ltk_meta/src/property/values/unordered_container.rs b/crates/ltk_meta/src/property/values/unordered_container.rs index 1766f6e5..b552105a 100644 --- a/crates/ltk_meta/src/property/values/unordered_container.rs +++ b/crates/ltk_meta/src/property/values/unordered_container.rs @@ -21,6 +21,11 @@ impl PropertyExt for UnorderedContainer { fn size_no_header(&self) -> usize { self.0.size_no_header() } + + type Meta = M; + fn meta(&self) -> &Self::Meta { + self.0.meta() + } } impl ReadProperty for UnorderedContainer { diff --git a/crates/ltk_meta/src/traits.rs b/crates/ltk_meta/src/traits.rs index e718f92f..8e655e1b 100644 --- a/crates/ltk_meta/src/traits.rs +++ b/crates/ltk_meta/src/traits.rs @@ -7,7 +7,6 @@ use enum_dispatch::enum_dispatch; const HEADER_SIZE: usize = 5; /// General methods for property values -#[enum_dispatch] pub trait PropertyExt { /// Get the size of the property value, including the kind header if specified fn size(&self, include_header: bool) -> usize { @@ -18,6 +17,9 @@ pub trait PropertyExt { } } fn size_no_header(&self) -> usize; + + type Meta; + fn meta(&self) -> &Self::Meta; } pub trait PropertyValueExt { From 6fbf4fd67a779c71ff909befc3e6f865374cfdbb Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Fri, 6 Mar 2026 20:15:49 +0000 Subject: [PATCH 007/187] fix: propagate meta generic to BinProperty/Struct --- crates/ltk_meta/src/property.rs | 22 ++++++++++++++----- .../ltk_meta/src/property/values/embedded.rs | 2 +- .../ltk_meta/src/property/values/optional.rs | 2 +- crates/ltk_meta/src/property/values/struct.rs | 4 ++-- 4 files changed, 20 insertions(+), 10 deletions(-) diff --git a/crates/ltk_meta/src/property.rs b/crates/ltk_meta/src/property.rs index b81d3afa..cde2592d 100644 --- a/crates/ltk_meta/src/property.rs +++ b/crates/ltk_meta/src/property.rs @@ -17,20 +17,27 @@ use crate::traits::PropertyExt; #[derive(Clone, Copy, Default, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct NoMeta; -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr( + feature = "serde", + derive(serde::Serialize, serde::Deserialize), + serde(bound = "for <'dee> M: serde::Serialize + serde::Deserialize<'dee>") +)] #[derive(Clone, PartialEq, Debug)] -pub struct BinProperty { +pub struct BinProperty { pub name_hash: u32, #[cfg_attr(feature = "serde", serde(flatten))] - pub value: PropertyValueEnum, + pub value: PropertyValueEnum, } -impl BinProperty { +impl BinProperty { /// Read a BinProperty from a reader. This will read the name_hash, prop kind and then value, in that order. pub fn from_reader( reader: &mut R, legacy: bool, - ) -> Result { + ) -> Result + where + M: Default, + { let name_hash = reader.read_u32::()?; let kind = reader.read_property_kind(legacy)?; @@ -42,7 +49,10 @@ impl BinProperty { pub fn to_writer( &self, writer: &mut W, - ) -> Result<(), io::Error> { + ) -> Result<(), io::Error> + where + M: Clone, + { writer.write_u32::(self.name_hash)?; writer.write_property_kind(self.value.kind())?; diff --git a/crates/ltk_meta/src/property/values/embedded.rs b/crates/ltk_meta/src/property/values/embedded.rs index e65c4785..986dc521 100644 --- a/crates/ltk_meta/src/property/values/embedded.rs +++ b/crates/ltk_meta/src/property/values/embedded.rs @@ -35,7 +35,7 @@ impl ReadProperty for Embedded { Struct::::from_reader(reader, legacy).map(Self) } } -impl WriteProperty for Embedded { +impl WriteProperty for Embedded { fn to_writer( &self, writer: &mut R, diff --git a/crates/ltk_meta/src/property/values/optional.rs b/crates/ltk_meta/src/property/values/optional.rs index 20e93cd2..48b0e633 100644 --- a/crates/ltk_meta/src/property/values/optional.rs +++ b/crates/ltk_meta/src/property/values/optional.rs @@ -175,7 +175,7 @@ impl ReadProperty for Optional { container_variants!(read_inner, (kind)) } } -impl WriteProperty for Optional { +impl WriteProperty for Optional { fn to_writer( &self, writer: &mut R, diff --git a/crates/ltk_meta/src/property/values/struct.rs b/crates/ltk_meta/src/property/values/struct.rs index c6376294..26c3ea8b 100644 --- a/crates/ltk_meta/src/property/values/struct.rs +++ b/crates/ltk_meta/src/property/values/struct.rs @@ -17,7 +17,7 @@ use ltk_io_ext::{measure, window_at}; #[derive(Clone, PartialEq, Debug, Default)] pub struct Struct { pub class_hash: u32, - pub properties: IndexMap, + pub properties: IndexMap>, pub meta: M, } @@ -75,7 +75,7 @@ impl ReadProperty for Struct { Ok(value) } } -impl WriteProperty for Struct { +impl WriteProperty for Struct { fn to_writer( &self, writer: &mut R, From 316fe9da3fe02a42acedbb563e2dc150d2b9ed49 Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Fri, 6 Mar 2026 20:20:35 +0000 Subject: [PATCH 008/187] feat: String::new_with_meta, with_meta --- crates/ltk_meta/src/property/values/string.rs | 25 +++++++++++++++---- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/crates/ltk_meta/src/property/values/string.rs b/crates/ltk_meta/src/property/values/string.rs index e0a6294b..1b20f6f3 100644 --- a/crates/ltk_meta/src/property/values/string.rs +++ b/crates/ltk_meta/src/property/values/string.rs @@ -16,13 +16,28 @@ pub struct String { pub meta: M, } -impl String { +impl String { #[inline(always)] #[must_use] - pub fn new(value: std::string::String) -> Self { - Self { - value, - meta: M::default(), + pub fn new(value: std::string::String) -> Self + where + M: Default, + { + Self::new_with_meta(value, M::default()) + } + + #[inline(always)] + #[must_use] + pub fn new_with_meta(value: std::string::String, meta: M) -> Self { + Self { value, meta } + } + + #[inline(always)] + #[must_use] + pub fn with_meta(self, meta: T) -> String { + String { + value: self.value, + meta, } } } From 45c916ce0619206a1f180706bc9d663861b1fb06 Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Fri, 6 Mar 2026 20:20:44 +0000 Subject: [PATCH 009/187] feat: new_with_meta for primitives --- crates/ltk_meta/src/property/values/primitives.rs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/crates/ltk_meta/src/property/values/primitives.rs b/crates/ltk_meta/src/property/values/primitives.rs index d0db8c31..e5458512 100644 --- a/crates/ltk_meta/src/property/values/primitives.rs +++ b/crates/ltk_meta/src/property/values/primitives.rs @@ -20,11 +20,17 @@ macro_rules! impl_prim { pub meta: M } - impl $name { + impl $name { #[inline(always)] #[must_use] - pub fn new(value: $rust) -> Self { - Self { value, meta: M::default() } + pub fn new(value: $rust) -> Self where M: Default { + Self::new_with_meta(value, M::default()) + } + + #[inline(always)] + #[must_use] + pub fn new_with_meta(value: $rust, meta: M) -> Self { + Self { value, meta } } } From 61e7270c74b866165b2c3fa1201f0805ac2ee5ad Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Fri, 6 Mar 2026 20:21:00 +0000 Subject: [PATCH 010/187] feat: None::new() --- crates/ltk_meta/src/property/values/none.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/crates/ltk_meta/src/property/values/none.rs b/crates/ltk_meta/src/property/values/none.rs index e636bfc5..ab4a401d 100644 --- a/crates/ltk_meta/src/property/values/none.rs +++ b/crates/ltk_meta/src/property/values/none.rs @@ -26,6 +26,12 @@ impl PropertyExt for None { } } +impl None { + pub fn new(meta: M) -> Self { + Self { meta } + } +} + impl ReadProperty for None { fn from_reader( _reader: &mut R, From 9b08f2f6aba1d342252d0eb781d844b7036b23ca Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Fri, 6 Mar 2026 20:24:19 +0000 Subject: [PATCH 011/187] feat: PropertyExt::meta_mut() --- crates/ltk_meta/src/property/enum.rs | 6 ++++++ crates/ltk_meta/src/property/values/container.rs | 7 +++++++ crates/ltk_meta/src/property/values/embedded.rs | 3 +++ crates/ltk_meta/src/property/values/map.rs | 3 +++ crates/ltk_meta/src/property/values/none.rs | 3 +++ crates/ltk_meta/src/property/values/optional.rs | 8 +++++++- crates/ltk_meta/src/property/values/primitives.rs | 3 +++ crates/ltk_meta/src/property/values/string.rs | 3 +++ crates/ltk_meta/src/property/values/struct.rs | 3 +++ .../ltk_meta/src/property/values/unordered_container.rs | 3 +++ crates/ltk_meta/src/traits.rs | 1 + 11 files changed, 42 insertions(+), 1 deletion(-) diff --git a/crates/ltk_meta/src/property/enum.rs b/crates/ltk_meta/src/property/enum.rs index a7653d78..93d95ab8 100644 --- a/crates/ltk_meta/src/property/enum.rs +++ b/crates/ltk_meta/src/property/enum.rs @@ -96,6 +96,12 @@ macro_rules! create_enum { $(Self::$variant(i) => i.meta(),)* } } + fn meta_mut(&mut self) -> &mut Self::Meta { + match self { + $(Self::$variant(i) => i.meta_mut(),)* + } + } + fn size(&self, include_header: bool) -> usize { match self { $(Self::$variant(i) => i.size(include_header),)* diff --git a/crates/ltk_meta/src/property/values/container.rs b/crates/ltk_meta/src/property/values/container.rs index a3e9c7c0..faddd357 100644 --- a/crates/ltk_meta/src/property/values/container.rs +++ b/crates/ltk_meta/src/property/values/container.rs @@ -51,6 +51,13 @@ macro_rules! define_container_enum { })* } } + fn meta_mut(&mut self) -> &mut Self::Meta { + match self { + $(Self::$variant{meta,..} => { + meta + })* + } + } } $( diff --git a/crates/ltk_meta/src/property/values/embedded.rs b/crates/ltk_meta/src/property/values/embedded.rs index 986dc521..d0aca89c 100644 --- a/crates/ltk_meta/src/property/values/embedded.rs +++ b/crates/ltk_meta/src/property/values/embedded.rs @@ -25,6 +25,9 @@ impl PropertyExt for Embedded { fn meta(&self) -> &Self::Meta { self.0.meta() } + fn meta_mut(&mut self) -> &mut Self::Meta { + self.0.meta_mut() + } } impl ReadProperty for Embedded { diff --git a/crates/ltk_meta/src/property/values/map.rs b/crates/ltk_meta/src/property/values/map.rs index 2e0119b9..0c89c6a2 100644 --- a/crates/ltk_meta/src/property/values/map.rs +++ b/crates/ltk_meta/src/property/values/map.rs @@ -146,6 +146,9 @@ impl PropertyExt for Map { fn meta(&self) -> &Self::Meta { &self.meta } + fn meta_mut(&mut self) -> &mut Self::Meta { + &mut self.meta + } } impl ReadProperty for Map { diff --git a/crates/ltk_meta/src/property/values/none.rs b/crates/ltk_meta/src/property/values/none.rs index ab4a401d..df2620ce 100644 --- a/crates/ltk_meta/src/property/values/none.rs +++ b/crates/ltk_meta/src/property/values/none.rs @@ -24,6 +24,9 @@ impl PropertyExt for None { fn meta(&self) -> &Self::Meta { &self.meta } + fn meta_mut(&mut self) -> &mut Self::Meta { + &mut self.meta + } } impl None { diff --git a/crates/ltk_meta/src/property/values/optional.rs b/crates/ltk_meta/src/property/values/optional.rs index 48b0e633..abd70bab 100644 --- a/crates/ltk_meta/src/property/values/optional.rs +++ b/crates/ltk_meta/src/property/values/optional.rs @@ -43,7 +43,13 @@ macro_rules! construct_enum { match &self { $(Self::$variant{meta, ..} => meta,)* } - + } + fn meta_mut(&mut self) -> &mut Self::Meta { + match self { + $(Self::$variant{meta, ..} => { + meta + })* + } } } diff --git a/crates/ltk_meta/src/property/values/primitives.rs b/crates/ltk_meta/src/property/values/primitives.rs index e5458512..088bb214 100644 --- a/crates/ltk_meta/src/property/values/primitives.rs +++ b/crates/ltk_meta/src/property/values/primitives.rs @@ -43,6 +43,9 @@ macro_rules! impl_prim { fn meta(&self) -> &Self::Meta { &self.meta } + fn meta_mut(&mut self) -> &mut Self::Meta { + &mut self.meta + } } impl PropertyValueExt for $name { diff --git a/crates/ltk_meta/src/property/values/string.rs b/crates/ltk_meta/src/property/values/string.rs index 1b20f6f3..42d71ac7 100644 --- a/crates/ltk_meta/src/property/values/string.rs +++ b/crates/ltk_meta/src/property/values/string.rs @@ -55,6 +55,9 @@ impl PropertyExt for String { fn meta(&self) -> &Self::Meta { &self.meta } + fn meta_mut(&mut self) -> &mut Self::Meta { + &mut self.meta + } } impl ReadProperty for String { diff --git a/crates/ltk_meta/src/property/values/struct.rs b/crates/ltk_meta/src/property/values/struct.rs index 26c3ea8b..77e6b265 100644 --- a/crates/ltk_meta/src/property/values/struct.rs +++ b/crates/ltk_meta/src/property/values/struct.rs @@ -37,6 +37,9 @@ impl PropertyExt for Struct { fn meta(&self) -> &Self::Meta { &self.meta } + fn meta_mut(&mut self) -> &mut Self::Meta { + &mut self.meta + } } impl ReadProperty for Struct { diff --git a/crates/ltk_meta/src/property/values/unordered_container.rs b/crates/ltk_meta/src/property/values/unordered_container.rs index b552105a..42167f7b 100644 --- a/crates/ltk_meta/src/property/values/unordered_container.rs +++ b/crates/ltk_meta/src/property/values/unordered_container.rs @@ -26,6 +26,9 @@ impl PropertyExt for UnorderedContainer { fn meta(&self) -> &Self::Meta { self.0.meta() } + fn meta_mut(&mut self) -> &mut Self::Meta { + self.0.meta_mut() + } } impl ReadProperty for UnorderedContainer { diff --git a/crates/ltk_meta/src/traits.rs b/crates/ltk_meta/src/traits.rs index 8e655e1b..e66ff12f 100644 --- a/crates/ltk_meta/src/traits.rs +++ b/crates/ltk_meta/src/traits.rs @@ -20,6 +20,7 @@ pub trait PropertyExt { type Meta; fn meta(&self) -> &Self::Meta; + fn meta_mut(&mut self) -> &mut Self::Meta; } pub trait PropertyValueExt { From ce7bc253aa90b55f43ea5677139951d79c8c70bc Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Fri, 6 Mar 2026 20:42:26 +0000 Subject: [PATCH 012/187] feat: propagate meta generic to BinObject --- crates/ltk_meta/src/property/kind.rs | 2 +- crates/ltk_meta/src/tree/object.rs | 12 +++++++++--- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/crates/ltk_meta/src/property/kind.rs b/crates/ltk_meta/src/property/kind.rs index 76937d71..5b467ef4 100644 --- a/crates/ltk_meta/src/property/kind.rs +++ b/crates/ltk_meta/src/property/kind.rs @@ -1,5 +1,5 @@ use super::Error; -use crate::PropertyValueEnum; +use crate::{property::values, PropertyValueEnum}; use num_enum::{IntoPrimitive, TryFromPrimitive}; use std::io; diff --git a/crates/ltk_meta/src/tree/object.rs b/crates/ltk_meta/src/tree/object.rs index a8273079..11403241 100644 --- a/crates/ltk_meta/src/tree/object.rs +++ b/crates/ltk_meta/src/tree/object.rs @@ -8,6 +8,8 @@ use std::io; use indexmap::IndexMap; use ltk_io_ext::{measure, window_at}; +use crate::property::NoMeta; + use super::super::{BinProperty, Error, PropertyValueEnum}; use byteorder::{ReadBytesExt, WriteBytesExt, LE}; @@ -34,9 +36,13 @@ use byteorder::{ReadBytesExt, WriteBytesExt, LE}; /// .property(0xBBBB, values::String::from("hello")) /// .build(); /// ``` -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr( + feature = "serde", + derive(serde::Serialize, serde::Deserialize), + serde(bound = "for <'dee> M: serde::Serialize + serde::Deserialize<'dee>") +)] #[derive(Debug, Clone, PartialEq)] -pub struct BinObject { +pub struct BinObject { /// The unique path hash identifying this object. pub path_hash: u32, @@ -44,7 +50,7 @@ pub struct BinObject { pub class_hash: u32, /// The properties of this object, keyed by their name hash. - pub properties: IndexMap, + pub properties: IndexMap>, } impl BinObject { From f15ceff1f34cd837b6a92d5ec58099a019f343bf Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Fri, 6 Mar 2026 21:00:56 +0000 Subject: [PATCH 013/187] feat: no_meta helper --- crates/ltk_meta/src/property.rs | 11 ++++++++++- crates/ltk_meta/src/property/enum.rs | 9 +++++++++ crates/ltk_meta/src/property/values/container.rs | 15 +++++++++++++++ crates/ltk_meta/src/property/values/embedded.rs | 8 ++++++++ crates/ltk_meta/src/property/values/map.rs | 15 +++++++++++++++ crates/ltk_meta/src/property/values/none.rs | 8 ++++++++ crates/ltk_meta/src/property/values/optional.rs | 12 ++++++++++-- .../ltk_meta/src/property/values/primitives.rs | 12 ++++++++++++ crates/ltk_meta/src/property/values/string.rs | 6 ++++++ crates/ltk_meta/src/property/values/struct.rs | 16 ++++++++++++++++ .../src/property/values/unordered_container.rs | 8 +++++++- 11 files changed, 116 insertions(+), 4 deletions(-) diff --git a/crates/ltk_meta/src/property.rs b/crates/ltk_meta/src/property.rs index cde2592d..822fda06 100644 --- a/crates/ltk_meta/src/property.rs +++ b/crates/ltk_meta/src/property.rs @@ -11,7 +11,7 @@ use super::Error; use byteorder::{ReadBytesExt as _, WriteBytesExt as _, LE}; use std::io; -use crate::traits::PropertyExt; +use crate::{traits::PropertyExt, Bin}; #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] #[derive(Clone, Copy, Default, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] @@ -30,6 +30,15 @@ pub struct BinProperty { } impl BinProperty { + #[inline(always)] + #[must_use] + pub fn no_meta(self) -> BinProperty { + BinProperty { + name_hash: self.name_hash, + value: self.value.no_meta(), + } + } + /// Read a BinProperty from a reader. This will read the name_hash, prop kind and then value, in that order. pub fn from_reader( reader: &mut R, diff --git a/crates/ltk_meta/src/property/enum.rs b/crates/ltk_meta/src/property/enum.rs index 93d95ab8..46c8ce45 100644 --- a/crates/ltk_meta/src/property/enum.rs +++ b/crates/ltk_meta/src/property/enum.rs @@ -80,6 +80,7 @@ macro_rules! create_enum { } } impl PropertyValueEnum { + #[inline(always)] #[must_use] pub fn kind(&self) -> Kind { match self { @@ -87,6 +88,14 @@ macro_rules! create_enum { } } + #[inline(always)] + #[must_use] + pub fn no_meta(self) -> PropertyValueEnum { + match self { + $(Self::$variant(i) => PropertyValueEnum::$variant(i.no_meta()),)* + } + } + } impl PropertyExt for PropertyValueEnum { diff --git a/crates/ltk_meta/src/property/values/container.rs b/crates/ltk_meta/src/property/values/container.rs index faddd357..cc3d3b82 100644 --- a/crates/ltk_meta/src/property/values/container.rs +++ b/crates/ltk_meta/src/property/values/container.rs @@ -124,6 +124,8 @@ macro_rules! define_container_enum { } impl Container { + #[inline(always)] + #[must_use] pub fn empty(item_kind: Kind) -> Result where M: Default @@ -138,6 +140,19 @@ macro_rules! define_container_enum { } } + #[inline(always)] + #[must_use] + pub fn no_meta(self) -> Container { + match self { + $(Self::$variant{items,..} => { + Container::$variant { + items: items.into_iter().map(|i| i.no_meta()).collect(), + meta: NoMeta + } + })* + } + } + pub fn push(&mut self, value: PropertyValueEnum) -> Result<(), Error>{ let got = value.kind(); let expected = self.item_kind(); diff --git a/crates/ltk_meta/src/property/values/embedded.rs b/crates/ltk_meta/src/property/values/embedded.rs index d0aca89c..2f8fce08 100644 --- a/crates/ltk_meta/src/property/values/embedded.rs +++ b/crates/ltk_meta/src/property/values/embedded.rs @@ -13,6 +13,14 @@ use super::Struct; #[derive(Clone, PartialEq, Debug, Default)] pub struct Embedded(pub Struct); +impl Embedded { + #[inline(always)] + #[must_use] + pub fn no_meta(self) -> Embedded { + Embedded(self.0.no_meta()) + } +} + impl PropertyValueExt for Embedded { const KIND: Kind = Kind::Embedded; } diff --git a/crates/ltk_meta/src/property/values/map.rs b/crates/ltk_meta/src/property/values/map.rs index 0c89c6a2..6d38a7e2 100644 --- a/crates/ltk_meta/src/property/values/map.rs +++ b/crates/ltk_meta/src/property/values/map.rs @@ -42,6 +42,21 @@ pub struct Map { } impl Map { + #[inline(always)] + #[must_use] + pub fn no_meta(self) -> Map { + Map { + key_kind: self.key_kind, + value_kind: self.value_kind, + entries: self + .entries + .into_iter() + .map(|(k, v)| (k.no_meta(), v.no_meta())) + .collect(), + meta: NoMeta, + } + } + #[inline(always)] #[must_use] pub fn key_kind(&self) -> Kind { diff --git a/crates/ltk_meta/src/property/values/none.rs b/crates/ltk_meta/src/property/values/none.rs index df2620ce..3fc37e68 100644 --- a/crates/ltk_meta/src/property/values/none.rs +++ b/crates/ltk_meta/src/property/values/none.rs @@ -30,9 +30,17 @@ impl PropertyExt for None { } impl None { + #[inline(always)] + #[must_use] pub fn new(meta: M) -> Self { Self { meta } } + + #[inline(always)] + #[must_use] + pub fn no_meta(self) -> None { + None { meta: NoMeta } + } } impl ReadProperty for None { diff --git a/crates/ltk_meta/src/property/values/optional.rs b/crates/ltk_meta/src/property/values/optional.rs index abd70bab..24ec6d2b 100644 --- a/crates/ltk_meta/src/property/values/optional.rs +++ b/crates/ltk_meta/src/property/values/optional.rs @@ -20,16 +20,24 @@ macro_rules! construct_enum { },)* } - impl Optional { + impl Optional { #[inline(always)] #[must_use] /// Helper function to create an empty [`Optional`], if the property kind can be stored in one. - pub fn empty(kind: Kind) -> Option { + pub fn empty(kind: Kind) -> Option where M: Default { Some(match kind { $(Kind::$variant => Self::$variant{value: None, meta: M::default()},)* _ => return None }) } + + #[inline(always)] + #[must_use] + pub fn no_meta(self) -> Optional { + match self { + $(Self::$variant{ value, meta: _ } => Optional::$variant{ value: value.map(|v| v.no_meta()), meta: NoMeta },)* + } + } } impl PropertyExt for Optional { diff --git a/crates/ltk_meta/src/property/values/primitives.rs b/crates/ltk_meta/src/property/values/primitives.rs index 088bb214..09077432 100644 --- a/crates/ltk_meta/src/property/values/primitives.rs +++ b/crates/ltk_meta/src/property/values/primitives.rs @@ -32,6 +32,18 @@ macro_rules! impl_prim { pub fn new_with_meta(value: $rust, meta: M) -> Self { Self { value, meta } } + + #[inline(always)] + #[must_use] + pub fn with_meta(self, meta: T) -> $name { + $name { value: self.value, meta } + } + + #[inline(always)] + #[must_use] + pub fn no_meta(self) -> $name { + self.with_meta(NoMeta) + } } impl PropertyExt for $name { diff --git a/crates/ltk_meta/src/property/values/string.rs b/crates/ltk_meta/src/property/values/string.rs index 42d71ac7..0004111c 100644 --- a/crates/ltk_meta/src/property/values/string.rs +++ b/crates/ltk_meta/src/property/values/string.rs @@ -40,6 +40,12 @@ impl String { meta, } } + + #[inline(always)] + #[must_use] + pub fn no_meta(self) -> String { + self.with_meta(NoMeta) + } } impl PropertyValueExt for String { diff --git a/crates/ltk_meta/src/property/values/struct.rs b/crates/ltk_meta/src/property/values/struct.rs index 77e6b265..6644ece8 100644 --- a/crates/ltk_meta/src/property/values/struct.rs +++ b/crates/ltk_meta/src/property/values/struct.rs @@ -21,6 +21,22 @@ pub struct Struct { pub meta: M, } +impl Struct { + #[inline(always)] + #[must_use] + pub fn no_meta(self) -> Struct { + Struct { + class_hash: self.class_hash, + properties: self + .properties + .into_iter() + .map(|(k, v)| (k, v.no_meta())) + .collect(), + meta: NoMeta, + } + } +} + impl PropertyValueExt for Struct { const KIND: Kind = Kind::Struct; } diff --git a/crates/ltk_meta/src/property/values/unordered_container.rs b/crates/ltk_meta/src/property/values/unordered_container.rs index 42167f7b..decd40a1 100644 --- a/crates/ltk_meta/src/property/values/unordered_container.rs +++ b/crates/ltk_meta/src/property/values/unordered_container.rs @@ -1,5 +1,5 @@ use crate::{ - property::Kind, + property::{Kind, NoMeta}, traits::{PropertyExt, PropertyValueExt, ReadProperty, WriteProperty}, }; @@ -13,6 +13,12 @@ use super::Container; #[derive(Clone, PartialEq, Debug, Default)] pub struct UnorderedContainer(pub Container); +impl UnorderedContainer { + pub fn no_meta(self) -> UnorderedContainer { + UnorderedContainer(self.0.no_meta()) + } +} + impl PropertyValueExt for UnorderedContainer { const KIND: Kind = Kind::UnorderedContainer; } From 7b173b01eb4bdefb2c5eac07f494685096e33fce Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Sat, 7 Mar 2026 01:05:43 +0000 Subject: [PATCH 014/187] fix: snapshot test --- .../ltk_meta/tests/snapshots/meta__read.snap | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/crates/ltk_meta/tests/snapshots/meta__read.snap b/crates/ltk_meta/tests/snapshots/meta__read.snap index dd129ded..423a0fed 100644 --- a/crates/ltk_meta/tests/snapshots/meta__read.snap +++ b/crates/ltk_meta/tests/snapshots/meta__read.snap @@ -29,10 +29,13 @@ Bin( 607245356: { "kind": Optional, "name_hash": 607245356, - "value": F32(Some(F32( - value: 10.0, + "value": F32( + value: Some(F32( + value: 10.0, + meta: NoMeta, + )), meta: NoMeta, - ))), + ), }, 895082843: { "kind": BitBool, @@ -61,10 +64,13 @@ Bin( 1376955374: { "kind": Optional, "name_hash": 1376955374, - "value": F32(Some(F32( - value: 1.0, + "value": F32( + value: Some(F32( + value: 1.0, + meta: NoMeta, + )), meta: NoMeta, - ))), + ), }, 2927860839: { "kind": Embedded, From c053fd72901ac46db933d3898958749474935f9d Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Mon, 23 Mar 2026 17:28:54 +0000 Subject: [PATCH 015/187] fix: clippy --- crates/ltk_meta/src/property.rs | 2 +- crates/ltk_meta/src/property/enum.rs | 2 - crates/ltk_meta/src/property/kind.rs | 2 +- .../ltk_meta/src/property/values/container.rs | 1 - .../src/property/values/container/variants.rs | 72 +++++++++---------- crates/ltk_meta/src/traits.rs | 3 +- 6 files changed, 39 insertions(+), 43 deletions(-) diff --git a/crates/ltk_meta/src/property.rs b/crates/ltk_meta/src/property.rs index 822fda06..c9ec963e 100644 --- a/crates/ltk_meta/src/property.rs +++ b/crates/ltk_meta/src/property.rs @@ -11,7 +11,7 @@ use super::Error; use byteorder::{ReadBytesExt as _, WriteBytesExt as _, LE}; use std::io; -use crate::{traits::PropertyExt, Bin}; +use crate::traits::PropertyExt; #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] #[derive(Clone, Copy, Default, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] diff --git a/crates/ltk_meta/src/property/enum.rs b/crates/ltk_meta/src/property/enum.rs index 46c8ce45..3bbd36dc 100644 --- a/crates/ltk_meta/src/property/enum.rs +++ b/crates/ltk_meta/src/property/enum.rs @@ -1,5 +1,3 @@ -use enum_dispatch::enum_dispatch; - use crate::{ property::{Kind, NoMeta}, traits::{PropertyExt, ReadProperty as _, WriteProperty as _}, diff --git a/crates/ltk_meta/src/property/kind.rs b/crates/ltk_meta/src/property/kind.rs index 5b467ef4..76937d71 100644 --- a/crates/ltk_meta/src/property/kind.rs +++ b/crates/ltk_meta/src/property/kind.rs @@ -1,5 +1,5 @@ use super::Error; -use crate::{property::values, PropertyValueEnum}; +use crate::PropertyValueEnum; use num_enum::{IntoPrimitive, TryFromPrimitive}; use std::io; diff --git a/crates/ltk_meta/src/property/values/container.rs b/crates/ltk_meta/src/property/values/container.rs index cc3d3b82..12094f7b 100644 --- a/crates/ltk_meta/src/property/values/container.rs +++ b/crates/ltk_meta/src/property/values/container.rs @@ -125,7 +125,6 @@ macro_rules! define_container_enum { impl Container { #[inline(always)] - #[must_use] pub fn empty(item_kind: Kind) -> Result where M: Default diff --git a/crates/ltk_meta/src/property/values/container/variants.rs b/crates/ltk_meta/src/property/values/container/variants.rs index f9924208..ac5fbaf9 100644 --- a/crates/ltk_meta/src/property/values/container/variants.rs +++ b/crates/ltk_meta/src/property/values/container/variants.rs @@ -23,42 +23,42 @@ macro_rules! container_variants { }; } -macro_rules! match_property { - ($value:expr, $on:ident, $inner:pat => $body:expr, $def:pat => $def_body: expr) => { - container_variants!(match_property_arms, ($value, $on, $inner => $body, $def => $def_body)) - }; - ($value:expr, $on:ident, $inner:pat => $body:expr) => { - container_variants!(match_property_arms, ($value, $on, $inner => $body)) - }; - - ($value:expr, $inner:pat => $body:expr, $def:pat => $def_body: expr) => { - container_variants!(match_property_arms, ($value, Self, $inner => $body, $def => $def_body)) - }; - ($value:expr, $inner:pat => $body:expr) => { - container_variants!(match_property_arms, ($value, Self, $inner => $body)) - }; -} - -macro_rules! match_property_arms { - (($value:expr, $on:ident, $inner:pat => $body:expr, $def:pat => $def_body: expr) - [$( $variant:ident, )*]) => { - match $value { - $( - $on::$variant($inner) => $body, - )* - $def => $def_body - } - }; - - (($value:expr, $on:ident, $inner:pat => $body:expr) - [$( $variant:ident, )*]) => { - match $value { - $( - $on::$variant($inner) => $body, - )* - } - }; -} +// macro_rules! match_property { +// ($value:expr, $on:ident, $inner:pat => $body:expr, $def:pat => $def_body: expr) => { +// container_variants!(match_property_arms, ($value, $on, $inner => $body, $def => $def_body)) +// }; +// ($value:expr, $on:ident, $inner:pat => $body:expr) => { +// container_variants!(match_property_arms, ($value, $on, $inner => $body)) +// }; +// +// ($value:expr, $inner:pat => $body:expr, $def:pat => $def_body: expr) => { +// container_variants!(match_property_arms, ($value, Self, $inner => $body, $def => $def_body)) +// }; +// ($value:expr, $inner:pat => $body:expr) => { +// container_variants!(match_property_arms, ($value, Self, $inner => $body)) +// }; +// } +// +// macro_rules! match_property_arms { +// (($value:expr, $on:ident, $inner:pat => $body:expr, $def:pat => $def_body: expr) +// [$( $variant:ident, )*]) => { +// match $value { +// $( +// $on::$variant($inner) => $body, +// )* +// $def => $def_body +// } +// }; +// +// (($value:expr, $on:ident, $inner:pat => $body:expr) +// [$( $variant:ident, )*]) => { +// match $value { +// $( +// $on::$variant($inner) => $body, +// )* +// } +// }; +// } // macro_rules! match_enum_inner { // (($value:expr, $on:ident, ||, $body:expr) diff --git a/crates/ltk_meta/src/traits.rs b/crates/ltk_meta/src/traits.rs index e66ff12f..1514428a 100644 --- a/crates/ltk_meta/src/traits.rs +++ b/crates/ltk_meta/src/traits.rs @@ -1,8 +1,7 @@ use std::io; -use super::property::{values::*, Kind, PropertyValueEnum}; +use super::property::Kind; use byteorder::{ReadBytesExt, WriteBytesExt}; -use enum_dispatch::enum_dispatch; const HEADER_SIZE: usize = 5; From 5e1e23834b285c479bc25998ad459b5f78d76628 Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Tue, 24 Mar 2026 18:56:15 +0000 Subject: [PATCH 016/187] feat!: remove BinProperty & name_hash duplication replaces BinProperty with trait methods on ReaderExt/WriterExt --- crates/ltk_meta/src/lib.rs | 6 +- crates/ltk_meta/src/property.rs | 61 ------ crates/ltk_meta/src/property/values/struct.rs | 26 ++- crates/ltk_meta/src/traits.rs | 35 +++- crates/ltk_meta/src/tree/object.rs | 128 +++++------- crates/ltk_meta/src/tree/object/builder.rs | 40 ++-- crates/ltk_meta/src/tree/tests.rs | 197 +++++------------- .../ltk_meta/tests/snapshots/meta__read.snap | 126 +++++------ crates/ltk_ritobin/src/parser.rs | 34 ++- crates/ltk_ritobin/src/writer.rs | 30 ++- crates/ltk_ritobin/tests/parse_sample.rs | 4 +- 11 files changed, 268 insertions(+), 419 deletions(-) diff --git a/crates/ltk_meta/src/lib.rs b/crates/ltk_meta/src/lib.rs index a7a53403..173d0dac 100644 --- a/crates/ltk_meta/src/lib.rs +++ b/crates/ltk_meta/src/lib.rs @@ -27,13 +27,13 @@ for (path_hash, object) in &tree.objects { ``` use ltk_meta::{Bin, BinObject}; -use ltk_meta::property::values; +use ltk_meta::property::{values, NoMeta}; // Using the builder pattern let tree = Bin::builder() .dependency("common.bin") .object( - BinObject::builder(0x12345678, 0xABCDEF00) + BinObject::::builder(0x12345678, 0xABCDEF00) .property(0x1111, values::I32::new(42)) .property(0x2222, values::String::from("hello")) .build() @@ -70,7 +70,7 @@ tree.to_writer(&mut output)?; ``` */ pub mod property; -pub use property::{BinProperty, Kind as PropertyKind, PropertyValueEnum}; +pub use property::{Kind as PropertyKind, PropertyValueEnum}; mod tree; pub use tree::*; diff --git a/crates/ltk_meta/src/property.rs b/crates/ltk_meta/src/property.rs index c9ec963e..8c1dfaf1 100644 --- a/crates/ltk_meta/src/property.rs +++ b/crates/ltk_meta/src/property.rs @@ -6,69 +6,8 @@ pub use kind::*; mod r#enum; pub use r#enum::*; -use super::traits::{ReaderExt as _, WriterExt as _}; use super::Error; -use byteorder::{ReadBytesExt as _, WriteBytesExt as _, LE}; -use std::io; - -use crate::traits::PropertyExt; #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] #[derive(Clone, Copy, Default, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct NoMeta; - -#[cfg_attr( - feature = "serde", - derive(serde::Serialize, serde::Deserialize), - serde(bound = "for <'dee> M: serde::Serialize + serde::Deserialize<'dee>") -)] -#[derive(Clone, PartialEq, Debug)] -pub struct BinProperty { - pub name_hash: u32, - #[cfg_attr(feature = "serde", serde(flatten))] - pub value: PropertyValueEnum, -} - -impl BinProperty { - #[inline(always)] - #[must_use] - pub fn no_meta(self) -> BinProperty { - BinProperty { - name_hash: self.name_hash, - value: self.value.no_meta(), - } - } - - /// Read a BinProperty from a reader. This will read the name_hash, prop kind and then value, in that order. - pub fn from_reader( - reader: &mut R, - legacy: bool, - ) -> Result - where - M: Default, - { - let name_hash = reader.read_u32::()?; - let kind = reader.read_property_kind(legacy)?; - - Ok(Self { - name_hash, - value: PropertyValueEnum::from_reader(reader, kind, legacy)?, - }) - } - pub fn to_writer( - &self, - writer: &mut W, - ) -> Result<(), io::Error> - where - M: Clone, - { - writer.write_u32::(self.name_hash)?; - writer.write_property_kind(self.value.kind())?; - - self.value.to_writer(writer)?; - Ok(()) - } - pub fn size(&self) -> usize { - 5 + self.value.size_no_header() - } -} diff --git a/crates/ltk_meta/src/property/values/struct.rs b/crates/ltk_meta/src/property/values/struct.rs index 6644ece8..77c0b9b6 100644 --- a/crates/ltk_meta/src/property/values/struct.rs +++ b/crates/ltk_meta/src/property/values/struct.rs @@ -2,8 +2,10 @@ use std::io; use crate::{ property::{Kind, NoMeta}, - traits::{PropertyExt, PropertyValueExt, ReadProperty, WriteProperty}, - BinProperty, Error, + traits::{ + PropertyExt, PropertyValueExt, ReadProperty, ReaderExt, WriteProperty, WriterExt as _, + }, + Error, PropertyValueEnum, }; use byteorder::{ReadBytesExt as _, WriteBytesExt as _, LE}; use indexmap::IndexMap; @@ -17,7 +19,7 @@ use ltk_io_ext::{measure, window_at}; #[derive(Clone, PartialEq, Debug, Default)] pub struct Struct { pub class_hash: u32, - pub properties: IndexMap>, + pub properties: IndexMap>, pub meta: M, } @@ -45,7 +47,13 @@ impl PropertyExt for Struct { fn size_no_header(&self) -> usize { match self.class_hash { 0 => 4, - _ => 10 + self.properties.values().map(|p| p.size()).sum::(), + _ => { + 10 + self + .properties + .values() + .map(|p| 5 + p.size_no_header()) + .sum::() + } } } @@ -77,8 +85,8 @@ impl ReadProperty for Struct { let prop_count = reader.read_u16::()?; let mut properties = IndexMap::with_capacity(prop_count as _); for _ in 0..prop_count { - let prop = BinProperty::from_reader(reader, legacy)?; - properties.insert(prop.name_hash, prop); + let (name_hash, value) = reader.read_property::(legacy)?; + properties.insert(name_hash, value); } Ok::<_, Error>(Self { class_hash, @@ -116,8 +124,10 @@ impl WriteProperty for Struct { let (size, _) = measure(writer, |writer| { writer.write_u16::(self.properties.len() as _)?; - for prop in self.properties.values() { - prop.to_writer(writer)?; + for (name_hash, value) in self.properties.iter() { + writer.write_u32::(*name_hash)?; + writer.write_property_kind(value.kind())?; + value.to_writer(writer)?; } Ok::<_, io::Error>(()) diff --git a/crates/ltk_meta/src/traits.rs b/crates/ltk_meta/src/traits.rs index 1514428a..be1a85f5 100644 --- a/crates/ltk_meta/src/traits.rs +++ b/crates/ltk_meta/src/traits.rs @@ -1,7 +1,9 @@ use std::io; +use crate::PropertyValueEnum; + use super::property::Kind; -use byteorder::{ReadBytesExt, WriteBytesExt}; +use byteorder::{ReadBytesExt, WriteBytesExt, LE}; const HEADER_SIZE: usize = 5; @@ -50,6 +52,22 @@ pub trait ReaderExt: io::Read { fn read_property_kind(&mut self, legacy: bool) -> Result { Kind::unpack(self.read_u8()?, legacy) } + + fn read_property( + &mut self, + legacy: bool, + ) -> Result<(u32, PropertyValueEnum), crate::Error> + where + Self: io::Seek, + { + let name_hash = self.read_u32::()?; + let kind = self.read_property_kind(legacy)?; + + Ok(( + name_hash, + PropertyValueEnum::from_reader(self, kind, legacy)?, + )) + } } impl ReaderExt for R {} @@ -68,6 +86,21 @@ pub trait WriterExt: io::Write { fn write_property_kind(&mut self, kind: Kind) -> Result<(), io::Error> { self.write_u8(kind.into()) } + + fn write_property( + &mut self, + name_hash: u32, + value: &PropertyValueEnum, + ) -> Result<(), io::Error> + where + M: Clone, + Self: io::Seek, + { + self.write_u32::(name_hash)?; + self.write_property_kind(value.kind())?; + value.to_writer(self)?; + Ok(()) + } } impl WriterExt for R {} diff --git a/crates/ltk_meta/src/tree/object.rs b/crates/ltk_meta/src/tree/object.rs index 11403241..81162f92 100644 --- a/crates/ltk_meta/src/tree/object.rs +++ b/crates/ltk_meta/src/tree/object.rs @@ -8,9 +8,12 @@ use std::io; use indexmap::IndexMap; use ltk_io_ext::{measure, window_at}; -use crate::property::NoMeta; +use crate::{ + property::NoMeta, + traits::{ReaderExt, WriterExt}, +}; -use super::super::{BinProperty, Error, PropertyValueEnum}; +use super::super::{Error, PropertyValueEnum}; use byteorder::{ReadBytesExt, WriteBytesExt, LE}; /// A node/object in the bin tree. @@ -25,13 +28,13 @@ use byteorder::{ReadBytesExt, WriteBytesExt, LE}; /// /// ``` /// use ltk_meta::BinObject; -/// use ltk_meta::property::values; +/// use ltk_meta::property::{values, NoMeta}; /// /// // Simple construction -/// let obj = BinObject::new(0x1234, 0x5678); +/// let obj = BinObject::::new(0x1234, 0x5678); /// /// // Builder pattern with properties -/// let obj = BinObject::builder(0x1234, 0x5678) +/// let obj = BinObject::::builder(0x1234, 0x5678) /// .property(0xAAAA, values::I32::new(42)) /// .property(0xBBBB, values::String::from("hello")) /// .build(); @@ -41,7 +44,7 @@ use byteorder::{ReadBytesExt, WriteBytesExt, LE}; derive(serde::Serialize, serde::Deserialize), serde(bound = "for <'dee> M: serde::Serialize + serde::Deserialize<'dee>") )] -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Clone, PartialEq, Default)] pub struct BinObject { /// The unique path hash identifying this object. pub path_hash: u32, @@ -50,10 +53,10 @@ pub struct BinObject { pub class_hash: u32, /// The properties of this object, keyed by their name hash. - pub properties: IndexMap>, + pub properties: IndexMap>, } -impl BinObject { +impl BinObject { /// Creates a new `BinObject` with the given path and class hashes. /// /// The object starts with no properties. @@ -61,16 +64,16 @@ impl BinObject { /// # Examples /// /// ``` - /// use ltk_meta::BinObject; + /// use ltk_meta::{property::NoMeta, BinObject}; /// - /// let obj = BinObject::new(0x12345678, 0xABCDEF00); + /// let obj = BinObject::::new(0x12345678, 0xABCDEF00); /// assert!(obj.properties.is_empty()); /// ``` pub fn new(path_hash: u32, class_hash: u32) -> Self { Self { path_hash, class_hash, - properties: IndexMap::new(), + properties: IndexMap::default(), } } @@ -80,9 +83,9 @@ impl BinObject { /// /// ``` /// use ltk_meta::BinObject; - /// use ltk_meta::property::values; + /// use ltk_meta::property::{values, NoMeta}; /// - /// let obj = BinObject::builder(0x12345678, 0xABCDEF00) + /// let obj = BinObject::::builder(0x12345678, 0xABCDEF00) /// .property(0x1111, values::I32::new(42)) /// .property(0x2222, values::String::from("hello")) /// .property(0x3333, values::Bool::new(true)) @@ -105,7 +108,10 @@ impl BinObject { reader: &mut R, class_hash: u32, legacy: bool, - ) -> Result { + ) -> Result + where + M: Default, + { let size = reader.read_u32::()?; let (real_size, value) = measure(reader, |reader| { let path_hash = reader.read_u32::()?; @@ -113,8 +119,8 @@ impl BinObject { let prop_count = reader.read_u16::()? as usize; let mut properties = IndexMap::with_capacity(prop_count); for _ in 0..prop_count { - let prop = BinProperty::from_reader(reader, legacy)?; - properties.insert(prop.name_hash, prop); + let (name_hash, value) = reader.read_property::(legacy)?; + properties.insert(name_hash, value); } Ok::<_, Error>(Self { @@ -135,15 +141,18 @@ impl BinObject { /// # Arguments /// /// * `writer` - A writer that implements io::Write and io::Seek. - pub fn to_writer(&self, writer: &mut W) -> io::Result<()> { + pub fn to_writer(&self, writer: &mut W) -> io::Result<()> + where + M: Clone, + { let size_pos = writer.stream_position()?; writer.write_u32::(0)?; let (size, _) = measure(writer, |writer| { writer.write_u32::(self.path_hash)?; writer.write_u16::(self.properties.len() as _)?; - for prop in self.properties.values() { - prop.to_writer(writer)?; + for (name_hash, value) in self.properties.iter() { + writer.write_property(*name_hash, value)?; } Ok::<_, io::Error>(()) })?; @@ -153,43 +162,36 @@ impl BinObject { } /// Returns the number of properties in this object. - #[inline] + #[must_use] + #[inline(always)] pub fn len(&self) -> usize { self.properties.len() } /// Returns `true` if this object has no properties. - #[inline] + #[must_use] + #[inline(always)] pub fn is_empty(&self) -> bool { self.properties.is_empty() } /// Returns a reference to the property with the given name hash, if it exists. - #[inline] - pub fn get_property(&self, name_hash: u32) -> Option<&BinProperty> { + #[must_use] + #[inline(always)] + pub fn get_property(&self, name_hash: u32) -> Option<&PropertyValueEnum> { self.properties.get(&name_hash) } /// Returns a mutable reference to the property with the given name hash, if it exists. - #[inline] - pub fn get_property_mut(&mut self, name_hash: u32) -> Option<&mut BinProperty> { + #[must_use] + #[inline(always)] + pub fn get_property_mut(&mut self, name_hash: u32) -> Option<&mut PropertyValueEnum> { self.properties.get_mut(&name_hash) } - /// Returns a reference to the property value with the given name hash, if it exists. - #[inline] - pub fn get_value(&self, name_hash: u32) -> Option<&PropertyValueEnum> { - self.properties.get(&name_hash).map(|p| &p.value) - } - - /// Returns a mutable reference to the property value with the given name hash, if it exists. - #[inline] - pub fn get_value_mut(&mut self, name_hash: u32) -> Option<&mut PropertyValueEnum> { - self.properties.get_mut(&name_hash).map(|p| &mut p.value) - } - /// Returns `true` if this object has a property with the given name hash. - #[inline] + #[must_use] + #[inline(always)] pub fn contains_property(&self, name_hash: u32) -> bool { self.properties.contains_key(&name_hash) } @@ -198,70 +200,54 @@ impl BinObject { /// /// If a property with the same name hash already exists, it is replaced /// and the old property is returned. - pub fn set_property(&mut self, property: BinProperty) -> Option { - self.properties.insert(property.name_hash, property) - } - - /// Adds or replaces a property value. - /// - /// This is a convenience method that creates a [`BinProperty`] from the - /// name hash and value. - /// - /// If a property with the same name hash already exists, it is replaced - /// and the old property is returned. - pub fn set_value( + #[inline(always)] + pub fn insert( &mut self, name_hash: u32, - value: impl Into, - ) -> Option { - self.properties.insert( - name_hash, - BinProperty { - name_hash, - value: value.into(), - }, - ) + value: impl Into>, + ) -> Option> { + self.properties.insert(name_hash, value.into()) } /// Removes and returns the property with the given name hash, if it exists. - pub fn remove_property(&mut self, name_hash: u32) -> Option { + pub fn remove_property(&mut self, name_hash: u32) -> Option> { self.properties.shift_remove(&name_hash) } /// Returns an iterator over the properties in this object. #[inline] - pub fn iter(&self) -> impl Iterator { + pub fn iter(&self) -> impl Iterator)> { self.properties.iter() } /// Returns a mutable iterator over the properties in this object. #[inline] - pub fn iter_mut(&mut self) -> impl Iterator { + pub fn iter_mut(&mut self) -> impl Iterator)> { self.properties.iter_mut() } } -impl<'a> IntoIterator for &'a BinObject { - type Item = (&'a u32, &'a BinProperty); - type IntoIter = indexmap::map::Iter<'a, u32, BinProperty>; +impl<'a, M> IntoIterator for &'a BinObject { + type Item = (&'a u32, &'a PropertyValueEnum); + type IntoIter = indexmap::map::Iter<'a, u32, PropertyValueEnum>; fn into_iter(self) -> Self::IntoIter { self.properties.iter() } } -impl<'a> IntoIterator for &'a mut BinObject { - type Item = (&'a u32, &'a mut BinProperty); - type IntoIter = indexmap::map::IterMut<'a, u32, BinProperty>; +impl<'a, M> IntoIterator for &'a mut BinObject { + type Item = (&'a u32, &'a mut PropertyValueEnum); + type IntoIter = indexmap::map::IterMut<'a, u32, PropertyValueEnum>; fn into_iter(self) -> Self::IntoIter { self.properties.iter_mut() } } -impl IntoIterator for BinObject { - type Item = (u32, BinProperty); - type IntoIter = indexmap::map::IntoIter; +impl IntoIterator for BinObject { + type Item = (u32, PropertyValueEnum); + type IntoIter = indexmap::map::IntoIter>; fn into_iter(self) -> Self::IntoIter { self.properties.into_iter() diff --git a/crates/ltk_meta/src/tree/object/builder.rs b/crates/ltk_meta/src/tree/object/builder.rs index 732b3196..c38b3999 100644 --- a/crates/ltk_meta/src/tree/object/builder.rs +++ b/crates/ltk_meta/src/tree/object/builder.rs @@ -1,18 +1,18 @@ use indexmap::IndexMap; -use crate::{BinObject, BinProperty, PropertyValueEnum}; +use crate::{property::NoMeta, BinObject, PropertyValueEnum}; /// A builder for constructing [`BinObject`] instances. /// /// See: [`BinObject::builder`] #[derive(Debug, Clone)] -pub struct Builder { +pub struct Builder { path_hash: u32, class_hash: u32, - properties: IndexMap, + properties: IndexMap>, } -impl Builder { +impl Builder { /// See: [`BinObject::builder`] pub fn new(path_hash: u32, class_hash: u32) -> Self { Self { @@ -32,37 +32,23 @@ impl Builder { self } - /// Add a [`BinProperty`] - pub fn bin_property(mut self, prop: BinProperty) -> Self { - self.properties.insert(prop.name_hash, prop); - self - } - /// Adds a property with the given name hash and value. - /// - /// This is a convenience method that accepts any type that can be converted - /// into a [`PropertyValueEnum`]. - pub fn property(mut self, name_hash: u32, value: impl Into) -> Self { - self.properties.insert( - name_hash, - BinProperty { - name_hash, - value: value.into(), - }, - ); + pub fn property(mut self, name_hash: u32, value: impl Into>) -> Self { + self.properties.insert(name_hash, value.into()); self } - /// Adds multiple properties from [`BinProperty`] instances. - pub fn bin_properties(mut self, props: impl IntoIterator) -> Self { - for prop in props { - self.properties.insert(prop.name_hash, prop); - } + /// Adds multiple properties from an iterator of name hashes & [`PropertyValueEnum`]s. + pub fn properties( + mut self, + props: impl IntoIterator)>, + ) -> Self { + self.properties.extend(props); self } /// Builds the final [`BinObject`]. - pub fn build(self) -> BinObject { + pub fn build(self) -> BinObject { BinObject { path_hash: self.path_hash, class_hash: self.class_hash, diff --git a/crates/ltk_meta/src/tree/tests.rs b/crates/ltk_meta/src/tree/tests.rs index 520694b4..6908efe4 100644 --- a/crates/ltk_meta/src/tree/tests.rs +++ b/crates/ltk_meta/src/tree/tests.rs @@ -6,18 +6,26 @@ use glam::{Mat4, Vec2, Vec3, Vec4}; use indexmap::IndexMap; use ltk_primitives::Color; -use crate::property::{values, NoMeta}; -use crate::property::{BinProperty, Kind, PropertyValueEnum}; +use crate::{ + property::{values, NoMeta}, + traits::WriterExt, +}; +use crate::{ + property::{Kind, PropertyValueEnum}, + traits::ReaderExt, +}; use crate::{Bin, BinObject as Object}; /// Helper to roundtrip a property value through write/read -fn roundtrip_property(prop: &BinProperty) -> BinProperty { +fn roundtrip_property(prop: &(u32, PropertyValueEnum)) -> (u32, PropertyValueEnum) { let mut buffer = Vec::new(); let mut cursor = Cursor::new(&mut buffer); - prop.to_writer(&mut cursor).expect("write failed"); + cursor + .write_property(prop.0, &prop.1) + .expect("write failed"); cursor.set_position(0); - BinProperty::from_reader(&mut cursor, false).expect("read failed") + cursor.read_property(false).expect("read failed") } /// Helper to roundtrip a Bin through write/read @@ -31,8 +39,8 @@ fn roundtrip_tree(tree: &Bin) -> Bin { } /// Helper to create a BinProperty with a given name hash and value -fn make_prop(name_hash: u32, value: PropertyValueEnum) -> BinProperty { - BinProperty { name_hash, value } +fn make_prop(name_hash: u32, value: PropertyValueEnum) -> (u32, PropertyValueEnum) { + (name_hash, value) } // ============================================================================= @@ -334,13 +342,7 @@ fn test_container_with_strings_roundtrip() { #[test] fn test_container_with_structs_roundtrip() { let mut properties = IndexMap::new(); - properties.insert( - 0xAAAA, - BinProperty { - name_hash: 0xAAAA, - value: PropertyValueEnum::I32(values::I32::new(42)), - }, - ); + properties.insert(0xAAAA, PropertyValueEnum::I32(values::I32::new(42))); let prop = make_prop( 0x1234, @@ -405,13 +407,7 @@ fn test_optional_some_string_roundtrip() { #[test] fn test_optional_some_struct_roundtrip() { let mut properties = IndexMap::new(); - properties.insert( - 0xAAAA, - BinProperty { - name_hash: 0xAAAA, - value: PropertyValueEnum::Bool(values::Bool::from(true)), - }, - ); + properties.insert(0xAAAA, PropertyValueEnum::Bool(values::Bool::from(true))); let prop = make_prop( 0x1234, @@ -465,10 +461,7 @@ fn test_map_hash_to_struct_roundtrip() { let mut struct_props = IndexMap::new(); struct_props.insert( 0x1111, - BinProperty { - name_hash: 0x1111, - value: PropertyValueEnum::F32(values::F32::new(std::f32::consts::PI)), - }, + PropertyValueEnum::F32(values::F32::new(std::f32::consts::PI)), ); let entries = vec![( @@ -509,27 +502,12 @@ fn test_struct_empty_roundtrip() { #[test] fn test_struct_with_properties_roundtrip() { let mut properties = IndexMap::new(); - properties.insert( - 0x1111, - BinProperty { - name_hash: 0x1111, - value: PropertyValueEnum::I32(values::I32::new(42)), - }, - ); + properties.insert(0x1111, PropertyValueEnum::I32(values::I32::new(42))); properties.insert( 0x2222, - BinProperty { - name_hash: 0x2222, - value: PropertyValueEnum::String(values::String::from("test")), - }, - ); - properties.insert( - 0x3333, - BinProperty { - name_hash: 0x3333, - value: PropertyValueEnum::Bool(values::Bool::new(true)), - }, + PropertyValueEnum::String(values::String::from("test")), ); + properties.insert(0x3333, PropertyValueEnum::Bool(values::Bool::new(true))); let prop = make_prop( 0x1234, @@ -546,25 +524,16 @@ fn test_struct_with_properties_roundtrip() { #[test] fn test_struct_nested_roundtrip() { let mut inner_props = IndexMap::new(); - inner_props.insert( - 0xAAAA, - BinProperty { - name_hash: 0xAAAA, - value: PropertyValueEnum::F32(values::F32::new(1.5)), - }, - ); + inner_props.insert(0xAAAA, PropertyValueEnum::F32(values::F32::new(1.5))); let mut outer_props = IndexMap::new(); outer_props.insert( 0xBBBB, - BinProperty { - name_hash: 0xBBBB, - value: PropertyValueEnum::Struct(values::Struct { - class_hash: 0x1111, - properties: inner_props, - meta: NoMeta, - }), - }, + PropertyValueEnum::Struct(values::Struct { + class_hash: 0x1111, + properties: inner_props, + meta: NoMeta, + }), ); let prop = make_prop( @@ -588,10 +557,7 @@ fn test_embedded_roundtrip() { let mut properties = IndexMap::new(); properties.insert( 0x1111, - BinProperty { - name_hash: 0x1111, - value: PropertyValueEnum::Vector3(values::Vector3::new(Vec3::new(1.0, 2.0, 3.0))), - }, + PropertyValueEnum::Vector3(values::Vector3::new(Vec3::new(1.0, 2.0, 3.0))), ); let prop = make_prop( @@ -612,10 +578,10 @@ fn test_embedded_roundtrip() { #[test] fn test_bin_tree_object_empty_roundtrip() { - let obj = Object { + let obj = Object:: { path_hash: 0x1234, class_hash: 0x5678, - properties: IndexMap::new(), + properties: Default::default(), }; let mut buffer = Vec::new(); @@ -630,22 +596,13 @@ fn test_bin_tree_object_empty_roundtrip() { #[test] fn test_bin_tree_object_with_properties_roundtrip() { let mut properties = IndexMap::new(); - properties.insert( - 0xAAAA, - BinProperty { - name_hash: 0xAAAA, - value: PropertyValueEnum::I32(values::I32::new(100)), - }, - ); + properties.insert(0xAAAA, PropertyValueEnum::I32(values::I32::new(100))); properties.insert( 0xBBBB, - BinProperty { - name_hash: 0xBBBB, - value: PropertyValueEnum::String(values::String::from("object property")), - }, + PropertyValueEnum::String(values::String::from("object property")), ); - let obj = Object { + let obj = Object:: { path_hash: 0x1234, class_hash: 0x5678, properties, @@ -684,15 +641,9 @@ fn test_bin_tree_with_dependencies_roundtrip() { #[test] fn test_bin_tree_with_objects_roundtrip() { let mut properties = IndexMap::new(); - properties.insert( - 0xAAAA, - BinProperty { - name_hash: 0xAAAA, - value: PropertyValueEnum::I32(values::I32::new(42)), - }, - ); + properties.insert(0xAAAA, PropertyValueEnum::I32(values::I32::new(42))); - let obj = Object { + let obj = Object:: { path_hash: 0x1234, class_hash: 0x5678, properties, @@ -707,30 +658,18 @@ fn test_bin_tree_with_objects_roundtrip() { fn test_bin_tree_complex_roundtrip() { // Create a complex tree with multiple objects and various property types let mut obj1_props = IndexMap::new(); - obj1_props.insert( - 0x1111, - BinProperty { - name_hash: 0x1111, - value: PropertyValueEnum::Bool(values::Bool::new(true)), - }, - ); + obj1_props.insert(0x1111, PropertyValueEnum::Bool(values::Bool::new(true))); obj1_props.insert( 0x2222, - BinProperty { - name_hash: 0x2222, - value: PropertyValueEnum::String(values::String::from("test string")), - }, + PropertyValueEnum::String(values::String::from("test string")), ); obj1_props.insert( 0x3333, - BinProperty { - name_hash: 0x3333, - value: PropertyValueEnum::Container(values::Container::from(vec![ - values::I32::new(1), - values::I32::new(2), - values::I32::new(3), - ])), - }, + PropertyValueEnum::Container(values::Container::from(vec![ + values::I32::new(1), + values::I32::new(2), + values::I32::new(3), + ])), ); let obj1 = Object { @@ -742,17 +681,11 @@ fn test_bin_tree_complex_roundtrip() { let mut obj2_props = IndexMap::new(); obj2_props.insert( 0x4444, - BinProperty { - name_hash: 0x4444, - value: PropertyValueEnum::Vector3(values::Vector3::new(Vec3::new(1.0, 2.0, 3.0))), - }, + PropertyValueEnum::Vector3(values::Vector3::new(Vec3::new(1.0, 2.0, 3.0))), ); obj2_props.insert( 0x5555, - BinProperty { - name_hash: 0x5555, - value: PropertyValueEnum::Optional(values::F32::new(std::f32::consts::PI).into()), - }, + PropertyValueEnum::Optional(values::F32::new(std::f32::consts::PI).into()), ); let obj2 = Object { @@ -826,38 +759,26 @@ fn test_property_kind_roundtrip() { fn test_deeply_nested_struct() { // Create a deeply nested struct to test recursion handling let mut deepest_props = IndexMap::new(); - deepest_props.insert( - 0x1111, - BinProperty { - name_hash: 0x1111, - value: PropertyValueEnum::I32(values::I32::new(42)), - }, - ); + deepest_props.insert(0x1111, PropertyValueEnum::I32(values::I32::new(42))); let mut level2_props = IndexMap::new(); level2_props.insert( 0x2222, - BinProperty { - name_hash: 0x2222, - value: PropertyValueEnum::Struct(values::Struct { - class_hash: 0xAAAA, - properties: deepest_props, - meta: NoMeta, - }), - }, + PropertyValueEnum::Struct(values::Struct { + class_hash: 0xAAAA, + properties: deepest_props, + meta: NoMeta, + }), ); let mut level1_props = IndexMap::new(); level1_props.insert( 0x3333, - BinProperty { - name_hash: 0x3333, - value: PropertyValueEnum::Struct(values::Struct { - class_hash: 0xBBBB, - properties: level2_props, - meta: NoMeta, - }), - }, + PropertyValueEnum::Struct(values::Struct { + class_hash: 0xBBBB, + properties: level2_props, + meta: NoMeta, + }), ); let prop = make_prop( @@ -875,13 +796,7 @@ fn test_deeply_nested_struct() { #[test] fn test_container_with_embedded_roundtrip() { let mut embedded_props = IndexMap::new(); - embedded_props.insert( - 0x1111, - BinProperty { - name_hash: 0x1111, - value: PropertyValueEnum::U32(values::U32::new(999)), - }, - ); + embedded_props.insert(0x1111, PropertyValueEnum::U32(values::U32::new(999))); let prop = make_prop( 0x1234, diff --git a/crates/ltk_meta/tests/snapshots/meta__read.snap b/crates/ltk_meta/tests/snapshots/meta__read.snap index 423a0fed..54b4e9d5 100644 --- a/crates/ltk_meta/tests/snapshots/meta__read.snap +++ b/crates/ltk_meta/tests/snapshots/meta__read.snap @@ -10,133 +10,119 @@ Bin( path_hash: 2154231397, class_hash: 1171098015, properties: { - 2257500010: { - "kind": Container, - "name_hash": 2257500010, - "value": Struct( + 2257500010: PropertyValueEnum( + kind: Container, + value: Struct( items: [ Struct( class_hash: 164488258, properties: { - 431879391: { - "kind": U8, - "name_hash": 431879391, - "value": U8( + 431879391: PropertyValueEnum( + kind: U8, + value: U8( value: 0, meta: NoMeta, ), - }, - 607245356: { - "kind": Optional, - "name_hash": 607245356, - "value": F32( + ), + 607245356: PropertyValueEnum( + kind: Optional, + value: F32( value: Some(F32( value: 10.0, meta: NoMeta, )), meta: NoMeta, ), - }, - 895082843: { - "kind": BitBool, - "name_hash": 895082843, - "value": BitBool( + ), + 895082843: PropertyValueEnum( + kind: BitBool, + value: BitBool( value: true, meta: NoMeta, ), - }, - 1013213428: { - "kind": String, - "name_hash": 1013213428, - "value": String( + ), + 1013213428: PropertyValueEnum( + kind: String, + value: String( value: "ASSETS/Characters/Leona/Skins/Base/Particles/common_Black.dds", meta: NoMeta, ), - }, - 1025882318: { - "kind": String, - "name_hash": 1025882318, - "value": String( + ), + 1025882318: PropertyValueEnum( + kind: String, + value: String( value: "empty", meta: NoMeta, ), - }, - 1376955374: { - "kind": Optional, - "name_hash": 1376955374, - "value": F32( + ), + 1376955374: PropertyValueEnum( + kind: Optional, + value: F32( value: Some(F32( value: 1.0, meta: NoMeta, )), meta: NoMeta, ), - }, - 2927860839: { - "kind": Embedded, - "name_hash": 2927860839, - "value": Embedded(Struct( + ), + 2927860839: PropertyValueEnum( + kind: Embedded, + value: Embedded(Struct( class_hash: 70254680, properties: { - 3031705514: { - "kind": F32, - "name_hash": 3031705514, - "value": F32( + 3031705514: PropertyValueEnum( + kind: F32, + value: F32( value: 1.0, meta: NoMeta, ), - }, + ), }, meta: NoMeta, )), - }, - 3043919889: { - "kind": String, - "name_hash": 3043919889, - "value": String( + ), + 3043919889: PropertyValueEnum( + kind: String, + value: String( value: "ASSETS/Characters/Leona/Skins/Base/Particles/common_Black.dds", meta: NoMeta, ), - }, + ), }, meta: NoMeta, ), ], meta: NoMeta, ), - }, - 2624027180: { - "kind": U16, - "name_hash": 2624027180, - "value": U16( + ), + 2624027180: PropertyValueEnum( + kind: U16, + value: U16( value: 132, meta: NoMeta, ), - }, - 3770906030: { - "kind": String, - "name_hash": 3770906030, - "value": String( + ), + 3770906030: PropertyValueEnum( + kind: String, + value: String( value: "Play_sfx_Leona_LeonaZenithBladeMissile_hit", meta: NoMeta, ), - }, - 3882058040: { - "kind": String, - "name_hash": 3882058040, - "value": String( + ), + 3882058040: PropertyValueEnum( + kind: String, + value: String( value: "Characters/Leona/Skins/Skin0/Particles/Leona_Base_E_ZB_sfx_01", meta: NoMeta, ), - }, - 3975268028: { - "kind": String, - "name_hash": 3975268028, - "value": String( + ), + 3975268028: PropertyValueEnum( + kind: String, + value: String( value: "Leona_Base_E_ZB_sfx_01", meta: NoMeta, ), - }, + ), }, ), }, diff --git a/crates/ltk_ritobin/src/parser.rs b/crates/ltk_ritobin/src/parser.rs index dbe88a58..7b262a2c 100644 --- a/crates/ltk_ritobin/src/parser.rs +++ b/crates/ltk_ritobin/src/parser.rs @@ -8,7 +8,7 @@ use indexmap::IndexMap; use ltk_hash::fnv1a::hash_lower; use ltk_meta::{ property::{values, NoMeta, PropertyValueEnum}, - Bin, BinObject, BinProperty, PropertyKind, + Bin, BinObject, PropertyKind, }; use ltk_primitives::Color; use nom::{ @@ -561,7 +561,7 @@ fn parse_optional_value(input: Span, inner_kind: PropertyKind) -> ParseResult ParseResult> { +fn parse_struct_fields(input: Span) -> ParseResult> { let (input, _) = preceded(ws, char('{'))(input)?; let (input, _) = ws(input)?; @@ -577,8 +577,8 @@ fn parse_struct_fields(input: Span) -> ParseResult> { } // Parse field: name: type = value - let (r, field) = parse_field(r)?; - properties.insert(field.name_hash, field); + let (r, (name_hash, value)) = parse_field(r)?; + properties.insert(name_hash, value); let (r, _) = ws(r)?; let (r, _) = opt(char(','))(r)?; @@ -587,7 +587,7 @@ fn parse_struct_fields(input: Span) -> ParseResult> { } /// Parse a single field: name: type = value -fn parse_field(input: Span) -> ParseResult { +fn parse_field(input: Span) -> ParseResult<(u32, PropertyValueEnum)> { let (input, _) = ws(input)?; let (input, name_span) = word(input)?; let name_str = *name_span.fragment(); @@ -604,7 +604,7 @@ fn parse_field(input: Span) -> ParseResult { let (input, _) = preceded(ws, char('='))(input)?; let (input, value) = parse_value_for_type(input, &ty)?; - Ok((input, BinProperty { name_hash, value })) + Ok((input, (name_hash, value))) } /// Parse a pointer value (null or name { fields }). @@ -827,7 +827,7 @@ fn parse_value_for_type<'a>( // ============================================================================ /// Parse a top-level entry: key: type = value -fn parse_entry(input: Span) -> ParseResult<(String, BinProperty)> { +fn parse_entry(input: Span) -> ParseResult<(String, (u32, PropertyValueEnum))> { let (input, _) = ws(input)?; let (input, key) = identifier(input)?; let (input, _) = preceded(ws, char(':'))(input)?; @@ -837,10 +837,7 @@ fn parse_entry(input: Span) -> ParseResult<(String, BinProperty)> { let name_hash = hash_lower(key.fragment()); - Ok(( - input, - (key.fragment().to_string(), BinProperty { name_hash, value }), - )) + Ok((input, (key.fragment().to_string(), (name_hash, value)))) } /// Parse the entire ritobin file. @@ -867,7 +864,7 @@ fn parse_ritobin(input: Span) -> ParseResult { /// A ritobin file representation (intermediate format before conversion to BinTree). #[derive(Debug, Clone, Default)] pub struct RitobinFile { - pub entries: IndexMap, + pub entries: IndexMap, } impl RitobinFile { @@ -880,7 +877,7 @@ impl RitobinFile { /// Get the "type" field value as a string. pub fn file_type(&self) -> Option<&str> { self.entries.get("type").and_then(|p| { - if let PropertyValueEnum::String(s) = &p.value { + if let PropertyValueEnum::String(s) = &p.1 { Some(s.value.as_str()) } else { None @@ -891,7 +888,7 @@ impl RitobinFile { /// Get the "version" field as u32. pub fn version(&self) -> Option { self.entries.get("version").and_then(|p| { - if let PropertyValueEnum::U32(v) = &p.value { + if let PropertyValueEnum::U32(v) = &p.1 { Some(**v) } else { None @@ -904,8 +901,7 @@ impl RitobinFile { self.entries .get("linked") .and_then(|p| { - if let PropertyValueEnum::Container(values::Container::String { items, .. }) = - &p.value + if let PropertyValueEnum::Container(values::Container::String { items, .. }) = &p.1 { Some(items.iter().cloned().map(|i| i.value).collect()) } else { @@ -920,7 +916,7 @@ impl RitobinFile { self.entries .get("entries") .and_then(|p| { - if let PropertyValueEnum::Map(map) = &p.value { + if let PropertyValueEnum::Map(map) = &p.1 { Some( map.entries() .iter() @@ -1025,7 +1021,7 @@ pos: vec3 = { 1.0, 2.5, -3.0 } "#; let file = parse(input).unwrap(); let prop = file.entries.get("pos").unwrap(); - if let PropertyValueEnum::Vector3(v) = &prop.value { + if let PropertyValueEnum::Vector3(v) = &prop.1 { assert_eq!(v.x, 1.0); assert_eq!(v.y, 2.5); assert_eq!(v.z, -3.0); @@ -1044,7 +1040,7 @@ data: embed = TestClass { "#; let file = parse(input).unwrap(); let prop = file.entries.get("data").unwrap(); - if let PropertyValueEnum::Embedded(values::Embedded(s)) = &prop.value { + if let PropertyValueEnum::Embedded(values::Embedded(s)) = &prop.1 { assert_eq!(s.class_hash, hash_lower("TestClass")); assert_eq!(s.properties.len(), 2); } else { diff --git a/crates/ltk_ritobin/src/writer.rs b/crates/ltk_ritobin/src/writer.rs index 4f131943..0e50f69c 100644 --- a/crates/ltk_ritobin/src/writer.rs +++ b/crates/ltk_ritobin/src/writer.rs @@ -7,7 +7,7 @@ use ltk_meta::{ values::{Embedded, Struct, UnorderedContainer}, PropertyValueEnum, }, - Bin, BinObject, BinProperty, + Bin, BinObject, }; use crate::{ @@ -323,8 +323,8 @@ impl<'a, H: HashProvider> TextWriter<'a, H> { } else { self.write_raw("{\n"); self.indent(); - for prop in v.properties.values() { - self.write_property(prop)?; + for (name_hash, value) in v.properties.iter() { + self.write_property(*name_hash, value)?; } self.dedent(); self.pad(); @@ -334,13 +334,17 @@ impl<'a, H: HashProvider> TextWriter<'a, H> { Ok(()) } - fn write_property(&mut self, prop: &BinProperty) -> Result<(), WriteError> { + fn write_property( + &mut self, + name_hash: u32, + value: &PropertyValueEnum, + ) -> Result<(), WriteError> { self.pad(); - self.write_field_hash(prop.name_hash)?; + self.write_field_hash(name_hash)?; self.write_raw(": "); - self.write_type(&prop.value); + self.write_type(value); self.write_raw(" = "); - self.write_value(&prop.value)?; + self.write_value(value)?; self.write_raw("\n"); Ok(()) } @@ -395,8 +399,8 @@ impl<'a, H: HashProvider> TextWriter<'a, H> { } else { self.write_raw("{\n"); self.indent(); - for prop in obj.properties.values() { - self.write_property(prop)?; + for (name_hash, value) in &obj.properties { + self.write_property(*name_hash, value)?; } self.dedent(); self.pad(); @@ -593,13 +597,7 @@ mod tests { // Create a simple tree with a hash value let mut properties = IndexMap::new(); let name_hash = ltk_hash::fnv1a::hash_lower("testField"); - properties.insert( - name_hash, - BinProperty { - name_hash, - value: PropertyValueEnum::String(String::from("hello")), - }, - ); + properties.insert(name_hash, PropertyValueEnum::String(String::from("hello"))); let path_hash = ltk_hash::fnv1a::hash_lower("Test/Path"); let class_hash = ltk_hash::fnv1a::hash_lower("TestClass"); diff --git a/crates/ltk_ritobin/tests/parse_sample.rs b/crates/ltk_ritobin/tests/parse_sample.rs index 740c4ec8..d10d0ba7 100644 --- a/crates/ltk_ritobin/tests/parse_sample.rs +++ b/crates/ltk_ritobin/tests/parse_sample.rs @@ -270,7 +270,7 @@ entries: map[hash,embed] = { let file = parse(input).expect("Failed to parse matrix input"); let tree = file.to_bin_tree(); let obj = tree.objects.values().next().expect("Expected one object"); - let parsed_mat = match &obj.properties.values().next().unwrap().value { + let parsed_mat = match &obj.properties.values().next().unwrap() { PropertyValueEnum::Matrix44(v) => v.value, other => panic!("Expected Matrix44, got {:?}", other), }; @@ -288,7 +288,7 @@ entries: map[hash,embed] = { .values() .next() .expect("Expected one object after round-trip"); - let roundtrip_mat = match &obj2.properties.values().next().unwrap().value { + let roundtrip_mat = match &obj2.properties.values().next().unwrap() { PropertyValueEnum::Matrix44(v) => v.value, other => panic!("Expected Matrix44 after round-trip, got {:?}", other), }; From c0273d0b70b945e51aeafe50e079930f4d8de54b Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Thu, 26 Mar 2026 20:19:09 +0000 Subject: [PATCH 017/187] feat: meta generic in Bin --- crates/ltk_meta/src/tree.rs | 48 ++++++++++++++++++-------------- crates/ltk_ritobin/src/writer.rs | 4 +-- 2 files changed, 29 insertions(+), 23 deletions(-) diff --git a/crates/ltk_meta/src/tree.rs b/crates/ltk_meta/src/tree.rs index 67c6b611..af0dd94e 100644 --- a/crates/ltk_meta/src/tree.rs +++ b/crates/ltk_meta/src/tree.rs @@ -12,6 +12,8 @@ mod tests; use indexmap::IndexMap; +use crate::property::NoMeta; + /// The complete contents of a League of Legends property bin file. /// /// It contains a collection of objects, each identified @@ -32,9 +34,13 @@ use indexmap::IndexMap; /// .dependency("base.bin") /// .build(); /// ``` -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr( + feature = "serde", + derive(serde::Serialize, serde::Deserialize), + serde(bound = "for <'dee> M: serde::Serialize + serde::Deserialize<'dee>") +)] #[derive(Debug, Clone, PartialEq)] -pub struct Bin { +pub struct Bin { /// Whether this is an override/patch bin file. pub is_override: bool, @@ -43,7 +49,7 @@ pub struct Bin { pub version: u32, /// The objects in this bin tree, keyed by their path hash. - pub objects: IndexMap, + pub objects: IndexMap>, /// List of other property bins this file depends on. /// @@ -67,7 +73,7 @@ impl Default for Bin { } } -impl Bin { +impl Bin { /// Creates a new `Bin` with the given objects and dependencies. /// /// The version is set to 3 and `is_override` is set to false. @@ -83,7 +89,7 @@ impl Bin { /// ); /// ``` pub fn new( - objects: impl IntoIterator, + objects: impl IntoIterator>, dependencies: impl IntoIterator>, ) -> Self { Self { @@ -91,7 +97,7 @@ impl Bin { is_override: false, objects: objects .into_iter() - .map(|o: BinObject| (o.path_hash, o)) + .map(|o: BinObject| (o.path_hash, o)) .collect(), dependencies: dependencies.into_iter().map(Into::into).collect(), data_overrides: Vec::new(), @@ -128,13 +134,13 @@ impl Bin { /// Returns a reference to the object with the given path hash, if it exists. #[inline] - pub fn get_object(&self, path_hash: u32) -> Option<&BinObject> { + pub fn get_object(&self, path_hash: u32) -> Option<&BinObject> { self.objects.get(&path_hash) } /// Returns a mutable reference to the object with the given path hash, if it exists. #[inline] - pub fn get_object_mut(&mut self, path_hash: u32) -> Option<&mut BinObject> { + pub fn get_object_mut(&mut self, path_hash: u32) -> Option<&mut BinObject> { self.objects.get_mut(&path_hash) } @@ -148,12 +154,12 @@ impl Bin { /// /// If an object with the same path hash already exists, it is replaced /// and the old object is returned. - pub fn add_object(&mut self, object: BinObject) -> Option { + pub fn add_object(&mut self, object: BinObject) -> Option> { self.objects.insert(object.path_hash, object) } /// Removes and returns the object with the given path hash, if it exists. - pub fn remove_object(&mut self, path_hash: u32) -> Option { + pub fn remove_object(&mut self, path_hash: u32) -> Option> { self.objects.shift_remove(&path_hash) } @@ -164,38 +170,38 @@ impl Bin { /// Returns an iterator over the objects in the tree. #[inline] - pub fn iter(&self) -> impl Iterator { + pub fn iter(&self) -> impl Iterator)> { self.objects.iter() } /// Returns a mutable iterator over the objects in the tree. #[inline] - pub fn iter_mut(&mut self) -> impl Iterator { + pub fn iter_mut(&mut self) -> impl Iterator)> { self.objects.iter_mut() } } -impl<'a> IntoIterator for &'a Bin { - type Item = (&'a u32, &'a BinObject); - type IntoIter = indexmap::map::Iter<'a, u32, BinObject>; +impl<'a, M> IntoIterator for &'a Bin { + type Item = (&'a u32, &'a BinObject); + type IntoIter = indexmap::map::Iter<'a, u32, BinObject>; fn into_iter(self) -> Self::IntoIter { self.objects.iter() } } -impl<'a> IntoIterator for &'a mut Bin { - type Item = (&'a u32, &'a mut BinObject); - type IntoIter = indexmap::map::IterMut<'a, u32, BinObject>; +impl<'a, M> IntoIterator for &'a mut Bin { + type Item = (&'a u32, &'a mut BinObject); + type IntoIter = indexmap::map::IterMut<'a, u32, BinObject>; fn into_iter(self) -> Self::IntoIter { self.objects.iter_mut() } } -impl IntoIterator for Bin { - type Item = (u32, BinObject); - type IntoIter = indexmap::map::IntoIter; +impl IntoIterator for Bin { + type Item = (u32, BinObject); + type IntoIter = indexmap::map::IntoIter>; fn into_iter(self) -> Self::IntoIter { self.objects.into_iter() diff --git a/crates/ltk_ritobin/src/writer.rs b/crates/ltk_ritobin/src/writer.rs index 0e50f69c..2281bf58 100644 --- a/crates/ltk_ritobin/src/writer.rs +++ b/crates/ltk_ritobin/src/writer.rs @@ -5,7 +5,7 @@ use std::fmt::Write; use ltk_meta::{ property::{ values::{Embedded, Struct, UnorderedContainer}, - PropertyValueEnum, + NoMeta, PropertyValueEnum, }, Bin, BinObject, }; @@ -524,7 +524,7 @@ impl RitobinBuilder { /// /// The resulting tree will have version 3, which is always used when writing. pub fn build(self) -> Bin { - Bin::builder() + Bin::::builder() .is_override(self.is_override) .dependencies(self.dependencies) .objects(self.objects) From a8950a09a846ac3112e3302f95c21ba75674d717 Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Sat, 28 Mar 2026 23:14:18 +0000 Subject: [PATCH 018/187] feat: meta generic in bin Builder --- crates/ltk_meta/src/tree.rs | 7 +++++-- crates/ltk_meta/src/tree/builder.rs | 17 ++++++++++------- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/crates/ltk_meta/src/tree.rs b/crates/ltk_meta/src/tree.rs index af0dd94e..a9766872 100644 --- a/crates/ltk_meta/src/tree.rs +++ b/crates/ltk_meta/src/tree.rs @@ -116,8 +116,11 @@ impl Bin { /// .object(BinObject::new(0x1234, 0x5678)) /// .build(); /// ``` - pub fn builder() -> builder::Builder { - builder::Builder::new() + pub fn builder() -> builder::Builder + where + M: Default, + { + builder::Builder::::new() } /// Returns the number of objects in the tree. diff --git a/crates/ltk_meta/src/tree/builder.rs b/crates/ltk_meta/src/tree/builder.rs index d1cd2827..b807ea92 100644 --- a/crates/ltk_meta/src/tree/builder.rs +++ b/crates/ltk_meta/src/tree/builder.rs @@ -16,15 +16,18 @@ use crate::Bin; /// .build(); /// ``` #[derive(Debug, Default, Clone)] -pub struct Builder { +pub struct Builder { is_override: bool, - objects: Vec, + objects: Vec>, dependencies: Vec, } -impl Builder { +impl Builder { /// See: [`Bin::builder`] - pub fn new() -> Self { + pub fn new() -> Self + where + M: Default, + { Self::default() } @@ -49,13 +52,13 @@ impl Builder { } /// Adds a single object. - pub fn object(mut self, obj: BinObject) -> Self { + pub fn object(mut self, obj: BinObject) -> Self { self.objects.push(obj); self } /// Adds multiple objects. - pub fn objects(mut self, objs: impl IntoIterator) -> Self { + pub fn objects(mut self, objs: impl IntoIterator>) -> Self { self.objects.extend(objs); self } @@ -63,7 +66,7 @@ impl Builder { /// Build the final [`Bin`]. /// /// The resulting tree will have version 3, which is always used when writing. - pub fn build(self) -> Bin { + pub fn build(self) -> Bin { Bin { version: 3, is_override: self.is_override, From 712582a87c18b69c06c86b881071e5d8d86e0adc Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Sat, 28 Mar 2026 23:42:41 +0000 Subject: [PATCH 019/187] fix: doctests --- crates/ltk_meta/src/lib.rs | 2 +- crates/ltk_meta/src/tree.rs | 14 +++++++------- crates/ltk_meta/src/tree/builder.rs | 4 ++-- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/crates/ltk_meta/src/lib.rs b/crates/ltk_meta/src/lib.rs index 173d0dac..b189cfd9 100644 --- a/crates/ltk_meta/src/lib.rs +++ b/crates/ltk_meta/src/lib.rs @@ -42,7 +42,7 @@ let tree = Bin::builder() // Or using the simple constructor let tree = Bin::new( - [BinObject::new(0x1234, 0x5678)], + [BinObject::::new(0x1234, 0x5678)], ["dependency.bin"], ); ``` diff --git a/crates/ltk_meta/src/tree.rs b/crates/ltk_meta/src/tree.rs index a9766872..40b694da 100644 --- a/crates/ltk_meta/src/tree.rs +++ b/crates/ltk_meta/src/tree.rs @@ -24,13 +24,13 @@ use crate::property::NoMeta; /// Use [`Bin::new`] for simple cases or [`Bin::builder`] for more control: /// /// ``` -/// use ltk_meta::{Bin, BinObject}; +/// use ltk_meta::{Bin, BinObject, property::NoMeta}; /// /// // Simple construction -/// let tree = Bin::new([], std::iter::empty::<&str>()); +/// let tree = Bin::::new([], std::iter::empty::<&str>()); /// /// // Builder pattern -/// let tree = Bin::builder() +/// let tree = Bin::::builder() /// .dependency("base.bin") /// .build(); /// ``` @@ -81,9 +81,9 @@ impl Bin { /// # Examples /// /// ``` - /// use ltk_meta::{Bin, BinObject}; + /// use ltk_meta::{Bin, BinObject, property::NoMeta}; /// - /// let tree = Bin::new( + /// let tree = Bin::::new( /// [BinObject::new(0x1234, 0x5678)], /// ["dependency.bin"], /// ); @@ -109,9 +109,9 @@ impl Bin { /// # Examples /// /// ``` - /// use ltk_meta::{Bin, BinObject}; + /// use ltk_meta::{Bin, BinObject, property::NoMeta}; /// - /// let tree = Bin::builder() + /// let tree = Bin::::builder() /// .dependency("common.bin") /// .object(BinObject::new(0x1234, 0x5678)) /// .build(); diff --git a/crates/ltk_meta/src/tree/builder.rs b/crates/ltk_meta/src/tree/builder.rs index b807ea92..a72ef205 100644 --- a/crates/ltk_meta/src/tree/builder.rs +++ b/crates/ltk_meta/src/tree/builder.rs @@ -6,9 +6,9 @@ use crate::Bin; /// # Examples /// /// ``` -/// use ltk_meta::{Bin, BinObject}; +/// use ltk_meta::{Bin, BinObject, property::NoMeta}; /// -/// let tree = Bin::builder() +/// let tree = Bin::::builder() /// .is_override(false) /// .dependency("base.bin") /// .dependencies(["extra1.bin", "extra2.bin"]) From 6100d9b23eae0577ed059f4c4bc15d022e3ff3dc Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Mon, 5 Jan 2026 15:29:36 +0000 Subject: [PATCH 020/187] chore: add cargo-public-api to flake + update flake --- flake.nix | 51 +++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 39 insertions(+), 12 deletions(-) diff --git a/flake.nix b/flake.nix index ba881876..ad03c07b 100644 --- a/flake.nix +++ b/flake.nix @@ -35,6 +35,32 @@ extensions = ["rust-src"]; })); + nightly = eachSystem (pkgs: + pkgs.rust-bin.selectLatestNightlyWith (t: + t.default.override { + extensions = ["rust-docs-json"]; + })); + + cargo-expand' = eachSystem (pkgs: let + nightly' = nightly.${pkgs.system}; + in + pkgs.writeShellScriptBin "cargo-expand" '' + export RUSTC="${nightly'}/bin/rustc"; + export CARGO="${nightly'}/bin/cargo"; + exec "${pkgs.cargo-expand}/bin/cargo-expand" "$@" + ''); + + cargo-public-api' = eachSystem (pkgs: let + nightly' = nightly.${pkgs.system}; + fakeRustup = pkgs.writeShellScriptBin "rustup" ''shift 3; ${pkgs.lib.getExe' nightly' "cargo"} "$@"''; + in + pkgs.writeShellScriptBin "cargo-public-api" '' + export RUSTC="${nightly'}/bin/rustc"; + export CARGO="${nightly'}/bin/cargo"; + export PATH="${fakeRustup}/bin:${nightly'}/bin:$PATH"; + exec "${pkgs.cargo-public-api}/bin/cargo-public-api" "$@" + ''); + treefmtEval = eachSystem (pkgs: treefmt-nix.lib.evalModule pkgs ./treefmt.nix); in { # You can use crane to build the Rust application with Nix @@ -49,8 +75,8 @@ devShells = eachSystem (pkgs: { # Based on a discussion at https://github.com/oxalica/rust-overlay/issues/129 - default = pkgs.mkShell (with pkgs; { - nativeBuildInputs = [ + default = pkgs.mkShell { + nativeBuildInputs = with pkgs; [ clang gdb # Use mold when we are runnning in Linux @@ -58,17 +84,18 @@ ]; buildInputs = [ rustToolchain.${pkgs.system} - rust-analyzer-unwrapped - cargo - cargo-insta - cargo-hack - cargo-expand - bacon - # pkg-config - # openssl + pkgs.rust-analyzer-unwrapped + pkgs.cargo + pkgs.cargo-insta + pkgs.cargo-hack + cargo-expand'.${pkgs.system} + cargo-public-api'.${pkgs.system} + pkgs.bacon + # pkgs.pkg-config + # pkgs.openssl ]; - RUST_SRC_PATH = rustPlatform.rustLibSrc; - }); + RUST_SRC_PATH = pkgs.rustPlatform.rustLibSrc; + }; }); formatter = eachSystem (pkgs: treefmtEval.${pkgs.system}.config.build.wrapper); From ceafa202665b282e27b060b80e631bcfd216ce6c Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Mon, 5 Jan 2026 15:42:29 +0000 Subject: [PATCH 021/187] fix: promote parser module to folder --- crates/ltk_ritobin/src/{parser.rs => parser/mod.rs} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename crates/ltk_ritobin/src/{parser.rs => parser/mod.rs} (100%) diff --git a/crates/ltk_ritobin/src/parser.rs b/crates/ltk_ritobin/src/parser/mod.rs similarity index 100% rename from crates/ltk_ritobin/src/parser.rs rename to crates/ltk_ritobin/src/parser/mod.rs From a9ebb621583416160c800c92dc0520283dbbf111 Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Wed, 7 Jan 2026 13:00:00 +0000 Subject: [PATCH 022/187] wip: CST parser + handrolled tokenizer --- crates/ltk_ritobin/Cargo.toml | 1 + crates/ltk_ritobin/src/error.rs | 13 +- crates/ltk_ritobin/src/parser/mod.rs | 3 + crates/ltk_ritobin/src/parser/real.rs | 466 +++++++++++++++++++++ crates/ltk_ritobin/src/parser/tokenizer.rs | 152 +++++++ 5 files changed, 630 insertions(+), 5 deletions(-) create mode 100644 crates/ltk_ritobin/src/parser/real.rs create mode 100644 crates/ltk_ritobin/src/parser/tokenizer.rs diff --git a/crates/ltk_ritobin/Cargo.toml b/crates/ltk_ritobin/Cargo.toml index 6d329e7b..7d067e24 100644 --- a/crates/ltk_ritobin/Cargo.toml +++ b/crates/ltk_ritobin/Cargo.toml @@ -25,6 +25,7 @@ ltk_hash = { version = "0.2.5", path = "../ltk_hash" } ltk_primitives = { version = "0.3.2", path = "../ltk_primitives" } serde = { workspace = true, optional = true } +salsa = "0.22.0" [dev-dependencies] insta = { workspace = true } diff --git a/crates/ltk_ritobin/src/error.rs b/crates/ltk_ritobin/src/error.rs index 350e35c0..3805b0ff 100644 --- a/crates/ltk_ritobin/src/error.rs +++ b/crates/ltk_ritobin/src/error.rs @@ -9,19 +9,22 @@ use thiserror::Error; /// A span in the source text (offset and length). #[derive(Debug, Clone, Copy, Default)] pub struct Span { - pub offset: usize, - pub len: usize, + pub start: u32, + pub end: u32, } impl Span { - pub fn new(offset: usize, len: usize) -> Self { - Self { offset, len } + pub fn new(start: u32, end: u32) -> Self { + Self { start, end } } } impl From for SourceSpan { fn from(span: Span) -> Self { - SourceSpan::new(span.offset.into(), span.len) + SourceSpan::new( + (span.start as usize).into(), + ((span.end - span.start) as usize).into(), + ) } } diff --git a/crates/ltk_ritobin/src/parser/mod.rs b/crates/ltk_ritobin/src/parser/mod.rs index 7b262a2c..50d355ad 100644 --- a/crates/ltk_ritobin/src/parser/mod.rs +++ b/crates/ltk_ritobin/src/parser/mod.rs @@ -3,6 +3,9 @@ // Nom-style parsers use elided lifetimes extensively #![allow(clippy::type_complexity)] +pub mod real; +pub mod tokenizer; + use glam::{Mat4, Vec2, Vec3, Vec4}; use indexmap::IndexMap; use ltk_hash::fnv1a::hash_lower; diff --git a/crates/ltk_ritobin/src/parser/real.rs b/crates/ltk_ritobin/src/parser/real.rs new file mode 100644 index 00000000..2963b30e --- /dev/null +++ b/crates/ltk_ritobin/src/parser/real.rs @@ -0,0 +1,466 @@ +use std::{ + cell::Cell, + fmt, + sync::{Arc, Mutex}, +}; + +use super::tokenizer::{lex, Token, TokenKind}; + +#[salsa::db] +#[derive(Clone)] +#[cfg_attr(not(test), derive(Default))] +pub struct CalcDatabaseImpl { + storage: salsa::Storage, + + // The logs are only used for testing and demonstrating reuse: + #[cfg(test)] + logs: Arc>>>, +} + +#[cfg(test)] +impl Default for CalcDatabaseImpl { + fn default() -> Self { + let logs = >>>>::default(); + Self { + storage: salsa::Storage::new(Some(Box::new({ + let logs = logs.clone(); + move |event| { + eprintln!("Event: {event:?}"); + // Log interesting events, if logging is enabled + if let Some(logs) = &mut *logs.lock().unwrap() { + // only log interesting events + if let salsa::EventKind::WillExecute { .. } = event.kind { + logs.push(format!("Event: {event:?}")); + } + } + } + }))), + logs, + } + } +} + +#[allow(unused_variables)] +pub trait Visitor { + fn enter_tree(&mut self, kind: TreeKind) {} + fn exit_tree(&mut self, kind: TreeKind) {} + fn visit_token(&mut self, token: &Token, context: TreeKind) {} +} + +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[rustfmt::skip] +pub enum TreeKind { + ErrorTree, + File, + TypeExpr, TypeArgList, TypeArg, + Block, + StmtEntry, + ExprLiteral, ExprName, +} + +#[derive(Clone)] +pub struct Tree { + kind: TreeKind, + children: Vec, +} + +impl Tree { + pub fn walk(&self, visitor: &mut V) { + self.walk_inner(visitor); + } + + fn walk_inner(&self, visitor: &mut V) { + visitor.enter_tree(self.kind); + + for child in &self.children { + match child { + Child::Token(token) => { + visitor.visit_token(token, self.kind); + } + Child::Tree(child_tree) => { + child_tree.walk_inner(visitor); + } + } + } + + visitor.exit_tree(self.kind); + } +} + +#[derive(Clone, Debug)] +pub enum Child { + Token(Token), + Tree(Tree), +} + +pub enum Event { + Open { kind: TreeKind }, + Close, + Advance, +} + +pub struct MarkOpened { + index: usize, +} +pub struct MarkClosed { + index: usize, +} + +pub struct Parser { + pub tokens: Vec, + pos: usize, + fuel: Cell, + pub events: Vec, +} + +impl Parser { + pub fn new(tokens: Vec) -> Parser { + Parser { + tokens, + pos: 0, + fuel: Cell::new(256), + events: Vec::new(), + } + } + + pub fn build_tree(self) -> Tree { + let mut tokens = self.tokens.into_iter(); + let mut events = self.events; + + assert!(matches!(events.pop(), Some(Event::Close))); + let mut stack = Vec::new(); + for event in events { + match event { + Event::Open { kind } => stack.push(Tree { + kind, + children: Vec::new(), + }), + Event::Close => { + let tree = stack.pop().unwrap(); + stack.last_mut().unwrap().children.push(Child::Tree(tree)); + } + Event::Advance => { + let token = tokens.next().unwrap(); + stack.last_mut().unwrap().children.push(Child::Token(token)); + } + } + } + + let tree = stack.pop().unwrap(); + assert!(stack.is_empty()); + assert!(tokens.next().is_none()); + tree + } + + fn open(&mut self) -> MarkOpened { + let mark = MarkOpened { + index: self.events.len(), + }; + self.events.push(Event::Open { + kind: TreeKind::ErrorTree, + }); + mark + } + + fn open_before(&mut self, m: MarkClosed) -> MarkOpened { + let mark = MarkOpened { index: m.index }; + self.events.insert( + m.index, + Event::Open { + kind: TreeKind::ErrorTree, + }, + ); + mark + } + + fn close(&mut self, m: MarkOpened, kind: TreeKind) -> MarkClosed { + self.events[m.index] = Event::Open { kind }; + self.events.push(Event::Close); + MarkClosed { index: m.index } + } + + fn advance(&mut self) { + assert!(!self.eof()); + self.fuel.set(256); + self.events.push(Event::Advance); + self.pos += 1; + } + + fn advance_with_error(&mut self, error: &str) { + let m = self.open(); + // TODO: Error reporting. + eprintln!("{error}"); + self.advance(); + self.close(m, TreeKind::ErrorTree); + } + + fn eof(&self) -> bool { + self.pos == self.tokens.len() + } + + fn nth(&self, lookahead: usize) -> TokenKind { + if self.fuel.get() == 0 { + panic!("parser is stuck") + } + self.fuel.set(self.fuel.get() - 1); + self.tokens + .get(self.pos + lookahead) + .map_or(TokenKind::Eof, |it| it.kind) + } + + fn at(&self, kind: TokenKind) -> bool { + self.nth(0) == kind + } + + fn at_any(&self, kinds: &[TokenKind]) -> bool { + kinds.contains(&self.nth(0)) + } + + fn eat(&mut self, kind: TokenKind) -> bool { + if self.at(kind) { + self.advance(); + true + } else { + false + } + } + + fn expect(&mut self, kind: TokenKind) { + if self.eat(kind) { + return; + } + // TODO: Error reporting. + eprintln!("expected {kind:?}"); + } +} + +pub fn parse(text: &str) -> Tree { + let tokens = lex(text); + eprintln!("tokens: {tokens:#?}"); + let mut p = Parser::new(tokens); + file(&mut p); + p.build_tree() +} + +pub fn file(p: &mut Parser) { + let m = p.open(); + while !p.eof() { + if p.at(TokenKind::Name) { + stmt_entry(p) + } else { + p.advance_with_error("expected a name"); + } + } + p.close(m, TreeKind::File); +} +pub fn stmt_entry(p: &mut Parser) { + let m = p.open(); + + p.expect(TokenKind::Name); + p.expect(TokenKind::Colon); + expr_type(p); + p.expect(TokenKind::Eq); + match p.nth(0) { + TokenKind::Quote => { + let m = p.open(); + p.advance(); + p.expect(TokenKind::Name); + p.expect(TokenKind::Quote); + p.close(m, TreeKind::ExprLiteral); + } + TokenKind::Int | TokenKind::Minus => { + let m = p.open(); + p.advance(); + p.close(m, TreeKind::ExprLiteral); + } + TokenKind::LCurly => { + block(p); + } + TokenKind::Eof | TokenKind::Name => {} + _ => p.advance_with_error("unexpected"), + } + + p.close(m, TreeKind::StmtEntry); +} + +pub fn expr_type(p: &mut Parser) -> MarkClosed { + let m = p.open(); + p.expect(TokenKind::Name); + if p.eat(TokenKind::LBrack) { + while !p.at(TokenKind::RBrack) && !p.eof() { + if p.at(TokenKind::Name) { + expr_type_arg(p); + } else { + break; + } + } + p.expect(TokenKind::RBrack); + } + p.close(m, TreeKind::TypeExpr) +} + +pub fn expr_type_arg(p: &mut Parser) -> MarkClosed { + use TokenKind::*; + assert!(p.at(Name)); + let m = p.open(); + + p.expect(Name); + if !p.at(RParen) { + p.expect(Comma); + } + + p.close(m, TreeKind::TypeArg) +} + +pub fn block(p: &mut Parser) { + use TokenKind::*; + assert!(p.at(LCurly)); + let m = p.open(); + + p.expect(LCurly); + while !p.at(RCurly) && !p.eof() { + stmt_entry(p) + } + p.expect(RCurly); + + p.close(m, TreeKind::Block); +} + +#[cfg(test)] +mod test { + use super::*; + #[test] + fn smoke_test() { + let text = r#" +type = 4 +version: list[u32, = 3 +linked: list[string] = { + "DATA/Characters/Test/Animations/Skin0.bin\" + "DATA/Characters/Test/Test.bin" + +version: u32 = 5 + +"#; + let cst = parse(text); + eprintln!("{cst:?}"); + } +} + +#[macro_export] +macro_rules! format_to { + ($buf:expr) => (); + ($buf:expr, $lit:literal $($arg:tt)*) => { + { use ::std::fmt::Write as _; let _ = ::std::write!($buf, $lit $($arg)*); } + }; +} +impl Tree { + fn print(&self, buf: &mut String, level: usize) { + let parent_indent = "│ ".repeat(level.saturating_sub(1)); + let indent = match level > 0 { + true => "├ ", + false => "", + }; + format_to!(buf, "{parent_indent}{indent}{:?}\n", self.kind); + for (i, child) in self.children.iter().enumerate() { + let bar = match i + 1 == self.children.len() { + true => '└', + false => '├', + }; + match child { + Child::Token(token) => { + format_to!(buf, "{parent_indent}│ {bar} {:?}\n", token.span) + } + Child::Tree(tree) => tree.print(buf, level + 1), + } + } + assert!(buf.ends_with('\n')); + } +} + +impl fmt::Debug for Tree { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let mut buf = String::new(); + self.print(&mut buf, 0); + write!(f, "{}", buf) + } +} + +#[salsa::db] +impl salsa::Database for CalcDatabaseImpl {} + +#[salsa::input(debug)] +pub struct SourceProgram { + #[returns(ref)] + pub text: String, +} + +#[salsa::tracked(debug)] +pub struct RitobinFile<'db> { + #[tracked] + #[returns(ref)] + pub statements: Vec>, +} + +#[salsa::interned(debug)] +pub struct PropertyName<'db> { + #[returns(ref)] + pub text: String, +} + +#[derive(PartialEq, Debug, Hash, salsa::Update)] +pub struct Statement<'db> { + pub span: Span<'db>, + pub name: PropertyName<'db>, + pub value: BinProperty, +} + +#[salsa::accumulator] +#[derive(Debug)] +#[allow(dead_code)] // Debug impl uses them +pub struct Diagnostic { + pub start: usize, + pub end: usize, + pub message: String, +} +impl Diagnostic { + pub fn new(start: usize, end: usize, message: String) -> Self { + Diagnostic { + start, + end, + message, + } + } + + // #[cfg(test)] + // pub fn render(&self, db: &dyn crate::Db, src: SourceProgram) -> String { + // use annotate_snippets::*; + // let line_start = src.text(db)[..self.start].lines().count() + 1; + // Renderer::plain() + // .render( + // Level::Error.title(&self.message).snippet( + // Snippet::source(src.text(db)) + // .line_start(line_start) + // .origin("input") + // .fold(true) + // .annotation(Level::Error.span(self.start..self.end).label("here")), + // ), + // ) + // .to_string() + // } +} + +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[derive(Clone, PartialEq, Debug, Hash, salsa::Update)] +pub struct BinProperty { + pub name_hash: u32, + #[cfg_attr(feature = "serde", serde(flatten))] + pub value: ltk_meta::PropertyValueEnum, +} + +#[salsa::tracked(debug)] +pub struct Span<'db> { + #[tracked] + pub start: usize, + #[tracked] + pub end: usize, +} diff --git a/crates/ltk_ritobin/src/parser/tokenizer.rs b/crates/ltk_ritobin/src/parser/tokenizer.rs new file mode 100644 index 00000000..11bda029 --- /dev/null +++ b/crates/ltk_ritobin/src/parser/tokenizer.rs @@ -0,0 +1,152 @@ +use crate::Span; + +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[rustfmt::skip] +pub enum TokenKind { + ErrorToken, Eof, + + LParen, RParen, LCurly, RCurly, + LBrack, RBrack, + Eq, Comma, Colon, + Minus, Star, Slash, + Quote, + + String, + + + True, False, + + Name, Int, +} + +#[derive(Clone, Copy, Debug)] +pub struct Token { + pub kind: TokenKind, + pub span: Span, +} +pub fn lex<'a>(mut text: &'a str) -> Vec { + use TokenKind::*; + let punctuation = ( + "( ) { } [ ] = , : - * / \" \'", + [ + LParen, RParen, LCurly, RCurly, LBrack, RBrack, Eq, Comma, Colon, Minus, Star, Slash, + Quote, + ], + ); + + let keywords = ("true false", [True, False]); + + let source = text; + + let mut result = Vec::new(); + while !text.is_empty() { + if let Some(rest) = trim(text, |it| it.is_ascii_whitespace()) { + text = rest; + continue; + } + let text_orig = text; + let mut kind = 'kind: { + for (i, symbol) in punctuation.0.split_ascii_whitespace().enumerate() { + if let Some(rest) = text.strip_prefix(symbol) { + text = rest; + break 'kind punctuation.1[i]; + } + } + if let Some(rest) = trim(text, |it| it.is_ascii_digit()) { + text = rest; + break 'kind Int; + } + if let Some(rest) = trim(text, name_char) { + text = rest; + break 'kind Name; + } + let error_index = text + .find(|it: char| it.is_ascii_whitespace()) + .unwrap_or(text.len()); + text = &text[error_index..]; + ErrorToken + }; + assert!(text.len() < text_orig.len()); + let token_text = &text_orig[..text_orig.len() - text.len()]; + + let start = source.len() - text_orig.len(); + let end = source.len() - text.len(); + + let span = Span { + start: start as u32, + end: end as u32, + }; + if kind == Name { + for (i, symbol) in keywords.0.split_ascii_whitespace().enumerate() { + if token_text == symbol { + kind = keywords.1[i]; + break; + } + } + } + result.push(Token { kind, span }); + if kind == Quote { + eprintln!("[lex] pushed quote!"); + let span = match find_string_closer(text) { + Some(close_idx) => { + let start = (source.len() - text.len()) as u32; + Span { + start, + end: start + close_idx as u32, + } + } + // &text[..close_idx], + None => { + let start = (source.len() - text.len()) as u32; + Span { + start, + end: start + text.len() as u32, + } + } + }; + eprintln!("[lex] token text: {token_text:?}"); + result.push(Token { kind: String, span }); + text = &text[token_text.len()..]; + result.push(Token { + kind: Quote, + span: Span { + start: span.end, + end: span.end + 1, + }, + }); + eprint!("[lex] text: {text:?}"); + text = &source[span.end as usize + 1..]; + eprintln!(" -> {text:?}"); + } + } + return result; + + fn name_char(c: char) -> bool { + matches!(c, '_' | 'a'..='z' | 'A'..='Z' | '0'..='9') + } + + fn trim(text: &str, predicate: impl std::ops::Fn(char) -> bool) -> Option<&str> { + let index = text.find(|it: char| !predicate(it)).unwrap_or(text.len()); + if index == 0 { + None + } else { + Some(&text[index..]) + } + } + + fn find_string_closer(text: &str) -> Option { + let mut skip = false; + for (i, char) in text.char_indices() { + if skip { + skip = false; + continue; + } + match char { + '\\' => skip = true, + '\'' | '"' => return Some(i), + _ => {} + } + } + None + } +} From bd70adc271f453bc5906e0b6b5ec28930d7a138e Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Wed, 7 Jan 2026 17:45:59 +0000 Subject: [PATCH 023/187] feat: Span::contains --- crates/ltk_ritobin/src/error.rs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/crates/ltk_ritobin/src/error.rs b/crates/ltk_ritobin/src/error.rs index 3805b0ff..2e4c2b09 100644 --- a/crates/ltk_ritobin/src/error.rs +++ b/crates/ltk_ritobin/src/error.rs @@ -14,16 +14,24 @@ pub struct Span { } impl Span { + #[must_use] + #[inline] pub fn new(start: u32, end: u32) -> Self { Self { start, end } } + + #[must_use] + #[inline] + pub fn contains(&self, offset: u32) -> bool { + self.start <= offset && offset <= self.end + } } impl From for SourceSpan { fn from(span: Span) -> Self { SourceSpan::new( (span.start as usize).into(), - ((span.end - span.start) as usize).into(), + (span.end - span.start) as usize, ) } } From ad7d359a885b4b1936e5d7270480b70a8f3f4426 Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Wed, 7 Jan 2026 17:46:22 +0000 Subject: [PATCH 024/187] feat: Visitor skip/stop behaviour --- crates/ltk_ritobin/src/parser/real.rs | 49 ++++++++++++++++++++------- 1 file changed, 37 insertions(+), 12 deletions(-) diff --git a/crates/ltk_ritobin/src/parser/real.rs b/crates/ltk_ritobin/src/parser/real.rs index 2963b30e..cae5323f 100644 --- a/crates/ltk_ritobin/src/parser/real.rs +++ b/crates/ltk_ritobin/src/parser/real.rs @@ -40,11 +40,27 @@ impl Default for CalcDatabaseImpl { } } +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub enum Visit { + Stop, + /// Skip the current tree + Skip, + Continue, +} #[allow(unused_variables)] pub trait Visitor { - fn enter_tree(&mut self, kind: TreeKind) {} - fn exit_tree(&mut self, kind: TreeKind) {} - fn visit_token(&mut self, token: &Token, context: TreeKind) {} + #[must_use] + fn enter_tree(&mut self, kind: TreeKind) -> Visit { + Visit::Continue + } + #[must_use] + fn exit_tree(&mut self, kind: TreeKind) -> Visit { + Visit::Continue + } + #[must_use] + fn visit_token(&mut self, token: &Token, context: TreeKind) -> Visit { + Visit::Continue + } } #[derive(Clone, Copy, PartialEq, Eq, Debug)] @@ -69,21 +85,30 @@ impl Tree { self.walk_inner(visitor); } - fn walk_inner(&self, visitor: &mut V) { - visitor.enter_tree(self.kind); + fn walk_inner(&self, visitor: &mut V) -> Visit { + let enter = visitor.enter_tree(self.kind); + if matches!(enter, Visit::Stop | Visit::Skip) { + return enter; + } for child in &self.children { match child { - Child::Token(token) => { - visitor.visit_token(token, self.kind); - } - Child::Tree(child_tree) => { - child_tree.walk_inner(visitor); - } + Child::Token(token) => match visitor.visit_token(token, self.kind) { + Visit::Continue => {} + Visit::Skip => break, + Visit::Stop => return Visit::Stop, + }, + Child::Tree(child_tree) => match child_tree.walk_inner(visitor) { + Visit::Continue => {} + Visit::Skip => { + break; + } + Visit::Stop => return Visit::Stop, + }, } } - visitor.exit_tree(self.kind); + visitor.exit_tree(self.kind) } } From 0e106c64821040d2c998c7f5259cd137b086c8fd Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Wed, 7 Jan 2026 17:56:57 +0000 Subject: [PATCH 025/187] fix: string parsing --- crates/ltk_ritobin/src/parser/real.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/ltk_ritobin/src/parser/real.rs b/crates/ltk_ritobin/src/parser/real.rs index cae5323f..ccdfa0cc 100644 --- a/crates/ltk_ritobin/src/parser/real.rs +++ b/crates/ltk_ritobin/src/parser/real.rs @@ -289,7 +289,7 @@ pub fn stmt_entry(p: &mut Parser) { TokenKind::Quote => { let m = p.open(); p.advance(); - p.expect(TokenKind::Name); + p.expect(TokenKind::String); p.expect(TokenKind::Quote); p.close(m, TreeKind::ExprLiteral); } From 36a6618f205151f414ca2da7a813c28da6757fed Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Wed, 7 Jan 2026 17:57:11 +0000 Subject: [PATCH 026/187] fix: better tree printing --- crates/ltk_ritobin/src/parser/real.rs | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/crates/ltk_ritobin/src/parser/real.rs b/crates/ltk_ritobin/src/parser/real.rs index ccdfa0cc..ac897170 100644 --- a/crates/ltk_ritobin/src/parser/real.rs +++ b/crates/ltk_ritobin/src/parser/real.rs @@ -112,7 +112,7 @@ impl Tree { } } -#[derive(Clone, Debug)] +#[derive(Clone)] pub enum Child { Token(Token), Tree(Tree), @@ -367,7 +367,9 @@ version: u32 = 5 "#; let cst = parse(text); - eprintln!("{cst:?}"); + let mut str = String::new(); + cst.print(&mut str, 0, text); + eprintln!("{str}"); } } @@ -379,7 +381,7 @@ macro_rules! format_to { }; } impl Tree { - fn print(&self, buf: &mut String, level: usize) { + fn print(&self, buf: &mut String, level: usize, source: &str) { let parent_indent = "│ ".repeat(level.saturating_sub(1)); let indent = match level > 0 { true => "├ ", @@ -393,23 +395,19 @@ impl Tree { }; match child { Child::Token(token) => { - format_to!(buf, "{parent_indent}│ {bar} {:?}\n", token.span) + format_to!( + buf, + "{parent_indent}│ {bar} {:?}\n", + &source[token.span.start as _..token.span.end as _] + ) } - Child::Tree(tree) => tree.print(buf, level + 1), + Child::Tree(tree) => tree.print(buf, level + 1, source), } } assert!(buf.ends_with('\n')); } } -impl fmt::Debug for Tree { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let mut buf = String::new(); - self.print(&mut buf, 0); - write!(f, "{}", buf) - } -} - #[salsa::db] impl salsa::Database for CalcDatabaseImpl {} From 95e8de1e31d2a800f96ad79acf0115eaebd93a77 Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Fri, 9 Jan 2026 20:17:14 +0000 Subject: [PATCH 027/187] feat: better string lexing + dedicated unterminated string token --- crates/ltk_ritobin/src/parser/real.rs | 9 +- crates/ltk_ritobin/src/parser/tokenizer.rs | 101 +++++++++++++-------- 2 files changed, 70 insertions(+), 40 deletions(-) diff --git a/crates/ltk_ritobin/src/parser/real.rs b/crates/ltk_ritobin/src/parser/real.rs index ac897170..e5c94d2d 100644 --- a/crates/ltk_ritobin/src/parser/real.rs +++ b/crates/ltk_ritobin/src/parser/real.rs @@ -286,11 +286,14 @@ pub fn stmt_entry(p: &mut Parser) { expr_type(p); p.expect(TokenKind::Eq); match p.nth(0) { - TokenKind::Quote => { + TokenKind::String => { let m = p.open(); p.advance(); - p.expect(TokenKind::String); - p.expect(TokenKind::Quote); + p.close(m, TreeKind::ExprLiteral); + } + TokenKind::UnterminatedString => { + let m = p.open(); + p.advance_with_error("unterminated string"); p.close(m, TreeKind::ExprLiteral); } TokenKind::Int | TokenKind::Minus => { diff --git a/crates/ltk_ritobin/src/parser/tokenizer.rs b/crates/ltk_ritobin/src/parser/tokenizer.rs index 11bda029..ecc0cc5b 100644 --- a/crates/ltk_ritobin/src/parser/tokenizer.rs +++ b/crates/ltk_ritobin/src/parser/tokenizer.rs @@ -11,7 +11,7 @@ pub enum TokenKind { Minus, Star, Slash, Quote, - String, + String, UnterminatedString, True, False, @@ -24,13 +24,12 @@ pub struct Token { pub kind: TokenKind, pub span: Span, } -pub fn lex<'a>(mut text: &'a str) -> Vec { +pub fn lex(mut text: &str) -> Vec { use TokenKind::*; let punctuation = ( - "( ) { } [ ] = , : - * / \" \'", + "( ) { } [ ] = , : - * /", [ LParen, RParen, LCurly, RCurly, LBrack, RBrack, Eq, Comma, Colon, Minus, Star, Slash, - Quote, ], ); @@ -56,10 +55,38 @@ pub fn lex<'a>(mut text: &'a str) -> Vec { text = rest; break 'kind Int; } + + if let Some(rest) = text.strip_prefix(['\'', '"']) { + text = rest; + let mut skip = false; + loop { + let Some(c) = text.chars().next() else { + break 'kind UnterminatedString; + }; + + text = &text[c.len_utf8()..]; + match c { + '\\' => { + skip = true; + } + '\'' | '"' => match skip { + true => { + skip = false; + } + false => { + break 'kind String; + } + }, + '\n' | '\r' => break 'kind UnterminatedString, + _ => {} + } + } + } if let Some(rest) = trim(text, name_char) { text = rest; break 'kind Name; } + let error_index = text .find(|it: char| it.is_ascii_whitespace()) .unwrap_or(text.len()); @@ -85,39 +112,39 @@ pub fn lex<'a>(mut text: &'a str) -> Vec { } } result.push(Token { kind, span }); - if kind == Quote { - eprintln!("[lex] pushed quote!"); - let span = match find_string_closer(text) { - Some(close_idx) => { - let start = (source.len() - text.len()) as u32; - Span { - start, - end: start + close_idx as u32, - } - } - // &text[..close_idx], - None => { - let start = (source.len() - text.len()) as u32; - Span { - start, - end: start + text.len() as u32, - } - } - }; - eprintln!("[lex] token text: {token_text:?}"); - result.push(Token { kind: String, span }); - text = &text[token_text.len()..]; - result.push(Token { - kind: Quote, - span: Span { - start: span.end, - end: span.end + 1, - }, - }); - eprint!("[lex] text: {text:?}"); - text = &source[span.end as usize + 1..]; - eprintln!(" -> {text:?}"); - } + // if kind == Quote { + // eprintln!("[lex] pushed quote!"); + // let span = match find_string_closer(text) { + // Some(close_idx) => { + // let start = (source.len() - text.len()) as u32; + // Span { + // start, + // end: start + close_idx as u32, + // } + // } + // // &text[..close_idx], + // None => { + // let start = (source.len() - text.len()) as u32; + // Span { + // start, + // end: start + text.len() as u32, + // } + // } + // }; + // eprintln!("[lex] token text: {token_text:?}"); + // result.push(Token { kind: String, span }); + // text = &source[span.end as _..]; + // result.push(Token { + // kind: Quote, + // span: Span { + // start: span.end, + // end: span.end + 1, + // }, + // }); + // eprint!("[lex] text: {text:?}"); + // text = &source[(span.end as usize + 1).min(source.len().saturating_sub(1))..]; + // eprintln!(" -> {text:?}"); + // } } return result; From f84925a9dbddec387fe6cbc1dcd0962fe9d91776 Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Fri, 9 Jan 2026 20:34:17 +0000 Subject: [PATCH 028/187] feat: pass whole tree in visitor methods --- crates/ltk_ritobin/src/parser/real.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/crates/ltk_ritobin/src/parser/real.rs b/crates/ltk_ritobin/src/parser/real.rs index e5c94d2d..a19c958d 100644 --- a/crates/ltk_ritobin/src/parser/real.rs +++ b/crates/ltk_ritobin/src/parser/real.rs @@ -50,15 +50,15 @@ pub enum Visit { #[allow(unused_variables)] pub trait Visitor { #[must_use] - fn enter_tree(&mut self, kind: TreeKind) -> Visit { + fn enter_tree(&mut self, tree: &Tree) -> Visit { Visit::Continue } #[must_use] - fn exit_tree(&mut self, kind: TreeKind) -> Visit { + fn exit_tree(&mut self, tree: &Tree) -> Visit { Visit::Continue } #[must_use] - fn visit_token(&mut self, token: &Token, context: TreeKind) -> Visit { + fn visit_token(&mut self, token: &Token, context: &Tree) -> Visit { Visit::Continue } } @@ -86,14 +86,14 @@ impl Tree { } fn walk_inner(&self, visitor: &mut V) -> Visit { - let enter = visitor.enter_tree(self.kind); + let enter = visitor.enter_tree(self); if matches!(enter, Visit::Stop | Visit::Skip) { return enter; } for child in &self.children { match child { - Child::Token(token) => match visitor.visit_token(token, self.kind) { + Child::Token(token) => match visitor.visit_token(token, self) { Visit::Continue => {} Visit::Skip => break, Visit::Stop => return Visit::Stop, @@ -108,7 +108,7 @@ impl Tree { } } - visitor.exit_tree(self.kind) + visitor.exit_tree(self) } } From cc678a634e3e295c81b29e4c2f5622cda57cdc0b Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Fri, 9 Jan 2026 20:34:27 +0000 Subject: [PATCH 029/187] feat: tree spans --- crates/ltk_ritobin/src/parser/real.rs | 54 ++++++++++++++++++++++----- 1 file changed, 44 insertions(+), 10 deletions(-) diff --git a/crates/ltk_ritobin/src/parser/real.rs b/crates/ltk_ritobin/src/parser/real.rs index a19c958d..7daf8242 100644 --- a/crates/ltk_ritobin/src/parser/real.rs +++ b/crates/ltk_ritobin/src/parser/real.rs @@ -76,8 +76,9 @@ pub enum TreeKind { #[derive(Clone)] pub struct Tree { - kind: TreeKind, - children: Vec, + pub span: crate::Span, + pub kind: TreeKind, + pub children: Vec, } impl Tree { @@ -154,19 +155,41 @@ impl Parser { assert!(matches!(events.pop(), Some(Event::Close))); let mut stack = Vec::new(); + let mut last_offset = 0; + let mut just_opened = false; for event in events { match event { - Event::Open { kind } => stack.push(Tree { - kind, - children: Vec::new(), - }), + Event::Open { kind } => { + just_opened = true; + stack.push(Tree { + span: crate::Span::new(last_offset, 0), + kind, + children: Vec::new(), + }) + } Event::Close => { - let tree = stack.pop().unwrap(); - stack.last_mut().unwrap().children.push(Child::Tree(tree)); + let mut tree = stack.pop().unwrap(); + let last = stack.last_mut().unwrap(); + if tree.span.end == 0 { + // empty trees + tree.span.end = tree.span.start; + } + last.span.end = tree.span.end.max(last.span.end); // update our parent tree's span + last.children.push(Child::Tree(tree)); } Event::Advance => { let token = tokens.next().unwrap(); - stack.last_mut().unwrap().children.push(Child::Token(token)); + let last = stack.last_mut().unwrap(); + + if just_opened { + // first token of the tree + last.span.start = token.span.start; + } + just_opened = false; + + last.span.end = token.span.end; + last_offset = last.span.end; + last.children.push(Child::Token(token)); } } } @@ -390,7 +413,18 @@ impl Tree { true => "├ ", false => "", }; - format_to!(buf, "{parent_indent}{indent}{:?}\n", self.kind); + let safe_span = match self.span.end >= self.span.start { + true => &source[self.span.start as _..self.span.end as _], + false => "!!!!!!", + }; + format_to!( + buf, + "{parent_indent}{indent}{:?} - ({}..{}): {:?}\n", + self.kind, + self.span.start, + self.span.end, + safe_span + ); for (i, child) in self.children.iter().enumerate() { let bar = match i + 1 == self.children.len() { true => '└', From fb3b0d2f02300367f14d156c065614d608cfad2f Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Fri, 9 Jan 2026 23:18:08 +0000 Subject: [PATCH 030/187] fix: impl Debug for Tree/Child --- crates/ltk_ritobin/src/parser/real.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/ltk_ritobin/src/parser/real.rs b/crates/ltk_ritobin/src/parser/real.rs index 7daf8242..b591367f 100644 --- a/crates/ltk_ritobin/src/parser/real.rs +++ b/crates/ltk_ritobin/src/parser/real.rs @@ -74,7 +74,7 @@ pub enum TreeKind { ExprLiteral, ExprName, } -#[derive(Clone)] +#[derive(Clone, Debug)] pub struct Tree { pub span: crate::Span, pub kind: TreeKind, @@ -113,7 +113,7 @@ impl Tree { } } -#[derive(Clone)] +#[derive(Clone, Debug)] pub enum Child { Token(Token), Tree(Tree), From 19a334dd139a98d306afbff48785dc963d9abac2 Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Fri, 9 Jan 2026 23:18:20 +0000 Subject: [PATCH 031/187] feat: helper span() method on Child --- crates/ltk_ritobin/src/parser/real.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/crates/ltk_ritobin/src/parser/real.rs b/crates/ltk_ritobin/src/parser/real.rs index b591367f..3cde0eab 100644 --- a/crates/ltk_ritobin/src/parser/real.rs +++ b/crates/ltk_ritobin/src/parser/real.rs @@ -119,6 +119,15 @@ pub enum Child { Tree(Tree), } +impl Child { + pub fn span(&self) -> crate::Span { + match self { + Child::Token(token) => token.span, + Child::Tree(tree) => tree.span, + } + } +} + pub enum Event { Open { kind: TreeKind }, Close, From 00f8865578a407361f7606c08e5a45fa27f4ec7c Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Fri, 9 Jan 2026 23:18:49 +0000 Subject: [PATCH 032/187] feat: impl Index for str --- crates/ltk_ritobin/src/error.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/crates/ltk_ritobin/src/error.rs b/crates/ltk_ritobin/src/error.rs index 2e4c2b09..b8fe5191 100644 --- a/crates/ltk_ritobin/src/error.rs +++ b/crates/ltk_ritobin/src/error.rs @@ -27,6 +27,14 @@ impl Span { } } +impl std::ops::Index for str { + type Output = str; + + fn index(&self, index: crate::Span) -> &Self::Output { + &self[index.start as _..index.end as _] + } +} + impl From for SourceSpan { fn from(span: Span) -> Self { SourceSpan::new( From b4aa7c5116b73ed43cecbd3c0c9cb48f9b3ae741 Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Fri, 9 Jan 2026 23:18:41 +0000 Subject: [PATCH 033/187] feat: parser errors --- crates/ltk_ritobin/src/parser/real.rs | 77 ++++++++++++++++++++++----- 1 file changed, 63 insertions(+), 14 deletions(-) diff --git a/crates/ltk_ritobin/src/parser/real.rs b/crates/ltk_ritobin/src/parser/real.rs index 3cde0eab..4be3fcc9 100644 --- a/crates/ltk_ritobin/src/parser/real.rs +++ b/crates/ltk_ritobin/src/parser/real.rs @@ -129,8 +129,14 @@ impl Child { } pub enum Event { - Open { kind: TreeKind }, + Open { + kind: TreeKind, + }, Close, + Error { + kind: ErrorKind, + span: Option, + }, Advance, } @@ -141,6 +147,25 @@ pub struct MarkClosed { index: usize, } +#[derive(Debug)] +pub enum ErrorKind { + Expected { + token: TokenKind, + for_tree: Option, + }, + UnterminatedString, + Unexpected { + token: TokenKind, + }, + Custom(&'static str), +} + +#[derive(Debug)] +pub struct ParseError { + pub span: crate::Span, + pub kind: ErrorKind, +} + pub struct Parser { pub tokens: Vec, pos: usize, @@ -158,10 +183,12 @@ impl Parser { } } - pub fn build_tree(self) -> Tree { + pub fn build_tree(self) -> (Tree, Vec) { let mut tokens = self.tokens.into_iter(); let mut events = self.events; + let mut errors = Vec::new(); + assert!(matches!(events.pop(), Some(Event::Close))); let mut stack = Vec::new(); let mut last_offset = 0; @@ -200,13 +227,22 @@ impl Parser { last_offset = last.span.end; last.children.push(Child::Token(token)); } + Event::Error { kind, span } => { + let cur_tree = stack.last_mut().unwrap(); + errors.push(ParseError { + span: span + .or(cur_tree.children.last().map(|c| c.span())) + .unwrap_or(cur_tree.span), + kind, + }); + } } } let tree = stack.pop().unwrap(); assert!(stack.is_empty()); assert!(tokens.next().is_none()); - tree + (tree, errors) } fn open(&mut self) -> MarkOpened { @@ -243,11 +279,14 @@ impl Parser { self.pos += 1; } - fn advance_with_error(&mut self, error: &str) { + fn report(&mut self, kind: ErrorKind) { + self.events.push(Event::Error { kind, span: None }); + } + + fn advance_with_error(&mut self, kind: ErrorKind, span: Option) { let m = self.open(); - // TODO: Error reporting. - eprintln!("{error}"); self.advance(); + self.events.push(Event::Error { kind, span }); self.close(m, TreeKind::ErrorTree); } @@ -291,7 +330,7 @@ impl Parser { } } -pub fn parse(text: &str) -> Tree { +pub fn parse(text: &str) -> (Tree, Vec) { let tokens = lex(text); eprintln!("tokens: {tokens:#?}"); let mut p = Parser::new(tokens); @@ -305,7 +344,13 @@ pub fn file(p: &mut Parser) { if p.at(TokenKind::Name) { stmt_entry(p) } else { - p.advance_with_error("expected a name"); + p.advance_with_error( + ErrorKind::Expected { + token: TokenKind::Name, + for_tree: Some(TreeKind::File), + }, + None, + ); } } p.close(m, TreeKind::File); @@ -325,7 +370,7 @@ pub fn stmt_entry(p: &mut Parser) { } TokenKind::UnterminatedString => { let m = p.open(); - p.advance_with_error("unterminated string"); + p.advance_with_error(ErrorKind::UnterminatedString, None); p.close(m, TreeKind::ExprLiteral); } TokenKind::Int | TokenKind::Minus => { @@ -336,8 +381,9 @@ pub fn stmt_entry(p: &mut Parser) { TokenKind::LCurly => { block(p); } - TokenKind::Eof | TokenKind::Name => {} - _ => p.advance_with_error("unexpected"), + // TokenKind::Eof | TokenKind::Name => {} + token @ TokenKind::Eof => p.report(ErrorKind::Unexpected { token }), + token => p.advance_with_error(ErrorKind::Unexpected { token }, None), } p.close(m, TreeKind::StmtEntry); @@ -401,10 +447,13 @@ linked: list[string] = { version: u32 = 5 "#; - let cst = parse(text); + let (cst, errors) = parse(text); let mut str = String::new(); cst.print(&mut str, 0, text); - eprintln!("{str}"); + eprintln!("{str}\n====== errors: ======\n"); + for err in errors { + eprintln!("{:?}: {:#?}", &text[err.span], err.kind); + } } } @@ -423,7 +472,7 @@ impl Tree { false => "", }; let safe_span = match self.span.end >= self.span.start { - true => &source[self.span.start as _..self.span.end as _], + true => &source[self.span], false => "!!!!!!", }; format_to!( From 441af73b9250cedbf202b940e17b65a847a0754d Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Fri, 9 Jan 2026 23:37:25 +0000 Subject: [PATCH 034/187] feat: embed errors in tree --- crates/ltk_ritobin/src/parser/real.rs | 92 +++++++++++++++++++-------- 1 file changed, 65 insertions(+), 27 deletions(-) diff --git a/crates/ltk_ritobin/src/parser/real.rs b/crates/ltk_ritobin/src/parser/real.rs index 4be3fcc9..f3b4c7c3 100644 --- a/crates/ltk_ritobin/src/parser/real.rs +++ b/crates/ltk_ritobin/src/parser/real.rs @@ -79,6 +79,7 @@ pub struct Tree { pub span: crate::Span, pub kind: TreeKind, pub children: Vec, + pub errors: Vec, } impl Tree { @@ -147,10 +148,11 @@ pub struct MarkClosed { index: usize, } -#[derive(Debug)] +#[derive(Debug, Clone, Copy)] pub enum ErrorKind { Expected { - token: TokenKind, + expected: TokenKind, + got: TokenKind, for_tree: Option, }, UnterminatedString, @@ -160,7 +162,7 @@ pub enum ErrorKind { Custom(&'static str), } -#[derive(Debug)] +#[derive(Debug, Clone, Copy)] pub struct ParseError { pub span: crate::Span, pub kind: ErrorKind, @@ -183,12 +185,10 @@ impl Parser { } } - pub fn build_tree(self) -> (Tree, Vec) { - let mut tokens = self.tokens.into_iter(); + pub fn build_tree(self) -> Tree { + let mut tokens = self.tokens.into_iter().peekable(); let mut events = self.events; - let mut errors = Vec::new(); - assert!(matches!(events.pop(), Some(Event::Close))); let mut stack = Vec::new(); let mut last_offset = 0; @@ -201,6 +201,7 @@ impl Parser { span: crate::Span::new(last_offset, 0), kind, children: Vec::new(), + errors: Vec::new(), }) } Event::Close => { @@ -229,7 +230,22 @@ impl Parser { } Event::Error { kind, span } => { let cur_tree = stack.last_mut().unwrap(); - errors.push(ParseError { + let (kind, span) = match kind { + ErrorKind::Expected { + expected, + got, + for_tree: None, + } => ( + ErrorKind::Expected { + expected, + got, + for_tree: Some(cur_tree.kind), + }, + tokens.peek().map(|t| t.span), + ), + kind => (kind, span), + }; + cur_tree.errors.push(ParseError { span: span .or(cur_tree.children.last().map(|c| c.span())) .unwrap_or(cur_tree.span), @@ -242,7 +258,7 @@ impl Parser { let tree = stack.pop().unwrap(); assert!(stack.is_empty()); assert!(tokens.next().is_none()); - (tree, errors) + tree } fn open(&mut self) -> MarkOpened { @@ -321,16 +337,20 @@ impl Parser { } } - fn expect(&mut self, kind: TokenKind) { + fn expect(&mut self, kind: TokenKind) -> bool { if self.eat(kind) { - return; + return true; } - // TODO: Error reporting. - eprintln!("expected {kind:?}"); + self.report(ErrorKind::Expected { + expected: kind, + got: self.nth(0), + for_tree: None, + }); + false } } -pub fn parse(text: &str) -> (Tree, Vec) { +pub fn parse(text: &str) -> Tree { let tokens = lex(text); eprintln!("tokens: {tokens:#?}"); let mut p = Parser::new(tokens); @@ -341,17 +361,7 @@ pub fn parse(text: &str) -> (Tree, Vec) { pub fn file(p: &mut Parser) { let m = p.open(); while !p.eof() { - if p.at(TokenKind::Name) { - stmt_entry(p) - } else { - p.advance_with_error( - ErrorKind::Expected { - token: TokenKind::Name, - for_tree: Some(TreeKind::File), - }, - None, - ); - } + stmt_entry(p) } p.close(m, TreeKind::File); } @@ -381,7 +391,6 @@ pub fn stmt_entry(p: &mut Parser) { TokenKind::LCurly => { block(p); } - // TokenKind::Eof | TokenKind::Name => {} token @ TokenKind::Eof => p.report(ErrorKind::Unexpected { token }), token => p.advance_with_error(ErrorKind::Unexpected { token }, None), } @@ -447,7 +456,9 @@ linked: list[string] = { version: u32 = 5 "#; - let (cst, errors) = parse(text); + let cst = parse(text); + let errors = FlatErrors::walk(&cst); + let mut str = String::new(); cst.print(&mut str, 0, text); eprintln!("{str}\n====== errors: ======\n"); @@ -457,6 +468,33 @@ version: u32 = 5 } } +#[derive(Default)] +pub struct FlatErrors { + errors: Vec, +} + +impl FlatErrors { + pub fn new() -> Self { + Self::default() + } + pub fn into_errors(self) -> Vec { + self.errors + } + + pub fn walk(tree: &Tree) -> Vec { + let mut errors = Self::new(); + tree.walk(&mut errors); + errors.into_errors() + } +} + +impl Visitor for FlatErrors { + fn exit_tree(&mut self, tree: &Tree) -> Visit { + self.errors.extend_from_slice(&tree.errors); + Visit::Continue + } +} + #[macro_export] macro_rules! format_to { ($buf:expr) => (); From 43e07881444de159aa99ee72aab7c20fa1a373af Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Sat, 10 Jan 2026 00:03:37 +0000 Subject: [PATCH 035/187] feat: rename ErrorToken -> Unknown --- crates/ltk_ritobin/src/parser/tokenizer.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/ltk_ritobin/src/parser/tokenizer.rs b/crates/ltk_ritobin/src/parser/tokenizer.rs index ecc0cc5b..2bbbdb0c 100644 --- a/crates/ltk_ritobin/src/parser/tokenizer.rs +++ b/crates/ltk_ritobin/src/parser/tokenizer.rs @@ -3,7 +3,7 @@ use crate::Span; #[derive(Clone, Copy, PartialEq, Eq, Debug)] #[rustfmt::skip] pub enum TokenKind { - ErrorToken, Eof, + Unknown, Eof, LParen, RParen, LCurly, RCurly, LBrack, RBrack, @@ -91,7 +91,7 @@ pub fn lex(mut text: &str) -> Vec { .find(|it: char| it.is_ascii_whitespace()) .unwrap_or(text.len()); text = &text[error_index..]; - ErrorToken + Unknown }; assert!(text.len() < text_orig.len()); let token_text = &text_orig[..text_orig.len() - text.len()]; From 8f85391bc307dd65208fba44f2416e569064c7c7 Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Sat, 10 Jan 2026 00:03:54 +0000 Subject: [PATCH 036/187] feat: impl Display for TokenKind/TreeKind --- crates/ltk_ritobin/src/parser/real.rs | 17 +++++++++++- crates/ltk_ritobin/src/parser/tokenizer.rs | 30 ++++++++++++++++++++++ 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/crates/ltk_ritobin/src/parser/real.rs b/crates/ltk_ritobin/src/parser/real.rs index f3b4c7c3..edafcd91 100644 --- a/crates/ltk_ritobin/src/parser/real.rs +++ b/crates/ltk_ritobin/src/parser/real.rs @@ -1,6 +1,6 @@ use std::{ cell::Cell, - fmt, + fmt::{self, Display}, sync::{Arc, Mutex}, }; @@ -73,6 +73,21 @@ pub enum TreeKind { StmtEntry, ExprLiteral, ExprName, } +impl Display for TreeKind { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.write_str(match self { + TreeKind::ErrorTree => "error tree", + TreeKind::File => "file", + TreeKind::TypeExpr => "bin entry type", + TreeKind::TypeArgList => "type argument list", + TreeKind::TypeArg => "type argument", + TreeKind::Block => "block", + TreeKind::StmtEntry => "bin entry", + TreeKind::ExprLiteral => "literal", + TreeKind::ExprName => "name?", // TODO: don't think I need this any more + }) + } +} #[derive(Clone, Debug)] pub struct Tree { diff --git a/crates/ltk_ritobin/src/parser/tokenizer.rs b/crates/ltk_ritobin/src/parser/tokenizer.rs index 2bbbdb0c..6f848e73 100644 --- a/crates/ltk_ritobin/src/parser/tokenizer.rs +++ b/crates/ltk_ritobin/src/parser/tokenizer.rs @@ -1,3 +1,5 @@ +use std::fmt::Display; + use crate::Span; #[derive(Clone, Copy, PartialEq, Eq, Debug)] @@ -19,6 +21,34 @@ pub enum TokenKind { Name, Int, } +impl Display for TokenKind { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.write_str(match self { + TokenKind::Unknown => "unknown text", + TokenKind::Eof => "end of file", + TokenKind::LParen => "'('", + TokenKind::RParen => "')'", + TokenKind::LCurly => "'{'", + TokenKind::RCurly => "'}'", + TokenKind::LBrack => "'['", + TokenKind::RBrack => "']'", + TokenKind::Eq => "'='", + TokenKind::Comma => "','", + TokenKind::Colon => "':'", + TokenKind::Minus => "'-'", + TokenKind::Star => "'*'", + TokenKind::Slash => "'/'", + TokenKind::Quote => "'\"'", + TokenKind::String => "string literal", + TokenKind::UnterminatedString => "unterminated string literal", + TokenKind::True => "'true'", + TokenKind::False => "'false'", + TokenKind::Name => "keyword", + TokenKind::Int => "number", + }) + } +} + #[derive(Clone, Copy, Debug)] pub struct Token { pub kind: TokenKind, From 7c8b391fe177b81ef686127a7f19b52d15b47cd1 Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Sat, 10 Jan 2026 00:04:03 +0000 Subject: [PATCH 037/187] feat: parser helper methods --- crates/ltk_ritobin/src/parser/real.rs | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/crates/ltk_ritobin/src/parser/real.rs b/crates/ltk_ritobin/src/parser/real.rs index edafcd91..4044d0ca 100644 --- a/crates/ltk_ritobin/src/parser/real.rs +++ b/crates/ltk_ritobin/src/parser/real.rs @@ -286,6 +286,22 @@ impl Parser { mark } + fn scope(&mut self, kind: TreeKind, mut f: F) -> MarkClosed + where + F: FnMut(&mut Self) -> R, + { + let m = MarkOpened { + index: self.events.len(), + }; + self.events.push(Event::Open { + kind: TreeKind::ErrorTree, + }); + let _ = f(self); + self.events[m.index] = Event::Open { kind }; + self.events.push(Event::Close); + MarkClosed { index: m.index } + } + fn open_before(&mut self, m: MarkClosed) -> MarkOpened { let mark = MarkOpened { index: m.index }; self.events.insert( @@ -363,6 +379,13 @@ impl Parser { }); false } + + fn expect_fallable(&mut self, kind: TokenKind) -> Result<(), ()> { + match self.expect(kind) { + true => Ok(()), + false => Err(()), + } + } } pub fn parse(text: &str) -> Tree { From 4ef8a3fda68a1bb8bba56f71144c89ce435c9fa9 Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Sat, 10 Jan 2026 00:04:15 +0000 Subject: [PATCH 038/187] wip: parser tweaks --- crates/ltk_ritobin/src/parser/real.rs | 56 +++++++++++++-------------- 1 file changed, 27 insertions(+), 29 deletions(-) diff --git a/crates/ltk_ritobin/src/parser/real.rs b/crates/ltk_ritobin/src/parser/real.rs index 4044d0ca..56bae5df 100644 --- a/crates/ltk_ritobin/src/parser/real.rs +++ b/crates/ltk_ritobin/src/parser/real.rs @@ -404,36 +404,34 @@ pub fn file(p: &mut Parser) { p.close(m, TreeKind::File); } pub fn stmt_entry(p: &mut Parser) { - let m = p.open(); - - p.expect(TokenKind::Name); - p.expect(TokenKind::Colon); - expr_type(p); - p.expect(TokenKind::Eq); - match p.nth(0) { - TokenKind::String => { - let m = p.open(); - p.advance(); - p.close(m, TreeKind::ExprLiteral); - } - TokenKind::UnterminatedString => { - let m = p.open(); - p.advance_with_error(ErrorKind::UnterminatedString, None); - p.close(m, TreeKind::ExprLiteral); - } - TokenKind::Int | TokenKind::Minus => { - let m = p.open(); - p.advance(); - p.close(m, TreeKind::ExprLiteral); - } - TokenKind::LCurly => { - block(p); + p.scope(TreeKind::StmtEntry, |p| { + p.expect(TokenKind::Name); + p.expect(TokenKind::Colon); + expr_type(p); + p.expect(TokenKind::Eq); + match p.nth(0) { + TokenKind::String => { + let m = p.open(); + p.advance(); + p.close(m, TreeKind::ExprLiteral); + } + TokenKind::UnterminatedString => { + let m = p.open(); + p.advance_with_error(ErrorKind::UnterminatedString, None); + p.close(m, TreeKind::ExprLiteral); + } + TokenKind::Int | TokenKind::Minus => { + let m = p.open(); + p.advance(); + p.close(m, TreeKind::ExprLiteral); + } + TokenKind::LCurly => { + block(p); + } + token @ TokenKind::Eof => p.report(ErrorKind::Unexpected { token }), + token => p.advance_with_error(ErrorKind::Unexpected { token }, None), } - token @ TokenKind::Eof => p.report(ErrorKind::Unexpected { token }), - token => p.advance_with_error(ErrorKind::Unexpected { token }, None), - } - - p.close(m, TreeKind::StmtEntry); + }); } pub fn expr_type(p: &mut Parser) -> MarkClosed { From ccad9bf7093c3c2bb81b10e03eb4a23707489ab6 Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Sat, 10 Jan 2026 00:38:10 +0000 Subject: [PATCH 039/187] feat: impl Index<&Span> for str --- crates/ltk_ritobin/src/error.rs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/crates/ltk_ritobin/src/error.rs b/crates/ltk_ritobin/src/error.rs index b8fe5191..092d58ad 100644 --- a/crates/ltk_ritobin/src/error.rs +++ b/crates/ltk_ritobin/src/error.rs @@ -31,7 +31,16 @@ impl std::ops::Index for str { type Output = str; fn index(&self, index: crate::Span) -> &Self::Output { - &self[index.start as _..index.end as _] + &self[&index] + } +} +impl std::ops::Index<&crate::Span> for str { + type Output = str; + + fn index(&self, index: &crate::Span) -> &Self::Output { + let start = index.start as usize; + let end = index.end as usize; + &self[start..end] } } From 6486a3a6e41ca710a6d538383f008f00d13faf26 Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Sat, 10 Jan 2026 01:12:20 +0000 Subject: [PATCH 040/187] wip: parser changes --- crates/ltk_ritobin/src/parser/real.rs | 90 +++++++++++++-------------- 1 file changed, 43 insertions(+), 47 deletions(-) diff --git a/crates/ltk_ritobin/src/parser/real.rs b/crates/ltk_ritobin/src/parser/real.rs index 56bae5df..eaa7446e 100644 --- a/crates/ltk_ritobin/src/parser/real.rs +++ b/crates/ltk_ritobin/src/parser/real.rs @@ -70,8 +70,9 @@ pub enum TreeKind { File, TypeExpr, TypeArgList, TypeArg, Block, - StmtEntry, - ExprLiteral, ExprName, + + Entry, EntryKey, EntryValue, + Literal, } impl Display for TreeKind { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { @@ -82,9 +83,10 @@ impl Display for TreeKind { TreeKind::TypeArgList => "type argument list", TreeKind::TypeArg => "type argument", TreeKind::Block => "block", - TreeKind::StmtEntry => "bin entry", - TreeKind::ExprLiteral => "literal", - TreeKind::ExprName => "name?", // TODO: don't think I need this any more + TreeKind::Entry => "bin entry", + TreeKind::EntryKey => "key", + TreeKind::EntryValue => "value", + TreeKind::Literal => "literal", }) } } @@ -165,21 +167,16 @@ pub struct MarkClosed { #[derive(Debug, Clone, Copy)] pub enum ErrorKind { - Expected { - expected: TokenKind, - got: TokenKind, - for_tree: Option, - }, + Expected { expected: TokenKind, got: TokenKind }, UnterminatedString, - Unexpected { - token: TokenKind, - }, + Unexpected { token: TokenKind }, Custom(&'static str), } #[derive(Debug, Clone, Copy)] pub struct ParseError { pub span: crate::Span, + pub tree: TreeKind, pub kind: ErrorKind, } @@ -201,19 +198,21 @@ impl Parser { } pub fn build_tree(self) -> Tree { + let last_token = self.tokens.last().copied(); + let mut tokens = self.tokens.into_iter().peekable(); let mut events = self.events; assert!(matches!(events.pop(), Some(Event::Close))); let mut stack = Vec::new(); - let mut last_offset = 0; + let mut last_span = crate::Span::default(); let mut just_opened = false; for event in events { match event { Event::Open { kind } => { just_opened = true; stack.push(Tree { - span: crate::Span::new(last_offset, 0), + span: crate::Span::new(last_span.end, 0), kind, children: Vec::new(), errors: Vec::new(), @@ -240,30 +239,34 @@ impl Parser { just_opened = false; last.span.end = token.span.end; - last_offset = last.span.end; + last_span = token.span; last.children.push(Child::Token(token)); } Event::Error { kind, span } => { let cur_tree = stack.last_mut().unwrap(); - let (kind, span) = match kind { - ErrorKind::Expected { - expected, - got, - for_tree: None, - } => ( - ErrorKind::Expected { - expected, - got, - for_tree: Some(cur_tree.kind), - }, - tokens.peek().map(|t| t.span), - ), - kind => (kind, span), + let span = match kind { + // these errors are talking about what they wanted next + ErrorKind::Expected { .. } | ErrorKind::Unexpected { .. } => { + let mut span = tokens.peek().map(|t| t.span).unwrap_or(last_span); + // so we point at the character just after our token + span.end += 1; + span.start = span.end - 1; + span + } + kind => span + .or(cur_tree.children.last().map(|c| c.span())) + // we can't use Tree.span.end because that's only known on Close + .unwrap_or(crate::Span::new( + cur_tree.span.start, + last_token + .as_ref() + .map(|t| t.span.end) + .unwrap_or(cur_tree.span.start), + )), }; cur_tree.errors.push(ParseError { - span: span - .or(cur_tree.children.last().map(|c| c.span())) - .unwrap_or(cur_tree.span), + span, + tree: cur_tree.kind, kind, }); } @@ -375,7 +378,6 @@ impl Parser { self.report(ErrorKind::Expected { expected: kind, got: self.nth(0), - for_tree: None, }); false } @@ -404,38 +406,33 @@ pub fn file(p: &mut Parser) { p.close(m, TreeKind::File); } pub fn stmt_entry(p: &mut Parser) { - p.scope(TreeKind::StmtEntry, |p| { - p.expect(TokenKind::Name); + p.scope(TreeKind::Entry, |p| { + p.scope(TreeKind::EntryKey, |p| p.expect(TokenKind::Name)); p.expect(TokenKind::Colon); - expr_type(p); + p.scope(TreeKind::TypeExpr, type_expr); p.expect(TokenKind::Eq); - match p.nth(0) { + p.scope(TreeKind::EntryValue, |p| match p.nth(0) { TokenKind::String => { - let m = p.open(); p.advance(); - p.close(m, TreeKind::ExprLiteral); } TokenKind::UnterminatedString => { - let m = p.open(); p.advance_with_error(ErrorKind::UnterminatedString, None); - p.close(m, TreeKind::ExprLiteral); } TokenKind::Int | TokenKind::Minus => { let m = p.open(); p.advance(); - p.close(m, TreeKind::ExprLiteral); + p.close(m, TreeKind::Literal); } TokenKind::LCurly => { block(p); } token @ TokenKind::Eof => p.report(ErrorKind::Unexpected { token }), token => p.advance_with_error(ErrorKind::Unexpected { token }, None), - } + }); }); } -pub fn expr_type(p: &mut Parser) -> MarkClosed { - let m = p.open(); +pub fn type_expr(p: &mut Parser) { p.expect(TokenKind::Name); if p.eat(TokenKind::LBrack) { while !p.at(TokenKind::RBrack) && !p.eof() { @@ -447,7 +444,6 @@ pub fn expr_type(p: &mut Parser) -> MarkClosed { } p.expect(TokenKind::RBrack); } - p.close(m, TreeKind::TypeExpr) } pub fn expr_type_arg(p: &mut Parser) -> MarkClosed { From 720431d7287b08859b5bb7cdb281627ea246cf8f Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Sat, 10 Jan 2026 01:17:26 +0000 Subject: [PATCH 041/187] feat: add semicolon to lexer --- crates/ltk_ritobin/src/parser/tokenizer.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/crates/ltk_ritobin/src/parser/tokenizer.rs b/crates/ltk_ritobin/src/parser/tokenizer.rs index 6f848e73..df058299 100644 --- a/crates/ltk_ritobin/src/parser/tokenizer.rs +++ b/crates/ltk_ritobin/src/parser/tokenizer.rs @@ -9,7 +9,7 @@ pub enum TokenKind { LParen, RParen, LCurly, RCurly, LBrack, RBrack, - Eq, Comma, Colon, + Eq, Comma, Colon, SemiColon, Minus, Star, Slash, Quote, @@ -35,6 +35,7 @@ impl Display for TokenKind { TokenKind::Eq => "'='", TokenKind::Comma => "','", TokenKind::Colon => "':'", + TokenKind::SemiColon => "';'", TokenKind::Minus => "'-'", TokenKind::Star => "'*'", TokenKind::Slash => "'/'", @@ -57,9 +58,10 @@ pub struct Token { pub fn lex(mut text: &str) -> Vec { use TokenKind::*; let punctuation = ( - "( ) { } [ ] = , : - * /", + "( ) { } [ ] = , : ; - * /", [ - LParen, RParen, LCurly, RCurly, LBrack, RBrack, Eq, Comma, Colon, Minus, Star, Slash, + LParen, RParen, LCurly, RCurly, LBrack, RBrack, Eq, Comma, Colon, SemiColon, Minus, + Star, Slash, ], ); From 9f67e8c0838a527d98f3d9d3c78f7326681b0a7f Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Sat, 10 Jan 2026 01:56:32 +0000 Subject: [PATCH 042/187] feat (lex): spit newline when at possibly statement ending token --- crates/ltk_ritobin/src/parser/tokenizer.rs | 71 ++++++---------------- 1 file changed, 20 insertions(+), 51 deletions(-) diff --git a/crates/ltk_ritobin/src/parser/tokenizer.rs b/crates/ltk_ritobin/src/parser/tokenizer.rs index df058299..099d0136 100644 --- a/crates/ltk_ritobin/src/parser/tokenizer.rs +++ b/crates/ltk_ritobin/src/parser/tokenizer.rs @@ -5,7 +5,7 @@ use crate::Span; #[derive(Clone, Copy, PartialEq, Eq, Debug)] #[rustfmt::skip] pub enum TokenKind { - Unknown, Eof, + Unknown, Eof, Newline, LParen, RParen, LCurly, RCurly, LBrack, RBrack, @@ -26,6 +26,7 @@ impl Display for TokenKind { f.write_str(match self { TokenKind::Unknown => "unknown text", TokenKind::Eof => "end of file", + TokenKind::Newline => "new line", TokenKind::LParen => "'('", TokenKind::RParen => "')'", TokenKind::LCurly => "'{'", @@ -69,9 +70,26 @@ pub fn lex(mut text: &str) -> Vec { let source = text; - let mut result = Vec::new(); + let mut result: Vec = Vec::new(); while !text.is_empty() { if let Some(rest) = trim(text, |it| it.is_ascii_whitespace()) { + let eaten = &source[source.len() - text.len()..source.len() - rest.len()]; + if let Some(last_token) = result.last() { + if matches!( + last_token.kind, + TokenKind::Name | TokenKind::Int | TokenKind::RCurly | TokenKind::String + ) && eaten.find(['\n', '\r']).is_some() + { + let start = source.len() - text.len(); + let end = source.len() - rest.len(); + let span = Span::new(start as _, end as _); + result.push(Token { + span, + kind: TokenKind::Newline, + }); + } + } + text = rest; continue; } @@ -144,39 +162,6 @@ pub fn lex(mut text: &str) -> Vec { } } result.push(Token { kind, span }); - // if kind == Quote { - // eprintln!("[lex] pushed quote!"); - // let span = match find_string_closer(text) { - // Some(close_idx) => { - // let start = (source.len() - text.len()) as u32; - // Span { - // start, - // end: start + close_idx as u32, - // } - // } - // // &text[..close_idx], - // None => { - // let start = (source.len() - text.len()) as u32; - // Span { - // start, - // end: start + text.len() as u32, - // } - // } - // }; - // eprintln!("[lex] token text: {token_text:?}"); - // result.push(Token { kind: String, span }); - // text = &source[span.end as _..]; - // result.push(Token { - // kind: Quote, - // span: Span { - // start: span.end, - // end: span.end + 1, - // }, - // }); - // eprint!("[lex] text: {text:?}"); - // text = &source[(span.end as usize + 1).min(source.len().saturating_sub(1))..]; - // eprintln!(" -> {text:?}"); - // } } return result; @@ -192,20 +177,4 @@ pub fn lex(mut text: &str) -> Vec { Some(&text[index..]) } } - - fn find_string_closer(text: &str) -> Option { - let mut skip = false; - for (i, char) in text.char_indices() { - if skip { - skip = false; - continue; - } - match char { - '\\' => skip = true, - '\'' | '"' => return Some(i), - _ => {} - } - } - None - } } From b365c78e7211d641bc6f33a90e29c89818abd161 Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Sat, 10 Jan 2026 01:56:45 +0000 Subject: [PATCH 043/187] feat: entry termination parsing --- crates/ltk_ritobin/src/parser/real.rs | 59 ++++++++++++++++++++++----- 1 file changed, 48 insertions(+), 11 deletions(-) diff --git a/crates/ltk_ritobin/src/parser/real.rs b/crates/ltk_ritobin/src/parser/real.rs index eaa7446e..923474bd 100644 --- a/crates/ltk_ritobin/src/parser/real.rs +++ b/crates/ltk_ritobin/src/parser/real.rs @@ -71,7 +71,7 @@ pub enum TreeKind { TypeExpr, TypeArgList, TypeArg, Block, - Entry, EntryKey, EntryValue, + Entry, EntryKey, EntryValue, EntryTerminator, Literal, } impl Display for TreeKind { @@ -87,6 +87,7 @@ impl Display for TreeKind { TreeKind::EntryKey => "key", TreeKind::EntryValue => "value", TreeKind::Literal => "literal", + TreeKind::EntryTerminator => "bin entry terminator (new line or ';')", }) } } @@ -167,9 +168,16 @@ pub struct MarkClosed { #[derive(Debug, Clone, Copy)] pub enum ErrorKind { - Expected { expected: TokenKind, got: TokenKind }, + Expected { + expected: TokenKind, + got: TokenKind, + }, UnterminatedString, - Unexpected { token: TokenKind }, + Unexpected { + token: TokenKind, + }, + /// When the entire tree we're in is unexpected + UnexpectedTree, Custom(&'static str), } @@ -253,7 +261,9 @@ impl Parser { span.start = span.end - 1; span } - kind => span + // whole tree is the problem + ErrorKind::UnexpectedTree => cur_tree.span, + _ => span .or(cur_tree.children.last().map(|c| c.span())) // we can't use Tree.span.end because that's only known on Close .unwrap_or(crate::Span::new( @@ -324,7 +334,6 @@ impl Parser { fn advance(&mut self) { assert!(!self.eof()); - self.fuel.set(256); self.events.push(Event::Advance); self.pos += 1; } @@ -362,6 +371,15 @@ impl Parser { kinds.contains(&self.nth(0)) } + fn eat_any(&mut self, kinds: &[TokenKind]) -> bool { + if self.at_any(kinds) { + self.advance(); + true + } else { + false + } + } + fn eat(&mut self, kind: TokenKind) -> bool { if self.at(kind) { self.advance(); @@ -429,6 +447,30 @@ pub fn stmt_entry(p: &mut Parser) { token @ TokenKind::Eof => p.report(ErrorKind::Unexpected { token }), token => p.advance_with_error(ErrorKind::Unexpected { token }, None), }); + p.scope(TreeKind::EntryTerminator, |p| { + let mut one = false; + if p.eof() { + return; + } + while p.eat_any(&[TokenKind::SemiColon, TokenKind::Newline]) { + one = true; + } + + if !one { + // if something was between us and our statement terminator, + // we eat it all and then try again + p.scope(TreeKind::ErrorTree, |p| { + while !matches!( + p.nth(0), + TokenKind::SemiColon | TokenKind::Newline | TokenKind::Eof + ) { + p.advance(); + } + p.report(ErrorKind::UnexpectedTree); + }); + while p.eat_any(&[TokenKind::SemiColon, TokenKind::Newline]) {} + } + }); }); } @@ -479,12 +521,7 @@ mod test { #[test] fn smoke_test() { let text = r#" -type = 4 -version: list[u32, = 3 -linked: list[string] = { - "DATA/Characters/Test/Animations/Skin0.bin\" - "DATA/Characters/Test/Test.bin" - +type = 4 a version: u32 = 5 "#; From 97a004fb59608950d87791c2893e80cf721232f8 Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Sat, 10 Jan 2026 15:20:03 +0000 Subject: [PATCH 044/187] fix: type argument parsing --- crates/ltk_ritobin/src/parser/real.rs | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/crates/ltk_ritobin/src/parser/real.rs b/crates/ltk_ritobin/src/parser/real.rs index 923474bd..5b4b45e7 100644 --- a/crates/ltk_ritobin/src/parser/real.rs +++ b/crates/ltk_ritobin/src/parser/real.rs @@ -477,13 +477,15 @@ pub fn stmt_entry(p: &mut Parser) { pub fn type_expr(p: &mut Parser) { p.expect(TokenKind::Name); if p.eat(TokenKind::LBrack) { - while !p.at(TokenKind::RBrack) && !p.eof() { - if p.at(TokenKind::Name) { - expr_type_arg(p); - } else { - break; + p.scope(TreeKind::TypeArgList, |p| { + while !p.at(TokenKind::RBrack) && !p.eof() { + if p.at(TokenKind::Name) { + expr_type_arg(p); + } else { + break; + } } - } + }); p.expect(TokenKind::RBrack); } } @@ -494,7 +496,7 @@ pub fn expr_type_arg(p: &mut Parser) -> MarkClosed { let m = p.open(); p.expect(Name); - if !p.at(RParen) { + if !p.at(RBrack) { p.expect(Comma); } From be18926a8a05328c35963dcff5fe7c40b2662032 Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Sat, 10 Jan 2026 16:01:36 +0000 Subject: [PATCH 045/187] feat: proper block/list parsing --- crates/ltk_ritobin/src/parser/real.rs | 50 +++++++++++++++++++--- crates/ltk_ritobin/src/parser/tokenizer.rs | 7 +++ 2 files changed, 51 insertions(+), 6 deletions(-) diff --git a/crates/ltk_ritobin/src/parser/real.rs b/crates/ltk_ritobin/src/parser/real.rs index 5b4b45e7..b86a8e51 100644 --- a/crates/ltk_ritobin/src/parser/real.rs +++ b/crates/ltk_ritobin/src/parser/real.rs @@ -69,7 +69,7 @@ pub enum TreeKind { ErrorTree, File, TypeExpr, TypeArgList, TypeArg, - Block, + Block, BlockKey, Class, ListItem, Entry, EntryKey, EntryValue, EntryTerminator, Literal, @@ -88,6 +88,9 @@ impl Display for TreeKind { TreeKind::EntryValue => "value", TreeKind::Literal => "literal", TreeKind::EntryTerminator => "bin entry terminator (new line or ';')", + TreeKind::BlockKey => "key", + TreeKind::Class => "bin class", + TreeKind::ListItem => "list item", }) } } @@ -172,6 +175,10 @@ pub enum ErrorKind { expected: TokenKind, got: TokenKind, }, + ExpectedAny { + expected: &'static [TokenKind], + got: TokenKind, + }, UnterminatedString, Unexpected { token: TokenKind, @@ -389,6 +396,17 @@ impl Parser { } } + fn expect_any(&mut self, kinds: &'static [TokenKind]) -> bool { + if self.eat_any(kinds) { + return true; + } + self.report(ErrorKind::ExpectedAny { + expected: kinds, + got: self.nth(0), + }); + false + } + fn expect(&mut self, kind: TokenKind) -> bool { if self.eat(kind) { return true; @@ -425,9 +443,12 @@ pub fn file(p: &mut Parser) { } pub fn stmt_entry(p: &mut Parser) { p.scope(TreeKind::Entry, |p| { - p.scope(TreeKind::EntryKey, |p| p.expect(TokenKind::Name)); - p.expect(TokenKind::Colon); - p.scope(TreeKind::TypeExpr, type_expr); + p.scope(TreeKind::EntryKey, |p| { + p.expect_any(&[TokenKind::Name, TokenKind::String]) + }); + if p.eat(TokenKind::Colon) { + p.scope(TreeKind::TypeExpr, type_expr); + } p.expect(TokenKind::Eq); p.scope(TreeKind::EntryValue, |p| match p.nth(0) { TokenKind::String => { @@ -441,6 +462,12 @@ pub fn stmt_entry(p: &mut Parser) { p.advance(); p.close(m, TreeKind::Literal); } + TokenKind::Name => { + p.scope(TreeKind::Class, |p| { + p.advance(); + block(p); + }); + } TokenKind::LCurly => { block(p); } @@ -507,16 +534,27 @@ pub fn block(p: &mut Parser) { use TokenKind::*; assert!(p.at(LCurly)); let m = p.open(); - p.expect(LCurly); while !p.at(RCurly) && !p.eof() { - stmt_entry(p) + match (p.nth(0), p.nth(1)) { + (Name, Eq) | (String, Eq) | (Name, Colon) | (String, Colon) => stmt_entry(p), + _ => list_item(p), + } } p.expect(RCurly); p.close(m, TreeKind::Block); } +pub fn list_item(p: &mut Parser) { + use TokenKind::*; + let m = p.open(); + + p.advance(); // list item + while p.eat(Newline) {} + p.close(m, TreeKind::ListItem); +} + #[cfg(test)] mod test { use super::*; diff --git a/crates/ltk_ritobin/src/parser/tokenizer.rs b/crates/ltk_ritobin/src/parser/tokenizer.rs index 099d0136..c69803fa 100644 --- a/crates/ltk_ritobin/src/parser/tokenizer.rs +++ b/crates/ltk_ritobin/src/parser/tokenizer.rs @@ -21,6 +21,13 @@ pub enum TokenKind { Name, Int, } +impl TokenKind { + /// Whether we are a string/unterminated string + pub fn is_string(&self) -> bool { + matches!(self, Self::String | Self::UnterminatedString) + } +} + impl Display for TokenKind { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.write_str(match self { From 24eb2fc5fb2112e2f12dc36e314e6c60005da3fc Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Sat, 10 Jan 2026 16:19:59 +0000 Subject: [PATCH 046/187] feat: tokenize hex literals --- crates/ltk_ritobin/src/parser/tokenizer.rs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/crates/ltk_ritobin/src/parser/tokenizer.rs b/crates/ltk_ritobin/src/parser/tokenizer.rs index c69803fa..cb369864 100644 --- a/crates/ltk_ritobin/src/parser/tokenizer.rs +++ b/crates/ltk_ritobin/src/parser/tokenizer.rs @@ -18,7 +18,7 @@ pub enum TokenKind { True, False, - Name, Int, + Name, Int, HexLit, } impl TokenKind { @@ -54,6 +54,7 @@ impl Display for TokenKind { TokenKind::False => "'false'", TokenKind::Name => "keyword", TokenKind::Int => "number", + TokenKind::HexLit => "hexadecimal literal", }) } } @@ -108,6 +109,15 @@ pub fn lex(mut text: &str) -> Vec { break 'kind punctuation.1[i]; } } + + if let Some(rest) = text.strip_prefix("0x") { + text = rest; + if let Some(rest) = trim(text, |it| matches!(it, 'a'..'f' | 'A'..'F' | '0'..='9')) { + text = rest; + } + break 'kind HexLit; + } + if let Some(rest) = trim(text, |it| it.is_ascii_digit()) { text = rest; break 'kind Int; From b62833974e661c5d9d308d9709446b3813b78587 Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Sat, 10 Jan 2026 17:09:13 +0000 Subject: [PATCH 047/187] wip: cleanup --- crates/ltk_ritobin/src/error.rs | 198 --- crates/ltk_ritobin/src/lib.rs | 3 +- .../ltk_ritobin/src/parse/cst/flat_errors.rs | 34 + crates/ltk_ritobin/src/parse/cst/mod.rs | 9 + crates/ltk_ritobin/src/parse/cst/tree.rs | 104 ++ crates/ltk_ritobin/src/parse/cst/visitor.rs | 59 + crates/ltk_ritobin/src/parse/error.rs | 27 + crates/ltk_ritobin/src/parse/impls.rs | 122 ++ crates/ltk_ritobin/src/parse/mod.rs | 49 + crates/ltk_ritobin/src/parse/parser.rs | 253 ++++ crates/ltk_ritobin/src/parse/real.rs | 119 ++ crates/ltk_ritobin/src/parse/span.rs | 37 + .../src/{parser => parse}/tokenizer.rs | 2 +- crates/ltk_ritobin/src/parser/mod.rs | 1072 ----------------- crates/ltk_ritobin/src/parser/real.rs | 731 ----------- 15 files changed, 815 insertions(+), 2004 deletions(-) create mode 100644 crates/ltk_ritobin/src/parse/cst/flat_errors.rs create mode 100644 crates/ltk_ritobin/src/parse/cst/mod.rs create mode 100644 crates/ltk_ritobin/src/parse/cst/tree.rs create mode 100644 crates/ltk_ritobin/src/parse/cst/visitor.rs create mode 100644 crates/ltk_ritobin/src/parse/error.rs create mode 100644 crates/ltk_ritobin/src/parse/impls.rs create mode 100644 crates/ltk_ritobin/src/parse/mod.rs create mode 100644 crates/ltk_ritobin/src/parse/parser.rs create mode 100644 crates/ltk_ritobin/src/parse/real.rs create mode 100644 crates/ltk_ritobin/src/parse/span.rs rename crates/ltk_ritobin/src/{parser => parse}/tokenizer.rs (99%) delete mode 100644 crates/ltk_ritobin/src/parser/mod.rs delete mode 100644 crates/ltk_ritobin/src/parser/real.rs diff --git a/crates/ltk_ritobin/src/error.rs b/crates/ltk_ritobin/src/error.rs index 092d58ad..720bfb61 100644 --- a/crates/ltk_ritobin/src/error.rs +++ b/crates/ltk_ritobin/src/error.rs @@ -6,204 +6,6 @@ use miette::{Diagnostic, SourceSpan}; use thiserror::Error; -/// A span in the source text (offset and length). -#[derive(Debug, Clone, Copy, Default)] -pub struct Span { - pub start: u32, - pub end: u32, -} - -impl Span { - #[must_use] - #[inline] - pub fn new(start: u32, end: u32) -> Self { - Self { start, end } - } - - #[must_use] - #[inline] - pub fn contains(&self, offset: u32) -> bool { - self.start <= offset && offset <= self.end - } -} - -impl std::ops::Index for str { - type Output = str; - - fn index(&self, index: crate::Span) -> &Self::Output { - &self[&index] - } -} -impl std::ops::Index<&crate::Span> for str { - type Output = str; - - fn index(&self, index: &crate::Span) -> &Self::Output { - let start = index.start as usize; - let end = index.end as usize; - &self[start..end] - } -} - -impl From for SourceSpan { - fn from(span: Span) -> Self { - SourceSpan::new( - (span.start as usize).into(), - (span.end - span.start) as usize, - ) - } -} - -/// Errors that can occur during ritobin parsing. -#[derive(Debug, Error, Diagnostic)] -pub enum ParseError { - #[error("unexpected end of input")] - #[diagnostic(code(ltk_ritobin::unexpected_eof))] - UnexpectedEof, - - #[error("invalid header: expected '#PROP_text'")] - #[diagnostic(code(ltk_ritobin::invalid_header))] - InvalidHeader { - #[source_code] - src: String, - #[label("expected '#PROP_text' here")] - span: SourceSpan, - }, - - #[error("unknown type name: '{type_name}'")] - #[diagnostic(code(ltk_ritobin::unknown_type), help("valid types: bool, i8, u8, i16, u16, i32, u32, i64, u64, f32, vec2, vec3, vec4, mtx44, rgba, string, hash, file, link, flag, list, list2, option, map, pointer, embed"))] - UnknownType { - type_name: String, - #[source_code] - src: String, - #[label("unknown type")] - span: SourceSpan, - }, - - #[error("invalid number: '{value}'")] - #[diagnostic(code(ltk_ritobin::invalid_number))] - InvalidNumber { - value: String, - #[source_code] - src: String, - #[label("could not parse as number")] - span: SourceSpan, - }, - - #[error("invalid hex value: '{value}'")] - #[diagnostic(code(ltk_ritobin::invalid_hex))] - InvalidHex { - value: String, - #[source_code] - src: String, - #[label("invalid hexadecimal")] - span: SourceSpan, - }, - - #[error("expected '{expected}'")] - #[diagnostic(code(ltk_ritobin::expected))] - Expected { - expected: String, - #[source_code] - src: String, - #[label("expected {expected}")] - span: SourceSpan, - }, - - #[error("missing type info for container type")] - #[diagnostic( - code(ltk_ritobin::missing_type_info), - help( - "container types require inner type specification, e.g. list[string], map[hash,embed]" - ) - )] - MissingTypeInfo { - #[source_code] - src: String, - #[label("container type needs type parameters")] - span: SourceSpan, - }, - - #[error("unexpected content after parsing")] - #[diagnostic(code(ltk_ritobin::trailing_content))] - TrailingContent { - #[source_code] - src: String, - #[label("unexpected content here")] - span: SourceSpan, - }, - - #[error("parse error: {message}")] - #[diagnostic(code(ltk_ritobin::parse_error))] - ParseErrorAt { - message: String, - #[source_code] - src: String, - #[label("{message}")] - span: SourceSpan, - }, - - #[error("invalid escape sequence")] - #[diagnostic(code(ltk_ritobin::invalid_escape))] - InvalidEscape { - #[source_code] - src: String, - #[label("invalid escape sequence")] - span: SourceSpan, - }, - - #[error("unclosed string")] - #[diagnostic(code(ltk_ritobin::unclosed_string))] - UnclosedString { - #[source_code] - src: String, - #[label("string starts here but is never closed")] - span: SourceSpan, - }, - - #[error("unclosed block")] - #[diagnostic(code(ltk_ritobin::unclosed_block))] - UnclosedBlock { - #[source_code] - src: String, - #[label("block starts here but is never closed with '}}'")] - span: SourceSpan, - }, -} - -impl ParseError { - /// Create an "expected" error with span information. - pub fn expected(expected: impl Into, src: &str, offset: usize, len: usize) -> Self { - Self::Expected { - expected: expected.into(), - src: src.to_string(), - span: SourceSpan::new(offset.into(), len), - } - } - - /// Create a parse error with span information. - pub fn at(message: impl Into, src: &str, offset: usize, len: usize) -> Self { - Self::ParseErrorAt { - message: message.into(), - src: src.to_string(), - span: SourceSpan::new(offset.into(), len), - } - } - - /// Create an unknown type error. - pub fn unknown_type( - type_name: impl Into, - src: &str, - offset: usize, - len: usize, - ) -> Self { - Self::UnknownType { - type_name: type_name.into(), - src: src.to_string(), - span: SourceSpan::new(offset.into(), len), - } - } -} - /// Errors that can occur during ritobin writing. #[derive(Debug, Error, Diagnostic)] pub enum WriteError { diff --git a/crates/ltk_ritobin/src/lib.rs b/crates/ltk_ritobin/src/lib.rs index 1ba3e2d9..71ad5184 100644 --- a/crates/ltk_ritobin/src/lib.rs +++ b/crates/ltk_ritobin/src/lib.rs @@ -46,12 +46,11 @@ pub mod error; pub mod hashes; -pub mod parser; +pub mod parse; pub mod types; pub mod writer; pub use error::*; pub use hashes::*; -pub use parser::{parse, parse_to_bin_tree, RitobinFile}; pub use types::*; pub use writer::*; diff --git a/crates/ltk_ritobin/src/parse/cst/flat_errors.rs b/crates/ltk_ritobin/src/parse/cst/flat_errors.rs new file mode 100644 index 00000000..58bcb809 --- /dev/null +++ b/crates/ltk_ritobin/src/parse/cst/flat_errors.rs @@ -0,0 +1,34 @@ +use crate::parse::{ + cst::{ + visitor::{Visit, Visitor}, + Cst, + }, + Error, +}; + +#[derive(Default)] +pub struct FlatErrors { + errors: Vec, +} + +impl FlatErrors { + pub fn new() -> Self { + Self::default() + } + pub fn into_errors(self) -> Vec { + self.errors + } + + pub fn walk(tree: &Cst) -> Vec { + let mut errors = Self::new(); + tree.walk(&mut errors); + errors.into_errors() + } +} + +impl Visitor for FlatErrors { + fn exit_tree(&mut self, tree: &Cst) -> Visit { + self.errors.extend_from_slice(&tree.errors); + Visit::Continue + } +} diff --git a/crates/ltk_ritobin/src/parse/cst/mod.rs b/crates/ltk_ritobin/src/parse/cst/mod.rs new file mode 100644 index 00000000..fcb28b23 --- /dev/null +++ b/crates/ltk_ritobin/src/parse/cst/mod.rs @@ -0,0 +1,9 @@ +mod tree; +pub use tree::Kind as TreeKind; +pub use tree::*; + +pub mod visitor; +pub use visitor::Visitor; + +mod flat_errors; +pub use flat_errors::*; diff --git a/crates/ltk_ritobin/src/parse/cst/tree.rs b/crates/ltk_ritobin/src/parse/cst/tree.rs new file mode 100644 index 00000000..4d15727e --- /dev/null +++ b/crates/ltk_ritobin/src/parse/cst/tree.rs @@ -0,0 +1,104 @@ +use std::fmt::Display; + +use crate::parse::{self, tokenizer::Token, Span}; + +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[rustfmt::skip] +pub enum Kind { + ErrorTree, + File, + TypeExpr, TypeArgList, TypeArg, + Block, BlockKey, Class, ListItem, + + Entry, EntryKey, EntryValue, EntryTerminator, + Literal, +} +impl Display for Kind { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.write_str(match self { + Self::ErrorTree => "error tree", + Self::File => "file", + Self::TypeExpr => "bin entry type", + Self::TypeArgList => "type argument list", + Self::TypeArg => "type argument", + Self::Block => "block", + Self::Entry => "bin entry", + Self::EntryKey => "key", + Self::EntryValue => "value", + Self::Literal => "literal", + Self::EntryTerminator => "bin entry terminator (new line or ';')", + Self::BlockKey => "key", + Self::Class => "bin class", + Self::ListItem => "list item", + }) + } +} + +#[derive(Clone, Debug)] +pub struct Cst { + pub span: Span, + pub kind: Kind, + pub children: Vec, + pub errors: Vec, +} + +#[derive(Clone, Debug)] +pub enum Child { + Token(Token), + Tree(Cst), +} + +impl Child { + pub fn span(&self) -> Span { + match self { + Child::Token(token) => token.span, + Child::Tree(tree) => tree.span, + } + } +} + +#[macro_export] +macro_rules! format_to { + ($buf:expr) => (); + ($buf:expr, $lit:literal $($arg:tt)*) => { + { use ::std::fmt::Write as _; let _ = ::std::write!($buf, $lit $($arg)*); } + }; +} +impl Cst { + pub fn print(&self, buf: &mut String, level: usize, source: &str) { + let parent_indent = "│ ".repeat(level.saturating_sub(1)); + let indent = match level > 0 { + true => "├ ", + false => "", + }; + let safe_span = match self.span.end >= self.span.start { + true => &source[self.span], + false => "!!!!!!", + }; + format_to!( + buf, + "{parent_indent}{indent}{:?} - ({}..{}): {:?}\n", + self.kind, + self.span.start, + self.span.end, + safe_span + ); + for (i, child) in self.children.iter().enumerate() { + let bar = match i + 1 == self.children.len() { + true => '└', + false => '├', + }; + match child { + Child::Token(token) => { + format_to!( + buf, + "{parent_indent}│ {bar} {:?}\n", + &source[token.span.start as _..token.span.end as _] + ) + } + Child::Tree(tree) => tree.print(buf, level + 1, source), + } + } + assert!(buf.ends_with('\n')); + } +} diff --git a/crates/ltk_ritobin/src/parse/cst/visitor.rs b/crates/ltk_ritobin/src/parse/cst/visitor.rs new file mode 100644 index 00000000..a9e324fd --- /dev/null +++ b/crates/ltk_ritobin/src/parse/cst/visitor.rs @@ -0,0 +1,59 @@ +use crate::parse::{ + cst::{tree::Child, Cst}, + tokenizer::Token, +}; + +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub enum Visit { + Stop, + /// Skip the current tree + Skip, + Continue, +} +#[allow(unused_variables)] +pub trait Visitor { + #[must_use] + fn enter_tree(&mut self, tree: &Cst) -> Visit { + Visit::Continue + } + #[must_use] + fn exit_tree(&mut self, tree: &Cst) -> Visit { + Visit::Continue + } + #[must_use] + fn visit_token(&mut self, token: &Token, context: &Cst) -> Visit { + Visit::Continue + } +} + +impl Cst { + pub fn walk(&self, visitor: &mut V) { + self.walk_inner(visitor); + } + + fn walk_inner(&self, visitor: &mut V) -> Visit { + let enter = visitor.enter_tree(self); + if matches!(enter, Visit::Stop | Visit::Skip) { + return enter; + } + + for child in &self.children { + match child { + Child::Token(token) => match visitor.visit_token(token, self) { + Visit::Continue => {} + Visit::Skip => break, + Visit::Stop => return Visit::Stop, + }, + Child::Tree(child_tree) => match child_tree.walk_inner(visitor) { + Visit::Continue => {} + Visit::Skip => { + break; + } + Visit::Stop => return Visit::Stop, + }, + } + } + + visitor.exit_tree(self) + } +} diff --git a/crates/ltk_ritobin/src/parse/error.rs b/crates/ltk_ritobin/src/parse/error.rs new file mode 100644 index 00000000..af15b8e2 --- /dev/null +++ b/crates/ltk_ritobin/src/parse/error.rs @@ -0,0 +1,27 @@ +use crate::parse::{cst, tokenizer::TokenKind, Span}; + +#[derive(Debug, Clone, Copy)] +pub enum ErrorKind { + Expected { + expected: TokenKind, + got: TokenKind, + }, + ExpectedAny { + expected: &'static [TokenKind], + got: TokenKind, + }, + UnterminatedString, + Unexpected { + token: TokenKind, + }, + /// When the entire tree we're in is unexpected + UnexpectedTree, + Custom(&'static str), +} + +#[derive(Debug, Clone, Copy)] +pub struct Error { + pub span: Span, + pub tree: cst::Kind, + pub kind: ErrorKind, +} diff --git a/crates/ltk_ritobin/src/parse/impls.rs b/crates/ltk_ritobin/src/parse/impls.rs new file mode 100644 index 00000000..5ed19378 --- /dev/null +++ b/crates/ltk_ritobin/src/parse/impls.rs @@ -0,0 +1,122 @@ +use crate::parse::{cst::Kind as TreeKind, error::ErrorKind, parser::Parser, tokenizer::TokenKind}; + +use TokenKind::*; + +pub fn file(p: &mut Parser) { + let m = p.open(); + while !p.eof() { + stmt_entry(p) + } + p.close(m, TreeKind::File); +} + +pub fn stmt_entry(p: &mut Parser) { + p.scope(TreeKind::Entry, |p| { + p.scope(TreeKind::EntryKey, |p| { + p.expect_any(&[TokenKind::Name, TokenKind::String]) + }); + if p.eat(TokenKind::Colon) { + p.scope(TreeKind::TypeExpr, type_expr); + } + p.expect(TokenKind::Eq); + p.scope(TreeKind::EntryValue, |p| match p.nth(0) { + TokenKind::String => { + p.advance(); + } + TokenKind::UnterminatedString => { + p.advance_with_error(ErrorKind::UnterminatedString, None); + } + TokenKind::Int | TokenKind::Minus => { + let m = p.open(); + p.advance(); + p.close(m, TreeKind::Literal); + } + TokenKind::Name => { + p.scope(TreeKind::Class, |p| { + p.advance(); + block(p); + }); + } + TokenKind::LCurly => { + block(p); + } + token @ TokenKind::Eof => p.report(ErrorKind::Unexpected { token }), + token => p.advance_with_error(ErrorKind::Unexpected { token }, None), + }); + p.scope(TreeKind::EntryTerminator, |p| { + let mut one = false; + if p.eof() { + return; + } + while p.eat_any(&[TokenKind::SemiColon, TokenKind::Newline]) { + one = true; + } + + if !one { + // if something was between us and our statement terminator, + // we eat it all and then try again + p.scope(TreeKind::ErrorTree, |p| { + while !matches!( + p.nth(0), + TokenKind::SemiColon | TokenKind::Newline | TokenKind::Eof + ) { + p.advance(); + } + p.report(ErrorKind::UnexpectedTree); + }); + while p.eat_any(&[TokenKind::SemiColon, TokenKind::Newline]) {} + } + }); + }); +} + +pub fn type_expr(p: &mut Parser) { + p.expect(TokenKind::Name); + if p.eat(TokenKind::LBrack) { + p.scope(TreeKind::TypeArgList, |p| { + while !p.at(TokenKind::RBrack) && !p.eof() { + if p.at(TokenKind::Name) { + expr_type_arg(p); + } else { + break; + } + } + }); + p.expect(TokenKind::RBrack); + } +} + +pub fn expr_type_arg(p: &mut Parser) { + assert!(p.at(Name)); + let m = p.open(); + + p.expect(Name); + p.close(m, TreeKind::TypeArg); + + if !p.at(RBrack) { + p.expect(Comma); + } +} + +pub fn block(p: &mut Parser) { + assert!(p.at(LCurly)); + let m = p.open(); + p.expect(LCurly); + while !p.at(RCurly) && !p.eof() { + match (p.nth(0), p.nth(1)) { + (Name, Eq) | (String, Eq) | (Name, Colon) | (String, Colon) => stmt_entry(p), + _ => list_item(p), + } + } + p.expect(RCurly); + + p.close(m, TreeKind::Block); +} + +pub fn list_item(p: &mut Parser) { + let m = p.open(); + + p.advance(); // list item + while p.eat(Newline) {} + p.close(m, TreeKind::ListItem); +} diff --git a/crates/ltk_ritobin/src/parse/mod.rs b/crates/ltk_ritobin/src/parse/mod.rs new file mode 100644 index 00000000..49a39fd1 --- /dev/null +++ b/crates/ltk_ritobin/src/parse/mod.rs @@ -0,0 +1,49 @@ +//! Parser for ritobin text format with CST output for better error reporting. + +pub mod cst; + +pub mod error; +pub use error::*; + +pub mod parser; +pub mod real; +pub mod tokenizer; +pub use tokenizer::{Token, TokenKind}; + +pub mod impls; + +mod span; +pub use span::Span; + +pub fn parse(text: &str) -> cst::Cst { + let tokens = tokenizer::lex(text); + eprintln!("tokens: {tokens:#?}"); + let mut p = parser::Parser::new(tokens); + impls::file(&mut p); + p.build_tree() +} + +#[cfg(test)] +mod test { + use super::*; + #[test] + fn smoke_test() { + let text = r#" +linked: list[string, cock] = { + "DATA/Characters/Yasuo/Yasuo.bin" + "data/Yasuo_skin0_concat.bin" + "data/Yasuo_skin0_StaticMat_proxy.bin" +} + +"#; + let cst = parse(text); + let errors = cst::FlatErrors::walk(&cst); + + let mut str = String::new(); + cst.print(&mut str, 0, text); + eprintln!("{str}\n====== errors: ======\n"); + for err in errors { + eprintln!("{:?}: {:#?}", &text[err.span], err.kind); + } + } +} diff --git a/crates/ltk_ritobin/src/parse/parser.rs b/crates/ltk_ritobin/src/parse/parser.rs new file mode 100644 index 00000000..92861be5 --- /dev/null +++ b/crates/ltk_ritobin/src/parse/parser.rs @@ -0,0 +1,253 @@ +use std::cell::Cell; + +use crate::parse::{ + cst::{Child, Cst, Kind as TreeKind}, + error::{Error, ErrorKind}, + tokenizer::{Token, TokenKind}, + Span, +}; + +pub enum Event { + Open { kind: TreeKind }, + Close, + Error { kind: ErrorKind, span: Option }, + Advance, +} + +pub struct MarkOpened { + index: usize, +} +pub struct MarkClosed { + index: usize, +} + +pub struct Parser { + pub tokens: Vec, + pos: usize, + fuel: Cell, + pub events: Vec, +} + +impl Parser { + pub fn new(tokens: Vec) -> Parser { + Parser { + tokens, + pos: 0, + fuel: Cell::new(256), + events: Vec::new(), + } + } + + pub fn build_tree(self) -> Cst { + let last_token = self.tokens.last().copied(); + + let mut tokens = self.tokens.into_iter().peekable(); + let mut events = self.events; + + assert!(matches!(events.pop(), Some(Event::Close))); + let mut stack = Vec::new(); + let mut last_span = Span::default(); + let mut just_opened = false; + for event in events { + match event { + Event::Open { kind } => { + just_opened = true; + stack.push(Cst { + span: Span::new(last_span.end, 0), + kind, + children: Vec::new(), + errors: Vec::new(), + }) + } + Event::Close => { + let mut tree = stack.pop().unwrap(); + let last = stack.last_mut().unwrap(); + if tree.span.end == 0 { + // empty trees + tree.span.end = tree.span.start; + } + last.span.end = tree.span.end.max(last.span.end); // update our parent tree's span + last.children.push(Child::Tree(tree)); + } + Event::Advance => { + let token = tokens.next().unwrap(); + let last = stack.last_mut().unwrap(); + + if just_opened { + // first token of the tree + last.span.start = token.span.start; + } + just_opened = false; + + last.span.end = token.span.end; + last_span = token.span; + last.children.push(Child::Token(token)); + } + Event::Error { kind, span } => { + let cur_tree = stack.last_mut().unwrap(); + let span = match kind { + // these errors are talking about what they wanted next + ErrorKind::Expected { .. } | ErrorKind::Unexpected { .. } => { + let mut span = tokens.peek().map(|t| t.span).unwrap_or(last_span); + // so we point at the character just after our token + span.end += 1; + span.start = span.end - 1; + span + } + // whole tree is the problem + ErrorKind::UnexpectedTree => cur_tree.span, + _ => span + .or(cur_tree.children.last().map(|c| c.span())) + // we can't use Tree.span.end because that's only known on Close + .unwrap_or(Span::new( + cur_tree.span.start, + last_token + .as_ref() + .map(|t| t.span.end) + .unwrap_or(cur_tree.span.start), + )), + }; + cur_tree.errors.push(Error { + span, + tree: cur_tree.kind, + kind, + }); + } + } + } + + let tree = stack.pop().unwrap(); + assert!(stack.is_empty()); + assert!(tokens.next().is_none()); + tree + } + + pub(crate) fn open(&mut self) -> MarkOpened { + let mark = MarkOpened { + index: self.events.len(), + }; + self.events.push(Event::Open { + kind: TreeKind::ErrorTree, + }); + mark + } + + pub(crate) fn scope(&mut self, kind: TreeKind, mut f: F) -> MarkClosed + where + F: FnMut(&mut Self) -> R, + { + let m = MarkOpened { + index: self.events.len(), + }; + self.events.push(Event::Open { + kind: TreeKind::ErrorTree, + }); + let _ = f(self); + self.events[m.index] = Event::Open { kind }; + self.events.push(Event::Close); + MarkClosed { index: m.index } + } + + pub(crate) fn open_before(&mut self, m: MarkClosed) -> MarkOpened { + let mark = MarkOpened { index: m.index }; + self.events.insert( + m.index, + Event::Open { + kind: TreeKind::ErrorTree, + }, + ); + mark + } + + pub(crate) fn close(&mut self, m: MarkOpened, kind: TreeKind) -> MarkClosed { + self.events[m.index] = Event::Open { kind }; + self.events.push(Event::Close); + MarkClosed { index: m.index } + } + + pub(crate) fn advance(&mut self) { + assert!(!self.eof()); + self.events.push(Event::Advance); + self.pos += 1; + } + + pub(crate) fn report(&mut self, kind: ErrorKind) { + self.events.push(Event::Error { kind, span: None }); + } + + pub(crate) fn advance_with_error(&mut self, kind: ErrorKind, span: Option) { + let m = self.open(); + self.advance(); + self.events.push(Event::Error { kind, span }); + self.close(m, TreeKind::ErrorTree); + } + + pub(crate) fn eof(&self) -> bool { + self.pos == self.tokens.len() + } + + pub(crate) fn nth(&self, lookahead: usize) -> TokenKind { + if self.fuel.get() == 0 { + panic!("parser is stuck") + } + self.fuel.set(self.fuel.get() - 1); + self.tokens + .get(self.pos + lookahead) + .map_or(TokenKind::Eof, |it| it.kind) + } + + pub(crate) fn at(&self, kind: TokenKind) -> bool { + self.nth(0) == kind + } + + pub(crate) fn at_any(&self, kinds: &[TokenKind]) -> bool { + kinds.contains(&self.nth(0)) + } + + pub(crate) fn eat_any(&mut self, kinds: &[TokenKind]) -> bool { + if self.at_any(kinds) { + self.advance(); + true + } else { + false + } + } + + pub(crate) fn eat(&mut self, kind: TokenKind) -> bool { + if self.at(kind) { + self.advance(); + true + } else { + false + } + } + + pub(crate) fn expect_any(&mut self, kinds: &'static [TokenKind]) -> bool { + if self.eat_any(kinds) { + return true; + } + self.report(ErrorKind::ExpectedAny { + expected: kinds, + got: self.nth(0), + }); + false + } + + pub(crate) fn expect(&mut self, kind: TokenKind) -> bool { + if self.eat(kind) { + return true; + } + self.report(ErrorKind::Expected { + expected: kind, + got: self.nth(0), + }); + false + } + + pub(crate) fn expect_fallable(&mut self, kind: TokenKind) -> Result<(), ()> { + match self.expect(kind) { + true => Ok(()), + false => Err(()), + } + } +} diff --git a/crates/ltk_ritobin/src/parse/real.rs b/crates/ltk_ritobin/src/parse/real.rs new file mode 100644 index 00000000..c72fbe76 --- /dev/null +++ b/crates/ltk_ritobin/src/parse/real.rs @@ -0,0 +1,119 @@ +use std::{ + cell::Cell, + fmt::{self, Display}, + sync::{Arc, Mutex}, +}; + +#[salsa::db] +#[derive(Clone)] +#[cfg_attr(not(test), derive(Default))] +pub struct CalcDatabaseImpl { + storage: salsa::Storage, + + // The logs are only used for testing and demonstrating reuse: + #[cfg(test)] + logs: Arc>>>, +} + +#[cfg(test)] +impl Default for CalcDatabaseImpl { + fn default() -> Self { + let logs = >>>>::default(); + Self { + storage: salsa::Storage::new(Some(Box::new({ + let logs = logs.clone(); + move |event| { + eprintln!("Event: {event:?}"); + // Log interesting events, if logging is enabled + if let Some(logs) = &mut *logs.lock().unwrap() { + // only log interesting events + if let salsa::EventKind::WillExecute { .. } = event.kind { + logs.push(format!("Event: {event:?}")); + } + } + } + }))), + logs, + } + } +} + +#[salsa::db] +impl salsa::Database for CalcDatabaseImpl {} + +#[salsa::input(debug)] +pub struct SourceProgram { + #[returns(ref)] + pub text: String, +} + +#[salsa::tracked(debug)] +pub struct RitobinFile<'db> { + #[tracked] + #[returns(ref)] + pub statements: Vec>, +} + +#[salsa::interned(debug)] +pub struct PropertyName<'db> { + #[returns(ref)] + pub text: String, +} + +#[derive(PartialEq, Debug, Hash, salsa::Update)] +pub struct Statement<'db> { + pub span: Span<'db>, + pub name: PropertyName<'db>, + pub value: BinProperty, +} + +#[salsa::accumulator] +#[derive(Debug)] +#[allow(dead_code)] // Debug impl uses them +pub struct Diagnostic { + pub start: usize, + pub end: usize, + pub message: String, +} +impl Diagnostic { + pub fn new(start: usize, end: usize, message: String) -> Self { + Diagnostic { + start, + end, + message, + } + } + + // #[cfg(test)] + // pub fn render(&self, db: &dyn crate::Db, src: SourceProgram) -> String { + // use annotate_snippets::*; + // let line_start = src.text(db)[..self.start].lines().count() + 1; + // Renderer::plain() + // .render( + // Level::Error.title(&self.message).snippet( + // Snippet::source(src.text(db)) + // .line_start(line_start) + // .origin("input") + // .fold(true) + // .annotation(Level::Error.span(self.start..self.end).label("here")), + // ), + // ) + // .to_string() + // } +} + +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[derive(Clone, PartialEq, Debug, Hash, salsa::Update)] +pub struct BinProperty { + pub name_hash: u32, + #[cfg_attr(feature = "serde", serde(flatten))] + pub value: ltk_meta::PropertyValueEnum, +} + +#[salsa::tracked(debug)] +pub struct Span<'db> { + #[tracked] + pub start: usize, + #[tracked] + pub end: usize, +} diff --git a/crates/ltk_ritobin/src/parse/span.rs b/crates/ltk_ritobin/src/parse/span.rs new file mode 100644 index 00000000..8ab2bea5 --- /dev/null +++ b/crates/ltk_ritobin/src/parse/span.rs @@ -0,0 +1,37 @@ +/// A span in the source text (offset and length). +#[derive(Debug, Clone, Copy, Default)] +pub struct Span { + pub start: u32, + pub end: u32, +} + +impl Span { + #[must_use] + #[inline] + pub fn new(start: u32, end: u32) -> Self { + Self { start, end } + } + + #[must_use] + #[inline] + pub fn contains(&self, offset: u32) -> bool { + self.start <= offset && offset <= self.end + } +} + +impl std::ops::Index for str { + type Output = str; + + fn index(&self, index: Span) -> &Self::Output { + &self[&index] + } +} +impl std::ops::Index<&Span> for str { + type Output = str; + + fn index(&self, index: &Span) -> &Self::Output { + let start = index.start as usize; + let end = index.end as usize; + &self[start..end] + } +} diff --git a/crates/ltk_ritobin/src/parser/tokenizer.rs b/crates/ltk_ritobin/src/parse/tokenizer.rs similarity index 99% rename from crates/ltk_ritobin/src/parser/tokenizer.rs rename to crates/ltk_ritobin/src/parse/tokenizer.rs index cb369864..e5664063 100644 --- a/crates/ltk_ritobin/src/parser/tokenizer.rs +++ b/crates/ltk_ritobin/src/parse/tokenizer.rs @@ -1,6 +1,6 @@ use std::fmt::Display; -use crate::Span; +use crate::parse::Span; #[derive(Clone, Copy, PartialEq, Eq, Debug)] #[rustfmt::skip] diff --git a/crates/ltk_ritobin/src/parser/mod.rs b/crates/ltk_ritobin/src/parser/mod.rs deleted file mode 100644 index 50d355ad..00000000 --- a/crates/ltk_ritobin/src/parser/mod.rs +++ /dev/null @@ -1,1072 +0,0 @@ -//! Nom parser for ritobin text format with span tracking for error reporting. - -// Nom-style parsers use elided lifetimes extensively -#![allow(clippy::type_complexity)] - -pub mod real; -pub mod tokenizer; - -use glam::{Mat4, Vec2, Vec3, Vec4}; -use indexmap::IndexMap; -use ltk_hash::fnv1a::hash_lower; -use ltk_meta::{ - property::{values, NoMeta, PropertyValueEnum}, - Bin, BinObject, PropertyKind, -}; -use ltk_primitives::Color; -use nom::{ - branch::alt, - bytes::complete::{is_not, tag, take_until, take_while, take_while1}, - character::complete::{char, hex_digit1, multispace1, one_of}, - combinator::{map, map_res, opt, recognize, value}, - error::{ErrorKind, FromExternalError, ParseError as NomParseError}, - multi::many0, - sequence::{delimited, pair, preceded, tuple}, - Err as NomErr, IResult, -}; -use nom_locate::LocatedSpan; - -use crate::{ - error::ParseError, - types::{type_name_to_kind, RitobinType}, -}; - -// ============================================================================ -// Span Types and Custom Error -// ============================================================================ - -/// Input type that tracks position in the source. -pub type Span<'a> = LocatedSpan<&'a str>; - -/// Custom error type that preserves span information. -#[derive(Debug, Clone)] -pub struct SpannedError<'a> { - pub span: Span<'a>, - pub kind: SpannedErrorKind, -} - -#[derive(Debug, Clone)] -pub enum SpannedErrorKind { - Nom(ErrorKind), - Expected(&'static str), - UnknownType(String), - InvalidNumber(String), - InvalidHex(String), - UnclosedString, - UnclosedBlock, - Context(&'static str), -} - -impl<'a> NomParseError> for SpannedError<'a> { - fn from_error_kind(input: Span<'a>, kind: ErrorKind) -> Self { - SpannedError { - span: input, - kind: SpannedErrorKind::Nom(kind), - } - } - - fn append(_input: Span<'a>, _kind: ErrorKind, other: Self) -> Self { - other - } -} - -impl<'a, E> FromExternalError, E> for SpannedError<'a> { - fn from_external_error(input: Span<'a>, kind: ErrorKind, _e: E) -> Self { - SpannedError { - span: input, - kind: SpannedErrorKind::Nom(kind), - } - } -} - -impl<'a> SpannedError<'a> { - pub fn expected(span: Span<'a>, what: &'static str) -> Self { - SpannedError { - span, - kind: SpannedErrorKind::Expected(what), - } - } - - pub fn unknown_type(span: Span<'a>, type_name: String) -> Self { - SpannedError { - span, - kind: SpannedErrorKind::UnknownType(type_name), - } - } - - pub fn to_parse_error(&self, src: &str) -> ParseError { - let offset = self.span.location_offset(); - let len = self.span.fragment().len().max(1); - - match &self.kind { - SpannedErrorKind::Nom(kind) => ParseError::ParseErrorAt { - message: format!("{:?}", kind), - src: src.to_string(), - span: miette::SourceSpan::new(offset.into(), len), - }, - SpannedErrorKind::Expected(what) => ParseError::Expected { - expected: (*what).to_string(), - src: src.to_string(), - span: miette::SourceSpan::new(offset.into(), len), - }, - SpannedErrorKind::UnknownType(name) => ParseError::UnknownType { - type_name: name.clone(), - src: src.to_string(), - span: miette::SourceSpan::new(offset.into(), len), - }, - SpannedErrorKind::InvalidNumber(val) => ParseError::InvalidNumber { - value: val.clone(), - src: src.to_string(), - span: miette::SourceSpan::new(offset.into(), len), - }, - SpannedErrorKind::InvalidHex(val) => ParseError::InvalidHex { - value: val.clone(), - src: src.to_string(), - span: miette::SourceSpan::new(offset.into(), len), - }, - SpannedErrorKind::UnclosedString => ParseError::UnclosedString { - src: src.to_string(), - span: miette::SourceSpan::new(offset.into(), len), - }, - SpannedErrorKind::UnclosedBlock => ParseError::UnclosedBlock { - src: src.to_string(), - span: miette::SourceSpan::new(offset.into(), len), - }, - SpannedErrorKind::Context(ctx) => ParseError::ParseErrorAt { - message: (*ctx).to_string(), - src: src.to_string(), - span: miette::SourceSpan::new(offset.into(), len), - }, - } - } -} - -type ParseResult<'a, T> = IResult, T, SpannedError<'a>>; - -// ============================================================================ -// Basic Parsers -// ============================================================================ - -/// Parse whitespace and comments (lines starting with #, except at the very beginning). -fn ws(input: Span) -> ParseResult<()> { - value( - (), - many0(alt(( - value((), multispace1), - value( - (), - pair(char('#'), alt((take_until("\n"), take_while(|_| true)))), - ), - ))), - )(input) -} - -/// Parse an identifier (alphanumeric + underscore, starting with letter or underscore). -fn identifier(input: Span) -> ParseResult { - preceded(ws, take_while1(|c: char| c.is_alphanumeric() || c == '_'))(input) -} - -/// Parse a word that can include various characters found in paths/identifiers. -fn word(input: Span) -> ParseResult { - preceded( - ws, - take_while1(|c: char| { - c.is_alphanumeric() || c == '_' || c == '+' || c == '-' || c == '.' || c == '/' - }), - )(input) -} - -/// Parse a quoted string with escape sequences. -fn quoted_string(input: Span) -> ParseResult { - preceded( - ws, - alt(( - delimited( - char('"'), - map( - many0(alt(( - map(is_not("\\\""), |s: Span| s.fragment().to_string()), - map(preceded(char('\\'), one_of("nrt\\\"'")), |c| match c { - 'n' => "\n".to_string(), - 'r' => "\r".to_string(), - 't' => "\t".to_string(), - '\\' => "\\".to_string(), - '"' => "\"".to_string(), - '\'' => "'".to_string(), - _ => c.to_string(), - }), - ))), - |parts| parts.join(""), - ), - char('"'), - ), - delimited( - char('\''), - map( - many0(alt(( - map(is_not("\\'"), |s: Span| s.fragment().to_string()), - map(preceded(char('\\'), one_of("nrt\\\"'")), |c| match c { - 'n' => "\n".to_string(), - 'r' => "\r".to_string(), - 't' => "\t".to_string(), - '\\' => "\\".to_string(), - '"' => "\"".to_string(), - '\'' => "'".to_string(), - _ => c.to_string(), - }), - ))), - |parts| parts.join(""), - ), - char('\''), - ), - )), - )(input) -} - -/// Parse a hex u32 (0x12345678 or decimal). -fn hex_u32(input: Span) -> ParseResult { - preceded( - ws, - alt(( - map_res( - preceded(alt((tag("0x"), tag("0X"))), hex_digit1), - |s: Span| u32::from_str_radix(s.fragment(), 16), - ), - map_res( - recognize(pair( - opt(char('-')), - take_while1(|c: char| c.is_ascii_digit()), - )), - |s: Span| s.fragment().parse::(), - ), - )), - )(input) -} - -/// Parse a hex u64 (0x123456789abcdef0 or decimal). -fn hex_u64(input: Span) -> ParseResult { - preceded( - ws, - alt(( - map_res( - preceded(alt((tag("0x"), tag("0X"))), hex_digit1), - |s: Span| u64::from_str_radix(s.fragment(), 16), - ), - map_res(take_while1(|c: char| c.is_ascii_digit()), |s: Span| { - s.fragment().parse::() - }), - )), - )(input) -} - -/// Parse a boolean. -fn parse_bool(input: Span) -> ParseResult { - preceded( - ws, - alt((value(true, tag("true")), value(false, tag("false")))), - )(input) -} - -/// Parse an integer number. -fn parse_int(input: Span) -> ParseResult { - preceded( - ws, - map_res( - recognize(pair( - opt(char('-')), - take_while1(|c: char| c.is_ascii_digit()), - )), - |s: Span| s.fragment().parse::(), - ), - )(input) -} - -/// Parse a float number. -fn parse_float(input: Span) -> ParseResult { - preceded( - ws, - map_res( - recognize(tuple(( - opt(char('-')), - take_while1(|c: char| c.is_ascii_digit() || c == '.'), - opt(pair( - one_of("eE"), - pair(opt(one_of("+-")), take_while1(|c: char| c.is_ascii_digit())), - )), - ))), - |s: Span| s.fragment().parse::(), - ), - )(input) -} - -// ============================================================================ -// Type Parsers -// ============================================================================ - -/// Parse a type name and return the BinPropertyKind. -fn parse_type_name(input: Span) -> ParseResult { - let (input, type_span) = word(input)?; - match type_name_to_kind(type_span.fragment()) { - Some(kind) => Ok((input, kind)), - None => Err(NomErr::Failure(SpannedError::unknown_type( - type_span, - type_span.fragment().to_string(), - ))), - } -} - -/// Parse container type parameters: `\[type\]` or `\[key,value\]`. -fn parse_container_type_params(input: Span) -> ParseResult<(PropertyKind, Option)> { - preceded( - ws, - delimited( - char('['), - alt(( - // map[key,value] - map( - tuple(( - parse_type_name, - preceded(tuple((ws, char(','), ws)), parse_type_name), - )), - |(k, v)| (k, Some(v)), - ), - // list[type] or option[type] - map(parse_type_name, |t| (t, None)), - )), - preceded(ws, char(']')), - ), - )(input) -} - -/// Parse a full type specification including container parameters. -fn parse_type(input: Span) -> ParseResult { - let (input, kind) = parse_type_name(input)?; - - if kind.is_container() || kind == PropertyKind::Optional { - let (input, (inner, value_kind)) = parse_container_type_params(input)?; - if kind == PropertyKind::Map { - Ok(( - input, - RitobinType::map(inner, value_kind.unwrap_or(PropertyKind::None)), - )) - } else { - Ok((input, RitobinType::container(kind, inner))) - } - } else { - Ok((input, RitobinType::simple(kind))) - } -} - -// ============================================================================ -// Value Parsers -// ============================================================================ - -/// Parse a vec2: { x, y } -fn parse_vec2(input: Span) -> ParseResult { - delimited( - preceded(ws, char('{')), - map( - tuple(( - parse_float, - preceded(tuple((ws, char(','), ws)), parse_float), - )), - |(x, y)| Vec2::new(x, y), - ), - preceded(ws, char('}')), - )(input) -} - -/// Parse a vec3: { x, y, z } -fn parse_vec3(input: Span) -> ParseResult { - delimited( - preceded(ws, char('{')), - map( - tuple(( - parse_float, - preceded(tuple((ws, char(','), ws)), parse_float), - preceded(tuple((ws, char(','), ws)), parse_float), - )), - |(x, y, z)| Vec3::new(x, y, z), - ), - preceded(ws, char('}')), - )(input) -} - -/// Parse a vec4: { x, y, z, w } -fn parse_vec4(input: Span) -> ParseResult { - delimited( - preceded(ws, char('{')), - map( - tuple(( - parse_float, - preceded(tuple((ws, char(','), ws)), parse_float), - preceded(tuple((ws, char(','), ws)), parse_float), - preceded(tuple((ws, char(','), ws)), parse_float), - )), - |(x, y, z, w)| Vec4::new(x, y, z, w), - ), - preceded(ws, char('}')), - )(input) -} - -/// Parse a mtx44: { 16 floats } -fn parse_mtx44(input: Span) -> ParseResult { - let (input, _) = preceded(ws, char('{'))(input)?; - - let mut values = [0.0f32; 16]; - let mut remaining = input; - - for (i, val) in values.iter_mut().enumerate() { - let (r, _) = ws(remaining)?; - let (r, v) = parse_float(r)?; - *val = v; - - // Handle optional comma or whitespace between values - let (r, _) = ws(r)?; - let (r, _) = opt(char(','))(r)?; - remaining = r; - - if i < 15 { - let (r, _) = ws(remaining)?; - remaining = r; - } - } - - let (remaining, _) = preceded(ws, char('}'))(remaining)?; - - // text values are row-major but from_cols_array expects column-major, - // so transpose to get the correct internal layout. - Ok((remaining, Mat4::from_cols_array(&values).transpose())) -} - -/// Parse rgba: { r, g, b, a } -fn parse_rgba(input: Span) -> ParseResult> { - delimited( - preceded(ws, char('{')), - map( - tuple(( - parse_int::, - preceded(tuple((ws, char(','), ws)), parse_int::), - preceded(tuple((ws, char(','), ws)), parse_int::), - preceded(tuple((ws, char(','), ws)), parse_int::), - )), - |(r, g, b, a)| Color::new(r, g, b, a), - ), - preceded(ws, char('}')), - )(input) -} - -/// Parse a hash value (hex or quoted string that gets hashed). -fn parse_hash_value(input: Span) -> ParseResult { - preceded(ws, alt((map(quoted_string, |s| hash_lower(&s)), hex_u32)))(input) -} - -/// Parse a file hash (u64). -fn parse_file_hash(input: Span) -> ParseResult { - preceded( - ws, - alt(( - map(quoted_string, |s| { - xxhash_rust::xxh64::xxh64(s.to_lowercase().as_bytes(), 0) - }), - hex_u64, - )), - )(input) -} - -/// Parse a link value (hash or quoted string). -fn parse_link_value(input: Span) -> ParseResult { - preceded(ws, alt((map(quoted_string, |s| hash_lower(&s)), hex_u32)))(input) -} - -/// Parse items in a list/container. -fn parse_list_items(input: Span, item_kind: PropertyKind) -> ParseResult> { - let (input, _) = preceded(ws, char('{'))(input)?; - let (input, _) = ws(input)?; - - let mut items = Vec::new(); - let mut remaining = input; - - loop { - let (r, _) = ws(remaining)?; - - // Check for closing brace - if let Ok((r, _)) = char::('}')(r) { - return Ok((r, items)); - } - - // Parse an item - let (r, item) = parse_value_for_kind(r, item_kind)?; - items.push(item); - - let (r, _) = ws(r)?; - // Optional comma or newline separator - let (r, _) = opt(char(','))(r)?; - remaining = r; - } -} - -/// Parse map entries. -fn parse_map_entries( - input: Span, - key_kind: PropertyKind, - value_kind: PropertyKind, -) -> ParseResult> { - let (input, _) = preceded(ws, char('{'))(input)?; - let (input, _) = ws(input)?; - - let mut entries = Vec::new(); - let mut remaining = input; - - loop { - let (r, _) = ws(remaining)?; - - // Check for closing brace - if let Ok((r, _)) = char::('}')(r) { - return Ok((r, entries)); - } - - // Parse key = value - let (r, key) = parse_value_for_kind(r, key_kind)?; - let (r, _) = preceded(ws, char('='))(r)?; - let (r, value) = parse_value_for_kind(r, value_kind)?; - - entries.push((key, value)); - - let (r, _) = ws(r)?; - let (r, _) = opt(char(','))(r)?; - remaining = r; - } -} - -/// Parse optional value. -fn parse_optional_value(input: Span, inner_kind: PropertyKind) -> ParseResult { - let (input, _) = preceded(ws, char('{'))(input)?; - let (input, _) = ws(input)?; - - // Check for empty optional - if let Ok((input, _)) = char::('}')(input) { - return Ok(( - input, - values::Optional::empty(inner_kind).expect("invalid item type for optional"), - )); - } - - // Parse the inner value - let (input, value) = parse_value_for_kind(input, inner_kind)?; - let (input, _) = ws(input)?; - let (input, _) = char('}')(input)?; - - Ok(( - input, - values::Optional::new(inner_kind, Some(value)).expect("valid inner item for optional"), - )) -} - -/// Parse struct/embed fields. -fn parse_struct_fields(input: Span) -> ParseResult> { - let (input, _) = preceded(ws, char('{'))(input)?; - let (input, _) = ws(input)?; - - let mut properties = IndexMap::new(); - let mut remaining = input; - - loop { - let (r, _) = ws(remaining)?; - - // Check for closing brace - if let Ok((r, _)) = char::('}')(r) { - return Ok((r, properties)); - } - - // Parse field: name: type = value - let (r, (name_hash, value)) = parse_field(r)?; - properties.insert(name_hash, value); - - let (r, _) = ws(r)?; - let (r, _) = opt(char(','))(r)?; - remaining = r; - } -} - -/// Parse a single field: name: type = value -fn parse_field(input: Span) -> ParseResult<(u32, PropertyValueEnum)> { - let (input, _) = ws(input)?; - let (input, name_span) = word(input)?; - let name_str = *name_span.fragment(); - - // Determine hash from name - let name_hash = if name_str.starts_with("0x") || name_str.starts_with("0X") { - u32::from_str_radix(&name_str[2..], 16).unwrap_or(0) - } else { - hash_lower(name_str) - }; - - let (input, _) = preceded(ws, char(':'))(input)?; - let (input, ty) = parse_type(input)?; - let (input, _) = preceded(ws, char('='))(input)?; - let (input, value) = parse_value_for_type(input, &ty)?; - - Ok((input, (name_hash, value))) -} - -/// Parse a pointer value (null or name { fields }). -fn parse_pointer_value(input: Span) -> ParseResult { - let (input, _) = ws(input)?; - - // Check for null - if let Ok((input, _)) = tag::<&str, Span, SpannedError>("null")(input) { - return Ok(( - input, - values::Struct { - class_hash: 0, - properties: IndexMap::new(), - meta: NoMeta, - }, - )); - } - - // Parse class name - let (input, class_span) = word(input)?; - let class_str = *class_span.fragment(); - let class_hash = if class_str.starts_with("0x") || class_str.starts_with("0X") { - u32::from_str_radix(&class_str[2..], 16).unwrap_or(0) - } else { - hash_lower(class_str) - }; - - // Check for empty struct - let (input, _) = ws(input)?; - if let Ok((input, _)) = tag::<&str, Span, SpannedError>("{}")(input) { - return Ok(( - input, - values::Struct { - class_hash, - properties: IndexMap::new(), - meta: NoMeta, - }, - )); - } - - // Parse fields - let (input, properties) = parse_struct_fields(input)?; - - Ok(( - input, - values::Struct { - class_hash, - properties, - meta: NoMeta, - }, - )) -} - -/// Parse an embed value (name { fields }). -fn parse_embed_value(input: Span) -> ParseResult { - let (input, struct_val) = parse_pointer_value(input)?; - Ok((input, values::Embedded(struct_val))) -} - -/// Parse a value given a BinPropertyKind. -fn parse_value_for_kind(input: Span, kind: PropertyKind) -> ParseResult { - match kind { - PropertyKind::None => { - let (input, _) = preceded(ws, tag("null"))(input)?; - Ok((input, PropertyValueEnum::None(values::None::default()))) - } - PropertyKind::Bool => { - let (input, v) = parse_bool(input)?; - Ok((input, PropertyValueEnum::Bool(values::Bool::new(v)))) - } - PropertyKind::I8 => { - let (input, v) = parse_int::(input)?; - Ok((input, PropertyValueEnum::I8(values::I8::new(v)))) - } - PropertyKind::U8 => { - let (input, v) = parse_int::(input)?; - Ok((input, PropertyValueEnum::U8(values::U8::new(v)))) - } - PropertyKind::I16 => { - let (input, v) = parse_int::(input)?; - Ok((input, PropertyValueEnum::I16(values::I16::new(v)))) - } - PropertyKind::U16 => { - let (input, v) = parse_int::(input)?; - Ok((input, PropertyValueEnum::U16(values::U16::new(v)))) - } - PropertyKind::I32 => { - let (input, v) = parse_int::(input)?; - Ok((input, PropertyValueEnum::I32(values::I32::new(v)))) - } - PropertyKind::U32 => { - let (input, v) = hex_u32(input)?; - Ok((input, PropertyValueEnum::U32(values::U32::new(v)))) - } - PropertyKind::I64 => { - let (input, v) = parse_int::(input)?; - Ok((input, PropertyValueEnum::I64(values::I64::new(v)))) - } - PropertyKind::U64 => { - let (input, v) = hex_u64(input)?; - Ok((input, PropertyValueEnum::U64(values::U64::new(v)))) - } - PropertyKind::F32 => { - let (input, v) = parse_float(input)?; - Ok((input, PropertyValueEnum::F32(values::F32::new(v)))) - } - PropertyKind::Vector2 => { - let (input, v) = parse_vec2(input)?; - Ok((input, PropertyValueEnum::Vector2(values::Vector2::new(v)))) - } - PropertyKind::Vector3 => { - let (input, v) = parse_vec3(input)?; - Ok((input, PropertyValueEnum::Vector3(values::Vector3::new(v)))) - } - PropertyKind::Vector4 => { - let (input, v) = parse_vec4(input)?; - Ok((input, PropertyValueEnum::Vector4(values::Vector4::new(v)))) - } - PropertyKind::Matrix44 => { - let (input, v) = parse_mtx44(input)?; - Ok((input, PropertyValueEnum::Matrix44(values::Matrix44::new(v)))) - } - PropertyKind::Color => { - let (input, v) = parse_rgba(input)?; - Ok((input, PropertyValueEnum::Color(values::Color::new(v)))) - } - PropertyKind::String => { - let (input, v) = preceded(ws, quoted_string)(input)?; - Ok((input, PropertyValueEnum::String(values::String::new(v)))) - } - PropertyKind::Hash => { - let (input, v) = parse_hash_value(input)?; - Ok((input, PropertyValueEnum::Hash(values::Hash::new(v)))) - } - PropertyKind::WadChunkLink => { - let (input, v) = parse_file_hash(input)?; - Ok(( - input, - PropertyValueEnum::WadChunkLink(values::WadChunkLink::new(v)), - )) - } - PropertyKind::ObjectLink => { - let (input, v) = parse_link_value(input)?; - Ok(( - input, - PropertyValueEnum::ObjectLink(values::ObjectLink::new(v)), - )) - } - PropertyKind::BitBool => { - let (input, v) = parse_bool(input)?; - Ok((input, PropertyValueEnum::BitBool(values::BitBool::new(v)))) - } - PropertyKind::Struct => { - let (input, v) = parse_pointer_value(input)?; - Ok((input, PropertyValueEnum::Struct(v))) - } - PropertyKind::Embedded => { - let (input, v) = parse_embed_value(input)?; - Ok((input, PropertyValueEnum::Embedded(v))) - } - // Container types need additional type info, handled separately - PropertyKind::Container - | PropertyKind::UnorderedContainer - | PropertyKind::Optional - | PropertyKind::Map => Err(NomErr::Failure(SpannedError::expected( - input, - "non-container type", - ))), - } -} - -/// Parse a value given a full RitobinType. -fn parse_value_for_type<'a>( - input: Span<'a>, - ty: &RitobinType, -) -> ParseResult<'a, PropertyValueEnum> { - match ty.kind { - PropertyKind::Container => { - let inner_kind = ty.inner_kind.unwrap_or(PropertyKind::None); - let (input, items) = parse_list_items(input, inner_kind)?; - Ok(( - input, - PropertyValueEnum::Container( - values::Container::try_from(items).unwrap_or_default(), - ), // TODO: handle error here - )) - } - PropertyKind::UnorderedContainer => { - let inner_kind = ty.inner_kind.unwrap_or(PropertyKind::None); - let (input, items) = parse_list_items(input, inner_kind)?; - Ok(( - input, - PropertyValueEnum::UnorderedContainer(values::UnorderedContainer( - values::Container::try_from(items).unwrap_or_default(), // TODO: handle error here - )), - )) - } - PropertyKind::Optional => { - let inner_kind = ty.inner_kind.unwrap_or(PropertyKind::None); - let (input, opt_val) = parse_optional_value(input, inner_kind)?; - Ok((input, PropertyValueEnum::Optional(opt_val))) - } - PropertyKind::Map => { - let key_kind = ty.inner_kind.unwrap_or(PropertyKind::Hash); - let value_kind = ty.value_kind.unwrap_or(PropertyKind::None); - let (input, entries) = parse_map_entries(input, key_kind, value_kind)?; - Ok(( - input, - PropertyValueEnum::Map( - values::Map::new(key_kind, value_kind, entries).expect("valid items in map"), - ), - )) - } - _ => parse_value_for_kind(input, ty.kind), - } -} - -// ============================================================================ -// Top-Level Parsers -// ============================================================================ - -/// Parse a top-level entry: key: type = value -fn parse_entry(input: Span) -> ParseResult<(String, (u32, PropertyValueEnum))> { - let (input, _) = ws(input)?; - let (input, key) = identifier(input)?; - let (input, _) = preceded(ws, char(':'))(input)?; - let (input, ty) = parse_type(input)?; - let (input, _) = preceded(ws, char('='))(input)?; - let (input, value) = parse_value_for_type(input, &ty)?; - - let name_hash = hash_lower(key.fragment()); - - Ok((input, (key.fragment().to_string(), (name_hash, value)))) -} - -/// Parse the entire ritobin file. -fn parse_ritobin(input: Span) -> ParseResult { - let (input, _) = ws(input)?; - // The header comment is consumed by ws, but we should verify it's present - // For now, we're lenient about the header - - let (input, entries) = many0(parse_entry)(input)?; - let (input, _) = ws(input)?; - - let mut file = RitobinFile::new(); - for (key, prop) in entries { - file.entries.insert(key, prop); - } - - Ok((input, file)) -} - -// ============================================================================ -// Public Types and API -// ============================================================================ - -/// A ritobin file representation (intermediate format before conversion to BinTree). -#[derive(Debug, Clone, Default)] -pub struct RitobinFile { - pub entries: IndexMap, -} - -impl RitobinFile { - pub fn new() -> Self { - Self { - entries: IndexMap::new(), - } - } - - /// Get the "type" field value as a string. - pub fn file_type(&self) -> Option<&str> { - self.entries.get("type").and_then(|p| { - if let PropertyValueEnum::String(s) = &p.1 { - Some(s.value.as_str()) - } else { - None - } - }) - } - - /// Get the "version" field as u32. - pub fn version(&self) -> Option { - self.entries.get("version").and_then(|p| { - if let PropertyValueEnum::U32(v) = &p.1 { - Some(**v) - } else { - None - } - }) - } - - /// Get the "linked" dependencies list. - pub fn linked(&self) -> Vec { - self.entries - .get("linked") - .and_then(|p| { - if let PropertyValueEnum::Container(values::Container::String { items, .. }) = &p.1 - { - Some(items.iter().cloned().map(|i| i.value).collect()) - } else { - None - } - }) - .unwrap_or_default() - } - - /// Get the "entries" map as BinTreeObjects. - pub fn objects(&self) -> IndexMap { - self.entries - .get("entries") - .and_then(|p| { - if let PropertyValueEnum::Map(map) = &p.1 { - Some( - map.entries() - .iter() - .filter_map(|(key, value)| { - let path_hash = match &key { - PropertyValueEnum::Hash(h) => **h, - _ => return None, - }; - - if let PropertyValueEnum::Embedded(values::Embedded(struct_val)) = - value - { - Some(( - path_hash, - BinObject { - path_hash, - class_hash: struct_val.class_hash, - properties: struct_val.properties.clone(), - }, - )) - } else { - None - } - }) - .collect(), - ) - } else { - None - } - }) - .unwrap_or_default() - } - - /// Convert to a BinTree. - pub fn to_bin_tree(&self) -> Bin { - Bin::new(self.objects().into_values(), self.linked()) - } -} - -/// Parse ritobin text format. -pub fn parse(input: &str) -> Result { - let span = Span::new(input); - match parse_ritobin(span) { - Ok((remaining, file)) => { - let trimmed = remaining.fragment().trim(); - if !trimmed.is_empty() { - Err(ParseError::TrailingContent { - src: input.to_string(), - span: miette::SourceSpan::new( - remaining.location_offset().into(), - trimmed.len().min(50), - ), - }) - } else { - Ok(file) - } - } - Err(NomErr::Error(e)) | Err(NomErr::Failure(e)) => Err(e.to_parse_error(input)), - Err(NomErr::Incomplete(_)) => Err(ParseError::UnexpectedEof), - } -} - -/// Parse ritobin text directly to BinTree. -pub fn parse_to_bin_tree(input: &str) -> Result { - parse(input).map(|f| f.to_bin_tree()) -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_parse_simple_types() { - let input = r#" -#PROP_text -type: string = "PROP" -version: u32 = 3 -"#; - let file = parse(input).unwrap(); - assert_eq!(file.file_type(), Some("PROP")); - assert_eq!(file.version(), Some(3)); - } - - #[test] - fn test_parse_list() { - let input = r#" -linked: list[string] = { - "path/to/file1.bin" - "path/to/file2.bin" -} -"#; - let file = parse(input).unwrap(); - let linked = file.linked(); - assert_eq!(linked.len(), 2); - assert_eq!(linked[0], "path/to/file1.bin"); - } - - #[test] - fn test_parse_vec3() { - let input = r#" -pos: vec3 = { 1.0, 2.5, -3.0 } -"#; - let file = parse(input).unwrap(); - let prop = file.entries.get("pos").unwrap(); - if let PropertyValueEnum::Vector3(v) = &prop.1 { - assert_eq!(v.x, 1.0); - assert_eq!(v.y, 2.5); - assert_eq!(v.z, -3.0); - } else { - panic!("Expected Vector3"); - } - } - - #[test] - fn test_parse_embed() { - let input = r#" -data: embed = TestClass { - name: string = "test" - value: u32 = 42 -} -"#; - let file = parse(input).unwrap(); - let prop = file.entries.get("data").unwrap(); - if let PropertyValueEnum::Embedded(values::Embedded(s)) = &prop.1 { - assert_eq!(s.class_hash, hash_lower("TestClass")); - assert_eq!(s.properties.len(), 2); - } else { - panic!("Expected Embedded"); - } - } - - #[test] - fn test_error_reporting() { - let input = r#" -test: unknowntype = 42 -"#; - let err = parse(input).unwrap_err(); - // The error should be an UnknownType with span info - match err { - ParseError::UnknownType { - type_name, span, .. - } => { - assert_eq!(type_name, "unknowntype"); - // Span should point to "unknowntype" - assert!(span.offset() > 0); - } - _ => panic!("Expected UnknownType error, got: {:?}", err), - } - } -} diff --git a/crates/ltk_ritobin/src/parser/real.rs b/crates/ltk_ritobin/src/parser/real.rs deleted file mode 100644 index b86a8e51..00000000 --- a/crates/ltk_ritobin/src/parser/real.rs +++ /dev/null @@ -1,731 +0,0 @@ -use std::{ - cell::Cell, - fmt::{self, Display}, - sync::{Arc, Mutex}, -}; - -use super::tokenizer::{lex, Token, TokenKind}; - -#[salsa::db] -#[derive(Clone)] -#[cfg_attr(not(test), derive(Default))] -pub struct CalcDatabaseImpl { - storage: salsa::Storage, - - // The logs are only used for testing and demonstrating reuse: - #[cfg(test)] - logs: Arc>>>, -} - -#[cfg(test)] -impl Default for CalcDatabaseImpl { - fn default() -> Self { - let logs = >>>>::default(); - Self { - storage: salsa::Storage::new(Some(Box::new({ - let logs = logs.clone(); - move |event| { - eprintln!("Event: {event:?}"); - // Log interesting events, if logging is enabled - if let Some(logs) = &mut *logs.lock().unwrap() { - // only log interesting events - if let salsa::EventKind::WillExecute { .. } = event.kind { - logs.push(format!("Event: {event:?}")); - } - } - } - }))), - logs, - } - } -} - -#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub enum Visit { - Stop, - /// Skip the current tree - Skip, - Continue, -} -#[allow(unused_variables)] -pub trait Visitor { - #[must_use] - fn enter_tree(&mut self, tree: &Tree) -> Visit { - Visit::Continue - } - #[must_use] - fn exit_tree(&mut self, tree: &Tree) -> Visit { - Visit::Continue - } - #[must_use] - fn visit_token(&mut self, token: &Token, context: &Tree) -> Visit { - Visit::Continue - } -} - -#[derive(Clone, Copy, PartialEq, Eq, Debug)] -#[rustfmt::skip] -pub enum TreeKind { - ErrorTree, - File, - TypeExpr, TypeArgList, TypeArg, - Block, BlockKey, Class, ListItem, - - Entry, EntryKey, EntryValue, EntryTerminator, - Literal, -} -impl Display for TreeKind { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.write_str(match self { - TreeKind::ErrorTree => "error tree", - TreeKind::File => "file", - TreeKind::TypeExpr => "bin entry type", - TreeKind::TypeArgList => "type argument list", - TreeKind::TypeArg => "type argument", - TreeKind::Block => "block", - TreeKind::Entry => "bin entry", - TreeKind::EntryKey => "key", - TreeKind::EntryValue => "value", - TreeKind::Literal => "literal", - TreeKind::EntryTerminator => "bin entry terminator (new line or ';')", - TreeKind::BlockKey => "key", - TreeKind::Class => "bin class", - TreeKind::ListItem => "list item", - }) - } -} - -#[derive(Clone, Debug)] -pub struct Tree { - pub span: crate::Span, - pub kind: TreeKind, - pub children: Vec, - pub errors: Vec, -} - -impl Tree { - pub fn walk(&self, visitor: &mut V) { - self.walk_inner(visitor); - } - - fn walk_inner(&self, visitor: &mut V) -> Visit { - let enter = visitor.enter_tree(self); - if matches!(enter, Visit::Stop | Visit::Skip) { - return enter; - } - - for child in &self.children { - match child { - Child::Token(token) => match visitor.visit_token(token, self) { - Visit::Continue => {} - Visit::Skip => break, - Visit::Stop => return Visit::Stop, - }, - Child::Tree(child_tree) => match child_tree.walk_inner(visitor) { - Visit::Continue => {} - Visit::Skip => { - break; - } - Visit::Stop => return Visit::Stop, - }, - } - } - - visitor.exit_tree(self) - } -} - -#[derive(Clone, Debug)] -pub enum Child { - Token(Token), - Tree(Tree), -} - -impl Child { - pub fn span(&self) -> crate::Span { - match self { - Child::Token(token) => token.span, - Child::Tree(tree) => tree.span, - } - } -} - -pub enum Event { - Open { - kind: TreeKind, - }, - Close, - Error { - kind: ErrorKind, - span: Option, - }, - Advance, -} - -pub struct MarkOpened { - index: usize, -} -pub struct MarkClosed { - index: usize, -} - -#[derive(Debug, Clone, Copy)] -pub enum ErrorKind { - Expected { - expected: TokenKind, - got: TokenKind, - }, - ExpectedAny { - expected: &'static [TokenKind], - got: TokenKind, - }, - UnterminatedString, - Unexpected { - token: TokenKind, - }, - /// When the entire tree we're in is unexpected - UnexpectedTree, - Custom(&'static str), -} - -#[derive(Debug, Clone, Copy)] -pub struct ParseError { - pub span: crate::Span, - pub tree: TreeKind, - pub kind: ErrorKind, -} - -pub struct Parser { - pub tokens: Vec, - pos: usize, - fuel: Cell, - pub events: Vec, -} - -impl Parser { - pub fn new(tokens: Vec) -> Parser { - Parser { - tokens, - pos: 0, - fuel: Cell::new(256), - events: Vec::new(), - } - } - - pub fn build_tree(self) -> Tree { - let last_token = self.tokens.last().copied(); - - let mut tokens = self.tokens.into_iter().peekable(); - let mut events = self.events; - - assert!(matches!(events.pop(), Some(Event::Close))); - let mut stack = Vec::new(); - let mut last_span = crate::Span::default(); - let mut just_opened = false; - for event in events { - match event { - Event::Open { kind } => { - just_opened = true; - stack.push(Tree { - span: crate::Span::new(last_span.end, 0), - kind, - children: Vec::new(), - errors: Vec::new(), - }) - } - Event::Close => { - let mut tree = stack.pop().unwrap(); - let last = stack.last_mut().unwrap(); - if tree.span.end == 0 { - // empty trees - tree.span.end = tree.span.start; - } - last.span.end = tree.span.end.max(last.span.end); // update our parent tree's span - last.children.push(Child::Tree(tree)); - } - Event::Advance => { - let token = tokens.next().unwrap(); - let last = stack.last_mut().unwrap(); - - if just_opened { - // first token of the tree - last.span.start = token.span.start; - } - just_opened = false; - - last.span.end = token.span.end; - last_span = token.span; - last.children.push(Child::Token(token)); - } - Event::Error { kind, span } => { - let cur_tree = stack.last_mut().unwrap(); - let span = match kind { - // these errors are talking about what they wanted next - ErrorKind::Expected { .. } | ErrorKind::Unexpected { .. } => { - let mut span = tokens.peek().map(|t| t.span).unwrap_or(last_span); - // so we point at the character just after our token - span.end += 1; - span.start = span.end - 1; - span - } - // whole tree is the problem - ErrorKind::UnexpectedTree => cur_tree.span, - _ => span - .or(cur_tree.children.last().map(|c| c.span())) - // we can't use Tree.span.end because that's only known on Close - .unwrap_or(crate::Span::new( - cur_tree.span.start, - last_token - .as_ref() - .map(|t| t.span.end) - .unwrap_or(cur_tree.span.start), - )), - }; - cur_tree.errors.push(ParseError { - span, - tree: cur_tree.kind, - kind, - }); - } - } - } - - let tree = stack.pop().unwrap(); - assert!(stack.is_empty()); - assert!(tokens.next().is_none()); - tree - } - - fn open(&mut self) -> MarkOpened { - let mark = MarkOpened { - index: self.events.len(), - }; - self.events.push(Event::Open { - kind: TreeKind::ErrorTree, - }); - mark - } - - fn scope(&mut self, kind: TreeKind, mut f: F) -> MarkClosed - where - F: FnMut(&mut Self) -> R, - { - let m = MarkOpened { - index: self.events.len(), - }; - self.events.push(Event::Open { - kind: TreeKind::ErrorTree, - }); - let _ = f(self); - self.events[m.index] = Event::Open { kind }; - self.events.push(Event::Close); - MarkClosed { index: m.index } - } - - fn open_before(&mut self, m: MarkClosed) -> MarkOpened { - let mark = MarkOpened { index: m.index }; - self.events.insert( - m.index, - Event::Open { - kind: TreeKind::ErrorTree, - }, - ); - mark - } - - fn close(&mut self, m: MarkOpened, kind: TreeKind) -> MarkClosed { - self.events[m.index] = Event::Open { kind }; - self.events.push(Event::Close); - MarkClosed { index: m.index } - } - - fn advance(&mut self) { - assert!(!self.eof()); - self.events.push(Event::Advance); - self.pos += 1; - } - - fn report(&mut self, kind: ErrorKind) { - self.events.push(Event::Error { kind, span: None }); - } - - fn advance_with_error(&mut self, kind: ErrorKind, span: Option) { - let m = self.open(); - self.advance(); - self.events.push(Event::Error { kind, span }); - self.close(m, TreeKind::ErrorTree); - } - - fn eof(&self) -> bool { - self.pos == self.tokens.len() - } - - fn nth(&self, lookahead: usize) -> TokenKind { - if self.fuel.get() == 0 { - panic!("parser is stuck") - } - self.fuel.set(self.fuel.get() - 1); - self.tokens - .get(self.pos + lookahead) - .map_or(TokenKind::Eof, |it| it.kind) - } - - fn at(&self, kind: TokenKind) -> bool { - self.nth(0) == kind - } - - fn at_any(&self, kinds: &[TokenKind]) -> bool { - kinds.contains(&self.nth(0)) - } - - fn eat_any(&mut self, kinds: &[TokenKind]) -> bool { - if self.at_any(kinds) { - self.advance(); - true - } else { - false - } - } - - fn eat(&mut self, kind: TokenKind) -> bool { - if self.at(kind) { - self.advance(); - true - } else { - false - } - } - - fn expect_any(&mut self, kinds: &'static [TokenKind]) -> bool { - if self.eat_any(kinds) { - return true; - } - self.report(ErrorKind::ExpectedAny { - expected: kinds, - got: self.nth(0), - }); - false - } - - fn expect(&mut self, kind: TokenKind) -> bool { - if self.eat(kind) { - return true; - } - self.report(ErrorKind::Expected { - expected: kind, - got: self.nth(0), - }); - false - } - - fn expect_fallable(&mut self, kind: TokenKind) -> Result<(), ()> { - match self.expect(kind) { - true => Ok(()), - false => Err(()), - } - } -} - -pub fn parse(text: &str) -> Tree { - let tokens = lex(text); - eprintln!("tokens: {tokens:#?}"); - let mut p = Parser::new(tokens); - file(&mut p); - p.build_tree() -} - -pub fn file(p: &mut Parser) { - let m = p.open(); - while !p.eof() { - stmt_entry(p) - } - p.close(m, TreeKind::File); -} -pub fn stmt_entry(p: &mut Parser) { - p.scope(TreeKind::Entry, |p| { - p.scope(TreeKind::EntryKey, |p| { - p.expect_any(&[TokenKind::Name, TokenKind::String]) - }); - if p.eat(TokenKind::Colon) { - p.scope(TreeKind::TypeExpr, type_expr); - } - p.expect(TokenKind::Eq); - p.scope(TreeKind::EntryValue, |p| match p.nth(0) { - TokenKind::String => { - p.advance(); - } - TokenKind::UnterminatedString => { - p.advance_with_error(ErrorKind::UnterminatedString, None); - } - TokenKind::Int | TokenKind::Minus => { - let m = p.open(); - p.advance(); - p.close(m, TreeKind::Literal); - } - TokenKind::Name => { - p.scope(TreeKind::Class, |p| { - p.advance(); - block(p); - }); - } - TokenKind::LCurly => { - block(p); - } - token @ TokenKind::Eof => p.report(ErrorKind::Unexpected { token }), - token => p.advance_with_error(ErrorKind::Unexpected { token }, None), - }); - p.scope(TreeKind::EntryTerminator, |p| { - let mut one = false; - if p.eof() { - return; - } - while p.eat_any(&[TokenKind::SemiColon, TokenKind::Newline]) { - one = true; - } - - if !one { - // if something was between us and our statement terminator, - // we eat it all and then try again - p.scope(TreeKind::ErrorTree, |p| { - while !matches!( - p.nth(0), - TokenKind::SemiColon | TokenKind::Newline | TokenKind::Eof - ) { - p.advance(); - } - p.report(ErrorKind::UnexpectedTree); - }); - while p.eat_any(&[TokenKind::SemiColon, TokenKind::Newline]) {} - } - }); - }); -} - -pub fn type_expr(p: &mut Parser) { - p.expect(TokenKind::Name); - if p.eat(TokenKind::LBrack) { - p.scope(TreeKind::TypeArgList, |p| { - while !p.at(TokenKind::RBrack) && !p.eof() { - if p.at(TokenKind::Name) { - expr_type_arg(p); - } else { - break; - } - } - }); - p.expect(TokenKind::RBrack); - } -} - -pub fn expr_type_arg(p: &mut Parser) -> MarkClosed { - use TokenKind::*; - assert!(p.at(Name)); - let m = p.open(); - - p.expect(Name); - if !p.at(RBrack) { - p.expect(Comma); - } - - p.close(m, TreeKind::TypeArg) -} - -pub fn block(p: &mut Parser) { - use TokenKind::*; - assert!(p.at(LCurly)); - let m = p.open(); - p.expect(LCurly); - while !p.at(RCurly) && !p.eof() { - match (p.nth(0), p.nth(1)) { - (Name, Eq) | (String, Eq) | (Name, Colon) | (String, Colon) => stmt_entry(p), - _ => list_item(p), - } - } - p.expect(RCurly); - - p.close(m, TreeKind::Block); -} - -pub fn list_item(p: &mut Parser) { - use TokenKind::*; - let m = p.open(); - - p.advance(); // list item - while p.eat(Newline) {} - p.close(m, TreeKind::ListItem); -} - -#[cfg(test)] -mod test { - use super::*; - #[test] - fn smoke_test() { - let text = r#" -type = 4 a -version: u32 = 5 - -"#; - let cst = parse(text); - let errors = FlatErrors::walk(&cst); - - let mut str = String::new(); - cst.print(&mut str, 0, text); - eprintln!("{str}\n====== errors: ======\n"); - for err in errors { - eprintln!("{:?}: {:#?}", &text[err.span], err.kind); - } - } -} - -#[derive(Default)] -pub struct FlatErrors { - errors: Vec, -} - -impl FlatErrors { - pub fn new() -> Self { - Self::default() - } - pub fn into_errors(self) -> Vec { - self.errors - } - - pub fn walk(tree: &Tree) -> Vec { - let mut errors = Self::new(); - tree.walk(&mut errors); - errors.into_errors() - } -} - -impl Visitor for FlatErrors { - fn exit_tree(&mut self, tree: &Tree) -> Visit { - self.errors.extend_from_slice(&tree.errors); - Visit::Continue - } -} - -#[macro_export] -macro_rules! format_to { - ($buf:expr) => (); - ($buf:expr, $lit:literal $($arg:tt)*) => { - { use ::std::fmt::Write as _; let _ = ::std::write!($buf, $lit $($arg)*); } - }; -} -impl Tree { - fn print(&self, buf: &mut String, level: usize, source: &str) { - let parent_indent = "│ ".repeat(level.saturating_sub(1)); - let indent = match level > 0 { - true => "├ ", - false => "", - }; - let safe_span = match self.span.end >= self.span.start { - true => &source[self.span], - false => "!!!!!!", - }; - format_to!( - buf, - "{parent_indent}{indent}{:?} - ({}..{}): {:?}\n", - self.kind, - self.span.start, - self.span.end, - safe_span - ); - for (i, child) in self.children.iter().enumerate() { - let bar = match i + 1 == self.children.len() { - true => '└', - false => '├', - }; - match child { - Child::Token(token) => { - format_to!( - buf, - "{parent_indent}│ {bar} {:?}\n", - &source[token.span.start as _..token.span.end as _] - ) - } - Child::Tree(tree) => tree.print(buf, level + 1, source), - } - } - assert!(buf.ends_with('\n')); - } -} - -#[salsa::db] -impl salsa::Database for CalcDatabaseImpl {} - -#[salsa::input(debug)] -pub struct SourceProgram { - #[returns(ref)] - pub text: String, -} - -#[salsa::tracked(debug)] -pub struct RitobinFile<'db> { - #[tracked] - #[returns(ref)] - pub statements: Vec>, -} - -#[salsa::interned(debug)] -pub struct PropertyName<'db> { - #[returns(ref)] - pub text: String, -} - -#[derive(PartialEq, Debug, Hash, salsa::Update)] -pub struct Statement<'db> { - pub span: Span<'db>, - pub name: PropertyName<'db>, - pub value: BinProperty, -} - -#[salsa::accumulator] -#[derive(Debug)] -#[allow(dead_code)] // Debug impl uses them -pub struct Diagnostic { - pub start: usize, - pub end: usize, - pub message: String, -} -impl Diagnostic { - pub fn new(start: usize, end: usize, message: String) -> Self { - Diagnostic { - start, - end, - message, - } - } - - // #[cfg(test)] - // pub fn render(&self, db: &dyn crate::Db, src: SourceProgram) -> String { - // use annotate_snippets::*; - // let line_start = src.text(db)[..self.start].lines().count() + 1; - // Renderer::plain() - // .render( - // Level::Error.title(&self.message).snippet( - // Snippet::source(src.text(db)) - // .line_start(line_start) - // .origin("input") - // .fold(true) - // .annotation(Level::Error.span(self.start..self.end).label("here")), - // ), - // ) - // .to_string() - // } -} - -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] -#[derive(Clone, PartialEq, Debug, Hash, salsa::Update)] -pub struct BinProperty { - pub name_hash: u32, - #[cfg_attr(feature = "serde", serde(flatten))] - pub value: ltk_meta::PropertyValueEnum, -} - -#[salsa::tracked(debug)] -pub struct Span<'db> { - #[tracked] - pub start: usize, - #[tracked] - pub end: usize, -} From 8fd65cc8f826d8d4a350a842e471ece8c44d766e Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Sat, 10 Jan 2026 18:58:03 +0000 Subject: [PATCH 048/187] fix: tweak parser --- crates/ltk_ritobin/src/parse/impls.rs | 149 +++++++++++++--------- crates/ltk_ritobin/src/parse/parser.rs | 51 ++++---- crates/ltk_ritobin/src/parse/tokenizer.rs | 6 +- 3 files changed, 121 insertions(+), 85 deletions(-) diff --git a/crates/ltk_ritobin/src/parse/impls.rs b/crates/ltk_ritobin/src/parse/impls.rs index 5ed19378..ebd5006d 100644 --- a/crates/ltk_ritobin/src/parse/impls.rs +++ b/crates/ltk_ritobin/src/parse/impls.rs @@ -5,21 +5,76 @@ use TokenKind::*; pub fn file(p: &mut Parser) { let m = p.open(); while !p.eof() { - stmt_entry(p) + stmt_or_list_item(p) } p.close(m, TreeKind::File); } -pub fn stmt_entry(p: &mut Parser) { - p.scope(TreeKind::Entry, |p| { - p.scope(TreeKind::EntryKey, |p| { - p.expect_any(&[TokenKind::Name, TokenKind::String]) - }); - if p.eat(TokenKind::Colon) { - p.scope(TreeKind::TypeExpr, type_expr); +pub fn stmt_or_list_item(p: &mut Parser) { + let m = p.open(); + + // obvious list item literals + if p.eat_any(&[TokenKind::HexLit]) { + p.advance(); // list item + while p.eat(Newline) {} + p.close(m, TreeKind::ListItem); + return; + } + + p.scope(TreeKind::EntryKey, |p| { + p.expect_any(&[TokenKind::Name, TokenKind::String]) + }); + match p.nth(0) { + TokenKind::Colon => { + p.advance(); + type_expr(p); + p.expect(TokenKind::Eq); } - p.expect(TokenKind::Eq); - p.scope(TreeKind::EntryValue, |p| match p.nth(0) { + TokenKind::Eq => { + p.advance(); + } + _ => { + p.advance(); // list item + while p.eat(Newline) {} + p.close(m, TreeKind::ListItem); + return; + } + } + + if !entry_value(p) { + p.close(m, TreeKind::Entry); + return; + } + p.scope(TreeKind::EntryTerminator, |p| { + let mut one = false; + if p.eof() { + return; + } + while p.eat_any(&[TokenKind::SemiColon, TokenKind::Newline]) { + one = true; + } + + if !one { + // if something was between us and our statement terminator, + // we eat it all and then try again + p.scope(TreeKind::ErrorTree, |p| { + while !matches!( + p.nth(0), + TokenKind::SemiColon | TokenKind::Newline | TokenKind::Eof + ) { + p.advance(); + } + p.report(ErrorKind::UnexpectedTree); + }); + while p.eat_any(&[TokenKind::SemiColon, TokenKind::Newline]) {} + } + }); + p.close(m, TreeKind::Entry); +} + +pub fn entry_value(p: &mut Parser) -> bool { + p.scope(TreeKind::EntryValue, |p| { + match p.nth(0) { TokenKind::String => { p.advance(); } @@ -40,50 +95,35 @@ pub fn stmt_entry(p: &mut Parser) { TokenKind::LCurly => { block(p); } + TokenKind::Newline => { + p.advance_with_error(ErrorKind::Unexpected { token: Newline }, None); + while p.eat(Newline) {} + return false; + } token @ TokenKind::Eof => p.report(ErrorKind::Unexpected { token }), token => p.advance_with_error(ErrorKind::Unexpected { token }, None), - }); - p.scope(TreeKind::EntryTerminator, |p| { - let mut one = false; - if p.eof() { - return; - } - while p.eat_any(&[TokenKind::SemiColon, TokenKind::Newline]) { - one = true; - } - - if !one { - // if something was between us and our statement terminator, - // we eat it all and then try again - p.scope(TreeKind::ErrorTree, |p| { - while !matches!( - p.nth(0), - TokenKind::SemiColon | TokenKind::Newline | TokenKind::Eof - ) { - p.advance(); - } - p.report(ErrorKind::UnexpectedTree); - }); - while p.eat_any(&[TokenKind::SemiColon, TokenKind::Newline]) {} - } - }); - }); + } + true + }) + .0 } pub fn type_expr(p: &mut Parser) { - p.expect(TokenKind::Name); - if p.eat(TokenKind::LBrack) { - p.scope(TreeKind::TypeArgList, |p| { - while !p.at(TokenKind::RBrack) && !p.eof() { - if p.at(TokenKind::Name) { - expr_type_arg(p); - } else { - break; + p.scope(TreeKind::TypeExpr, |p| { + p.expect(TokenKind::Name); + if p.eat(TokenKind::LBrack) { + p.scope(TreeKind::TypeArgList, |p| { + while !p.at(TokenKind::RBrack) && !p.eof() { + if p.at(TokenKind::Name) { + expr_type_arg(p); + } else { + break; + } } - } - }); - p.expect(TokenKind::RBrack); - } + }); + p.expect(TokenKind::RBrack); + } + }); } pub fn expr_type_arg(p: &mut Parser) { @@ -103,20 +143,9 @@ pub fn block(p: &mut Parser) { let m = p.open(); p.expect(LCurly); while !p.at(RCurly) && !p.eof() { - match (p.nth(0), p.nth(1)) { - (Name, Eq) | (String, Eq) | (Name, Colon) | (String, Colon) => stmt_entry(p), - _ => list_item(p), - } + stmt_or_list_item(p); } p.expect(RCurly); p.close(m, TreeKind::Block); } - -pub fn list_item(p: &mut Parser) { - let m = p.open(); - - p.advance(); // list item - while p.eat(Newline) {} - p.close(m, TreeKind::ListItem); -} diff --git a/crates/ltk_ritobin/src/parse/parser.rs b/crates/ltk_ritobin/src/parse/parser.rs index 92861be5..920bb663 100644 --- a/crates/ltk_ritobin/src/parse/parser.rs +++ b/crates/ltk_ritobin/src/parse/parser.rs @@ -85,27 +85,30 @@ impl Parser { } Event::Error { kind, span } => { let cur_tree = stack.last_mut().unwrap(); - let span = match kind { - // these errors are talking about what they wanted next - ErrorKind::Expected { .. } | ErrorKind::Unexpected { .. } => { - let mut span = tokens.peek().map(|t| t.span).unwrap_or(last_span); - // so we point at the character just after our token - span.end += 1; - span.start = span.end - 1; - span - } - // whole tree is the problem - ErrorKind::UnexpectedTree => cur_tree.span, - _ => span - .or(cur_tree.children.last().map(|c| c.span())) - // we can't use Tree.span.end because that's only known on Close - .unwrap_or(Span::new( - cur_tree.span.start, - last_token - .as_ref() - .map(|t| t.span.end) - .unwrap_or(cur_tree.span.start), - )), + let span = match cur_tree.kind { + TreeKind::ErrorTree => cur_tree.span, + _ => match kind { + // these errors are talking about what they wanted next + ErrorKind::Expected { .. } | ErrorKind::Unexpected { .. } => { + let mut span = tokens.peek().map(|t| t.span).unwrap_or(last_span); + // so we point at the character just after our token + span.end += 1; + span.start = span.end - 1; + span + } + // whole tree is the problem + ErrorKind::UnexpectedTree => cur_tree.span, + _ => span + .or(cur_tree.children.last().map(|c| c.span())) + // we can't use Tree.span.end because that's only known on Close + .unwrap_or(Span::new( + cur_tree.span.start, + last_token + .as_ref() + .map(|t| t.span.end) + .unwrap_or(cur_tree.span.start), + )), + }, }; cur_tree.errors.push(Error { span, @@ -132,7 +135,7 @@ impl Parser { mark } - pub(crate) fn scope(&mut self, kind: TreeKind, mut f: F) -> MarkClosed + pub(crate) fn scope(&mut self, kind: TreeKind, mut f: F) -> (R, MarkClosed) where F: FnMut(&mut Self) -> R, { @@ -142,10 +145,10 @@ impl Parser { self.events.push(Event::Open { kind: TreeKind::ErrorTree, }); - let _ = f(self); + let ret = f(self); self.events[m.index] = Event::Open { kind }; self.events.push(Event::Close); - MarkClosed { index: m.index } + (ret, MarkClosed { index: m.index }) } pub(crate) fn open_before(&mut self, m: MarkClosed) -> MarkOpened { diff --git a/crates/ltk_ritobin/src/parse/tokenizer.rs b/crates/ltk_ritobin/src/parse/tokenizer.rs index e5664063..5ba3384b 100644 --- a/crates/ltk_ritobin/src/parse/tokenizer.rs +++ b/crates/ltk_ritobin/src/parse/tokenizer.rs @@ -85,7 +85,11 @@ pub fn lex(mut text: &str) -> Vec { if let Some(last_token) = result.last() { if matches!( last_token.kind, - TokenKind::Name | TokenKind::Int | TokenKind::RCurly | TokenKind::String + TokenKind::Name + | TokenKind::Int + | TokenKind::RCurly + | TokenKind::String + | TokenKind::Eq ) && eaten.find(['\n', '\r']).is_some() { let start = source.len() - text.len(); From ae46c497f841acf3152566fd0828ecaa9b3c258c Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Sat, 10 Jan 2026 19:01:54 +0000 Subject: [PATCH 049/187] fix: string literal lexing --- crates/ltk_ritobin/src/parse/tokenizer.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/crates/ltk_ritobin/src/parse/tokenizer.rs b/crates/ltk_ritobin/src/parse/tokenizer.rs index 5ba3384b..b4f678e9 100644 --- a/crates/ltk_ritobin/src/parse/tokenizer.rs +++ b/crates/ltk_ritobin/src/parse/tokenizer.rs @@ -128,6 +128,10 @@ pub fn lex(mut text: &str) -> Vec { } if let Some(rest) = text.strip_prefix(['\'', '"']) { + let eaten = &source[source.len() - text.len()..source.len() - rest.len()] + .chars() + .next() + .unwrap(); text = rest; let mut skip = false; loop { @@ -140,7 +144,7 @@ pub fn lex(mut text: &str) -> Vec { '\\' => { skip = true; } - '\'' | '"' => match skip { + c if c == *eaten => match skip { true => { skip = false; } @@ -149,7 +153,9 @@ pub fn lex(mut text: &str) -> Vec { } }, '\n' | '\r' => break 'kind UnterminatedString, - _ => {} + _ => { + skip = false; + } } } } From b80d516996105ec3fa3dd8b052b5bc75568d84a4 Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Sat, 10 Jan 2026 19:02:18 +0000 Subject: [PATCH 050/187] fix: disable some tests for now --- crates/ltk_ritobin/tests/parse_sample.rs | 198 ++++++++++++++++++++++- 1 file changed, 197 insertions(+), 1 deletion(-) diff --git a/crates/ltk_ritobin/tests/parse_sample.rs b/crates/ltk_ritobin/tests/parse_sample.rs index d10d0ba7..92a9d28a 100644 --- a/crates/ltk_ritobin/tests/parse_sample.rs +++ b/crates/ltk_ritobin/tests/parse_sample.rs @@ -1,6 +1,6 @@ //! Integration test for parsing a sample ritobin file. -use ltk_ritobin::{parse, write, ParseError}; +// use ltk_ritobin::{parse, write, ParseError}; const SAMPLE_RITOBIN: &str = r#"#PROP_text type: string = "PROP" @@ -310,3 +310,199 @@ fn test_error_is_miette_diagnostic() { let _labels = err.labels(); let _source = err.source_code(); } +// #[test] +// fn test_parse_sample() { +// let file = parse(SAMPLE_RITOBIN).expect("Failed to parse sample"); +// +// // Verify basic fields +// assert_eq!(file.file_type(), Some("PROP")); +// assert_eq!(file.version(), Some(3)); +// +// // Verify dependencies +// let linked = file.linked(); +// assert_eq!(linked.len(), 2); +// assert!(linked[0].contains("Animations")); +// +// // Verify objects +// let objects = file.objects(); +// assert_eq!(objects.len(), 1); +// +// // Convert to BinTree +// let tree = file.to_bin_tree(); +// assert_eq!(tree.version, 3); +// assert_eq!(tree.dependencies.len(), 2); +// assert_eq!(tree.objects.len(), 1); +// } +// +// #[test] +// fn test_roundtrip() { +// let file = parse(SAMPLE_RITOBIN).expect("Failed to parse sample"); +// let tree = file.to_bin_tree(); +// +// // Write back to text +// let output = write(&tree).expect("Failed to write"); +// +// // Parse again +// let file2 = parse(&output).expect("Failed to parse output"); +// let tree2 = file2.to_bin_tree(); +// +// // Verify structure is preserved +// assert_eq!(tree.version, tree2.version); +// assert_eq!(tree.dependencies.len(), tree2.dependencies.len()); +// assert_eq!(tree.objects.len(), tree2.objects.len()); +// } +// +// #[test] +// fn test_parse_primitives() { +// let input = r#" +// test_bool: bool = true +// test_i8: i8 = -128 +// test_u8: u8 = 255 +// test_i16: i16 = -32768 +// test_u16: u16 = 65535 +// test_i32: i32 = -2147483648 +// test_u32: u32 = 4294967295 +// test_f32: f32 = 3.14159 +// test_vec2: vec2 = { 1.0, 2.0 } +// test_vec3: vec3 = { 1.0, 2.0, 3.0 } +// test_vec4: vec4 = { 1.0, 2.0, 3.0, 4.0 } +// test_rgba: rgba = { 255, 128, 64, 255 } +// test_string: string = "Hello, World!" +// test_hash: hash = 0xdeadbeef +// test_link: link = "path/to/object" +// test_flag: flag = false +// "#; +// +// let file = parse(input).expect("Failed to parse primitives"); +// assert!(file.entries.contains_key("test_bool")); +// assert!(file.entries.contains_key("test_f32")); +// assert!(file.entries.contains_key("test_vec3")); +// assert!(file.entries.contains_key("test_rgba")); +// assert!(file.entries.contains_key("test_string")); +// } +// +// #[test] +// fn test_parse_containers() { +// let input = r#" +// test_list: list[string] = { +// "item1" +// "item2" +// "item3" +// } +// test_list2: list2[u32] = { +// 1 +// 2 +// 3 +// } +// test_option_some: option[string] = { +// "value" +// } +// test_option_none: option[string] = {} +// test_map: map[hash,string] = { +// 0x12345678 = "value1" +// 0xdeadbeef = "value2" +// } +// "#; +// +// let file = parse(input).expect("Failed to parse containers"); +// assert!(file.entries.contains_key("test_list")); +// assert!(file.entries.contains_key("test_list2")); +// assert!(file.entries.contains_key("test_option_some")); +// assert!(file.entries.contains_key("test_option_none")); +// assert!(file.entries.contains_key("test_map")); +// } +// +// #[test] +// fn test_parse_nested_embeds() { +// let input = r#" +// data: embed = OuterClass { +// name: string = "outer" +// inner: embed = InnerClass { +// value: u32 = 42 +// nested: embed = DeepClass { +// deep_value: f32 = 1.5 +// } +// } +// } +// "#; +// +// let file = parse(input).expect("Failed to parse nested embeds"); +// assert!(file.entries.contains_key("data")); +// } +// +// #[test] +// fn test_parse_pointer_null() { +// let input = r#" +// null_ptr: pointer = null +// "#; +// +// let file = parse(input).expect("Failed to parse null pointer"); +// assert!(file.entries.contains_key("null_ptr")); +// } +// +// #[test] +// fn test_parse_hex_property_names() { +// let input = r#" +// entries: map[hash,embed] = { +// "Test/Path" = TestClass { +// 0xcb13aff1: f32 = -40 +// normalName: string = "test" +// } +// } +// "#; +// +// let file = parse(input).expect("Failed to parse hex property names"); +// assert!(file.entries.contains_key("entries")); +// } +// +// #[test] +// fn test_error_span_unknown_type() { +// let input = "test: badtype = 42"; +// let err = parse(input).unwrap_err(); +// +// // Verify we get an UnknownType error with correct span +// match err { +// ParseError::UnknownType { +// type_name, span, .. +// } => { +// assert_eq!(type_name, "badtype"); +// // "badtype" starts at position 6 (after "test: ") +// assert_eq!(span.offset(), 6); +// assert_eq!(span.len(), 7); // "badtype" is 7 chars +// } +// _ => panic!("Expected UnknownType error, got: {:?}", err), +// } +// } +// +// #[test] +// fn test_error_span_multiline() { +// let input = r#" +// valid: string = "hello" +// broken: unknowntype = 123 +// "#; +// let err = parse(input).unwrap_err(); +// +// match err { +// ParseError::UnknownType { +// type_name, span, .. +// } => { +// assert_eq!(type_name, "unknowntype"); +// // The span offset should point into the second line +// assert!(span.offset() > 20); // After first line +// } +// _ => panic!("Expected UnknownType error, got: {:?}", err), +// } +// } +// +// #[test] +// fn test_error_is_miette_diagnostic() { +// use miette::Diagnostic; +// +// let input = "test: badtype = 42"; +// let err = parse(input).unwrap_err(); +// +// // ParseError implements Diagnostic +// let _code = err.code(); +// let _labels = err.labels(); +// let _source = err.source_code(); +// } From a3ab4039f10ac86bb9d13fc3cf4898d0fd04a63c Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Sat, 10 Jan 2026 20:02:40 +0000 Subject: [PATCH 051/187] feat: comments + numbers --- crates/ltk_ritobin/src/parse/cst/tree.rs | 3 ++ crates/ltk_ritobin/src/parse/impls.rs | 7 ++- crates/ltk_ritobin/src/parse/tokenizer.rs | 59 +++++++++++++++++++++-- 3 files changed, 62 insertions(+), 7 deletions(-) diff --git a/crates/ltk_ritobin/src/parse/cst/tree.rs b/crates/ltk_ritobin/src/parse/cst/tree.rs index 4d15727e..dbbddf15 100644 --- a/crates/ltk_ritobin/src/parse/cst/tree.rs +++ b/crates/ltk_ritobin/src/parse/cst/tree.rs @@ -12,6 +12,8 @@ pub enum Kind { Entry, EntryKey, EntryValue, EntryTerminator, Literal, + + Comment, } impl Display for Kind { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { @@ -30,6 +32,7 @@ impl Display for Kind { Self::BlockKey => "key", Self::Class => "bin class", Self::ListItem => "list item", + Self::Comment => "comment", }) } } diff --git a/crates/ltk_ritobin/src/parse/impls.rs b/crates/ltk_ritobin/src/parse/impls.rs index ebd5006d..28c96143 100644 --- a/crates/ltk_ritobin/src/parse/impls.rs +++ b/crates/ltk_ritobin/src/parse/impls.rs @@ -5,6 +5,9 @@ use TokenKind::*; pub fn file(p: &mut Parser) { let m = p.open(); while !p.eof() { + if p.at(Comment) { + p.scope(TreeKind::Comment, |p| p.advance()); + } stmt_or_list_item(p) } p.close(m, TreeKind::File); @@ -14,7 +17,7 @@ pub fn stmt_or_list_item(p: &mut Parser) { let m = p.open(); // obvious list item literals - if p.eat_any(&[TokenKind::HexLit]) { + if p.eat_any(&[TokenKind::HexLit, TokenKind::Number]) { p.advance(); // list item while p.eat(Newline) {} p.close(m, TreeKind::ListItem); @@ -81,7 +84,7 @@ pub fn entry_value(p: &mut Parser) -> bool { TokenKind::UnterminatedString => { p.advance_with_error(ErrorKind::UnterminatedString, None); } - TokenKind::Int | TokenKind::Minus => { + Number | Minus | HexLit | True | False => { let m = p.open(); p.advance(); p.close(m, TreeKind::Literal); diff --git a/crates/ltk_ritobin/src/parse/tokenizer.rs b/crates/ltk_ritobin/src/parse/tokenizer.rs index b4f678e9..0e955e86 100644 --- a/crates/ltk_ritobin/src/parse/tokenizer.rs +++ b/crates/ltk_ritobin/src/parse/tokenizer.rs @@ -15,10 +15,11 @@ pub enum TokenKind { String, UnterminatedString, +Comment, True, False, - Name, Int, HexLit, + Name, Number, HexLit, } impl TokenKind { @@ -53,8 +54,9 @@ impl Display for TokenKind { TokenKind::True => "'true'", TokenKind::False => "'false'", TokenKind::Name => "keyword", - TokenKind::Int => "number", + TokenKind::Number => "number", TokenKind::HexLit => "hexadecimal literal", + TokenKind::Comment => "comment", }) } } @@ -86,7 +88,10 @@ pub fn lex(mut text: &str) -> Vec { if matches!( last_token.kind, TokenKind::Name - | TokenKind::Int + | TokenKind::HexLit + | TokenKind::True + | TokenKind::False + | TokenKind::Number | TokenKind::RCurly | TokenKind::String | TokenKind::Eq @@ -114,6 +119,14 @@ pub fn lex(mut text: &str) -> Vec { } } + if let Some(rest) = text.strip_prefix('#') { + text = rest; + if let Some(rest) = trim(text, |t| !matches!(t, '\n' | '\r')) { + text = rest; + } + break 'kind Comment; + } + if let Some(rest) = text.strip_prefix("0x") { text = rest; if let Some(rest) = trim(text, |it| matches!(it, 'a'..'f' | 'A'..'F' | '0'..='9')) { @@ -122,9 +135,9 @@ pub fn lex(mut text: &str) -> Vec { break 'kind HexLit; } - if let Some(rest) = trim(text, |it| it.is_ascii_digit()) { + if let Some(rest) = scan_number(text) { text = rest; - break 'kind Int; + break 'kind Number; } if let Some(rest) = text.strip_prefix(['\'', '"']) { @@ -204,4 +217,40 @@ pub fn lex(mut text: &str) -> Vec { Some(&text[index..]) } } + + fn scan_number(mut s: &str) -> Option<&str> { + if let Some(rest) = s.strip_prefix('-') { + s = rest; + } + + let rest = trim(s, |c| matches!(c, '0'..='9' | '_'))?; + let int_part = &s[..s.len() - rest.len()]; + + if int_part.is_empty() + || int_part.starts_with('_') + || int_part.ends_with('_') + || int_part.contains("__") + { + return None; + } + + s = rest; + + if let Some(after_dot) = s.strip_prefix('.') { + let rest = trim(after_dot, |c| matches!(c, '0'..='9' | '_'))?; + // let frac_part = &after_dot[..after_dot.len() - rest.len()]; + // + // if frac_part.is_empty() + // || frac_part.starts_with('_') + // || frac_part.ends_with('_') + // || frac_part.contains("__") + // { + // return None; + // } + + s = rest; + } + + Some(s) + } } From 6a58081a282b4d041f5f5a8f7a069b1e371209b0 Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Sat, 10 Jan 2026 20:03:00 +0000 Subject: [PATCH 052/187] fix: bring back fuel reset oops --- crates/ltk_ritobin/src/parse/parser.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/ltk_ritobin/src/parse/parser.rs b/crates/ltk_ritobin/src/parse/parser.rs index 920bb663..158b5d2e 100644 --- a/crates/ltk_ritobin/src/parse/parser.rs +++ b/crates/ltk_ritobin/src/parse/parser.rs @@ -170,6 +170,7 @@ impl Parser { pub(crate) fn advance(&mut self) { assert!(!self.eof()); + self.fuel.set(256); self.events.push(Event::Advance); self.pos += 1; } From 062eecbc8d4dd20b4d851228a82e0c0649a12678 Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Sat, 10 Jan 2026 21:35:24 +0000 Subject: [PATCH 053/187] feat: better parser --- crates/ltk_ritobin/src/parse/impls.rs | 96 +++++++++++++++----------- crates/ltk_ritobin/src/parse/parser.rs | 33 +++++---- 2 files changed, 77 insertions(+), 52 deletions(-) diff --git a/crates/ltk_ritobin/src/parse/impls.rs b/crates/ltk_ritobin/src/parse/impls.rs index 28c96143..fc137bcd 100644 --- a/crates/ltk_ritobin/src/parse/impls.rs +++ b/crates/ltk_ritobin/src/parse/impls.rs @@ -14,46 +14,59 @@ pub fn file(p: &mut Parser) { } pub fn stmt_or_list_item(p: &mut Parser) { - let m = p.open(); - - // obvious list item literals - if p.eat_any(&[TokenKind::HexLit, TokenKind::Number]) { - p.advance(); // list item - while p.eat(Newline) {} - p.close(m, TreeKind::ListItem); - return; - } - - p.scope(TreeKind::EntryKey, |p| { - p.expect_any(&[TokenKind::Name, TokenKind::String]) - }); - match p.nth(0) { - TokenKind::Colon => { - p.advance(); - type_expr(p); - p.expect(TokenKind::Eq); + match (p.nth(0), p.nth(1), p.nth(2)) { + (Name | String | HexLit, Colon | Eq, _) => { + stmt(p); } - TokenKind::Eq => { + (Name | HexLit, LCurly, _) => { + let m = p.open(); p.advance(); + block(p); + p.close(m, TreeKind::Class); } - _ => { - p.advance(); // list item - while p.eat(Newline) {} + (LCurly, _, _) => { + let m = p.open(); + block(p); p.close(m, TreeKind::ListItem); - return; + p.eat(Comma); + } + (Name | HexLit | String | Number | True | False, _, _) => { + let m = p.open(); + p.advance(); + p.close(m, TreeKind::ListItem); + p.eat(Comma); } + _ => stmt(p), + } + + while p.eat(Newline) {} +} + +pub fn stmt(p: &mut Parser) { + let m = p.open(); + + p.scope(TreeKind::EntryKey, |p| { + p.expect_any(&[Name, String, HexLit]) + }); + if p.eat_any(&[Colon, Eq, Newline]) == Some(Colon) { + type_expr(p); + p.expect(TokenKind::Eq); } if !entry_value(p) { p.close(m, TreeKind::Entry); return; } + p.scope(TreeKind::EntryTerminator, |p| { let mut one = false; if p.eof() { return; } - while p.eat_any(&[TokenKind::SemiColon, TokenKind::Newline]) { + while p + .eat_any(&[TokenKind::SemiColon, TokenKind::Newline]) + .is_some() + { one = true; } @@ -69,7 +82,10 @@ pub fn stmt_or_list_item(p: &mut Parser) { } p.report(ErrorKind::UnexpectedTree); }); - while p.eat_any(&[TokenKind::SemiColon, TokenKind::Newline]) {} + while p + .eat_any(&[TokenKind::SemiColon, TokenKind::Newline]) + .is_some() + {} } }); p.close(m, TreeKind::Entry); @@ -77,34 +93,36 @@ pub fn stmt_or_list_item(p: &mut Parser) { pub fn entry_value(p: &mut Parser) -> bool { p.scope(TreeKind::EntryValue, |p| { - match p.nth(0) { - TokenKind::String => { + match (p.nth(0), p.nth(1)) { + (String, _) => { p.advance(); } - TokenKind::UnterminatedString => { + (UnterminatedString, _) => { p.advance_with_error(ErrorKind::UnterminatedString, None); } - Number | Minus | HexLit | True | False => { - let m = p.open(); - p.advance(); - p.close(m, TreeKind::Literal); - } - TokenKind::Name => { + (Name, _) | (HexLit, LCurly) => { p.scope(TreeKind::Class, |p| { p.advance(); - block(p); + if p.at(LCurly) { + block(p); + } }); } - TokenKind::LCurly => { + (Number | HexLit | True | False, _) => { + let m = p.open(); + p.advance(); + p.close(m, TreeKind::Literal); + } + (LCurly, _) => { block(p); } - TokenKind::Newline => { + (Newline, _) => { p.advance_with_error(ErrorKind::Unexpected { token: Newline }, None); while p.eat(Newline) {} return false; } - token @ TokenKind::Eof => p.report(ErrorKind::Unexpected { token }), - token => p.advance_with_error(ErrorKind::Unexpected { token }, None), + (token @ TokenKind::Eof, _) => p.report(ErrorKind::Unexpected { token }), + (token, _) => p.advance_with_error(ErrorKind::Unexpected { token }, None), } true }) diff --git a/crates/ltk_ritobin/src/parse/parser.rs b/crates/ltk_ritobin/src/parse/parser.rs index 158b5d2e..bacdedee 100644 --- a/crates/ltk_ritobin/src/parse/parser.rs +++ b/crates/ltk_ritobin/src/parse/parser.rs @@ -21,16 +21,18 @@ pub struct MarkClosed { index: usize, } -pub struct Parser { +pub struct Parser<'a> { + pub text: &'a str, pub tokens: Vec, pos: usize, fuel: Cell, pub events: Vec, } -impl Parser { - pub fn new(tokens: Vec) -> Parser { +impl<'a> Parser<'a> { + pub fn new(text: &'a str, tokens: Vec) -> Parser { Parser { + text, tokens, pos: 0, fuel: Cell::new(256), @@ -192,6 +194,11 @@ impl Parser { pub(crate) fn nth(&self, lookahead: usize) -> TokenKind { if self.fuel.get() == 0 { + eprintln!("last 5 tokens behind self.pos:"); + for tok in &self.tokens[self.pos.saturating_sub(5)..self.pos] { + eprintln!(" - {:?}: {:?}", tok.kind, &self.text[tok.span]); + } + panic!("parser is stuck") } self.fuel.set(self.fuel.get() - 1); @@ -204,16 +211,16 @@ impl Parser { self.nth(0) == kind } - pub(crate) fn at_any(&self, kinds: &[TokenKind]) -> bool { - kinds.contains(&self.nth(0)) + pub(crate) fn at_any(&self, kinds: &[TokenKind]) -> Option { + kinds.contains(&self.nth(0)).then_some(self.nth(0)) } - pub(crate) fn eat_any(&mut self, kinds: &[TokenKind]) -> bool { - if self.at_any(kinds) { + pub(crate) fn eat_any(&mut self, kinds: &[TokenKind]) -> Option { + if let Some(kind) = self.at_any(kinds) { self.advance(); - true + Some(kind) } else { - false + None } } @@ -226,15 +233,15 @@ impl Parser { } } - pub(crate) fn expect_any(&mut self, kinds: &'static [TokenKind]) -> bool { - if self.eat_any(kinds) { - return true; + pub(crate) fn expect_any(&mut self, kinds: &'static [TokenKind]) -> Option { + if let Some(kind) = self.eat_any(kinds) { + return Some(kind); } self.report(ErrorKind::ExpectedAny { expected: kinds, got: self.nth(0), }); - false + None } pub(crate) fn expect(&mut self, kind: TokenKind) -> bool { From 4e3f7b13ced147a9f1a25cd23dec4fc9ea092557 Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Sat, 10 Jan 2026 21:39:35 +0000 Subject: [PATCH 054/187] fix (lex): remove minus symbol + fix hex lexing --- crates/ltk_ritobin/src/parse/tokenizer.rs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/crates/ltk_ritobin/src/parse/tokenizer.rs b/crates/ltk_ritobin/src/parse/tokenizer.rs index 0e955e86..cdd104f1 100644 --- a/crates/ltk_ritobin/src/parse/tokenizer.rs +++ b/crates/ltk_ritobin/src/parse/tokenizer.rs @@ -10,7 +10,7 @@ pub enum TokenKind { LParen, RParen, LCurly, RCurly, LBrack, RBrack, Eq, Comma, Colon, SemiColon, - Minus, Star, Slash, + Star, Slash, Quote, String, UnterminatedString, @@ -45,7 +45,6 @@ impl Display for TokenKind { TokenKind::Comma => "','", TokenKind::Colon => "':'", TokenKind::SemiColon => "';'", - TokenKind::Minus => "'-'", TokenKind::Star => "'*'", TokenKind::Slash => "'/'", TokenKind::Quote => "'\"'", @@ -69,10 +68,10 @@ pub struct Token { pub fn lex(mut text: &str) -> Vec { use TokenKind::*; let punctuation = ( - "( ) { } [ ] = , : ; - * /", + "( ) { } [ ] = , : ; * /", [ - LParen, RParen, LCurly, RCurly, LBrack, RBrack, Eq, Comma, Colon, SemiColon, Minus, - Star, Slash, + LParen, RParen, LCurly, RCurly, LBrack, RBrack, Eq, Comma, Colon, SemiColon, Star, + Slash, ], ); @@ -129,7 +128,7 @@ pub fn lex(mut text: &str) -> Vec { if let Some(rest) = text.strip_prefix("0x") { text = rest; - if let Some(rest) = trim(text, |it| matches!(it, 'a'..'f' | 'A'..'F' | '0'..='9')) { + if let Some(rest) = trim(text, |it: char| it.is_ascii_hexdigit()) { text = rest; } break 'kind HexLit; From cf3e7543f2ae5e179d962b3d6a89821430a7e69f Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Sat, 10 Jan 2026 21:39:44 +0000 Subject: [PATCH 055/187] fix: safer slicing --- crates/ltk_ritobin/src/parse/span.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/ltk_ritobin/src/parse/span.rs b/crates/ltk_ritobin/src/parse/span.rs index 8ab2bea5..dd4beea7 100644 --- a/crates/ltk_ritobin/src/parse/span.rs +++ b/crates/ltk_ritobin/src/parse/span.rs @@ -32,6 +32,6 @@ impl std::ops::Index<&Span> for str { fn index(&self, index: &Span) -> &Self::Output { let start = index.start as usize; let end = index.end as usize; - &self[start..end] + &self[start..end.min(self.len())] } } From 65630f93c074a23b0a6afc5e8f9ea983b6cbacaa Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Sat, 10 Jan 2026 21:41:52 +0000 Subject: [PATCH 056/187] misc tweaks --- crates/ltk_ritobin/src/parse/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/ltk_ritobin/src/parse/mod.rs b/crates/ltk_ritobin/src/parse/mod.rs index 49a39fd1..aafaed5b 100644 --- a/crates/ltk_ritobin/src/parse/mod.rs +++ b/crates/ltk_ritobin/src/parse/mod.rs @@ -17,8 +17,7 @@ pub use span::Span; pub fn parse(text: &str) -> cst::Cst { let tokens = tokenizer::lex(text); - eprintln!("tokens: {tokens:#?}"); - let mut p = parser::Parser::new(tokens); + let mut p = parser::Parser::new(text, tokens); impls::file(&mut p); p.build_tree() } @@ -41,6 +40,7 @@ linked: list[string, cock] = { let mut str = String::new(); cst.print(&mut str, 0, text); + eprintln!("text len: {}", text.len()); eprintln!("{str}\n====== errors: ======\n"); for err in errors { eprintln!("{:?}: {:#?}", &text[err.span], err.kind); From cf576ae66aee5ce85b77e265a1eb97cf928a0093 Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Sat, 10 Jan 2026 23:02:02 +0000 Subject: [PATCH 057/187] wip: typecheck --- crates/ltk_ritobin/src/parse/cst/tree.rs | 12 ++ crates/ltk_ritobin/src/typecheck/mod.rs | 4 + crates/ltk_ritobin/src/typecheck/name_ext.rs | 73 ++++++++++++ crates/ltk_ritobin/src/typecheck/visitor.rs | 113 +++++++++++++++++++ 4 files changed, 202 insertions(+) create mode 100644 crates/ltk_ritobin/src/typecheck/mod.rs create mode 100644 crates/ltk_ritobin/src/typecheck/name_ext.rs create mode 100644 crates/ltk_ritobin/src/typecheck/visitor.rs diff --git a/crates/ltk_ritobin/src/parse/cst/tree.rs b/crates/ltk_ritobin/src/parse/cst/tree.rs index dbbddf15..22ca2c43 100644 --- a/crates/ltk_ritobin/src/parse/cst/tree.rs +++ b/crates/ltk_ritobin/src/parse/cst/tree.rs @@ -52,6 +52,18 @@ pub enum Child { } impl Child { + pub fn token(&self) -> Option<&Token> { + match self { + Child::Token(token) => Some(token), + Child::Tree(_) => None, + } + } + pub fn tree(&self) -> Option<&Cst> { + match self { + Child::Token(_) => None, + Child::Tree(cst) => Some(cst), + } + } pub fn span(&self) -> Span { match self { Child::Token(token) => token.span, diff --git a/crates/ltk_ritobin/src/typecheck/mod.rs b/crates/ltk_ritobin/src/typecheck/mod.rs new file mode 100644 index 00000000..942097ca --- /dev/null +++ b/crates/ltk_ritobin/src/typecheck/mod.rs @@ -0,0 +1,4 @@ +mod name_ext; +pub use name_ext::*; + +pub mod visitor; diff --git a/crates/ltk_ritobin/src/typecheck/name_ext.rs b/crates/ltk_ritobin/src/typecheck/name_ext.rs new file mode 100644 index 00000000..e388b7ea --- /dev/null +++ b/crates/ltk_ritobin/src/typecheck/name_ext.rs @@ -0,0 +1,73 @@ +use ltk_meta::BinPropertyKind; + +pub trait RitobinName: Sized { + fn from_ritobin_name(name: &str) -> Option; + fn to_ritobin_name(self) -> &'static str; +} + +impl RitobinName for BinPropertyKind { + fn from_ritobin_name(name: &str) -> Option { + match name { + "none" => Some(Self::None), + "bool" => Some(Self::Bool), + "i8" => Some(Self::I8), + "u8" => Some(Self::U8), + "i16" => Some(Self::I16), + "u16" => Some(Self::U16), + "i32" => Some(Self::I32), + "u32" => Some(Self::U32), + "i64" => Some(Self::I64), + "u64" => Some(Self::U64), + "f32" => Some(Self::F32), + "vec2" => Some(Self::Vector2), + "vec3" => Some(Self::Vector3), + "vec4" => Some(Self::Vector4), + "mtx44" => Some(Self::Matrix44), + "rgba" => Some(Self::Color), + "string" => Some(Self::String), + "hash" => Some(Self::Hash), + "file" => Some(Self::WadChunkLink), + "list" => Some(Self::Container), + "list2" => Some(Self::UnorderedContainer), + "pointer" => Some(Self::Struct), + "embed" => Some(Self::Embedded), + "link" => Some(Self::ObjectLink), + "option" => Some(Self::Optional), + "map" => Some(Self::Map), + "flag" => Some(Self::BitBool), + _ => None, + } + } + + fn to_ritobin_name(self) -> &'static str { + match self { + Self::None => "none", + Self::Bool => "bool", + Self::I8 => "i8", + Self::U8 => "u8", + Self::I16 => "i16", + Self::U16 => "u16", + Self::I32 => "i32", + Self::U32 => "u32", + Self::I64 => "i64", + Self::U64 => "u64", + Self::F32 => "f32", + Self::Vector2 => "vec2", + Self::Vector3 => "vec3", + Self::Vector4 => "vec4", + Self::Matrix44 => "mtx44", + Self::Color => "rgba", + Self::String => "string", + Self::Hash => "hash", + Self::WadChunkLink => "file", + Self::Container => "list", + Self::UnorderedContainer => "list2", + Self::Struct => "pointer", + Self::Embedded => "embed", + Self::ObjectLink => "link", + Self::Optional => "option", + Self::Map => "map", + Self::BitBool => "flag", + } + } +} diff --git a/crates/ltk_ritobin/src/typecheck/visitor.rs b/crates/ltk_ritobin/src/typecheck/visitor.rs new file mode 100644 index 00000000..6d16f972 --- /dev/null +++ b/crates/ltk_ritobin/src/typecheck/visitor.rs @@ -0,0 +1,113 @@ +use indexmap::IndexMap; +use ltk_meta::{BinPropertyKind, PropertyValueEnum}; + +use crate::{ + parse::{ + cst::{self, visitor::Visit, Cst, Kind, Visitor}, + Span, TokenKind, + }, + typecheck::RitobinName, +}; + +pub struct TypeChecker<'a> { + text: &'a str, + root: IndexMap, + current: Option<(String, PropertyValueEnum)>, +} + +pub enum Diagnostic { + MissingTree(cst::Kind), + EmptyTree(cst::Kind), + MissingToken(TokenKind), + UnknownType(Span), +} +use Diagnostic::*; + +pub struct RitoType { + pub base: BinPropertyKind, +} + +pub enum Statement { + KeyValue { + key: Span, + value: Span, + kind: Option, + }, +} + +pub fn resolve_rito_type<'a>(text: &'a str, tree: &Cst) -> Result { + let mut c = tree.children.iter(); + + let base = c + .find_map(|c| c.token().filter(|t| t.kind == TokenKind::Name)) + .ok_or(MissingToken(TokenKind::Name))?; + + let base = + BinPropertyKind::from_ritobin_name(&text[base.span]).ok_or(UnknownType(base.span))?; + + Ok(RitoType { base }) +} + +pub fn resolve_entry<'a>(text: &'a str, tree: &Cst) -> Result<(), Diagnostic> { + let mut c = tree.children.iter(); + + let key = c + .find_map(|c| c.tree().filter(|t| t.kind == Kind::TypeExpr)) + .ok_or(MissingTree(Kind::EntryKey))?; + + let kind = c + .find_map(|c| c.tree().filter(|t| t.kind == Kind::EntryKey)) + .map(|t| resolve_rito_type(text, t)) + .transpose()?; + + let value = c + .find_map(|c| c.tree().filter(|t| t.kind == Kind::EntryValue)) + .ok_or(MissingTree(Kind::EntryValue))?; + + Ok(()) +} + +pub fn resolve_list(tree: &Cst) -> Result<(), Diagnostic> { + Ok(()) +} + +impl Visitor for TypeChecker { + fn enter_tree(&mut self, tree: &Cst) -> Visit { + if tree.kind == cst::Kind::ErrorTree { + return Visit::Skip; + } + + match self.current.as_mut() { + Some((name, value)) => {} + None => { + if tree.kind != cst::Kind::Entry { + return Visit::Skip; + }; + + let mut children = tree.children.iter(); + + // let args = children.next().ok_or(); + } + } + + Visit::Continue + } + + fn exit_tree(&mut self, tree: &cst::Cst) -> Visit { + if tree.kind == cst::Kind::ErrorTree { + return Visit::Continue; + } + + match self.current.take() { + Some((name, value)) => { + // TODO: warn when shadowed + let _existing = self.root.insert(name, value); + } + None => { + eprintln!("exit tree with no current?"); + } + } + + Visit::Continue + } +} From 651ce21e370aa3a16fceda5ff7e815ae4e0b762e Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Sun, 11 Jan 2026 00:11:47 +0000 Subject: [PATCH 058/187] wip: typecheck --- crates/ltk_ritobin/src/lib.rs | 1 + crates/ltk_ritobin/src/typecheck/visitor.rs | 210 +++++++++++++++++--- 2 files changed, 186 insertions(+), 25 deletions(-) diff --git a/crates/ltk_ritobin/src/lib.rs b/crates/ltk_ritobin/src/lib.rs index 71ad5184..9669079d 100644 --- a/crates/ltk_ritobin/src/lib.rs +++ b/crates/ltk_ritobin/src/lib.rs @@ -47,6 +47,7 @@ pub mod error; pub mod hashes; pub mod parse; +pub mod typecheck; pub mod types; pub mod writer; diff --git a/crates/ltk_ritobin/src/typecheck/visitor.rs b/crates/ltk_ritobin/src/typecheck/visitor.rs index 6d16f972..ce998db3 100644 --- a/crates/ltk_ritobin/src/typecheck/visitor.rs +++ b/crates/ltk_ritobin/src/typecheck/visitor.rs @@ -4,25 +4,109 @@ use ltk_meta::{BinPropertyKind, PropertyValueEnum}; use crate::{ parse::{ cst::{self, visitor::Visit, Cst, Kind, Visitor}, - Span, TokenKind, + Span, Token, TokenKind, }, typecheck::RitobinName, }; pub struct TypeChecker<'a> { - text: &'a str, + ctx: Ctx<'a>, root: IndexMap, current: Option<(String, PropertyValueEnum)>, } +impl<'a> TypeChecker<'a> { + pub fn new(text: &'a str) -> Self { + Self { + ctx: Ctx { + text, + diagnostics: Vec::new(), + }, + root: IndexMap::new(), + current: None, + } + } + pub fn into_diagnostics(self) -> Vec { + self.ctx.diagnostics + } +} +#[derive(Debug, Clone, Copy)] pub enum Diagnostic { MissingTree(cst::Kind), EmptyTree(cst::Kind), MissingToken(TokenKind), UnknownType(Span), + + SubtypeCountMismatch { + span: Span, + got: u8, + expected: u8, + }, + /// Subtypes found on a type that has no subtypes + UnexpectedSubtypes { + span: Span, + base_type: Span, + }, } + +impl Diagnostic { + pub fn span(&self) -> Option<&Span> { + match self { + MissingTree(_) | EmptyTree(_) | MissingToken(_) => None, + UnknownType(span) + | SubtypeCountMismatch { span, .. } + | UnexpectedSubtypes { span, .. } => Some(span), + } + } + + pub fn default_span(self, span: Span) -> DiagnosticWithSpan { + DiagnosticWithSpan { + span: self.span().copied().unwrap_or(span), + diagnostic: self, + } + } + + pub fn unwrap(self) -> DiagnosticWithSpan { + DiagnosticWithSpan { + span: self.span().copied().unwrap(), + diagnostic: self, + } + } +} + +#[derive(Debug, Clone, Copy)] +pub struct DiagnosticWithSpan { + pub diagnostic: Diagnostic, + pub span: Span, +} + +#[derive(Debug, Clone, Copy)] +pub struct MaybeSpanDiag { + pub diagnostic: Diagnostic, + pub span: Option, +} + +impl MaybeSpanDiag { + pub fn fallback(self, span: Span) -> DiagnosticWithSpan { + DiagnosticWithSpan { + span: self.span.unwrap_or(span), + diagnostic: self.diagnostic, + } + } +} + +impl From for MaybeSpanDiag { + fn from(diagnostic: Diagnostic) -> Self { + Self { + span: diagnostic.span().copied(), + diagnostic, + } + } +} + use Diagnostic::*; +#[derive(Debug, Clone, Copy)] pub struct RitoType { pub base: BinPropertyKind, } @@ -35,43 +119,114 @@ pub enum Statement { }, } -pub fn resolve_rito_type<'a>(text: &'a str, tree: &Cst) -> Result { +trait TreeIterExt<'a>: Iterator { + fn expect_tree(&mut self, kind: cst::Kind) -> Result<&'a Cst, Diagnostic>; + fn expect_token(&mut self, kind: TokenKind) -> Result<&'a Token, Diagnostic>; +} + +impl<'a, I> TreeIterExt<'a> for I +where + I: Iterator, +{ + fn expect_tree(&mut self, kind: cst::Kind) -> Result<&'a Cst, Diagnostic> { + self.find_map(|c| c.tree().filter(|t| t.kind == kind)) + .ok_or(MissingTree(kind)) + } + fn expect_token(&mut self, kind: TokenKind) -> Result<&'a Token, Diagnostic> { + self.find_map(|c| c.token().filter(|t| t.kind == kind)) + .ok_or(MissingToken(kind)) + } +} + +pub struct Ctx<'a> { + text: &'a str, + diagnostics: Vec, +} + +pub fn resolve_rito_type(ctx: &mut Ctx<'_>, tree: &Cst) -> Result { let mut c = tree.children.iter(); - let base = c - .find_map(|c| c.token().filter(|t| t.kind == TokenKind::Name)) - .ok_or(MissingToken(TokenKind::Name))?; + let base = c.expect_token(TokenKind::Name)?; + let base_span = base.span; let base = - BinPropertyKind::from_ritobin_name(&text[base.span]).ok_or(UnknownType(base.span))?; + BinPropertyKind::from_ritobin_name(&ctx.text[base.span]).ok_or(UnknownType(base.span))?; + + if let Some(subtypes) = c + .clone() + .find_map(|c| c.tree().filter(|t| t.kind == Kind::TypeArgList)) + { + let subtypes_span = subtypes.span; + + let expected = base.subtype_count(); + + if expected == 0 { + return Err(UnexpectedSubtypes { + span: subtypes_span, + base_type: base_span, + }); + } + + let subtypes = subtypes + .children + .iter() + .filter_map(|c| c.tree().filter(|t| t.kind == Kind::TypeArg)) + .map(|t| { + let resolved = BinPropertyKind::from_ritobin_name(&ctx.text[t.span]); + if resolved.is_none() { + ctx.diagnostics.push(UnknownType(t.span).unwrap()); + } + (resolved, t.span) + }) + .collect::>(); + + if subtypes.len() > expected.into() { + return Err(SubtypeCountMismatch { + span: subtypes[expected as _..] + .iter() + .map(|s| s.1) + .reduce(|acc, s| Span::new(acc.start, s.end)) + .unwrap_or(subtypes_span), + got: subtypes.len() as u8, + expected, + }); + } + if subtypes.len() < expected.into() { + return Err(SubtypeCountMismatch { + span: subtypes.last().map(|s| s.1).unwrap_or(subtypes_span), + got: subtypes.len() as u8, + expected, + }); + } + } Ok(RitoType { base }) } -pub fn resolve_entry<'a>(text: &'a str, tree: &Cst) -> Result<(), Diagnostic> { +pub fn resolve_entry( + ctx: &mut Ctx, + tree: &Cst, +) -> Result<(Span, Option, Span), MaybeSpanDiag> { let mut c = tree.children.iter(); - let key = c - .find_map(|c| c.tree().filter(|t| t.kind == Kind::TypeExpr)) - .ok_or(MissingTree(Kind::EntryKey))?; + let key = c.expect_tree(Kind::EntryKey)?; let kind = c - .find_map(|c| c.tree().filter(|t| t.kind == Kind::EntryKey)) - .map(|t| resolve_rito_type(text, t)) + .clone() + .find_map(|c| c.tree().filter(|t| t.kind == Kind::TypeExpr)) + .map(|t| resolve_rito_type(ctx, t)) .transpose()?; - let value = c - .find_map(|c| c.tree().filter(|t| t.kind == Kind::EntryValue)) - .ok_or(MissingTree(Kind::EntryValue))?; + let value = c.expect_tree(Kind::EntryValue)?; - Ok(()) + Ok((key.span, kind, value.span)) } -pub fn resolve_list(tree: &Cst) -> Result<(), Diagnostic> { +pub fn resolve_list(ctx: &mut Ctx, tree: &Cst) -> Result<(), Diagnostic> { Ok(()) } -impl Visitor for TypeChecker { +impl Visitor for TypeChecker<'_> { fn enter_tree(&mut self, tree: &Cst) -> Visit { if tree.kind == cst::Kind::ErrorTree { return Visit::Skip; @@ -80,13 +235,18 @@ impl Visitor for TypeChecker { match self.current.as_mut() { Some((name, value)) => {} None => { - if tree.kind != cst::Kind::Entry { - return Visit::Skip; - }; - - let mut children = tree.children.iter(); + match tree.kind { + Kind::Entry => {} + Kind::File => return Visit::Continue, + _ => return Visit::Skip, + } - // let args = children.next().ok_or(); + match resolve_entry(&mut self.ctx, tree).map_err(|e| e.fallback(tree.span)) { + Ok(entry) => { + eprintln!("entry: {entry:?}"); + } + Err(e) => self.ctx.diagnostics.push(e), + } } } From b657edb8d572fe3b000dd70908b3ccce60ed8b15 Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Sun, 11 Jan 2026 00:31:15 +0000 Subject: [PATCH 059/187] feat: change visitor call logic --- crates/ltk_ritobin/src/parse/cst/visitor.rs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/crates/ltk_ritobin/src/parse/cst/visitor.rs b/crates/ltk_ritobin/src/parse/cst/visitor.rs index a9e324fd..dbdd1335 100644 --- a/crates/ltk_ritobin/src/parse/cst/visitor.rs +++ b/crates/ltk_ritobin/src/parse/cst/visitor.rs @@ -32,9 +32,15 @@ impl Cst { } fn walk_inner(&self, visitor: &mut V) -> Visit { - let enter = visitor.enter_tree(self); - if matches!(enter, Visit::Stop | Visit::Skip) { - return enter; + if let Some(ret) = match visitor.enter_tree(self) { + Visit::Stop => Some(Visit::Stop), + Visit::Skip => Some(Visit::Continue), + _ => None, + } { + if visitor.exit_tree(self) == Visit::Stop { + return Visit::Stop; + } + return ret; } for child in &self.children { From 46535d695f9eb3ee42865e020c5f802ae3e77fcf Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Sun, 11 Jan 2026 00:31:23 +0000 Subject: [PATCH 060/187] chore: add type check to smoke test --- crates/ltk_ritobin/src/parse/mod.rs | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/crates/ltk_ritobin/src/parse/mod.rs b/crates/ltk_ritobin/src/parse/mod.rs index aafaed5b..b3c0e0bb 100644 --- a/crates/ltk_ritobin/src/parse/mod.rs +++ b/crates/ltk_ritobin/src/parse/mod.rs @@ -24,15 +24,15 @@ pub fn parse(text: &str) -> cst::Cst { #[cfg(test)] mod test { + use crate::typecheck::visitor::TypeChecker; + use super::*; #[test] fn smoke_test() { let text = r#" -linked: list[string, cock] = { - "DATA/Characters/Yasuo/Yasuo.bin" - "data/Yasuo_skin0_concat.bin" - "data/Yasuo_skin0_StaticMat_proxy.bin" -} +EmitterName: string = "EyeTrail1" +map: map[string, string] = 2 +2 "#; let cst = parse(text); @@ -45,5 +45,13 @@ linked: list[string, cock] = { for err in errors { eprintln!("{:?}: {:#?}", &text[err.span], err.kind); } + + let mut checker = TypeChecker::new(text); + cst.walk(&mut checker); + + eprintln!("{str}\n====== type errors: ======\n"); + for err in checker.into_diagnostics() { + eprintln!("{:?}: {:#?}", &text[err.span], err.diagnostic); + } } } From 89039517d3d27a716e0bc27c05d8060669bff475 Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Sun, 11 Jan 2026 00:31:28 +0000 Subject: [PATCH 061/187] wip: typecheck --- crates/ltk_ritobin/src/typecheck/visitor.rs | 36 ++++++++++++++++----- 1 file changed, 28 insertions(+), 8 deletions(-) diff --git a/crates/ltk_ritobin/src/typecheck/visitor.rs b/crates/ltk_ritobin/src/typecheck/visitor.rs index ce998db3..26a0f890 100644 --- a/crates/ltk_ritobin/src/typecheck/visitor.rs +++ b/crates/ltk_ritobin/src/typecheck/visitor.rs @@ -1,5 +1,5 @@ use indexmap::IndexMap; -use ltk_meta::{BinPropertyKind, PropertyValueEnum}; +use ltk_meta::{value::NoneValue, BinPropertyKind, PropertyValueEnum}; use crate::{ parse::{ @@ -12,7 +12,8 @@ use crate::{ pub struct TypeChecker<'a> { ctx: Ctx<'a>, root: IndexMap, - current: Option<(String, PropertyValueEnum)>, + current: Option<(u32, String, PropertyValueEnum)>, + depth: u32, } impl<'a> TypeChecker<'a> { @@ -24,6 +25,7 @@ impl<'a> TypeChecker<'a> { }, root: IndexMap::new(), current: None, + depth: 0, } } pub fn into_diagnostics(self) -> Vec { @@ -37,6 +39,8 @@ pub enum Diagnostic { MissingToken(TokenKind), UnknownType(Span), + RootNonEntry, + SubtypeCountMismatch { span: Span, got: u8, @@ -52,7 +56,7 @@ pub enum Diagnostic { impl Diagnostic { pub fn span(&self) -> Option<&Span> { match self { - MissingTree(_) | EmptyTree(_) | MissingToken(_) => None, + MissingTree(_) | EmptyTree(_) | MissingToken(_) | RootNonEntry => None, UnknownType(span) | SubtypeCountMismatch { span, .. } | UnexpectedSubtypes { span, .. } => Some(span), @@ -228,22 +232,36 @@ pub fn resolve_list(ctx: &mut Ctx, tree: &Cst) -> Result<(), Diagnostic> { impl Visitor for TypeChecker<'_> { fn enter_tree(&mut self, tree: &Cst) -> Visit { + self.depth += 1; + eprintln!("depth -> {} | {}", self.depth, tree.kind); if tree.kind == cst::Kind::ErrorTree { return Visit::Skip; } match self.current.as_mut() { - Some((name, value)) => {} + Some((depth, name, value)) => {} None => { match tree.kind { Kind::Entry => {} Kind::File => return Visit::Continue, - _ => return Visit::Skip, + kind => { + if self.depth == 2 { + self.ctx + .diagnostics + .push(RootNonEntry.default_span(tree.span)); + } + return Visit::Skip; + } } match resolve_entry(&mut self.ctx, tree).map_err(|e| e.fallback(tree.span)) { Ok(entry) => { eprintln!("entry: {entry:?}"); + self.current.replace(( + self.depth, + self.ctx.text[entry.0].into(), + PropertyValueEnum::None(NoneValue), + )); } Err(e) => self.ctx.diagnostics.push(e), } @@ -254,17 +272,19 @@ impl Visitor for TypeChecker<'_> { } fn exit_tree(&mut self, tree: &cst::Cst) -> Visit { + self.depth -= 1; + eprintln!("depth <- {} | {}", self.depth, tree.kind); if tree.kind == cst::Kind::ErrorTree { return Visit::Continue; } match self.current.take() { - Some((name, value)) => { + Some((2, name, value)) => { // TODO: warn when shadowed let _existing = self.root.insert(name, value); } - None => { - eprintln!("exit tree with no current?"); + _ => { + // eprintln!("exit tree with no current?"); } } From d1da9eaa3ff21cb3383b972733ebb7b49a45c76d Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Sun, 11 Jan 2026 01:00:27 +0000 Subject: [PATCH 062/187] wip: typecheck --- crates/ltk_ritobin/src/typecheck/visitor.rs | 96 +++++++++++++++------ 1 file changed, 68 insertions(+), 28 deletions(-) diff --git a/crates/ltk_ritobin/src/typecheck/visitor.rs b/crates/ltk_ritobin/src/typecheck/visitor.rs index 26a0f890..ac93096c 100644 --- a/crates/ltk_ritobin/src/typecheck/visitor.rs +++ b/crates/ltk_ritobin/src/typecheck/visitor.rs @@ -12,7 +12,7 @@ use crate::{ pub struct TypeChecker<'a> { ctx: Ctx<'a>, root: IndexMap, - current: Option<(u32, String, PropertyValueEnum)>, + current: Option<(String, PropertyValueEnum)>, depth: u32, } @@ -38,6 +38,7 @@ pub enum Diagnostic { EmptyTree(cst::Kind), MissingToken(TokenKind), UnknownType(Span), + MissingType(Span), RootNonEntry, @@ -59,7 +60,8 @@ impl Diagnostic { MissingTree(_) | EmptyTree(_) | MissingToken(_) | RootNonEntry => None, UnknownType(span) | SubtypeCountMismatch { span, .. } - | UnexpectedSubtypes { span, .. } => Some(span), + | UnexpectedSubtypes { span, .. } + | MissingType(span) => Some(span), } } @@ -115,6 +117,11 @@ pub struct RitoType { pub base: BinPropertyKind, } +impl RitoType { + pub fn simple(kind: BinPropertyKind) -> Self { + Self { base: kind } + } +} pub enum Statement { KeyValue { key: Span, @@ -210,7 +217,7 @@ pub fn resolve_rito_type(ctx: &mut Ctx<'_>, tree: &Cst) -> Result Result<(Span, Option, Span), MaybeSpanDiag> { +) -> Result<(Span, PropertyValueEnum), MaybeSpanDiag> { let mut c = tree.children.iter(); let key = c.expect_tree(Kind::EntryKey)?; @@ -222,52 +229,85 @@ pub fn resolve_entry( .transpose()?; let value = c.expect_tree(Kind::EntryValue)?; - - Ok((key.span, kind, value.span)) + let inferred_value = match value.children.first() { + Some(cst::Child::Token(Token { + kind: TokenKind::String, + span, + .. + })) => Some(PropertyValueEnum::String(ltk_meta::value::StringValue( + ctx.text[span].into(), + ))), + _ => None, + }; + + let value = match (kind, inferred_value) { + (None, None) => return Err(MissingType(key.span).into()), + (Some(kind), Some(ivalue)) if ivalue.kind() == kind.base => ivalue, + (Some(kind), _) => kind.base.default_value(), + }; + + Ok((key.span, value)) } pub fn resolve_list(ctx: &mut Ctx, tree: &Cst) -> Result<(), Diagnostic> { Ok(()) } +impl TypeChecker<'_> { + fn inject_child(&mut self, name: Option, child: PropertyValueEnum) { + let Some(current) = self.current.as_mut() else { + let Some(name) = name else { + return; + }; + self.current.replace((name, child)); + return; + }; + } +} + impl Visitor for TypeChecker<'_> { fn enter_tree(&mut self, tree: &Cst) -> Visit { self.depth += 1; eprintln!("depth -> {} | {}", self.depth, tree.kind); - if tree.kind == cst::Kind::ErrorTree { - return Visit::Skip; - } - match self.current.as_mut() { - Some((depth, name, value)) => {} - None => { - match tree.kind { - Kind::Entry => {} - Kind::File => return Visit::Continue, - kind => { - if self.depth == 2 { - self.ctx - .diagnostics - .push(RootNonEntry.default_span(tree.span)); - } - return Visit::Skip; - } - } + match tree.kind { + Kind::ErrorTree => return Visit::Skip, + Kind::Entry => { match resolve_entry(&mut self.ctx, tree).map_err(|e| e.fallback(tree.span)) { Ok(entry) => { eprintln!("entry: {entry:?}"); - self.current.replace(( - self.depth, - self.ctx.text[entry.0].into(), - PropertyValueEnum::None(NoneValue), - )); + self.inject_child( + Some(self.ctx.text[entry.0].into()), + entry.1.base.make_empty(), + ); } Err(e) => self.ctx.diagnostics.push(e), } } + + _ => {} } + // match self.current.as_mut() { + // Some((depth, name, value)) => {} + // None => { + // match tree.kind { + // Kind::Entry => {} + // Kind::File => return Visit::Continue, + // kind => { + // if self.depth == 2 { + // self.ctx + // .diagnostics + // .push(RootNonEntry.default_span(tree.span)); + // } + // return Visit::Skip; + // } + // } + // + // } + // } + Visit::Continue } From 493719bcd7aea33c80e5b67d8e427913bc26b7c4 Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Sun, 11 Jan 2026 01:21:52 +0000 Subject: [PATCH 063/187] wip: typecheck --- crates/ltk_ritobin/src/parse/mod.rs | 11 ++- crates/ltk_ritobin/src/typecheck/visitor.rs | 83 ++++++++++++++++----- 2 files changed, 72 insertions(+), 22 deletions(-) diff --git a/crates/ltk_ritobin/src/parse/mod.rs b/crates/ltk_ritobin/src/parse/mod.rs index b3c0e0bb..be6156ff 100644 --- a/crates/ltk_ritobin/src/parse/mod.rs +++ b/crates/ltk_ritobin/src/parse/mod.rs @@ -31,8 +31,9 @@ mod test { fn smoke_test() { let text = r#" EmitterName: string = "EyeTrail1" -map: map[string, string] = 2 -2 +map: map[string, string] = { + a: string = "hi" +} "#; let cst = parse(text); @@ -49,9 +50,13 @@ map: map[string, string] = 2 let mut checker = TypeChecker::new(text); cst.walk(&mut checker); + let (roots, errors) = checker.into_parts(); + eprintln!("{str}\n====== type errors: ======\n"); - for err in checker.into_diagnostics() { + for err in errors { eprintln!("{:?}: {:#?}", &text[err.span], err.diagnostic); } + + eprintln!("{roots:#?}"); } } diff --git a/crates/ltk_ritobin/src/typecheck/visitor.rs b/crates/ltk_ritobin/src/typecheck/visitor.rs index ac93096c..e487f38e 100644 --- a/crates/ltk_ritobin/src/typecheck/visitor.rs +++ b/crates/ltk_ritobin/src/typecheck/visitor.rs @@ -1,5 +1,8 @@ use indexmap::IndexMap; -use ltk_meta::{value::NoneValue, BinPropertyKind, PropertyValueEnum}; +use ltk_meta::{ + value::{NoneValue, StringValue}, + BinPropertyKind, PropertyValueEnum, +}; use crate::{ parse::{ @@ -11,8 +14,8 @@ use crate::{ pub struct TypeChecker<'a> { ctx: Ctx<'a>, - root: IndexMap, - current: Option<(String, PropertyValueEnum)>, + pub root: IndexMap, + current: Option<(PropertyValueEnum, PropertyValueEnum)>, depth: u32, } @@ -28,8 +31,8 @@ impl<'a> TypeChecker<'a> { depth: 0, } } - pub fn into_diagnostics(self) -> Vec { - self.ctx.diagnostics + pub fn into_parts(self) -> (IndexMap, Vec) { + (self.root, self.ctx.diagnostics) } } #[derive(Debug, Clone, Copy)] @@ -115,11 +118,15 @@ use Diagnostic::*; #[derive(Debug, Clone, Copy)] pub struct RitoType { pub base: BinPropertyKind, + pub subtypes: [Option; 2], } impl RitoType { pub fn simple(kind: BinPropertyKind) -> Self { - Self { base: kind } + Self { + base: kind, + subtypes: [None, None], + } } } pub enum Statement { @@ -211,7 +218,10 @@ pub fn resolve_rito_type(ctx: &mut Ctx<'_>, tree: &Cst) -> Result value, (None, None) => return Err(MissingType(key.span).into()), (Some(kind), Some(ivalue)) if ivalue.kind() == kind.base => ivalue, (Some(kind), _) => kind.base.default_value(), @@ -254,14 +265,43 @@ pub fn resolve_list(ctx: &mut Ctx, tree: &Cst) -> Result<(), Diagnostic> { } impl TypeChecker<'_> { - fn inject_child(&mut self, name: Option, child: PropertyValueEnum) { + fn inject_child(&mut self, key: Option, child: PropertyValueEnum) { let Some(current) = self.current.as_mut() else { - let Some(name) = name else { + let Some(key) = key else { return; }; - self.current.replace((name, child)); + self.current.replace((key, child)); return; }; + + if current.1.kind().subtype_count() == 0 { + eprintln!("cant inject into non container"); + return; + } + match &mut current.1 { + PropertyValueEnum::Container(container_value) => todo!(), + PropertyValueEnum::UnorderedContainer(unordered_container_value) => todo!(), + PropertyValueEnum::Struct(struct_value) => todo!(), + PropertyValueEnum::Embedded(embedded_value) => todo!(), + PropertyValueEnum::ObjectLink(object_link_value) => todo!(), + PropertyValueEnum::Map(map_value) => { + if map_value.value_kind != child.kind() { + eprintln!( + "map value kind mismatch {:?} / {:?}", + map_value.value_kind, + child.kind() + ); + return; + } + let Some(key) = key else { + return; + }; + map_value + .entries + .insert(ltk_meta::value::PropertyValueUnsafeEq(key), child); + } + _ => unreachable!("non container"), + } } } @@ -278,8 +318,10 @@ impl Visitor for TypeChecker<'_> { Ok(entry) => { eprintln!("entry: {entry:?}"); self.inject_child( - Some(self.ctx.text[entry.0].into()), - entry.1.base.make_empty(), + Some(PropertyValueEnum::String(StringValue( + self.ctx.text[entry.0].to_string(), + ))), + entry.1, ); } Err(e) => self.ctx.diagnostics.push(e), @@ -318,13 +360,16 @@ impl Visitor for TypeChecker<'_> { return Visit::Continue; } - match self.current.take() { - Some((2, name, value)) => { - // TODO: warn when shadowed - let _existing = self.root.insert(name, value); - } - _ => { - // eprintln!("exit tree with no current?"); + if self.depth == 1 { + match self.current.take() { + Some((PropertyValueEnum::String(StringValue(name)), value)) => { + // TODO: warn when shadowed + + let _existing = self.root.insert(name, value); + } + _ => { + // eprintln!("exit tree with no current?"); + } } } From 9800d7f7674bfe3b3bbbf45a903f247e842fe037 Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Sun, 11 Jan 2026 20:17:02 +0000 Subject: [PATCH 064/187] feat: parent value type infer + more typecheck --- crates/ltk_ritobin/src/typecheck/visitor.rs | 183 ++++++++++++++------ 1 file changed, 133 insertions(+), 50 deletions(-) diff --git a/crates/ltk_ritobin/src/typecheck/visitor.rs b/crates/ltk_ritobin/src/typecheck/visitor.rs index e487f38e..c86c97b4 100644 --- a/crates/ltk_ritobin/src/typecheck/visitor.rs +++ b/crates/ltk_ritobin/src/typecheck/visitor.rs @@ -1,6 +1,8 @@ use indexmap::IndexMap; use ltk_meta::{ - value::{NoneValue, StringValue}, + value::{ + ContainerValue, MapValue, NoneValue, OptionalValue, StringValue, UnorderedContainerValue, + }, BinPropertyKind, PropertyValueEnum, }; @@ -115,6 +117,33 @@ impl From for MaybeSpanDiag { use Diagnostic::*; +pub trait PropertyValueExt { + fn rito_type(&self) -> RitoType; +} +impl PropertyValueExt for PropertyValueEnum { + fn rito_type(&self) -> RitoType { + let base = self.kind(); + let subtypes = match self { + PropertyValueEnum::Map(MapValue { + key_kind, + value_kind, + .. + }) => [Some(*key_kind), Some(*value_kind)], + PropertyValueEnum::UnorderedContainer(UnorderedContainerValue(ContainerValue { + item_kind, + .. + })) => [Some(*item_kind), None], + PropertyValueEnum::Container(ContainerValue { item_kind, .. }) => { + [Some(*item_kind), None] + } + PropertyValueEnum::Optional(OptionalValue { kind, .. }) => [Some(*kind), None], + + _ => [None, None], + }; + RitoType { base, subtypes } + } +} + #[derive(Debug, Clone, Copy)] pub struct RitoType { pub base: BinPropertyKind, @@ -128,6 +157,36 @@ impl RitoType { subtypes: [None, None], } } + + fn subtype(&self, idx: usize) -> BinPropertyKind { + self.subtypes[idx].unwrap_or_default() + } + + pub fn make_default(&self) -> PropertyValueEnum { + match self.base { + BinPropertyKind::Map => PropertyValueEnum::Map(MapValue { + key_kind: self.subtype(0), + value_kind: self.subtype(1), + ..Default::default() + }), + BinPropertyKind::UnorderedContainer => { + PropertyValueEnum::UnorderedContainer(UnorderedContainerValue(ContainerValue { + item_kind: self.subtype(0), + ..Default::default() + })) + } + BinPropertyKind::Container => PropertyValueEnum::Container(ContainerValue { + item_kind: self.subtype(0), + ..Default::default() + }), + BinPropertyKind::Optional => PropertyValueEnum::Optional(OptionalValue { + kind: self.subtype(0), + value: None, + }), + + _ => self.base.default_value(), + } + } } pub enum Statement { KeyValue { @@ -170,63 +229,70 @@ pub fn resolve_rito_type(ctx: &mut Ctx<'_>, tree: &Cst) -> Result { + let subtypes_span = subtypes.span; - let expected = base.subtype_count(); + let expected = base.subtype_count(); - if expected == 0 { - return Err(UnexpectedSubtypes { - span: subtypes_span, - base_type: base_span, - }); - } + if expected == 0 { + return Err(UnexpectedSubtypes { + span: subtypes_span, + base_type: base_span, + }); + } - let subtypes = subtypes - .children - .iter() - .filter_map(|c| c.tree().filter(|t| t.kind == Kind::TypeArg)) - .map(|t| { - let resolved = BinPropertyKind::from_ritobin_name(&ctx.text[t.span]); - if resolved.is_none() { - ctx.diagnostics.push(UnknownType(t.span).unwrap()); - } - (resolved, t.span) - }) - .collect::>(); - - if subtypes.len() > expected.into() { - return Err(SubtypeCountMismatch { - span: subtypes[expected as _..] - .iter() - .map(|s| s.1) - .reduce(|acc, s| Span::new(acc.start, s.end)) - .unwrap_or(subtypes_span), - got: subtypes.len() as u8, - expected, - }); - } - if subtypes.len() < expected.into() { - return Err(SubtypeCountMismatch { - span: subtypes.last().map(|s| s.1).unwrap_or(subtypes_span), - got: subtypes.len() as u8, - expected, - }); + let subtypes = subtypes + .children + .iter() + .filter_map(|c| c.tree().filter(|t| t.kind == Kind::TypeArg)) + .map(|t| { + let resolved = BinPropertyKind::from_ritobin_name(&ctx.text[t.span]); + if resolved.is_none() { + ctx.diagnostics.push(UnknownType(t.span).unwrap()); + } + (resolved, t.span) + }) + .collect::>(); + + if subtypes.len() > expected.into() { + return Err(SubtypeCountMismatch { + span: subtypes[expected as _..] + .iter() + .map(|s| s.1) + .reduce(|acc, s| Span::new(acc.start, s.end)) + .unwrap_or(subtypes_span), + got: subtypes.len() as u8, + expected, + }); + } + if subtypes.len() < expected.into() { + return Err(SubtypeCountMismatch { + span: subtypes.last().map(|s| s.1).unwrap_or(subtypes_span), + got: subtypes.len() as u8, + expected, + }); + } + + let mut subtypes = subtypes.iter(); + [ + subtypes.next().and_then(|s| s.0), + subtypes.next().and_then(|s| s.0), + ] } - } + None => [None, None], + }; - Ok(RitoType { - base, - subtypes: [None, None], - }) + Ok(RitoType { base, subtypes }) } pub fn resolve_entry( ctx: &mut Ctx, tree: &Cst, + parent_value_kind: Option, ) -> Result<(Span, PropertyValueEnum), MaybeSpanDiag> { let mut c = tree.children.iter(); @@ -236,7 +302,8 @@ pub fn resolve_entry( .clone() .find_map(|c| c.tree().filter(|t| t.kind == Kind::TypeExpr)) .map(|t| resolve_rito_type(ctx, t)) - .transpose()?; + .transpose()? + .or(parent_value_kind); let value = c.expect_tree(Kind::EntryValue)?; let inferred_value = match value.children.first() { @@ -254,7 +321,7 @@ pub fn resolve_entry( (None, Some(value)) => value, (None, None) => return Err(MissingType(key.span).into()), (Some(kind), Some(ivalue)) if ivalue.kind() == kind.base => ivalue, - (Some(kind), _) => kind.base.default_value(), + (Some(kind), _) => kind.make_default(), }; Ok((key.span, value)) @@ -279,8 +346,18 @@ impl TypeChecker<'_> { return; } match &mut current.1 { - PropertyValueEnum::Container(container_value) => todo!(), - PropertyValueEnum::UnorderedContainer(unordered_container_value) => todo!(), + PropertyValueEnum::Container(value) + | PropertyValueEnum::UnorderedContainer(UnorderedContainerValue(value)) => { + if value.item_kind != child.kind() { + eprintln!( + "container kind mismatch {:?} / {:?}", + value.item_kind, + child.kind() + ); + return; + } + value.items.push(child); + } PropertyValueEnum::Struct(struct_value) => todo!(), PropertyValueEnum::Embedded(embedded_value) => todo!(), PropertyValueEnum::ObjectLink(object_link_value) => todo!(), @@ -314,7 +391,13 @@ impl Visitor for TypeChecker<'_> { Kind::ErrorTree => return Visit::Skip, Kind::Entry => { - match resolve_entry(&mut self.ctx, tree).map_err(|e| e.fallback(tree.span)) { + match resolve_entry( + &mut self.ctx, + tree, + self.current.as_ref().map(|(_k, v)| v.rito_type()), + ) + .map_err(|e| e.fallback(tree.span)) + { Ok(entry) => { eprintln!("entry: {entry:?}"); self.inject_child( From b1fbdc3988346dc830c2670ffbe12db4772532ab Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Sun, 11 Jan 2026 21:11:15 +0000 Subject: [PATCH 065/187] feat: working basic type construction --- crates/ltk_ritobin/src/typecheck/visitor.rs | 194 ++++++++++++++------ 1 file changed, 142 insertions(+), 52 deletions(-) diff --git a/crates/ltk_ritobin/src/typecheck/visitor.rs b/crates/ltk_ritobin/src/typecheck/visitor.rs index c86c97b4..12ecdb07 100644 --- a/crates/ltk_ritobin/src/typecheck/visitor.rs +++ b/crates/ltk_ritobin/src/typecheck/visitor.rs @@ -14,10 +14,66 @@ use crate::{ typecheck::RitobinName, }; +#[derive(Debug, Clone)] +pub struct IrEntry { + pub key: PropertyValueEnum, + pub value: PropertyValueEnum, +} + +#[derive(Debug, Clone)] +pub struct IrListItem(pub PropertyValueEnum); + +#[derive(Debug, Clone)] +pub enum IrItem { + Entry(IrEntry), + ListItem(IrListItem), +} + +impl IrItem { + pub fn is_entry(&self) -> bool { + matches!(self, Self::Entry { .. }) + } + + pub fn as_entry(&self) -> Option<&IrEntry> { + match self { + IrItem::Entry(i) => Some(i), + _ => None, + } + } + pub fn is_list_item(&self) -> bool { + matches!(self, Self::ListItem { .. }) + } + pub fn as_list_item(&self) -> Option<&IrListItem> { + match self { + IrItem::ListItem(i) => Some(i), + _ => None, + } + } + pub fn value(&self) -> &PropertyValueEnum { + match self { + IrItem::Entry(i) => &i.value, + IrItem::ListItem(i) => &i.0, + } + } + pub fn value_mut(&mut self) -> &mut PropertyValueEnum { + match self { + IrItem::Entry(i) => &mut i.value, + IrItem::ListItem(i) => &mut i.0, + } + } + pub fn into_value(self) -> PropertyValueEnum { + match self { + IrItem::Entry(i) => i.value, + IrItem::ListItem(i) => i.0, + } + } +} + pub struct TypeChecker<'a> { ctx: Ctx<'a>, pub root: IndexMap, - current: Option<(PropertyValueEnum, PropertyValueEnum)>, + // current: Option<(PropertyValueEnum, PropertyValueEnum)>, + stack: Vec<(u32, IrItem)>, depth: u32, } @@ -29,7 +85,7 @@ impl<'a> TypeChecker<'a> { diagnostics: Vec::new(), }, root: IndexMap::new(), - current: None, + stack: Vec::new(), depth: 0, } } @@ -162,6 +218,10 @@ impl RitoType { self.subtypes[idx].unwrap_or_default() } + fn value_subtype(&self) -> Option { + self.subtypes[1].or(self.subtypes[0]) + } + pub fn make_default(&self) -> PropertyValueEnum { match self.base { BinPropertyKind::Map => PropertyValueEnum::Map(MapValue { @@ -293,11 +353,15 @@ pub fn resolve_entry( ctx: &mut Ctx, tree: &Cst, parent_value_kind: Option, -) -> Result<(Span, PropertyValueEnum), MaybeSpanDiag> { +) -> Result { let mut c = tree.children.iter(); let key = c.expect_tree(Kind::EntryKey)?; + let parent_value_kind = parent_value_kind + .and_then(|p| p.value_subtype()) + .map(RitoType::simple); + let kind = c .clone() .find_map(|c| c.tree().filter(|t| t.kind == Kind::TypeExpr)) @@ -324,7 +388,10 @@ pub fn resolve_entry( (Some(kind), _) => kind.make_default(), }; - Ok((key.span, value)) + Ok(IrEntry { + key: PropertyValueEnum::String(StringValue(ctx.text[key.span].into())), + value, + }) } pub fn resolve_list(ctx: &mut Ctx, tree: &Cst) -> Result<(), Diagnostic> { @@ -332,80 +399,73 @@ pub fn resolve_list(ctx: &mut Ctx, tree: &Cst) -> Result<(), Diagnostic> { } impl TypeChecker<'_> { - fn inject_child(&mut self, key: Option, child: PropertyValueEnum) { - let Some(current) = self.current.as_mut() else { - let Some(key) = key else { - return; - }; - self.current.replace((key, child)); - return; - }; - - if current.1.kind().subtype_count() == 0 { + fn merge_ir(&mut self, mut parent: IrItem, child: IrItem) -> IrItem { + if parent.value().kind().subtype_count() == 0 { eprintln!("cant inject into non container"); - return; + return parent; } - match &mut current.1 { - PropertyValueEnum::Container(value) - | PropertyValueEnum::UnorderedContainer(UnorderedContainerValue(value)) => { - if value.item_kind != child.kind() { + match parent.value_mut() { + PropertyValueEnum::Container(list) + | PropertyValueEnum::UnorderedContainer(UnorderedContainerValue(list)) => { + let IrItem::ListItem(IrListItem(value)) = child else { + eprintln!("list item must be list item"); + return parent; + }; + if list.item_kind != value.kind() { eprintln!( "container kind mismatch {:?} / {:?}", - value.item_kind, - child.kind() + list.item_kind, + value.kind() ); - return; + return parent; } - value.items.push(child); + list.items.push(value); } PropertyValueEnum::Struct(struct_value) => todo!(), PropertyValueEnum::Embedded(embedded_value) => todo!(), PropertyValueEnum::ObjectLink(object_link_value) => todo!(), PropertyValueEnum::Map(map_value) => { - if map_value.value_kind != child.kind() { + let IrItem::Entry(IrEntry { key, value }) = child else { + eprintln!("map item must be entry"); + return parent; + }; + if map_value.value_kind != value.kind() { eprintln!( "map value kind mismatch {:?} / {:?}", map_value.value_kind, - child.kind() + value.kind() ); - return; + return parent; } - let Some(key) = key else { - return; - }; map_value .entries - .insert(ltk_meta::value::PropertyValueUnsafeEq(key), child); + .insert(ltk_meta::value::PropertyValueUnsafeEq(key), value); } _ => unreachable!("non container"), } + parent } } impl Visitor for TypeChecker<'_> { fn enter_tree(&mut self, tree: &Cst) -> Visit { self.depth += 1; - eprintln!("depth -> {} | {}", self.depth, tree.kind); + let indent = " ".repeat(self.depth.saturating_sub(1) as _); + eprintln!("{indent}> d:{} | {:?}", self.depth, tree.kind); + eprintln!("{indent}> stack: {:?}", &self.stack); + + let parent = self.stack.last(); match tree.kind { Kind::ErrorTree => return Visit::Skip, Kind::Entry => { - match resolve_entry( - &mut self.ctx, - tree, - self.current.as_ref().map(|(_k, v)| v.rito_type()), - ) - .map_err(|e| e.fallback(tree.span)) + match resolve_entry(&mut self.ctx, tree, parent.map(|p| p.1.value().rito_type())) + .map_err(|e| e.fallback(tree.span)) { Ok(entry) => { eprintln!("entry: {entry:?}"); - self.inject_child( - Some(PropertyValueEnum::String(StringValue( - self.ctx.text[entry.0].to_string(), - ))), - entry.1, - ); + self.stack.push((self.depth, IrItem::Entry(entry))); } Err(e) => self.ctx.diagnostics.push(e), } @@ -438,21 +498,51 @@ impl Visitor for TypeChecker<'_> { fn exit_tree(&mut self, tree: &cst::Cst) -> Visit { self.depth -= 1; - eprintln!("depth <- {} | {}", self.depth, tree.kind); + let indent = " ".repeat(self.depth.saturating_sub(1) as _); + eprintln!("{indent}< d:{} | {:?}", self.depth, tree.kind); + eprintln!("{indent}< stack: {:?}", &self.stack); if tree.kind == cst::Kind::ErrorTree { return Visit::Continue; } - if self.depth == 1 { - match self.current.take() { - Some((PropertyValueEnum::String(StringValue(name)), value)) => { - // TODO: warn when shadowed - - let _existing = self.root.insert(name, value); + match self.stack.pop() { + Some(ir) => { + if ir.0 != self.depth + 1 { + self.stack.push(ir); + return Visit::Continue; } - _ => { - // eprintln!("exit tree with no current?"); + match self.stack.pop() { + Some(parent) => { + let parent = self.merge_ir(parent.1, ir.1); + self.stack.push((self.depth, parent)); + } + None => { + let ( + _, + IrItem::Entry(IrEntry { + key: PropertyValueEnum::String(StringValue(key)), + value, + }), + ) = ir.clone() + else { + match self.depth { + 1 => self + .ctx + .diagnostics + .push(RootNonEntry.default_span(tree.span)), + _ => { + self.stack.push(ir); + } + } + return Visit::Continue; + }; + let _existing = self.root.insert(key, value); + } } + // TODO: warn when shadowed + } + _ => { + // eprintln!("exit tree with no current?"); } } From edb44afd06be47335fdd8b4bc11496b8587bc31b Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Sun, 11 Jan 2026 23:07:09 +0000 Subject: [PATCH 066/187] wip: literal resolving --- crates/ltk_ritobin/src/typecheck/visitor.rs | 71 +++++++++++++++++---- 1 file changed, 58 insertions(+), 13 deletions(-) diff --git a/crates/ltk_ritobin/src/typecheck/visitor.rs b/crates/ltk_ritobin/src/typecheck/visitor.rs index 12ecdb07..27b27ff1 100644 --- a/crates/ltk_ritobin/src/typecheck/visitor.rs +++ b/crates/ltk_ritobin/src/typecheck/visitor.rs @@ -1,3 +1,5 @@ +use std::num::ParseIntError; + use indexmap::IndexMap; use ltk_meta::{ value::{ @@ -101,6 +103,8 @@ pub enum Diagnostic { UnknownType(Span), MissingType(Span), + ResolveLiteral, + RootNonEntry, SubtypeCountMismatch { @@ -118,7 +122,7 @@ pub enum Diagnostic { impl Diagnostic { pub fn span(&self) -> Option<&Span> { match self { - MissingTree(_) | EmptyTree(_) | MissingToken(_) | RootNonEntry => None, + MissingTree(_) | EmptyTree(_) | MissingToken(_) | RootNonEntry | ResolveLiteral => None, UnknownType(span) | SubtypeCountMismatch { span, .. } | UnexpectedSubtypes { span, .. } @@ -349,6 +353,46 @@ pub fn resolve_rito_type(ctx: &mut Ctx<'_>, tree: &Cst) -> Result, +) -> Result, Diagnostic> { + use ltk_meta::value::*; + use BinPropertyKind as K; + use PropertyValueEnum as P; + + if tree.children.len() != 1 { + return Ok(None); + } + Ok(Some( + match tree.children.first().unwrap(/* checked above */) { + cst::Child::Token(Token { + kind: TokenKind::String, + span, + }) => P::String(StringValue(ctx.text[span].into())), + cst::Child::Token(Token { + kind: TokenKind::Number, + span, + }) => { + let txt = &ctx.text[span]; + let Some(kind_hint) = kind_hint else { + return Ok(None); + }; + + dbg!(kind_hint); + match kind_hint { + K::U8 => P::U8(U8Value( + txt.parse().map_err(|_| Diagnostic::ResolveLiteral)?, + )), + _ => return Ok(None), + } + } + _ => return Ok(None), + }, + )) +} + pub fn resolve_entry( ctx: &mut Ctx, tree: &Cst, @@ -370,18 +414,19 @@ pub fn resolve_entry( .or(parent_value_kind); let value = c.expect_tree(Kind::EntryValue)?; - let inferred_value = match value.children.first() { - Some(cst::Child::Token(Token { - kind: TokenKind::String, - span, - .. - })) => Some(PropertyValueEnum::String(ltk_meta::value::StringValue( - ctx.text[span].into(), - ))), - _ => None, - }; - - let value = match (kind, inferred_value) { + let literal = resolve_literal(ctx, tree, kind.map(|k| k.base))?; + // let inferred_value = match value.children.first() { + // Some(cst::Child::Token(Token { + // kind: TokenKind::String, + // span, + // .. + // })) => Some(PropertyValueEnum::String(ltk_meta::value::StringValue( + // ctx.text[span].into(), + // ))), + // _ => None, + // }; + + let value = match (kind, literal) { (None, Some(value)) => value, (None, None) => return Err(MissingType(key.span).into()), (Some(kind), Some(ivalue)) if ivalue.kind() == kind.base => ivalue, From e55d17b640eb0017f20ba5219fee9423f30964ff Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Mon, 12 Jan 2026 10:59:20 +0000 Subject: [PATCH 067/187] feat: VisitorExt --- crates/ltk_ritobin/src/parse/cst/visitor.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/crates/ltk_ritobin/src/parse/cst/visitor.rs b/crates/ltk_ritobin/src/parse/cst/visitor.rs index dbdd1335..ff4c92f0 100644 --- a/crates/ltk_ritobin/src/parse/cst/visitor.rs +++ b/crates/ltk_ritobin/src/parse/cst/visitor.rs @@ -26,6 +26,15 @@ pub trait Visitor { } } +pub trait VisitorExt: Sized + Visitor { + fn walk(mut self, tree: &Cst) -> Self { + tree.walk(&mut self); + self + } +} + +impl VisitorExt for T {} + impl Cst { pub fn walk(&self, visitor: &mut V) { self.walk_inner(visitor); From 3c0b75c64fd3ad7aa8dbf71bce8522a71cf7d8ac Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Mon, 12 Jan 2026 10:59:24 +0000 Subject: [PATCH 068/187] feat: Span::intersects --- crates/ltk_ritobin/src/parse/span.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/crates/ltk_ritobin/src/parse/span.rs b/crates/ltk_ritobin/src/parse/span.rs index dd4beea7..48eac9d6 100644 --- a/crates/ltk_ritobin/src/parse/span.rs +++ b/crates/ltk_ritobin/src/parse/span.rs @@ -17,6 +17,12 @@ impl Span { pub fn contains(&self, offset: u32) -> bool { self.start <= offset && offset <= self.end } + + #[must_use] + #[inline] + pub fn intersects(&self, other: &Span) -> bool { + self.start < other.end && other.start < self.end + } } impl std::ops::Index for str { From c25620e1b71de6aa3fba670a86e2abc3e5e4610a Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Mon, 12 Jan 2026 10:59:47 +0000 Subject: [PATCH 069/187] feat: spanned IR entries + entry shadow diagnostic --- crates/ltk_ritobin/src/typecheck/visitor.rs | 136 ++++++++++++++------ 1 file changed, 99 insertions(+), 37 deletions(-) diff --git a/crates/ltk_ritobin/src/typecheck/visitor.rs b/crates/ltk_ritobin/src/typecheck/visitor.rs index 27b27ff1..842e21fe 100644 --- a/crates/ltk_ritobin/src/typecheck/visitor.rs +++ b/crates/ltk_ritobin/src/typecheck/visitor.rs @@ -1,4 +1,7 @@ -use std::num::ParseIntError; +use std::{ + num::ParseIntError, + ops::{Deref, DerefMut}, +}; use indexmap::IndexMap; use ltk_meta::{ @@ -16,14 +19,49 @@ use crate::{ typecheck::RitobinName, }; +pub trait SpannedExt { + fn with_span(self, span: Span) -> Spanned + where + Self: Sized, + { + Spanned::new(self, span) + } +} +impl SpannedExt for T {} + +#[derive(Debug, Clone, Copy)] +pub struct Spanned { + pub span: Span, + pub inner: T, +} + +impl Spanned { + pub fn new(item: T, span: Span) -> Self { + Self { inner: item, span } + } +} + +impl Deref for Spanned { + type Target = T; + + fn deref(&self) -> &Self::Target { + &self.inner + } +} +impl DerefMut for Spanned { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.inner + } +} + #[derive(Debug, Clone)] pub struct IrEntry { - pub key: PropertyValueEnum, - pub value: PropertyValueEnum, + pub key: Spanned, + pub value: Spanned, } #[derive(Debug, Clone)] -pub struct IrListItem(pub PropertyValueEnum); +pub struct IrListItem(pub Spanned); #[derive(Debug, Clone)] pub enum IrItem { @@ -51,19 +89,19 @@ impl IrItem { _ => None, } } - pub fn value(&self) -> &PropertyValueEnum { + pub fn value(&self) -> &Spanned { match self { IrItem::Entry(i) => &i.value, IrItem::ListItem(i) => &i.0, } } - pub fn value_mut(&mut self) -> &mut PropertyValueEnum { + pub fn value_mut(&mut self) -> &mut Spanned { match self { IrItem::Entry(i) => &mut i.value, IrItem::ListItem(i) => &mut i.0, } } - pub fn into_value(self) -> PropertyValueEnum { + pub fn into_value(self) -> Spanned { match self { IrItem::Entry(i) => i.value, IrItem::ListItem(i) => i.0, @@ -73,7 +111,7 @@ impl IrItem { pub struct TypeChecker<'a> { ctx: Ctx<'a>, - pub root: IndexMap, + pub root: IndexMap>, // current: Option<(PropertyValueEnum, PropertyValueEnum)>, stack: Vec<(u32, IrItem)>, depth: u32, @@ -91,7 +129,12 @@ impl<'a> TypeChecker<'a> { depth: 0, } } - pub fn into_parts(self) -> (IndexMap, Vec) { + pub fn into_parts( + self, + ) -> ( + IndexMap>, + Vec, + ) { (self.root, self.ctx.diagnostics) } } @@ -106,6 +149,10 @@ pub enum Diagnostic { ResolveLiteral, RootNonEntry, + ShadowedEntry { + shadowee: Span, + shadower: Span, + }, SubtypeCountMismatch { span: Span, @@ -126,7 +173,8 @@ impl Diagnostic { UnknownType(span) | SubtypeCountMismatch { span, .. } | UnexpectedSubtypes { span, .. } - | MissingType(span) => Some(span), + | MissingType(span) + | ShadowedEntry { shadower: span, .. } => Some(span), } } @@ -414,6 +462,7 @@ pub fn resolve_entry( .or(parent_value_kind); let value = c.expect_tree(Kind::EntryValue)?; + let value_span = value.span; let literal = resolve_literal(ctx, tree, kind.map(|k| k.base))?; // let inferred_value = match value.children.first() { // Some(cst::Child::Token(Token { @@ -434,8 +483,8 @@ pub fn resolve_entry( }; Ok(IrEntry { - key: PropertyValueEnum::String(StringValue(ctx.text[key.span].into())), - value, + key: PropertyValueEnum::String(StringValue(ctx.text[key.span].into())).with_span(key.span), + value: value.with_span(value_span), }) } @@ -446,45 +495,46 @@ pub fn resolve_list(ctx: &mut Ctx, tree: &Cst) -> Result<(), Diagnostic> { impl TypeChecker<'_> { fn merge_ir(&mut self, mut parent: IrItem, child: IrItem) -> IrItem { if parent.value().kind().subtype_count() == 0 { - eprintln!("cant inject into non container"); + // eprintln!("cant inject into non container"); return parent; } - match parent.value_mut() { + match &mut parent.value_mut().inner { PropertyValueEnum::Container(list) | PropertyValueEnum::UnorderedContainer(UnorderedContainerValue(list)) => { let IrItem::ListItem(IrListItem(value)) = child else { - eprintln!("list item must be list item"); + // eprintln!("list item must be list item"); return parent; }; if list.item_kind != value.kind() { - eprintln!( - "container kind mismatch {:?} / {:?}", - list.item_kind, - value.kind() - ); + // eprintln!( + // "container kind mismatch {:?} / {:?}", + // list.item_kind, + // value.kind() + // ); return parent; } - list.items.push(value); + list.items.push(value.inner); // FIXME: span info inside all containers?? } PropertyValueEnum::Struct(struct_value) => todo!(), PropertyValueEnum::Embedded(embedded_value) => todo!(), PropertyValueEnum::ObjectLink(object_link_value) => todo!(), PropertyValueEnum::Map(map_value) => { let IrItem::Entry(IrEntry { key, value }) = child else { - eprintln!("map item must be entry"); + // eprintln!("map item must be entry"); return parent; }; if map_value.value_kind != value.kind() { - eprintln!( - "map value kind mismatch {:?} / {:?}", - map_value.value_kind, - value.kind() - ); + // eprintln!( + // "map value kind mismatch {:?} / {:?}", + // map_value.value_kind, + // value.kind() + // ); return parent; } - map_value - .entries - .insert(ltk_meta::value::PropertyValueUnsafeEq(key), value); + map_value.entries.insert( + ltk_meta::value::PropertyValueUnsafeEq(key.inner), + value.inner, + ); } _ => unreachable!("non container"), } @@ -496,8 +546,8 @@ impl Visitor for TypeChecker<'_> { fn enter_tree(&mut self, tree: &Cst) -> Visit { self.depth += 1; let indent = " ".repeat(self.depth.saturating_sub(1) as _); - eprintln!("{indent}> d:{} | {:?}", self.depth, tree.kind); - eprintln!("{indent}> stack: {:?}", &self.stack); + // eprintln!("{indent}> d:{} | {:?}", self.depth, tree.kind); + // eprintln!("{indent}> stack: {:?}", &self.stack); let parent = self.stack.last(); @@ -509,7 +559,7 @@ impl Visitor for TypeChecker<'_> { .map_err(|e| e.fallback(tree.span)) { Ok(entry) => { - eprintln!("entry: {entry:?}"); + // eprintln!("entry: {entry:?}"); self.stack.push((self.depth, IrItem::Entry(entry))); } Err(e) => self.ctx.diagnostics.push(e), @@ -544,8 +594,8 @@ impl Visitor for TypeChecker<'_> { fn exit_tree(&mut self, tree: &cst::Cst) -> Visit { self.depth -= 1; let indent = " ".repeat(self.depth.saturating_sub(1) as _); - eprintln!("{indent}< d:{} | {:?}", self.depth, tree.kind); - eprintln!("{indent}< stack: {:?}", &self.stack); + // eprintln!("{indent}< d:{} | {:?}", self.depth, tree.kind); + // eprintln!("{indent}< stack: {:?}", &self.stack); if tree.kind == cst::Kind::ErrorTree { return Visit::Continue; } @@ -565,7 +615,11 @@ impl Visitor for TypeChecker<'_> { let ( _, IrItem::Entry(IrEntry { - key: PropertyValueEnum::String(StringValue(key)), + key: + Spanned { + span: key_span, + inner: PropertyValueEnum::String(StringValue(key)), + }, value, }), ) = ir.clone() @@ -581,7 +635,15 @@ impl Visitor for TypeChecker<'_> { } return Visit::Continue; }; - let _existing = self.root.insert(key, value); + if let Some(existing) = self.root.insert(key, value) { + self.ctx.diagnostics.push( + ShadowedEntry { + shadowee: existing.span, + shadower: key_span, + } + .unwrap(), + ); + } } } // TODO: warn when shadowed From 012aad56fa50aba6de84a4961eafb01bf3d0e6f0 Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Mon, 12 Jan 2026 11:17:37 +0000 Subject: [PATCH 070/187] fix: typecheck stack --- crates/ltk_ritobin/src/typecheck/visitor.rs | 83 ++++++++++++--------- 1 file changed, 48 insertions(+), 35 deletions(-) diff --git a/crates/ltk_ritobin/src/typecheck/visitor.rs b/crates/ltk_ritobin/src/typecheck/visitor.rs index 842e21fe..8ed51936 100644 --- a/crates/ltk_ritobin/src/typecheck/visitor.rs +++ b/crates/ltk_ritobin/src/typecheck/visitor.rs @@ -495,22 +495,22 @@ pub fn resolve_list(ctx: &mut Ctx, tree: &Cst) -> Result<(), Diagnostic> { impl TypeChecker<'_> { fn merge_ir(&mut self, mut parent: IrItem, child: IrItem) -> IrItem { if parent.value().kind().subtype_count() == 0 { - // eprintln!("cant inject into non container"); + eprintln!("cant inject into non container"); return parent; } match &mut parent.value_mut().inner { PropertyValueEnum::Container(list) | PropertyValueEnum::UnorderedContainer(UnorderedContainerValue(list)) => { let IrItem::ListItem(IrListItem(value)) = child else { - // eprintln!("list item must be list item"); + eprintln!("list item must be list item"); return parent; }; if list.item_kind != value.kind() { - // eprintln!( - // "container kind mismatch {:?} / {:?}", - // list.item_kind, - // value.kind() - // ); + eprintln!( + "container kind mismatch {:?} / {:?}", + list.item_kind, + value.kind() + ); return parent; } list.items.push(value.inner); // FIXME: span info inside all containers?? @@ -520,15 +520,15 @@ impl TypeChecker<'_> { PropertyValueEnum::ObjectLink(object_link_value) => todo!(), PropertyValueEnum::Map(map_value) => { let IrItem::Entry(IrEntry { key, value }) = child else { - // eprintln!("map item must be entry"); + eprintln!("map item must be entry"); return parent; }; if map_value.value_kind != value.kind() { - // eprintln!( - // "map value kind mismatch {:?} / {:?}", - // map_value.value_kind, - // value.kind() - // ); + eprintln!( + "map value kind mismatch {:?} / {:?}", + map_value.value_kind, + value.kind() + ); return parent; } map_value.entries.insert( @@ -545,9 +545,18 @@ impl TypeChecker<'_> { impl Visitor for TypeChecker<'_> { fn enter_tree(&mut self, tree: &Cst) -> Visit { self.depth += 1; - let indent = " ".repeat(self.depth.saturating_sub(1) as _); - // eprintln!("{indent}> d:{} | {:?}", self.depth, tree.kind); - // eprintln!("{indent}> stack: {:?}", &self.stack); + let depth = self.depth; + + let indent = " ".repeat(depth.saturating_sub(1) as _); + eprintln!("{indent}> d:{} | {:?}", depth, tree.kind); + eprint!("{indent} stack: "); + if self.stack.is_empty() { + eprint!("empty") + } + eprintln!(); + for s in &self.stack { + eprintln!("{indent} - {}: {:?}", s.0, s.1); + } let parent = self.stack.last(); @@ -559,8 +568,8 @@ impl Visitor for TypeChecker<'_> { .map_err(|e| e.fallback(tree.span)) { Ok(entry) => { - // eprintln!("entry: {entry:?}"); - self.stack.push((self.depth, IrItem::Entry(entry))); + eprintln!("{indent} push {entry:?}"); + self.stack.push((depth, IrItem::Entry(entry))); } Err(e) => self.ctx.diagnostics.push(e), } @@ -576,7 +585,7 @@ impl Visitor for TypeChecker<'_> { // Kind::Entry => {} // Kind::File => return Visit::Continue, // kind => { - // if self.depth == 2 { + // if depth == 2 { // self.ctx // .diagnostics // .push(RootNonEntry.default_span(tree.span)); @@ -592,26 +601,36 @@ impl Visitor for TypeChecker<'_> { } fn exit_tree(&mut self, tree: &cst::Cst) -> Visit { + let depth = self.depth; self.depth -= 1; - let indent = " ".repeat(self.depth.saturating_sub(1) as _); - // eprintln!("{indent}< d:{} | {:?}", self.depth, tree.kind); - // eprintln!("{indent}< stack: {:?}", &self.stack); + let indent = " ".repeat(depth.saturating_sub(1) as _); + eprintln!("{indent}< d:{} | {:?}", depth, tree.kind); + eprint!("{indent} stack: "); + if self.stack.is_empty() { + eprint!("empty") + } + eprintln!(); + for s in &self.stack { + eprintln!("{indent} - {}: {:?}", s.0, s.1); + } if tree.kind == cst::Kind::ErrorTree { return Visit::Continue; } match self.stack.pop() { Some(ir) => { - if ir.0 != self.depth + 1 { + eprintln!("{indent}< popped {}", ir.0); + if ir.0 != depth { self.stack.push(ir); return Visit::Continue; } match self.stack.pop() { - Some(parent) => { - let parent = self.merge_ir(parent.1, ir.1); - self.stack.push((self.depth, parent)); + Some((d, parent)) => { + let parent = self.merge_ir(parent, ir.1); + self.stack.push((d, parent)); } None => { + assert_eq!(depth, 2); let ( _, IrItem::Entry(IrEntry { @@ -624,15 +643,9 @@ impl Visitor for TypeChecker<'_> { }), ) = ir.clone() else { - match self.depth { - 1 => self - .ctx - .diagnostics - .push(RootNonEntry.default_span(tree.span)), - _ => { - self.stack.push(ir); - } - } + self.ctx + .diagnostics + .push(RootNonEntry.default_span(tree.span)); return Visit::Continue; }; if let Some(existing) = self.root.insert(key, value) { From b7a67d7e4815bc22b604cb8f69d0b05caeff9905 Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Mon, 12 Jan 2026 11:30:15 +0000 Subject: [PATCH 071/187] fix (parse): wrap string literals in TreeKind::Literal --- crates/ltk_ritobin/src/parse/impls.rs | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/crates/ltk_ritobin/src/parse/impls.rs b/crates/ltk_ritobin/src/parse/impls.rs index fc137bcd..9bbc8c9e 100644 --- a/crates/ltk_ritobin/src/parse/impls.rs +++ b/crates/ltk_ritobin/src/parse/impls.rs @@ -32,7 +32,7 @@ pub fn stmt_or_list_item(p: &mut Parser) { } (Name | HexLit | String | Number | True | False, _, _) => { let m = p.open(); - p.advance(); + p.scope(TreeKind::Literal, |p| p.advance()); p.close(m, TreeKind::ListItem); p.eat(Comma); } @@ -94,12 +94,6 @@ pub fn stmt(p: &mut Parser) { pub fn entry_value(p: &mut Parser) -> bool { p.scope(TreeKind::EntryValue, |p| { match (p.nth(0), p.nth(1)) { - (String, _) => { - p.advance(); - } - (UnterminatedString, _) => { - p.advance_with_error(ErrorKind::UnterminatedString, None); - } (Name, _) | (HexLit, LCurly) => { p.scope(TreeKind::Class, |p| { p.advance(); @@ -108,10 +102,11 @@ pub fn entry_value(p: &mut Parser) -> bool { } }); } - (Number | HexLit | True | False, _) => { - let m = p.open(); - p.advance(); - p.close(m, TreeKind::Literal); + (UnterminatedString, _) => { + p.advance_with_error(ErrorKind::UnterminatedString, None); + } + (String | Number | HexLit | True | False, _) => { + p.scope(TreeKind::Literal, |p| p.advance()); } (LCurly, _) => { block(p); From 5d700b370434438b2ea3e91ab398b4f70c2843c8 Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Mon, 12 Jan 2026 11:30:30 +0000 Subject: [PATCH 072/187] fix: look for Literal when calling literal resolve --- crates/ltk_ritobin/src/typecheck/visitor.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/crates/ltk_ritobin/src/typecheck/visitor.rs b/crates/ltk_ritobin/src/typecheck/visitor.rs index 8ed51936..be1197df 100644 --- a/crates/ltk_ritobin/src/typecheck/visitor.rs +++ b/crates/ltk_ritobin/src/typecheck/visitor.rs @@ -463,7 +463,14 @@ pub fn resolve_entry( let value = c.expect_tree(Kind::EntryValue)?; let value_span = value.span; - let literal = resolve_literal(ctx, tree, kind.map(|k| k.base))?; + let literal = value + .children + .iter() + .expect_tree(Kind::Literal) + .ok() + .map(|tree| resolve_literal(ctx, tree, kind.map(|k| k.base))) + .transpose()? + .flatten(); // let inferred_value = match value.children.first() { // Some(cst::Child::Token(Token { // kind: TokenKind::String, From b7507ad9a3a551bde04c9f12e22a696c18af4cf5 Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Mon, 12 Jan 2026 11:30:36 +0000 Subject: [PATCH 073/187] feat: TypeMismatch error --- crates/ltk_ritobin/src/typecheck/visitor.rs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/crates/ltk_ritobin/src/typecheck/visitor.rs b/crates/ltk_ritobin/src/typecheck/visitor.rs index be1197df..1f85ccf2 100644 --- a/crates/ltk_ritobin/src/typecheck/visitor.rs +++ b/crates/ltk_ritobin/src/typecheck/visitor.rs @@ -174,6 +174,7 @@ impl Diagnostic { | SubtypeCountMismatch { span, .. } | UnexpectedSubtypes { span, .. } | MissingType(span) + | TypeMismatch { span, .. } | ShadowedEntry { shadower: span, .. } => Some(span), } } @@ -485,7 +486,17 @@ pub fn resolve_entry( let value = match (kind, literal) { (None, Some(value)) => value, (None, None) => return Err(MissingType(key.span).into()), - (Some(kind), Some(ivalue)) if ivalue.kind() == kind.base => ivalue, + (Some(kind), Some(ivalue)) => match ivalue.kind() == kind.base { + true => ivalue, + false => { + return Err(TypeMismatch { + span: value_span, + expected: kind, + got: ivalue.rito_type(), + } + .into()) + } + }, (Some(kind), _) => kind.make_default(), }; From 6a6bfc3741f02b4459703d85a1f4c787f7460f51 Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Mon, 12 Jan 2026 11:45:47 +0000 Subject: [PATCH 074/187] feat: err on type mismatch in resolve_literal --- crates/ltk_ritobin/src/typecheck/visitor.rs | 70 ++++++++++++++++++--- 1 file changed, 63 insertions(+), 7 deletions(-) diff --git a/crates/ltk_ritobin/src/typecheck/visitor.rs b/crates/ltk_ritobin/src/typecheck/visitor.rs index 1f85ccf2..a79a557e 100644 --- a/crates/ltk_ritobin/src/typecheck/visitor.rs +++ b/crates/ltk_ritobin/src/typecheck/visitor.rs @@ -1,4 +1,5 @@ use std::{ + fmt::{Debug, Display}, num::ParseIntError, ops::{Deref, DerefMut}, }; @@ -138,6 +139,34 @@ impl<'a> TypeChecker<'a> { (self.root, self.ctx.diagnostics) } } + +#[derive(Debug, Clone, Copy)] +pub enum RitoTypeOrNumeric { + RitoType(RitoType), + Numeric, +} + +impl RitoTypeOrNumeric { + pub fn numeric() -> Self { + Self::Numeric + } +} + +impl From for RitoTypeOrNumeric { + fn from(value: RitoType) -> Self { + RitoTypeOrNumeric::RitoType(value) + } +} + +impl Display for RitoTypeOrNumeric { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + RitoTypeOrNumeric::RitoType(rito_type) => Display::fmt(rito_type, f), + RitoTypeOrNumeric::Numeric => f.write_str("numeric type"), + } + } +} + #[derive(Debug, Clone, Copy)] pub enum Diagnostic { MissingTree(cst::Kind), @@ -146,6 +175,12 @@ pub enum Diagnostic { UnknownType(Span), MissingType(Span), + TypeMismatch { + span: Span, + expected: RitoType, + got: RitoTypeOrNumeric, + }, + ResolveLiteral, RootNonEntry, @@ -259,6 +294,20 @@ pub struct RitoType { pub subtypes: [Option; 2], } +impl Display for RitoType { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let base = self.base.to_ritobin_name(); + match self.subtypes { + [None, None] => f.write_str(base), + [Some(a), None] => write!(f, "{base}[{}]", a.to_ritobin_name()), + [Some(a), Some(b)] => { + write!(f, "{base}[{},{}]", a.to_ritobin_name(), b.to_ritobin_name()) + } + _ => write!(f, "{base}[!!]"), + } + } +} + impl RitoType { pub fn simple(kind: BinPropertyKind) -> Self { Self { @@ -406,7 +455,7 @@ pub fn resolve_literal( ctx: &mut Ctx, tree: &Cst, kind_hint: Option, -) -> Result, Diagnostic> { +) -> Result>, Diagnostic> { use ltk_meta::value::*; use BinPropertyKind as K; use PropertyValueEnum as P; @@ -419,7 +468,7 @@ pub fn resolve_literal( cst::Child::Token(Token { kind: TokenKind::String, span, - }) => P::String(StringValue(ctx.text[span].into())), + }) => P::String(StringValue(ctx.text[span].into())).with_span(*span), cst::Child::Token(Token { kind: TokenKind::Number, span, @@ -434,8 +483,15 @@ pub fn resolve_literal( K::U8 => P::U8(U8Value( txt.parse().map_err(|_| Diagnostic::ResolveLiteral)?, )), - _ => return Ok(None), + _ => { + return Err(TypeMismatch { + span: *span, + expected: RitoType::simple(kind_hint), + got: RitoTypeOrNumeric::numeric(), + }) + } } + .with_span(*span) } _ => return Ok(None), }, @@ -490,19 +546,19 @@ pub fn resolve_entry( true => ivalue, false => { return Err(TypeMismatch { - span: value_span, + span: ivalue.span, expected: kind, - got: ivalue.rito_type(), + got: ivalue.rito_type().into(), } .into()) } }, - (Some(kind), _) => kind.make_default(), + (Some(kind), _) => kind.make_default().with_span(value_span), }; Ok(IrEntry { key: PropertyValueEnum::String(StringValue(ctx.text[key.span].into())).with_span(key.span), - value: value.with_span(value_span), + value, }) } From 9b29083c0258c91158421baaae739eccea837e39 Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Mon, 12 Jan 2026 11:48:53 +0000 Subject: [PATCH 075/187] feat: resolve all numeric literals --- crates/ltk_ritobin/src/typecheck/visitor.rs | 22 ++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/crates/ltk_ritobin/src/typecheck/visitor.rs b/crates/ltk_ritobin/src/typecheck/visitor.rs index a79a557e..c298dc0a 100644 --- a/crates/ltk_ritobin/src/typecheck/visitor.rs +++ b/crates/ltk_ritobin/src/typecheck/visitor.rs @@ -478,11 +478,31 @@ pub fn resolve_literal( return Ok(None); }; - dbg!(kind_hint); match kind_hint { K::U8 => P::U8(U8Value( txt.parse().map_err(|_| Diagnostic::ResolveLiteral)?, )), + K::U16 => P::U16(U16Value( + txt.parse().map_err(|_| Diagnostic::ResolveLiteral)?, + )), + K::U32 => P::U32(U32Value( + txt.parse().map_err(|_| Diagnostic::ResolveLiteral)?, + )), + K::U64 => P::U64(U64Value( + txt.parse().map_err(|_| Diagnostic::ResolveLiteral)?, + )), + K::I8 => P::I8(I8Value( + txt.parse().map_err(|_| Diagnostic::ResolveLiteral)?, + )), + K::I16 => P::I16(I16Value( + txt.parse().map_err(|_| Diagnostic::ResolveLiteral)?, + )), + K::I32 => P::I32(I32Value( + txt.parse().map_err(|_| Diagnostic::ResolveLiteral)?, + )), + K::I64 => P::I64(I64Value( + txt.parse().map_err(|_| Diagnostic::ResolveLiteral)?, + )), _ => { return Err(TypeMismatch { span: *span, From 46d4cc9e53541ae8b3bb27e2ada606caa84373b9 Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Mon, 12 Jan 2026 11:54:17 +0000 Subject: [PATCH 076/187] feat: type mismatch error in merge_ir --- crates/ltk_ritobin/src/typecheck/visitor.rs | 54 +++++++++++++-------- 1 file changed, 33 insertions(+), 21 deletions(-) diff --git a/crates/ltk_ritobin/src/typecheck/visitor.rs b/crates/ltk_ritobin/src/typecheck/visitor.rs index c298dc0a..074e07f2 100644 --- a/crates/ltk_ritobin/src/typecheck/visitor.rs +++ b/crates/ltk_ritobin/src/typecheck/visitor.rs @@ -599,15 +599,22 @@ impl TypeChecker<'_> { eprintln!("list item must be list item"); return parent; }; - if list.item_kind != value.kind() { - eprintln!( - "container kind mismatch {:?} / {:?}", - list.item_kind, - value.kind() - ); - return parent; - } - list.items.push(value.inner); // FIXME: span info inside all containers?? + let value = match list.item_kind == value.kind() { + true => value.inner, // FIXME: span info inside all containers?? + false => { + self.ctx.diagnostics.push( + TypeMismatch { + span: value.span, + expected: RitoType::simple(list.item_kind), + got: RitoType::simple(value.kind()).into(), + } + .unwrap(), + ); + list.item_kind.default_value() + } + }; + + list.items.push(value); } PropertyValueEnum::Struct(struct_value) => todo!(), PropertyValueEnum::Embedded(embedded_value) => todo!(), @@ -617,18 +624,23 @@ impl TypeChecker<'_> { eprintln!("map item must be entry"); return parent; }; - if map_value.value_kind != value.kind() { - eprintln!( - "map value kind mismatch {:?} / {:?}", - map_value.value_kind, - value.kind() - ); - return parent; - } - map_value.entries.insert( - ltk_meta::value::PropertyValueUnsafeEq(key.inner), - value.inner, - ); + let value = match map_value.value_kind == value.kind() { + true => value.inner, // FIXME: span info inside all containers?? + false => { + self.ctx.diagnostics.push( + TypeMismatch { + span: value.span, + expected: RitoType::simple(map_value.value_kind), + got: RitoType::simple(value.kind()).into(), + } + .unwrap(), + ); + map_value.value_kind.default_value() + } + }; + map_value + .entries + .insert(ltk_meta::value::PropertyValueUnsafeEq(key.inner), value); } _ => unreachable!("non container"), } From 15fe5a54070ef8bfedd5885cf2610bd510857bd8 Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Mon, 12 Jan 2026 12:01:57 +0000 Subject: [PATCH 077/187] feat: type mismatch error for explicit type conflict w/ parent value type --- crates/ltk_ritobin/src/typecheck/visitor.rs | 36 ++++++++++++++++++--- 1 file changed, 31 insertions(+), 5 deletions(-) diff --git a/crates/ltk_ritobin/src/typecheck/visitor.rs b/crates/ltk_ritobin/src/typecheck/visitor.rs index 074e07f2..61870a68 100644 --- a/crates/ltk_ritobin/src/typecheck/visitor.rs +++ b/crates/ltk_ritobin/src/typecheck/visitor.rs @@ -288,7 +288,7 @@ impl PropertyValueExt for PropertyValueEnum { } } -#[derive(Debug, Clone, Copy)] +#[derive(Debug, Clone, Copy, PartialEq, Eq)] pub struct RitoType { pub base: BinPropertyKind, pub subtypes: [Option; 2], @@ -533,13 +533,39 @@ pub fn resolve_entry( let kind = c .clone() - .find_map(|c| c.tree().filter(|t| t.kind == Kind::TypeExpr)) - .map(|t| resolve_rito_type(ctx, t)) - .transpose()? - .or(parent_value_kind); + .find_map(|c| c.tree().filter(|t| t.kind == Kind::TypeExpr)); + let kind_span = kind.map(|k| k.span); + let kind = kind.map(|t| resolve_rito_type(ctx, t)).transpose()?; let value = c.expect_tree(Kind::EntryValue)?; let value_span = value.span; + + // entries: map[string, u8] = { + // "bad": string = "string" + // ^ + // } + if let Some(parent) = parent_value_kind.as_ref() { + if let Some((kind, kind_span)) = kind.as_ref().zip(kind_span) { + if parent != kind { + ctx.diagnostics.push( + TypeMismatch { + span: kind_span, + expected: *parent, + got: (*kind).into(), + } + .unwrap(), + ); + return Ok(IrEntry { + key: PropertyValueEnum::String(StringValue(ctx.text[key.span].into())) + .with_span(key.span), + value: parent.make_default().with_span(value.span), + }); + } + } + } + + let kind = kind.or(parent_value_kind); + let literal = value .children .iter() From f1a60580e6110e8e8cd5551dd82caa30494a751c Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Mon, 12 Jan 2026 12:25:15 +0000 Subject: [PATCH 078/187] feat: add expected_span to TypeMismatch diag --- crates/ltk_ritobin/src/typecheck/visitor.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/crates/ltk_ritobin/src/typecheck/visitor.rs b/crates/ltk_ritobin/src/typecheck/visitor.rs index 61870a68..bf3966f9 100644 --- a/crates/ltk_ritobin/src/typecheck/visitor.rs +++ b/crates/ltk_ritobin/src/typecheck/visitor.rs @@ -178,6 +178,7 @@ pub enum Diagnostic { TypeMismatch { span: Span, expected: RitoType, + expected_span: Option, got: RitoTypeOrNumeric, }, @@ -507,8 +508,9 @@ pub fn resolve_literal( return Err(TypeMismatch { span: *span, expected: RitoType::simple(kind_hint), + expected_span: None, // TODO: would be nice here got: RitoTypeOrNumeric::numeric(), - }) + }); } } .with_span(*span) @@ -551,6 +553,7 @@ pub fn resolve_entry( TypeMismatch { span: kind_span, expected: *parent, + expected_span: None, // TODO: would be nice here got: (*kind).into(), } .unwrap(), @@ -594,6 +597,7 @@ pub fn resolve_entry( return Err(TypeMismatch { span: ivalue.span, expected: kind, + expected_span: kind_span, got: ivalue.rito_type().into(), } .into()) @@ -632,6 +636,7 @@ impl TypeChecker<'_> { TypeMismatch { span: value.span, expected: RitoType::simple(list.item_kind), + expected_span: None, // TODO: would be nice here got: RitoType::simple(value.kind()).into(), } .unwrap(), @@ -657,6 +662,7 @@ impl TypeChecker<'_> { TypeMismatch { span: value.span, expected: RitoType::simple(map_value.value_kind), + expected_span: None, // TODO: would be nice here got: RitoType::simple(value.kind()).into(), } .unwrap(), From 68af9bd05602524139e071a22b0d2e8320233f92 Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Mon, 12 Jan 2026 12:25:31 +0000 Subject: [PATCH 079/187] feat: merge_ir for struct/embedded --- crates/ltk_ritobin/src/typecheck/visitor.rs | 36 ++++++++++++++++----- 1 file changed, 28 insertions(+), 8 deletions(-) diff --git a/crates/ltk_ritobin/src/typecheck/visitor.rs b/crates/ltk_ritobin/src/typecheck/visitor.rs index bf3966f9..ac3540e7 100644 --- a/crates/ltk_ritobin/src/typecheck/visitor.rs +++ b/crates/ltk_ritobin/src/typecheck/visitor.rs @@ -5,9 +5,11 @@ use std::{ }; use indexmap::IndexMap; +use ltk_hash::fnv1a; use ltk_meta::{ value::{ - ContainerValue, MapValue, NoneValue, OptionalValue, StringValue, UnorderedContainerValue, + ContainerValue, EmbeddedValue, HashValue, MapValue, NoneValue, OptionalValue, StringValue, + UnorderedContainerValue, }, BinPropertyKind, PropertyValueEnum, }; @@ -618,10 +620,6 @@ pub fn resolve_list(ctx: &mut Ctx, tree: &Cst) -> Result<(), Diagnostic> { impl TypeChecker<'_> { fn merge_ir(&mut self, mut parent: IrItem, child: IrItem) -> IrItem { - if parent.value().kind().subtype_count() == 0 { - eprintln!("cant inject into non container"); - return parent; - } match &mut parent.value_mut().inner { PropertyValueEnum::Container(list) | PropertyValueEnum::UnorderedContainer(UnorderedContainerValue(list)) => { @@ -647,8 +645,30 @@ impl TypeChecker<'_> { list.items.push(value); } - PropertyValueEnum::Struct(struct_value) => todo!(), - PropertyValueEnum::Embedded(embedded_value) => todo!(), + PropertyValueEnum::Struct(struct_val) + | PropertyValueEnum::Embedded(EmbeddedValue(struct_val)) => { + let IrItem::Entry(IrEntry { key, value }) = child else { + eprintln!("struct item must be entry"); + return parent; + }; + + let key = match key.inner { + PropertyValueEnum::String(StringValue(str)) => fnv1a::hash_lower(&str), + PropertyValueEnum::Hash(HashValue(hash)) => hash, + other => { + eprintln!("{other:?} not valid hash"); + return parent; + } + }; + + struct_val.properties.insert( + key, + ltk_meta::BinProperty { + name_hash: key, + value: value.inner, + }, + ); + } PropertyValueEnum::ObjectLink(object_link_value) => todo!(), PropertyValueEnum::Map(map_value) => { let IrItem::Entry(IrEntry { key, value }) = child else { @@ -674,7 +694,7 @@ impl TypeChecker<'_> { .entries .insert(ltk_meta::value::PropertyValueUnsafeEq(key.inner), value); } - _ => unreachable!("non container"), + other => unreachable!("cant inject into {:?}", other.kind()), } parent } From ea013efa5185cde0c02226d345005b0a913e8f49 Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Mon, 12 Jan 2026 12:54:55 +0000 Subject: [PATCH 080/187] feat: resolve embeds/structs with class hash --- crates/ltk_ritobin/src/typecheck/visitor.rs | 176 ++++++++++++-------- 1 file changed, 103 insertions(+), 73 deletions(-) diff --git a/crates/ltk_ritobin/src/typecheck/visitor.rs b/crates/ltk_ritobin/src/typecheck/visitor.rs index ac3540e7..9cf8bf24 100644 --- a/crates/ltk_ritobin/src/typecheck/visitor.rs +++ b/crates/ltk_ritobin/src/typecheck/visitor.rs @@ -57,6 +57,12 @@ impl DerefMut for Spanned { } } +#[derive(Debug, Clone)] +pub enum ClassKind { + Str(String), + Hash(u32), +} + #[derive(Debug, Clone)] pub struct IrEntry { pub key: Spanned, @@ -454,7 +460,7 @@ pub fn resolve_rito_type(ctx: &mut Ctx<'_>, tree: &Cst) -> Result, @@ -463,63 +469,104 @@ pub fn resolve_literal( use BinPropertyKind as K; use PropertyValueEnum as P; - if tree.children.len() != 1 { + let Some(child) = tree.children.first() else { return Ok(None); - } - Ok(Some( - match tree.children.first().unwrap(/* checked above */) { - cst::Child::Token(Token { - kind: TokenKind::String, - span, - }) => P::String(StringValue(ctx.text[span].into())).with_span(*span), - cst::Child::Token(Token { - kind: TokenKind::Number, - span, - }) => { - let txt = &ctx.text[span]; - let Some(kind_hint) = kind_hint else { + }; + Ok(Some(match child { + cst::Child::Tree(Cst { + kind: Kind::Class, + children, + .. + }) => { + let Some(kind_hint) = kind_hint else { + return Ok(None); + }; + let class_span = children + .iter() + .expect_token(TokenKind::Name) + .map_err(|_| ResolveLiteral)? + .span; + + let class_hash = fnv1a::hash_lower(&ctx.text[class_span]); + match kind_hint { + K::Struct => P::Struct(StructValue { + class_hash, + properties: Default::default(), + }), + K::Embedded => P::Embedded(EmbeddedValue(StructValue { + class_hash, + properties: Default::default(), + })), + other => { + eprintln!("can't create class value from kind {other:?}"); return Ok(None); - }; - - match kind_hint { - K::U8 => P::U8(U8Value( - txt.parse().map_err(|_| Diagnostic::ResolveLiteral)?, - )), - K::U16 => P::U16(U16Value( - txt.parse().map_err(|_| Diagnostic::ResolveLiteral)?, - )), - K::U32 => P::U32(U32Value( - txt.parse().map_err(|_| Diagnostic::ResolveLiteral)?, - )), - K::U64 => P::U64(U64Value( - txt.parse().map_err(|_| Diagnostic::ResolveLiteral)?, - )), - K::I8 => P::I8(I8Value( - txt.parse().map_err(|_| Diagnostic::ResolveLiteral)?, - )), - K::I16 => P::I16(I16Value( - txt.parse().map_err(|_| Diagnostic::ResolveLiteral)?, - )), - K::I32 => P::I32(I32Value( - txt.parse().map_err(|_| Diagnostic::ResolveLiteral)?, - )), - K::I64 => P::I64(I64Value( - txt.parse().map_err(|_| Diagnostic::ResolveLiteral)?, - )), - _ => { - return Err(TypeMismatch { - span: *span, - expected: RitoType::simple(kind_hint), - expected_span: None, // TODO: would be nice here - got: RitoTypeOrNumeric::numeric(), - }); + } + } + .with_span(class_span) + } + cst::Child::Tree(Cst { + kind: Kind::Literal, + children, + .. + }) => { + let Some(child) = children.first() else { + return Ok(None); + }; + match child { + cst::Child::Token(Token { + kind: TokenKind::String, + span, + }) => P::String(StringValue(ctx.text[span].into())).with_span(*span), + cst::Child::Token(Token { + kind: TokenKind::Number, + span, + }) => { + let txt = &ctx.text[span]; + let Some(kind_hint) = kind_hint else { + return Ok(None); + }; + + match kind_hint { + K::U8 => P::U8(U8Value( + txt.parse().map_err(|_| Diagnostic::ResolveLiteral)?, + )), + K::U16 => P::U16(U16Value( + txt.parse().map_err(|_| Diagnostic::ResolveLiteral)?, + )), + K::U32 => P::U32(U32Value( + txt.parse().map_err(|_| Diagnostic::ResolveLiteral)?, + )), + K::U64 => P::U64(U64Value( + txt.parse().map_err(|_| Diagnostic::ResolveLiteral)?, + )), + K::I8 => P::I8(I8Value( + txt.parse().map_err(|_| Diagnostic::ResolveLiteral)?, + )), + K::I16 => P::I16(I16Value( + txt.parse().map_err(|_| Diagnostic::ResolveLiteral)?, + )), + K::I32 => P::I32(I32Value( + txt.parse().map_err(|_| Diagnostic::ResolveLiteral)?, + )), + K::I64 => P::I64(I64Value( + txt.parse().map_err(|_| Diagnostic::ResolveLiteral)?, + )), + _ => { + return Err(TypeMismatch { + span: *span, + expected: RitoType::simple(kind_hint), + expected_span: None, // TODO: would be nice here + got: RitoTypeOrNumeric::numeric(), + }); + } } + .with_span(*span) } - .with_span(*span) + _ => return Ok(None), } - _ => return Ok(None), - }, - )) + } + _ => return Ok(None), + })) } pub fn resolve_entry( @@ -571,26 +618,9 @@ pub fn resolve_entry( let kind = kind.or(parent_value_kind); - let literal = value - .children - .iter() - .expect_tree(Kind::Literal) - .ok() - .map(|tree| resolve_literal(ctx, tree, kind.map(|k| k.base))) - .transpose()? - .flatten(); - // let inferred_value = match value.children.first() { - // Some(cst::Child::Token(Token { - // kind: TokenKind::String, - // span, - // .. - // })) => Some(PropertyValueEnum::String(ltk_meta::value::StringValue( - // ctx.text[span].into(), - // ))), - // _ => None, - // }; - - let value = match (kind, literal) { + let resolved_val = resolve_value(ctx, value, kind.map(|k| k.base))?; + + let value = match (kind, resolved_val) { (None, Some(value)) => value, (None, None) => return Err(MissingType(key.span).into()), (Some(kind), Some(ivalue)) => match ivalue.kind() == kind.base { From 21a082faf9b6b8531a1da921cef580700c898a58 Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Mon, 12 Jan 2026 14:43:06 +0000 Subject: [PATCH 081/187] fix: hex hash parsing + better struct resolving --- crates/ltk_ritobin/src/typecheck/visitor.rs | 68 +++++++++++++++------ 1 file changed, 49 insertions(+), 19 deletions(-) diff --git a/crates/ltk_ritobin/src/typecheck/visitor.rs b/crates/ltk_ritobin/src/typecheck/visitor.rs index 9cf8bf24..2359c60b 100644 --- a/crates/ltk_ritobin/src/typecheck/visitor.rs +++ b/crates/ltk_ritobin/src/typecheck/visitor.rs @@ -149,28 +149,30 @@ impl<'a> TypeChecker<'a> { } #[derive(Debug, Clone, Copy)] -pub enum RitoTypeOrNumeric { +pub enum RitoTypeOrVirtual { RitoType(RitoType), Numeric, + StructOrEmbedded, } -impl RitoTypeOrNumeric { +impl RitoTypeOrVirtual { pub fn numeric() -> Self { Self::Numeric } } -impl From for RitoTypeOrNumeric { +impl From for RitoTypeOrVirtual { fn from(value: RitoType) -> Self { - RitoTypeOrNumeric::RitoType(value) + RitoTypeOrVirtual::RitoType(value) } } -impl Display for RitoTypeOrNumeric { +impl Display for RitoTypeOrVirtual { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { - RitoTypeOrNumeric::RitoType(rito_type) => Display::fmt(rito_type, f), - RitoTypeOrNumeric::Numeric => f.write_str("numeric type"), + Self::RitoType(rito_type) => Display::fmt(rito_type, f), + Self::Numeric => f.write_str("numeric type"), + Self::StructOrEmbedded => f.write_str("struct/embedded"), } } } @@ -187,7 +189,7 @@ pub enum Diagnostic { span: Span, expected: RitoType, expected_span: Option, - got: RitoTypeOrNumeric, + got: RitoTypeOrVirtual, }, ResolveLiteral, @@ -198,6 +200,8 @@ pub enum Diagnostic { shadower: Span, }, + InvalidHash(Span), + SubtypeCountMismatch { span: Span, got: u8, @@ -219,7 +223,8 @@ impl Diagnostic { | UnexpectedSubtypes { span, .. } | MissingType(span) | TypeMismatch { span, .. } - | ShadowedEntry { shadower: span, .. } => Some(span), + | ShadowedEntry { shadower: span, .. } + | InvalidHash(span) => Some(span), } } @@ -476,18 +481,38 @@ pub fn resolve_value( cst::Child::Tree(Cst { kind: Kind::Class, children, + span, .. }) => { let Some(kind_hint) = kind_hint else { - return Ok(None); + return Ok(None); // TODO: err + }; + let Some(class) = children.first().and_then(|t| t.token()) else { + return Err(InvalidHash(*span)); }; - let class_span = children - .iter() - .expect_token(TokenKind::Name) - .map_err(|_| ResolveLiteral)? - .span; - let class_hash = fnv1a::hash_lower(&ctx.text[class_span]); + let class_hash = match class { + Token { + kind: TokenKind::Name, + span, + } => fnv1a::hash_lower(&ctx.text[span]), + Token { + kind: TokenKind::HexLit, + span, + } => { + // TODO: better err here? + u32::from_str_radix( + ctx.text[span] + .strip_prefix("0x") + .ok_or(InvalidHash(class.span))?, + 16, + ) + .map_err(|_| InvalidHash(class.span))? + } + _ => { + return Err(InvalidHash(class.span)); + } + }; match kind_hint { K::Struct => P::Struct(StructValue { class_hash, @@ -499,10 +524,15 @@ pub fn resolve_value( })), other => { eprintln!("can't create class value from kind {other:?}"); - return Ok(None); + return Err(TypeMismatch { + span: class.span, + expected: RitoType::simple(other), + expected_span: None, + got: RitoTypeOrVirtual::StructOrEmbedded, + }); } } - .with_span(class_span) + .with_span(class.span) } cst::Child::Tree(Cst { kind: Kind::Literal, @@ -556,7 +586,7 @@ pub fn resolve_value( span: *span, expected: RitoType::simple(kind_hint), expected_span: None, // TODO: would be nice here - got: RitoTypeOrNumeric::numeric(), + got: RitoTypeOrVirtual::numeric(), }); } } From a71479f6eab39d35b156ee9e7533a4166ab74045 Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Mon, 12 Jan 2026 14:43:49 +0000 Subject: [PATCH 082/187] feat: f32 resolving --- crates/ltk_ritobin/src/typecheck/visitor.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/crates/ltk_ritobin/src/typecheck/visitor.rs b/crates/ltk_ritobin/src/typecheck/visitor.rs index 2359c60b..d3f89c3f 100644 --- a/crates/ltk_ritobin/src/typecheck/visitor.rs +++ b/crates/ltk_ritobin/src/typecheck/visitor.rs @@ -581,6 +581,9 @@ pub fn resolve_value( K::I64 => P::I64(I64Value( txt.parse().map_err(|_| Diagnostic::ResolveLiteral)?, )), + K::F32 => P::F32(F32Value( + txt.parse().map_err(|_| Diagnostic::ResolveLiteral)?, + )), _ => { return Err(TypeMismatch { span: *span, From 833a15a1df01edf4ded5f47258431604f966d71d Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Mon, 12 Jan 2026 15:22:57 +0000 Subject: [PATCH 083/187] fix: wrap classes inside blocks with ListItem --- crates/ltk_ritobin/src/parse/impls.rs | 55 +++++++++++++++++---------- 1 file changed, 35 insertions(+), 20 deletions(-) diff --git a/crates/ltk_ritobin/src/parse/impls.rs b/crates/ltk_ritobin/src/parse/impls.rs index 9bbc8c9e..5a616262 100644 --- a/crates/ltk_ritobin/src/parse/impls.rs +++ b/crates/ltk_ritobin/src/parse/impls.rs @@ -1,4 +1,9 @@ -use crate::parse::{cst::Kind as TreeKind, error::ErrorKind, parser::Parser, tokenizer::TokenKind}; +use crate::parse::{ + cst::Kind as TreeKind, + error::ErrorKind, + parser::{MarkClosed, Parser}, + tokenizer::TokenKind, +}; use TokenKind::*; @@ -8,41 +13,46 @@ pub fn file(p: &mut Parser) { if p.at(Comment) { p.scope(TreeKind::Comment, |p| p.advance()); } - stmt_or_list_item(p) + stmt_or_list_item(p); } p.close(m, TreeKind::File); } -pub fn stmt_or_list_item(p: &mut Parser) { +pub fn stmt_or_list_item(p: &mut Parser) -> (MarkClosed, TreeKind) { + let res; match (p.nth(0), p.nth(1), p.nth(2)) { - (Name | String | HexLit, Colon | Eq, _) => { - stmt(p); - } (Name | HexLit, LCurly, _) => { let m = p.open(); p.advance(); block(p); - p.close(m, TreeKind::Class); + res = (p.close(m, TreeKind::Class), TreeKind::Class); + } + (Name | String | HexLit, Colon | Eq, _) => { + res = (stmt(p), TreeKind::Entry); } (LCurly, _, _) => { let m = p.open(); block(p); - p.close(m, TreeKind::ListItem); + res = (p.close(m, TreeKind::ListItem), TreeKind::ListItem); p.eat(Comma); } (Name | HexLit | String | Number | True | False, _, _) => { let m = p.open(); p.scope(TreeKind::Literal, |p| p.advance()); - p.close(m, TreeKind::ListItem); + res = (p.close(m, TreeKind::ListItem), TreeKind::ListItem); p.eat(Comma); } - _ => stmt(p), + _ => { + res = (stmt(p), TreeKind::Entry); + } } while p.eat(Newline) {} + + res } -pub fn stmt(p: &mut Parser) { +pub fn stmt(p: &mut Parser) -> MarkClosed { let m = p.open(); p.scope(TreeKind::EntryKey, |p| { @@ -54,8 +64,7 @@ pub fn stmt(p: &mut Parser) { } if !entry_value(p) { - p.close(m, TreeKind::Entry); - return; + return p.close(m, TreeKind::Entry); } p.scope(TreeKind::EntryTerminator, |p| { @@ -88,18 +97,20 @@ pub fn stmt(p: &mut Parser) { {} } }); - p.close(m, TreeKind::Entry); + p.close(m, TreeKind::Entry) } pub fn entry_value(p: &mut Parser) -> bool { p.scope(TreeKind::EntryValue, |p| { match (p.nth(0), p.nth(1)) { (Name, _) | (HexLit, LCurly) => { - p.scope(TreeKind::Class, |p| { - p.advance(); - if p.at(LCurly) { - block(p); - } + p.scope(TreeKind::ListItem, |p| { + p.scope(TreeKind::Class, |p| { + p.advance(); + if p.at(LCurly) { + block(p); + } + }); }); } (UnterminatedString, _) => { @@ -159,7 +170,11 @@ pub fn block(p: &mut Parser) { let m = p.open(); p.expect(LCurly); while !p.at(RCurly) && !p.eof() { - stmt_or_list_item(p); + let (mark, kind) = stmt_or_list_item(p); + if kind == TreeKind::Class { + let m = p.open_before(mark); + p.close(m, TreeKind::ListItem); + } } p.expect(RCurly); From 1a509aef98fb8843c07f17ce9ff218329d7df0d8 Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Mon, 12 Jan 2026 15:25:18 +0000 Subject: [PATCH 084/187] feat: AmbiguousNumeric diag --- crates/ltk_ritobin/src/typecheck/visitor.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/crates/ltk_ritobin/src/typecheck/visitor.rs b/crates/ltk_ritobin/src/typecheck/visitor.rs index d3f89c3f..6b14c9fc 100644 --- a/crates/ltk_ritobin/src/typecheck/visitor.rs +++ b/crates/ltk_ritobin/src/typecheck/visitor.rs @@ -193,6 +193,7 @@ pub enum Diagnostic { }, ResolveLiteral, + AmbiguousNumeric(Span), RootNonEntry, ShadowedEntry { @@ -224,7 +225,8 @@ impl Diagnostic { | MissingType(span) | TypeMismatch { span, .. } | ShadowedEntry { shadower: span, .. } - | InvalidHash(span) => Some(span), + | InvalidHash(span) + | AmbiguousNumeric(span) => Some(span), } } @@ -553,7 +555,7 @@ pub fn resolve_value( }) => { let txt = &ctx.text[span]; let Some(kind_hint) = kind_hint else { - return Ok(None); + return Err(AmbiguousNumeric(*span)); }; match kind_hint { From 12a7f60297f6a21d28559a51b505b25bda90d314 Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Mon, 12 Jan 2026 15:25:29 +0000 Subject: [PATCH 085/187] fix: remove unreachable! (it's now reachable) --- crates/ltk_ritobin/src/typecheck/visitor.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/crates/ltk_ritobin/src/typecheck/visitor.rs b/crates/ltk_ritobin/src/typecheck/visitor.rs index 6b14c9fc..5a17947a 100644 --- a/crates/ltk_ritobin/src/typecheck/visitor.rs +++ b/crates/ltk_ritobin/src/typecheck/visitor.rs @@ -759,7 +759,9 @@ impl TypeChecker<'_> { .entries .insert(ltk_meta::value::PropertyValueUnsafeEq(key.inner), value); } - other => unreachable!("cant inject into {:?}", other.kind()), + other => { + eprintln!("cant inject into {:?}", other.kind()) + } } parent } From 9f7ffe57c52118bad1cf455fdab8c9ad3f48b9b4 Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Mon, 12 Jan 2026 15:25:55 +0000 Subject: [PATCH 086/187] fix: put debug logs behind RB_STACK env var --- crates/ltk_ritobin/src/typecheck/visitor.rs | 40 ++++++++++++--------- 1 file changed, 23 insertions(+), 17 deletions(-) diff --git a/crates/ltk_ritobin/src/typecheck/visitor.rs b/crates/ltk_ritobin/src/typecheck/visitor.rs index 5a17947a..c142f9d3 100644 --- a/crates/ltk_ritobin/src/typecheck/visitor.rs +++ b/crates/ltk_ritobin/src/typecheck/visitor.rs @@ -773,14 +773,16 @@ impl Visitor for TypeChecker<'_> { let depth = self.depth; let indent = " ".repeat(depth.saturating_sub(1) as _); - eprintln!("{indent}> d:{} | {:?}", depth, tree.kind); - eprint!("{indent} stack: "); - if self.stack.is_empty() { - eprint!("empty") - } - eprintln!(); - for s in &self.stack { - eprintln!("{indent} - {}: {:?}", s.0, s.1); + if std::env::var("RB_STACK").is_ok() { + eprintln!("{indent}> d:{} | {:?}", depth, tree.kind); + eprint!("{indent} stack: "); + if self.stack.is_empty() { + eprint!("empty") + } + eprintln!(); + for s in &self.stack { + eprintln!("{indent} - {}: {:?}", s.0, s.1); + } } let parent = self.stack.last(); @@ -829,14 +831,16 @@ impl Visitor for TypeChecker<'_> { let depth = self.depth; self.depth -= 1; let indent = " ".repeat(depth.saturating_sub(1) as _); - eprintln!("{indent}< d:{} | {:?}", depth, tree.kind); - eprint!("{indent} stack: "); - if self.stack.is_empty() { - eprint!("empty") - } - eprintln!(); - for s in &self.stack { - eprintln!("{indent} - {}: {:?}", s.0, s.1); + if std::env::var("RB_STACK").is_ok() { + eprintln!("{indent}< d:{} | {:?}", depth, tree.kind); + eprint!("{indent} stack: "); + if self.stack.is_empty() { + eprint!("empty") + } + eprintln!(); + for s in &self.stack { + eprintln!("{indent} - {}: {:?}", s.0, s.1); + } } if tree.kind == cst::Kind::ErrorTree { return Visit::Continue; @@ -844,7 +848,9 @@ impl Visitor for TypeChecker<'_> { match self.stack.pop() { Some(ir) => { - eprintln!("{indent}< popped {}", ir.0); + if std::env::var("RB_STACK").is_ok() { + eprintln!("{indent}< popped {}", ir.0); + } if ir.0 != depth { self.stack.push(ir); return Visit::Continue; From 23583167ef5c6b4b98aa5bd311bfc941eef8d1e9 Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Mon, 12 Jan 2026 15:30:57 +0000 Subject: [PATCH 087/187] wip: list item resolving --- crates/ltk_ritobin/src/typecheck/visitor.rs | 32 +++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/crates/ltk_ritobin/src/typecheck/visitor.rs b/crates/ltk_ritobin/src/typecheck/visitor.rs index c142f9d3..92f58255 100644 --- a/crates/ltk_ritobin/src/typecheck/visitor.rs +++ b/crates/ltk_ritobin/src/typecheck/visitor.rs @@ -476,6 +476,8 @@ pub fn resolve_value( use BinPropertyKind as K; use PropertyValueEnum as P; + dbg!(tree, kind_hint); + let Some(child) = tree.children.first() else { return Ok(None); }; @@ -790,6 +792,36 @@ impl Visitor for TypeChecker<'_> { match tree.kind { Kind::ErrorTree => return Visit::Skip, + Kind::ListItem => { + dbg!(parent); + match resolve_value( + &mut self.ctx, + tree, + parent.and_then(|p| { + let t = p.1.value().rito_type(); + if let Some(subtype) = t.value_subtype() { + return Some(subtype); + } + use BinPropertyKind as K; + dbg!(t.base); + match t.base { + K::Vector2 | K::Vector3 | K::Vector4 => Some(BinPropertyKind::F32), + K::Color => Some(BinPropertyKind::U8), + _ => None, + } + }), + ) { + Ok(Some(item)) => { + eprintln!("{indent} push {item:?}"); + self.stack.push((depth, IrItem::ListItem(IrListItem(item)))); + } + Ok(None) => { + eprintln!("{indent} ERROR empty item"); + } + Err(e) => self.ctx.diagnostics.push(e.default_span(tree.span)), + } + } + Kind::Entry => { match resolve_entry(&mut self.ctx, tree, parent.map(|p| p.1.value().rito_type())) .map_err(|e| e.fallback(tree.span)) From 38b1624ad05c8e83e100c25d3336d36095b8f0db Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Mon, 12 Jan 2026 17:12:45 +0000 Subject: [PATCH 088/187] wip: vec/color population --- crates/ltk_ritobin/src/typecheck/visitor.rs | 178 +++++++++++++++++--- 1 file changed, 153 insertions(+), 25 deletions(-) diff --git a/crates/ltk_ritobin/src/typecheck/visitor.rs b/crates/ltk_ritobin/src/typecheck/visitor.rs index 92f58255..812725ba 100644 --- a/crates/ltk_ritobin/src/typecheck/visitor.rs +++ b/crates/ltk_ritobin/src/typecheck/visitor.rs @@ -8,8 +8,8 @@ use indexmap::IndexMap; use ltk_hash::fnv1a; use ltk_meta::{ value::{ - ContainerValue, EmbeddedValue, HashValue, MapValue, NoneValue, OptionalValue, StringValue, - UnorderedContainerValue, + ContainerValue, EmbeddedValue, F32Value, HashValue, MapValue, NoneValue, OptionalValue, + StringValue, UnorderedContainerValue, Vector2Value, Vector3Value, }, BinPropertyKind, PropertyValueEnum, }; @@ -123,6 +123,7 @@ pub struct TypeChecker<'a> { pub root: IndexMap>, // current: Option<(PropertyValueEnum, PropertyValueEnum)>, stack: Vec<(u32, IrItem)>, + list_queue: Vec, depth: u32, } @@ -135,6 +136,7 @@ impl<'a> TypeChecker<'a> { }, root: IndexMap::new(), stack: Vec::new(), + list_queue: Vec::new(), depth: 0, } } @@ -177,6 +179,14 @@ impl Display for RitoTypeOrVirtual { } } +#[derive(Debug, Clone, Copy)] +pub enum ColorOrVec { + Color, + Vec2, + Vec3, + Vec4, +} + #[derive(Debug, Clone, Copy)] pub enum Diagnostic { MissingTree(cst::Kind), @@ -195,6 +205,17 @@ pub enum Diagnostic { ResolveLiteral, AmbiguousNumeric(Span), + NotEnoughItems { + span: Span, + got: u8, + expected: ColorOrVec, + }, + TooManyItems { + span: Span, + extra: u8, + expected: ColorOrVec, + }, + RootNonEntry, ShadowedEntry { shadowee: Span, @@ -226,7 +247,9 @@ impl Diagnostic { | TypeMismatch { span, .. } | ShadowedEntry { shadower: span, .. } | InvalidHash(span) - | AmbiguousNumeric(span) => Some(span), + | AmbiguousNumeric(span) + | NotEnoughItems { span, .. } + | TooManyItems { span, .. } => Some(span), } } @@ -476,7 +499,7 @@ pub fn resolve_value( use BinPropertyKind as K; use PropertyValueEnum as P; - dbg!(tree, kind_hint); + // dbg!(tree, kind_hint); let Some(child) = tree.children.first() else { return Ok(None); @@ -769,6 +792,96 @@ impl TypeChecker<'_> { } } +fn populate_vec_or_color( + target: &mut IrItem, + items: &mut Vec, +) -> Result<(), MaybeSpanDiag> { + let resolve_f32 = |n: Spanned| -> Result { + match n.inner { + PropertyValueEnum::F32(F32Value(n)) => Ok(n), + _ => Err(TypeMismatch { + span: n.span, + expected: RitoType::simple(BinPropertyKind::F32), + expected_span: None, // TODO: would be nice + got: RitoTypeOrVirtual::RitoType(RitoType::simple(n.inner.kind())), + } + .into()), + } + }; + let resolve_u8 = |n: Spanned| -> Result { + match n.inner { + PropertyValueEnum::U8(U8Value(n)) => Ok(n), + _ => Err(TypeMismatch { + span: n.span, + expected: RitoType::simple(BinPropertyKind::U8), + expected_span: None, // TODO: would be nice + got: RitoTypeOrVirtual::RitoType(RitoType::simple(n.inner.kind())), + } + .into()), + } + }; + + let mut items = items.drain(..); + let mut get_next = |span: &mut Span| -> Result<_, Diagnostic> { + let item = items + .next() + .ok_or(NotEnoughItems { + span: *span, + got: 0, + expected: ColorOrVec::Vec2, + })? + .0; + *span = item.span; + Ok(item) + }; + + use ltk_meta::value::*; + use PropertyValueEnum as V; + let mut span = Span::new(0, 0); // FIXME: get a span in here stat + let expected; + match &mut **target.value_mut() { + V::Vector2(Vector2Value(vec)) => { + vec.x = resolve_f32(get_next(&mut span)?)?; + vec.y = resolve_f32(get_next(&mut span)?)?; + expected = ColorOrVec::Vec2; + } + V::Vector3(Vector3Value(vec)) => { + vec.x = resolve_f32(get_next(&mut span)?)?; + vec.y = resolve_f32(get_next(&mut span)?)?; + vec.z = resolve_f32(get_next(&mut span)?)?; + expected = ColorOrVec::Vec3; + } + V::Vector4(Vector4Value(vec)) => { + vec.x = resolve_f32(get_next(&mut span)?)?; + vec.y = resolve_f32(get_next(&mut span)?)?; + vec.z = resolve_f32(get_next(&mut span)?)?; + vec.w = resolve_f32(get_next(&mut span)?)?; + expected = ColorOrVec::Vec4; + } + V::Color(ColorValue(color)) => { + color.r = resolve_u8(get_next(&mut span)?)?; + color.g = resolve_u8(get_next(&mut span)?)?; + color.b = resolve_u8(get_next(&mut span)?)?; + color.a = resolve_u8(get_next(&mut span)?)?; + expected = ColorOrVec::Color; + } + _ => { + unreachable!("non-empty list queue with non color/vec type receiver?"); + } + } + + if let Some(extra) = items.next() { + let count = 1 + items.count(); + return Err(TooManyItems { + span: extra.0.span, + extra: count as _, + expected, + } + .into()); + } + Ok(()) +} + impl Visitor for TypeChecker<'_> { fn enter_tree(&mut self, tree: &Cst) -> Visit { self.depth += 1; @@ -793,27 +906,32 @@ impl Visitor for TypeChecker<'_> { Kind::ErrorTree => return Visit::Skip, Kind::ListItem => { - dbg!(parent); - match resolve_value( - &mut self.ctx, - tree, - parent.and_then(|p| { - let t = p.1.value().rito_type(); - if let Some(subtype) = t.value_subtype() { - return Some(subtype); - } - use BinPropertyKind as K; - dbg!(t.base); - match t.base { - K::Vector2 | K::Vector3 | K::Vector4 => Some(BinPropertyKind::F32), - K::Color => Some(BinPropertyKind::U8), - _ => None, - } - }), - ) { + let Some((_, parent)) = parent else { + self.ctx + .diagnostics + .push(RootNonEntry.default_span(tree.span)); + return Visit::Skip; + }; + + let parent_type = parent.value().rito_type(); + + use BinPropertyKind as K; + let color_vec_type = match parent_type.base { + K::Vector2 | K::Vector3 | K::Vector4 => Some(BinPropertyKind::F32), + K::Color => Some(BinPropertyKind::U8), + _ => None, + }; + + let value_hint = color_vec_type.or(parent_type.value_subtype()); + + match resolve_value(&mut self.ctx, tree, value_hint) { Ok(Some(item)) => { - eprintln!("{indent} push {item:?}"); - self.stack.push((depth, IrItem::ListItem(IrListItem(item)))); + eprintln!("{indent} list q {item:?}"); + if color_vec_type.is_some() { + self.list_queue.push(IrListItem(item)); + } else { + self.stack.push((depth, IrItem::ListItem(IrListItem(item)))); + } } Ok(None) => { eprintln!("{indent} ERROR empty item"); @@ -879,7 +997,7 @@ impl Visitor for TypeChecker<'_> { } match self.stack.pop() { - Some(ir) => { + Some(mut ir) => { if std::env::var("RB_STACK").is_ok() { eprintln!("{indent}< popped {}", ir.0); } @@ -887,6 +1005,16 @@ impl Visitor for TypeChecker<'_> { self.stack.push(ir); return Visit::Continue; } + + if !self.list_queue.is_empty() { + // let (d, mut ir) = &mut ir; + if let Err(e) = populate_vec_or_color(&mut ir.1, &mut self.list_queue) { + self.ctx.diagnostics.push(e.fallback(ir.1.value().span)); + } + // self.stack.push((d, ir)); + // return Visit::Continue; + } + match self.stack.pop() { Some((d, parent)) => { let parent = self.merge_ir(parent, ir.1); From 666b34bd2f75948501a41975819aa79fa9cc246c Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Wed, 14 Jan 2026 10:57:17 +0000 Subject: [PATCH 089/187] wip: lists from blocks still needs tree exit logic or summat --- crates/ltk_ritobin/src/parse/mod.rs | 5 +--- crates/ltk_ritobin/src/typecheck/visitor.rs | 31 +++++++++++++++++++-- 2 files changed, 30 insertions(+), 6 deletions(-) diff --git a/crates/ltk_ritobin/src/parse/mod.rs b/crates/ltk_ritobin/src/parse/mod.rs index be6156ff..bde76dc2 100644 --- a/crates/ltk_ritobin/src/parse/mod.rs +++ b/crates/ltk_ritobin/src/parse/mod.rs @@ -30,10 +30,7 @@ mod test { #[test] fn smoke_test() { let text = r#" -EmitterName: string = "EyeTrail1" -map: map[string, string] = { - a: string = "hi" -} +a: list[vec4] = { { 1.5, 2.5, 6.9, -1000.21 } } "#; let cst = parse(text); diff --git a/crates/ltk_ritobin/src/typecheck/visitor.rs b/crates/ltk_ritobin/src/typecheck/visitor.rs index 812725ba..081c56f8 100644 --- a/crates/ltk_ritobin/src/typecheck/visitor.rs +++ b/crates/ltk_ritobin/src/typecheck/visitor.rs @@ -8,8 +8,8 @@ use indexmap::IndexMap; use ltk_hash::fnv1a; use ltk_meta::{ value::{ - ContainerValue, EmbeddedValue, F32Value, HashValue, MapValue, NoneValue, OptionalValue, - StringValue, UnorderedContainerValue, Vector2Value, Vector3Value, + ContainerValue, EmbeddedValue, HashValue, MapValue, NoneValue, OptionalValue, StringValue, + UnorderedContainerValue, Vector2Value, Vector3Value, }, BinPropertyKind, PropertyValueEnum, }; @@ -905,6 +905,33 @@ impl Visitor for TypeChecker<'_> { match tree.kind { Kind::ErrorTree => return Visit::Skip, + Kind::Block => { + let Some((_, parent)) = parent else { + self.ctx + .diagnostics + .push(RootNonEntry.default_span(tree.span)); + return Visit::Skip; + }; + + let parent_type = parent.value().rito_type(); + + use BinPropertyKind as K; + match parent_type.base { + K::Container | K::UnorderedContainer => { + let value_type = parent_type + .value_subtype() + .expect("container must have value_subtype"); + self.stack.push(( + depth, + IrItem::ListItem(IrListItem( + value_type.default_value().with_span(tree.span), + )), + )); + } + _ => {} + } + } + Kind::ListItem => { let Some((_, parent)) = parent else { self.ctx From 46642f782833727c3d9246d8586fe7576b467821 Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Wed, 14 Jan 2026 20:44:01 +0000 Subject: [PATCH 090/187] chore: remove unused imports --- crates/ltk_ritobin/src/typecheck/visitor.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/crates/ltk_ritobin/src/typecheck/visitor.rs b/crates/ltk_ritobin/src/typecheck/visitor.rs index 081c56f8..0f347aac 100644 --- a/crates/ltk_ritobin/src/typecheck/visitor.rs +++ b/crates/ltk_ritobin/src/typecheck/visitor.rs @@ -1,6 +1,5 @@ use std::{ fmt::{Debug, Display}, - num::ParseIntError, ops::{Deref, DerefMut}, }; @@ -8,7 +7,7 @@ use indexmap::IndexMap; use ltk_hash::fnv1a; use ltk_meta::{ value::{ - ContainerValue, EmbeddedValue, HashValue, MapValue, NoneValue, OptionalValue, StringValue, + ContainerValue, EmbeddedValue, HashValue, MapValue, OptionalValue, StringValue, UnorderedContainerValue, Vector2Value, Vector3Value, }, BinPropertyKind, PropertyValueEnum, From c1aae52e1b3238424bb2ec9225f8b13d6010ec48 Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Sat, 17 Jan 2026 15:03:26 +0000 Subject: [PATCH 091/187] feat: ListBlock token to distinguish blocks as list items from blocks in general --- crates/ltk_ritobin/src/parse/cst/tree.rs | 3 ++- crates/ltk_ritobin/src/parse/impls.rs | 22 ++++++++++++---------- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/crates/ltk_ritobin/src/parse/cst/tree.rs b/crates/ltk_ritobin/src/parse/cst/tree.rs index 22ca2c43..90d46e5b 100644 --- a/crates/ltk_ritobin/src/parse/cst/tree.rs +++ b/crates/ltk_ritobin/src/parse/cst/tree.rs @@ -8,7 +8,7 @@ pub enum Kind { ErrorTree, File, TypeExpr, TypeArgList, TypeArg, - Block, BlockKey, Class, ListItem, + Block, BlockKey, Class, ListItem, ListBlock, Entry, EntryKey, EntryValue, EntryTerminator, Literal, @@ -32,6 +32,7 @@ impl Display for Kind { Self::BlockKey => "key", Self::Class => "bin class", Self::ListItem => "list item", + Self::ListBlock => "list item (block)", Self::Comment => "comment", }) } diff --git a/crates/ltk_ritobin/src/parse/impls.rs b/crates/ltk_ritobin/src/parse/impls.rs index 5a616262..5a8594af 100644 --- a/crates/ltk_ritobin/src/parse/impls.rs +++ b/crates/ltk_ritobin/src/parse/impls.rs @@ -1,7 +1,7 @@ use crate::parse::{ cst::Kind as TreeKind, error::ErrorKind, - parser::{MarkClosed, Parser}, + parser::{MarkClosed, MarkOpened, Parser}, tokenizer::TokenKind, }; @@ -24,16 +24,16 @@ pub fn stmt_or_list_item(p: &mut Parser) -> (MarkClosed, TreeKind) { (Name | HexLit, LCurly, _) => { let m = p.open(); p.advance(); - block(p); + let block = block(p); + p.close(block, TreeKind::Block); res = (p.close(m, TreeKind::Class), TreeKind::Class); } (Name | String | HexLit, Colon | Eq, _) => { res = (stmt(p), TreeKind::Entry); } (LCurly, _, _) => { - let m = p.open(); - block(p); - res = (p.close(m, TreeKind::ListItem), TreeKind::ListItem); + let m = block(p); + res = (p.close(m, TreeKind::ListBlock), TreeKind::ListBlock); p.eat(Comma); } (Name | HexLit | String | Number | True | False, _, _) => { @@ -108,7 +108,8 @@ pub fn entry_value(p: &mut Parser) -> bool { p.scope(TreeKind::Class, |p| { p.advance(); if p.at(LCurly) { - block(p); + let block = block(p); + p.close(block, TreeKind::Block); } }); }); @@ -120,7 +121,8 @@ pub fn entry_value(p: &mut Parser) -> bool { p.scope(TreeKind::Literal, |p| p.advance()); } (LCurly, _) => { - block(p); + let block = block(p); + p.close(block, TreeKind::Block); } (Newline, _) => { p.advance_with_error(ErrorKind::Unexpected { token: Newline }, None); @@ -165,7 +167,8 @@ pub fn expr_type_arg(p: &mut Parser) { } } -pub fn block(p: &mut Parser) { +#[must_use] +pub fn block(p: &mut Parser) -> MarkOpened { assert!(p.at(LCurly)); let m = p.open(); p.expect(LCurly); @@ -177,6 +180,5 @@ pub fn block(p: &mut Parser) { } } p.expect(RCurly); - - p.close(m, TreeKind::Block); + m } From ab42c37b57ef1dd612a4cbfe1116219e702fae63 Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Sat, 17 Jan 2026 15:03:43 +0000 Subject: [PATCH 092/187] feat: improve list item handling --- crates/ltk_ritobin/src/typecheck/visitor.rs | 49 ++++++++++++--------- 1 file changed, 27 insertions(+), 22 deletions(-) diff --git a/crates/ltk_ritobin/src/typecheck/visitor.rs b/crates/ltk_ritobin/src/typecheck/visitor.rs index 0f347aac..d39ec631 100644 --- a/crates/ltk_ritobin/src/typecheck/visitor.rs +++ b/crates/ltk_ritobin/src/typecheck/visitor.rs @@ -712,27 +712,31 @@ impl TypeChecker<'_> { match &mut parent.value_mut().inner { PropertyValueEnum::Container(list) | PropertyValueEnum::UnorderedContainer(UnorderedContainerValue(list)) => { - let IrItem::ListItem(IrListItem(value)) = child else { - eprintln!("list item must be list item"); - return parent; - }; - let value = match list.item_kind == value.kind() { - true => value.inner, // FIXME: span info inside all containers?? - false => { - self.ctx.diagnostics.push( - TypeMismatch { - span: value.span, - expected: RitoType::simple(list.item_kind), - expected_span: None, // TODO: would be nice here - got: RitoType::simple(value.kind()).into(), + match child { + IrItem::ListItem(IrListItem(value)) => { + let value = match list.item_kind == value.kind() { + true => value.inner, // FIXME: span info inside all containers?? + false => { + self.ctx.diagnostics.push( + TypeMismatch { + span: value.span, + expected: RitoType::simple(list.item_kind), + expected_span: None, // TODO: would be nice here + got: RitoType::simple(value.kind()).into(), + } + .unwrap(), + ); + list.item_kind.default_value() } - .unwrap(), - ); - list.item_kind.default_value() - } - }; + }; - list.items.push(value); + list.items.push(value); + } + IrItem::Entry(IrEntry { key, value }) => { + eprintln!("list item must be list item"); + return parent; + } + } } PropertyValueEnum::Struct(struct_val) | PropertyValueEnum::Embedded(EmbeddedValue(struct_val)) => { @@ -904,7 +908,7 @@ impl Visitor for TypeChecker<'_> { match tree.kind { Kind::ErrorTree => return Visit::Skip, - Kind::Block => { + Kind::ListBlock => { let Some((_, parent)) = parent else { self.ctx .diagnostics @@ -930,7 +934,6 @@ impl Visitor for TypeChecker<'_> { _ => {} } } - Kind::ListItem => { let Some((_, parent)) = parent else { self.ctx @@ -948,11 +951,13 @@ impl Visitor for TypeChecker<'_> { _ => None, }; + // dbg!(color_vec_type, parent_type); + let value_hint = color_vec_type.or(parent_type.value_subtype()); match resolve_value(&mut self.ctx, tree, value_hint) { Ok(Some(item)) => { - eprintln!("{indent} list q {item:?}"); + eprintln!("{indent} list item {item:?}"); if color_vec_type.is_some() { self.list_queue.push(IrListItem(item)); } else { From d5d6f7ee78d6d8bce53b5c14b511d1b58f3fb123 Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Thu, 5 Mar 2026 19:33:35 +0000 Subject: [PATCH 093/187] fix: match latest ltk_meta --- crates/ltk_ritobin/src/typecheck/name_ext.rs | 4 +- crates/ltk_ritobin/src/typecheck/visitor.rs | 188 +++++++++---------- 2 files changed, 89 insertions(+), 103 deletions(-) diff --git a/crates/ltk_ritobin/src/typecheck/name_ext.rs b/crates/ltk_ritobin/src/typecheck/name_ext.rs index e388b7ea..58cb8c33 100644 --- a/crates/ltk_ritobin/src/typecheck/name_ext.rs +++ b/crates/ltk_ritobin/src/typecheck/name_ext.rs @@ -1,11 +1,11 @@ -use ltk_meta::BinPropertyKind; +use ltk_meta::PropertyKind; pub trait RitobinName: Sized { fn from_ritobin_name(name: &str) -> Option; fn to_ritobin_name(self) -> &'static str; } -impl RitobinName for BinPropertyKind { +impl RitobinName for PropertyKind { fn from_ritobin_name(name: &str) -> Option { match name { "none" => Some(Self::None), diff --git a/crates/ltk_ritobin/src/typecheck/visitor.rs b/crates/ltk_ritobin/src/typecheck/visitor.rs index d39ec631..275bd249 100644 --- a/crates/ltk_ritobin/src/typecheck/visitor.rs +++ b/crates/ltk_ritobin/src/typecheck/visitor.rs @@ -6,11 +6,8 @@ use std::{ use indexmap::IndexMap; use ltk_hash::fnv1a; use ltk_meta::{ - value::{ - ContainerValue, EmbeddedValue, HashValue, MapValue, OptionalValue, StringValue, - UnorderedContainerValue, Vector2Value, Vector3Value, - }, - BinPropertyKind, PropertyValueEnum, + property::{values, NoMeta}, + PropertyKind, PropertyValueEnum, }; use crate::{ @@ -306,19 +303,10 @@ impl PropertyValueExt for PropertyValueEnum { fn rito_type(&self) -> RitoType { let base = self.kind(); let subtypes = match self { - PropertyValueEnum::Map(MapValue { - key_kind, - value_kind, - .. - }) => [Some(*key_kind), Some(*value_kind)], - PropertyValueEnum::UnorderedContainer(UnorderedContainerValue(ContainerValue { - item_kind, - .. - })) => [Some(*item_kind), None], - PropertyValueEnum::Container(ContainerValue { item_kind, .. }) => { - [Some(*item_kind), None] - } - PropertyValueEnum::Optional(OptionalValue { kind, .. }) => [Some(*kind), None], + PropertyValueEnum::Map(map) => [Some(map.key_kind()), Some(map.value_kind())], + PropertyValueEnum::UnorderedContainer(values::UnorderedContainer(container)) + | PropertyValueEnum::Container(container) => [Some(container.item_kind()), None], + PropertyValueEnum::Optional(optional) => [Some(optional.item_kind()), None], _ => [None, None], }; @@ -328,8 +316,8 @@ impl PropertyValueExt for PropertyValueEnum { #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub struct RitoType { - pub base: BinPropertyKind, - pub subtypes: [Option; 2], + pub base: PropertyKind, + pub subtypes: [Option; 2], } impl Display for RitoType { @@ -347,42 +335,37 @@ impl Display for RitoType { } impl RitoType { - pub fn simple(kind: BinPropertyKind) -> Self { + pub fn simple(kind: PropertyKind) -> Self { Self { base: kind, subtypes: [None, None], } } - fn subtype(&self, idx: usize) -> BinPropertyKind { + fn subtype(&self, idx: usize) -> PropertyKind { self.subtypes[idx].unwrap_or_default() } - fn value_subtype(&self) -> Option { + fn value_subtype(&self) -> Option { self.subtypes[1].or(self.subtypes[0]) } pub fn make_default(&self) -> PropertyValueEnum { match self.base { - BinPropertyKind::Map => PropertyValueEnum::Map(MapValue { - key_kind: self.subtype(0), - value_kind: self.subtype(1), - ..Default::default() - }), - BinPropertyKind::UnorderedContainer => { - PropertyValueEnum::UnorderedContainer(UnorderedContainerValue(ContainerValue { - item_kind: self.subtype(0), - ..Default::default() - })) + PropertyKind::Map => { + PropertyValueEnum::Map(values::Map::empty(self.subtype(0), self.subtype(1))) + } + PropertyKind::UnorderedContainer => { + PropertyValueEnum::UnorderedContainer(values::UnorderedContainer( + values::Container::empty(self.subtype(0)).unwrap_or_default(), + )) } - BinPropertyKind::Container => PropertyValueEnum::Container(ContainerValue { - item_kind: self.subtype(0), - ..Default::default() - }), - BinPropertyKind::Optional => PropertyValueEnum::Optional(OptionalValue { - kind: self.subtype(0), - value: None, - }), + PropertyKind::Container => PropertyValueEnum::Container( + values::Container::empty(self.subtype(0)).unwrap_or_default(), + ), + PropertyKind::Optional => PropertyValueEnum::Optional( + values::Optional::empty(self.subtype(0)).unwrap_or_default(), + ), _ => self.base.default_value(), } @@ -427,7 +410,7 @@ pub fn resolve_rito_type(ctx: &mut Ctx<'_>, tree: &Cst) -> Result, tree: &Cst) -> Result, tree: &Cst) -> Result, + kind_hint: Option, ) -> Result>, Diagnostic> { - use ltk_meta::value::*; - use BinPropertyKind as K; + use PropertyKind as K; use PropertyValueEnum as P; // dbg!(tree, kind_hint); @@ -540,12 +522,14 @@ pub fn resolve_value( } }; match kind_hint { - K::Struct => P::Struct(StructValue { + K::Struct => P::Struct(values::Struct { class_hash, + meta: NoMeta, properties: Default::default(), }), - K::Embedded => P::Embedded(EmbeddedValue(StructValue { + K::Embedded => P::Embedded(values::Embedded(values::Struct { class_hash, + meta: NoMeta, properties: Default::default(), })), other => { @@ -572,7 +556,7 @@ pub fn resolve_value( cst::Child::Token(Token { kind: TokenKind::String, span, - }) => P::String(StringValue(ctx.text[span].into())).with_span(*span), + }) => P::String(ctx.text[span].into()).with_span(*span), cst::Child::Token(Token { kind: TokenKind::Number, span, @@ -583,31 +567,33 @@ pub fn resolve_value( }; match kind_hint { - K::U8 => P::U8(U8Value( + K::U8 => P::U8( + txt.parse::() + .map_err(|_| Diagnostic::ResolveLiteral)? + .into(), + ), + K::U16 => P::U16(values::U16::new( txt.parse().map_err(|_| Diagnostic::ResolveLiteral)?, )), - K::U16 => P::U16(U16Value( + K::U32 => P::U32(values::U32::new( txt.parse().map_err(|_| Diagnostic::ResolveLiteral)?, )), - K::U32 => P::U32(U32Value( + K::U64 => P::U64(values::U64::new( txt.parse().map_err(|_| Diagnostic::ResolveLiteral)?, )), - K::U64 => P::U64(U64Value( + K::I8 => P::I8(values::I8::new( txt.parse().map_err(|_| Diagnostic::ResolveLiteral)?, )), - K::I8 => P::I8(I8Value( + K::I16 => P::I16(values::I16::new( txt.parse().map_err(|_| Diagnostic::ResolveLiteral)?, )), - K::I16 => P::I16(I16Value( + K::I32 => P::I32(values::I32::new( txt.parse().map_err(|_| Diagnostic::ResolveLiteral)?, )), - K::I32 => P::I32(I32Value( + K::I64 => P::I64(values::I64::new( txt.parse().map_err(|_| Diagnostic::ResolveLiteral)?, )), - K::I64 => P::I64(I64Value( - txt.parse().map_err(|_| Diagnostic::ResolveLiteral)?, - )), - K::F32 => P::F32(F32Value( + K::F32 => P::F32(values::F32::new( txt.parse().map_err(|_| Diagnostic::ResolveLiteral)?, )), _ => { @@ -667,8 +653,7 @@ pub fn resolve_entry( .unwrap(), ); return Ok(IrEntry { - key: PropertyValueEnum::String(StringValue(ctx.text[key.span].into())) - .with_span(key.span), + key: PropertyValueEnum::String(ctx.text[key.span].into()).with_span(key.span), value: parent.make_default().with_span(value.span), }); } @@ -698,7 +683,7 @@ pub fn resolve_entry( }; Ok(IrEntry { - key: PropertyValueEnum::String(StringValue(ctx.text[key.span].into())).with_span(key.span), + key: PropertyValueEnum::String(ctx.text[key.span].into()).with_span(key.span), value, }) } @@ -711,26 +696,26 @@ impl TypeChecker<'_> { fn merge_ir(&mut self, mut parent: IrItem, child: IrItem) -> IrItem { match &mut parent.value_mut().inner { PropertyValueEnum::Container(list) - | PropertyValueEnum::UnorderedContainer(UnorderedContainerValue(list)) => { + | PropertyValueEnum::UnorderedContainer(values::UnorderedContainer(list)) => { match child { IrItem::ListItem(IrListItem(value)) => { - let value = match list.item_kind == value.kind() { - true => value.inner, // FIXME: span info inside all containers?? - false => { + match list.push(value.inner) { + Ok(_) => {} + Err(ltk_meta::Error::MismatchedContainerTypes { expected, got }) => { self.ctx.diagnostics.push( TypeMismatch { - span: value.span, - expected: RitoType::simple(list.item_kind), + span: value.span, // FIXME: span info inside all containers + expected: RitoType::simple(expected), expected_span: None, // TODO: would be nice here - got: RitoType::simple(value.kind()).into(), + got: RitoType::simple(got).into(), } .unwrap(), ); - list.item_kind.default_value() } - }; - - list.items.push(value); + Err(e) => { + todo!("handle unexpected error"); + } + } } IrItem::Entry(IrEntry { key, value }) => { eprintln!("list item must be list item"); @@ -739,15 +724,15 @@ impl TypeChecker<'_> { } } PropertyValueEnum::Struct(struct_val) - | PropertyValueEnum::Embedded(EmbeddedValue(struct_val)) => { + | PropertyValueEnum::Embedded(values::Embedded(struct_val)) => { let IrItem::Entry(IrEntry { key, value }) = child else { eprintln!("struct item must be entry"); return parent; }; let key = match key.inner { - PropertyValueEnum::String(StringValue(str)) => fnv1a::hash_lower(&str), - PropertyValueEnum::Hash(HashValue(hash)) => hash, + PropertyValueEnum::String(str) => fnv1a::hash_lower(&str), + PropertyValueEnum::Hash(hash) => *hash, other => { eprintln!("{other:?} not valid hash"); return parent; @@ -768,24 +753,23 @@ impl TypeChecker<'_> { eprintln!("map item must be entry"); return parent; }; - let value = match map_value.value_kind == value.kind() { - true => value.inner, // FIXME: span info inside all containers?? - false => { + match map_value.push(key.inner, value.inner) { + Ok(()) => {} + Err(ltk_meta::Error::MismatchedContainerTypes { expected, got }) => { self.ctx.diagnostics.push( TypeMismatch { span: value.span, - expected: RitoType::simple(map_value.value_kind), + expected: RitoType::simple(expected), expected_span: None, // TODO: would be nice here - got: RitoType::simple(value.kind()).into(), + got: RitoType::simple(got).into(), } .unwrap(), ); - map_value.value_kind.default_value() } - }; - map_value - .entries - .insert(ltk_meta::value::PropertyValueUnsafeEq(key.inner), value); + Err(e) => { + todo!("handle unexpected err"); + } + } } other => { eprintln!("cant inject into {:?}", other.kind()) @@ -801,10 +785,10 @@ fn populate_vec_or_color( ) -> Result<(), MaybeSpanDiag> { let resolve_f32 = |n: Spanned| -> Result { match n.inner { - PropertyValueEnum::F32(F32Value(n)) => Ok(n), + PropertyValueEnum::F32(values::F32 { value: n, .. }) => Ok(n), _ => Err(TypeMismatch { span: n.span, - expected: RitoType::simple(BinPropertyKind::F32), + expected: RitoType::simple(PropertyKind::F32), expected_span: None, // TODO: would be nice got: RitoTypeOrVirtual::RitoType(RitoType::simple(n.inner.kind())), } @@ -813,10 +797,10 @@ fn populate_vec_or_color( }; let resolve_u8 = |n: Spanned| -> Result { match n.inner { - PropertyValueEnum::U8(U8Value(n)) => Ok(n), + PropertyValueEnum::U8(values::U8 { value: n, .. }) => Ok(n), _ => Err(TypeMismatch { span: n.span, - expected: RitoType::simple(BinPropertyKind::U8), + expected: RitoType::simple(PropertyKind::U8), expected_span: None, // TODO: would be nice got: RitoTypeOrVirtual::RitoType(RitoType::simple(n.inner.kind())), } @@ -838,30 +822,29 @@ fn populate_vec_or_color( Ok(item) }; - use ltk_meta::value::*; use PropertyValueEnum as V; let mut span = Span::new(0, 0); // FIXME: get a span in here stat let expected; match &mut **target.value_mut() { - V::Vector2(Vector2Value(vec)) => { + V::Vector2(values::Vector2 { value: vec, .. }) => { vec.x = resolve_f32(get_next(&mut span)?)?; vec.y = resolve_f32(get_next(&mut span)?)?; expected = ColorOrVec::Vec2; } - V::Vector3(Vector3Value(vec)) => { + V::Vector3(values::Vector3 { value: vec, .. }) => { vec.x = resolve_f32(get_next(&mut span)?)?; vec.y = resolve_f32(get_next(&mut span)?)?; vec.z = resolve_f32(get_next(&mut span)?)?; expected = ColorOrVec::Vec3; } - V::Vector4(Vector4Value(vec)) => { + V::Vector4(values::Vector4 { value: vec, .. }) => { vec.x = resolve_f32(get_next(&mut span)?)?; vec.y = resolve_f32(get_next(&mut span)?)?; vec.z = resolve_f32(get_next(&mut span)?)?; vec.w = resolve_f32(get_next(&mut span)?)?; expected = ColorOrVec::Vec4; } - V::Color(ColorValue(color)) => { + V::Color(values::Color { value: color, .. }) => { color.r = resolve_u8(get_next(&mut span)?)?; color.g = resolve_u8(get_next(&mut span)?)?; color.b = resolve_u8(get_next(&mut span)?)?; @@ -918,7 +901,7 @@ impl Visitor for TypeChecker<'_> { let parent_type = parent.value().rito_type(); - use BinPropertyKind as K; + use PropertyKind as K; match parent_type.base { K::Container | K::UnorderedContainer => { let value_type = parent_type @@ -944,10 +927,10 @@ impl Visitor for TypeChecker<'_> { let parent_type = parent.value().rito_type(); - use BinPropertyKind as K; + use PropertyKind as K; let color_vec_type = match parent_type.base { - K::Vector2 | K::Vector3 | K::Vector4 => Some(BinPropertyKind::F32), - K::Color => Some(BinPropertyKind::U8), + K::Vector2 | K::Vector3 | K::Vector4 => Some(K::F32), + K::Color => Some(K::U8), _ => None, }; @@ -1059,7 +1042,10 @@ impl Visitor for TypeChecker<'_> { key: Spanned { span: key_span, - inner: PropertyValueEnum::String(StringValue(key)), + inner: + PropertyValueEnum::String(values::String { + value: key, .. + }), }, value, }), From 503594c6206f5a58dae54da3025cbaf376e910de Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Thu, 5 Mar 2026 21:29:23 +0000 Subject: [PATCH 094/187] wip: disable old tests for now --- crates/ltk_ritobin/tests/parse_sample.rs | 534 +++++++++++------------ 1 file changed, 267 insertions(+), 267 deletions(-) diff --git a/crates/ltk_ritobin/tests/parse_sample.rs b/crates/ltk_ritobin/tests/parse_sample.rs index 92a9d28a..334198b0 100644 --- a/crates/ltk_ritobin/tests/parse_sample.rs +++ b/crates/ltk_ritobin/tests/parse_sample.rs @@ -43,273 +43,273 @@ entries: map[hash,embed] = { } "#; -#[test] -fn test_parse_sample() { - let file = parse(SAMPLE_RITOBIN).expect("Failed to parse sample"); - - // Verify basic fields - assert_eq!(file.file_type(), Some("PROP")); - assert_eq!(file.version(), Some(3)); - - // Verify dependencies - let linked = file.linked(); - assert_eq!(linked.len(), 2); - assert!(linked[0].contains("Animations")); - - // Verify objects - let objects = file.objects(); - assert_eq!(objects.len(), 1); - - // Convert to BinTree - let tree = file.to_bin_tree(); - assert_eq!(tree.version, 3); - assert_eq!(tree.dependencies.len(), 2); - assert_eq!(tree.objects.len(), 1); -} - -#[test] -fn test_roundtrip() { - let file = parse(SAMPLE_RITOBIN).expect("Failed to parse sample"); - let tree = file.to_bin_tree(); - - // Write back to text - let output = write(&tree).expect("Failed to write"); - - // Parse again - let file2 = parse(&output).expect("Failed to parse output"); - let tree2 = file2.to_bin_tree(); - - // Verify structure is preserved - assert_eq!(tree.version, tree2.version); - assert_eq!(tree.dependencies.len(), tree2.dependencies.len()); - assert_eq!(tree.objects.len(), tree2.objects.len()); -} - -#[test] -fn test_parse_primitives() { - let input = r#" -test_bool: bool = true -test_i8: i8 = -128 -test_u8: u8 = 255 -test_i16: i16 = -32768 -test_u16: u16 = 65535 -test_i32: i32 = -2147483648 -test_u32: u32 = 4294967295 -test_f32: f32 = 3.14159 -test_vec2: vec2 = { 1.0, 2.0 } -test_vec3: vec3 = { 1.0, 2.0, 3.0 } -test_vec4: vec4 = { 1.0, 2.0, 3.0, 4.0 } -test_rgba: rgba = { 255, 128, 64, 255 } -test_string: string = "Hello, World!" -test_hash: hash = 0xdeadbeef -test_link: link = "path/to/object" -test_flag: flag = false -"#; - - let file = parse(input).expect("Failed to parse primitives"); - assert!(file.entries.contains_key("test_bool")); - assert!(file.entries.contains_key("test_f32")); - assert!(file.entries.contains_key("test_vec3")); - assert!(file.entries.contains_key("test_rgba")); - assert!(file.entries.contains_key("test_string")); -} - -#[test] -fn test_parse_containers() { - let input = r#" -test_list: list[string] = { - "item1" - "item2" - "item3" -} -test_list2: list2[u32] = { - 1 - 2 - 3 -} -test_option_some: option[string] = { - "value" -} -test_option_none: option[string] = {} -test_map: map[hash,string] = { - 0x12345678 = "value1" - 0xdeadbeef = "value2" -} -"#; - - let file = parse(input).expect("Failed to parse containers"); - assert!(file.entries.contains_key("test_list")); - assert!(file.entries.contains_key("test_list2")); - assert!(file.entries.contains_key("test_option_some")); - assert!(file.entries.contains_key("test_option_none")); - assert!(file.entries.contains_key("test_map")); -} - -#[test] -fn test_parse_nested_embeds() { - let input = r#" -data: embed = OuterClass { - name: string = "outer" - inner: embed = InnerClass { - value: u32 = 42 - nested: embed = DeepClass { - deep_value: f32 = 1.5 - } - } -} -"#; - - let file = parse(input).expect("Failed to parse nested embeds"); - assert!(file.entries.contains_key("data")); -} - -#[test] -fn test_parse_pointer_null() { - let input = r#" -null_ptr: pointer = null -"#; - - let file = parse(input).expect("Failed to parse null pointer"); - assert!(file.entries.contains_key("null_ptr")); -} - -#[test] -fn test_parse_hex_property_names() { - let input = r#" -entries: map[hash,embed] = { - "Test/Path" = TestClass { - 0xcb13aff1: f32 = -40 - normalName: string = "test" - } -} -"#; - - let file = parse(input).expect("Failed to parse hex property names"); - assert!(file.entries.contains_key("entries")); -} - -#[test] -fn test_error_span_unknown_type() { - let input = "test: badtype = 42"; - let err = parse(input).unwrap_err(); - - // Verify we get an UnknownType error with correct span - match err { - ParseError::UnknownType { - type_name, span, .. - } => { - assert_eq!(type_name, "badtype"); - // "badtype" starts at position 6 (after "test: ") - assert_eq!(span.offset(), 6); - assert_eq!(span.len(), 7); // "badtype" is 7 chars - } - _ => panic!("Expected UnknownType error, got: {:?}", err), - } -} - -#[test] -fn test_error_span_multiline() { - let input = r#" -valid: string = "hello" -broken: unknowntype = 123 -"#; - let err = parse(input).unwrap_err(); - - match err { - ParseError::UnknownType { - type_name, span, .. - } => { - assert_eq!(type_name, "unknowntype"); - // The span offset should point into the second line - assert!(span.offset() > 20); // After first line - } - _ => panic!("Expected UnknownType error, got: {:?}", err), - } -} - -/// Make sure mtx44 values don't get mangled during a text round-trip. -/// uh the text format is row-major but glam stores column-major so we -/// transpose on write and on parse, i guess this just makes sure that -/// doesn't break anything and the values come out right. -#[test] -fn test_matrix44_roundtrip_ordering() { - use glam::Mat4; - use ltk_meta::property::PropertyValueEnum; - - // non-symmetric so we'd notice if it got transposed wrong - // text layout (row-major): - // 1 2 3 4 - // 5 6 7 8 - // 9 10 11 12 - // 13 14 15 16 - // - // glam is column-major internally so: - let expected = Mat4::from_cols_array(&[ - 1.0, 5.0, 9.0, 13.0, // col0 - 2.0, 6.0, 10.0, 14.0, // col1 - 3.0, 7.0, 11.0, 15.0, // col2 - 4.0, 8.0, 12.0, 16.0, // col3 - ]); - - let input = r#"#PROP_text -type: string = "PROP" -version: u32 = 3 -entries: map[hash,embed] = { - "test/object" = TestClass { - transform: mtx44 = { - 1, 2, 3, 4 - 5, 6, 7, 8 - 9, 10, 11, 12 - 13, 14, 15, 16 - } - } -} -"#; - - // 1) Parse and verify the Mat4 matches expected column-major layout - let file = parse(input).expect("Failed to parse matrix input"); - let tree = file.to_bin_tree(); - let obj = tree.objects.values().next().expect("Expected one object"); - let parsed_mat = match &obj.properties.values().next().unwrap() { - PropertyValueEnum::Matrix44(v) => v.value, - other => panic!("Expected Matrix44, got {:?}", other), - }; - assert_eq!( - parsed_mat, expected, - "Parsed Mat4 should match expected column-major layout" - ); - - // 2) Write back to text, parse again, verify values survive the round-trip - let output = write(&tree).expect("Failed to write tree"); - let file2 = parse(&output).expect("Failed to re-parse written output"); - let tree2 = file2.to_bin_tree(); - let obj2 = tree2 - .objects - .values() - .next() - .expect("Expected one object after round-trip"); - let roundtrip_mat = match &obj2.properties.values().next().unwrap() { - PropertyValueEnum::Matrix44(v) => v.value, - other => panic!("Expected Matrix44 after round-trip, got {:?}", other), - }; - assert_eq!( - roundtrip_mat, expected, - "Matrix44 should survive text round-trip unchanged" - ); -} - -#[test] -fn test_error_is_miette_diagnostic() { - use miette::Diagnostic; - - let input = "test: badtype = 42"; - let err = parse(input).unwrap_err(); - - // ParseError implements Diagnostic - let _code = err.code(); - let _labels = err.labels(); - let _source = err.source_code(); -} +// #[test] +// fn test_parse_sample() { +// let file = parse(SAMPLE_RITOBIN).expect("Failed to parse sample"); +// +// // Verify basic fields +// assert_eq!(file.file_type(), Some("PROP")); +// assert_eq!(file.version(), Some(3)); +// +// // Verify dependencies +// let linked = file.linked(); +// assert_eq!(linked.len(), 2); +// assert!(linked[0].contains("Animations")); +// +// // Verify objects +// let objects = file.objects(); +// assert_eq!(objects.len(), 1); +// +// // Convert to BinTree +// let tree = file.to_bin_tree(); +// assert_eq!(tree.version, 3); +// assert_eq!(tree.dependencies.len(), 2); +// assert_eq!(tree.objects.len(), 1); +// } +// +// #[test] +// fn test_roundtrip() { +// let file = parse(SAMPLE_RITOBIN).expect("Failed to parse sample"); +// let tree = file.to_bin_tree(); +// +// // Write back to text +// let output = write(&tree).expect("Failed to write"); +// +// // Parse again +// let file2 = parse(&output).expect("Failed to parse output"); +// let tree2 = file2.to_bin_tree(); +// +// // Verify structure is preserved +// assert_eq!(tree.version, tree2.version); +// assert_eq!(tree.dependencies.len(), tree2.dependencies.len()); +// assert_eq!(tree.objects.len(), tree2.objects.len()); +// } +// +// #[test] +// fn test_parse_primitives() { +// let input = r#" +// test_bool: bool = true +// test_i8: i8 = -128 +// test_u8: u8 = 255 +// test_i16: i16 = -32768 +// test_u16: u16 = 65535 +// test_i32: i32 = -2147483648 +// test_u32: u32 = 4294967295 +// test_f32: f32 = 3.14159 +// test_vec2: vec2 = { 1.0, 2.0 } +// test_vec3: vec3 = { 1.0, 2.0, 3.0 } +// test_vec4: vec4 = { 1.0, 2.0, 3.0, 4.0 } +// test_rgba: rgba = { 255, 128, 64, 255 } +// test_string: string = "Hello, World!" +// test_hash: hash = 0xdeadbeef +// test_link: link = "path/to/object" +// test_flag: flag = false +// "#; +// +// let file = parse(input).expect("Failed to parse primitives"); +// assert!(file.entries.contains_key("test_bool")); +// assert!(file.entries.contains_key("test_f32")); +// assert!(file.entries.contains_key("test_vec3")); +// assert!(file.entries.contains_key("test_rgba")); +// assert!(file.entries.contains_key("test_string")); +// } +// +// #[test] +// fn test_parse_containers() { +// let input = r#" +// test_list: list[string] = { +// "item1" +// "item2" +// "item3" +// } +// test_list2: list2[u32] = { +// 1 +// 2 +// 3 +// } +// test_option_some: option[string] = { +// "value" +// } +// test_option_none: option[string] = {} +// test_map: map[hash,string] = { +// 0x12345678 = "value1" +// 0xdeadbeef = "value2" +// } +// "#; +// +// let file = parse(input).expect("Failed to parse containers"); +// assert!(file.entries.contains_key("test_list")); +// assert!(file.entries.contains_key("test_list2")); +// assert!(file.entries.contains_key("test_option_some")); +// assert!(file.entries.contains_key("test_option_none")); +// assert!(file.entries.contains_key("test_map")); +// } +// +// #[test] +// fn test_parse_nested_embeds() { +// let input = r#" +// data: embed = OuterClass { +// name: string = "outer" +// inner: embed = InnerClass { +// value: u32 = 42 +// nested: embed = DeepClass { +// deep_value: f32 = 1.5 +// } +// } +// } +// "#; +// +// let file = parse(input).expect("Failed to parse nested embeds"); +// assert!(file.entries.contains_key("data")); +// } +// +// #[test] +// fn test_parse_pointer_null() { +// let input = r#" +// null_ptr: pointer = null +// "#; +// +// let file = parse(input).expect("Failed to parse null pointer"); +// assert!(file.entries.contains_key("null_ptr")); +// } +// +// #[test] +// fn test_parse_hex_property_names() { +// let input = r#" +// entries: map[hash,embed] = { +// "Test/Path" = TestClass { +// 0xcb13aff1: f32 = -40 +// normalName: string = "test" +// } +// } +// "#; +// +// let file = parse(input).expect("Failed to parse hex property names"); +// assert!(file.entries.contains_key("entries")); +// } +// +// #[test] +// fn test_error_span_unknown_type() { +// let input = "test: badtype = 42"; +// let err = parse(input).unwrap_err(); +// +// // Verify we get an UnknownType error with correct span +// match err { +// ParseError::UnknownType { +// type_name, span, .. +// } => { +// assert_eq!(type_name, "badtype"); +// // "badtype" starts at position 6 (after "test: ") +// assert_eq!(span.offset(), 6); +// assert_eq!(span.len(), 7); // "badtype" is 7 chars +// } +// _ => panic!("Expected UnknownType error, got: {:?}", err), +// } +// } +// +// #[test] +// fn test_error_span_multiline() { +// let input = r#" +// valid: string = "hello" +// broken: unknowntype = 123 +// "#; +// let err = parse(input).unwrap_err(); +// +// match err { +// ParseError::UnknownType { +// type_name, span, .. +// } => { +// assert_eq!(type_name, "unknowntype"); +// // The span offset should point into the second line +// assert!(span.offset() > 20); // After first line +// } +// _ => panic!("Expected UnknownType error, got: {:?}", err), +// } +// } +// +// /// Make sure mtx44 values don't get mangled during a text round-trip. +// /// uh the text format is row-major but glam stores column-major so we +// /// transpose on write and on parse, i guess this just makes sure that +// /// doesn't break anything and the values come out right. +// #[test] +// fn test_matrix44_roundtrip_ordering() { +// use glam::Mat4; +// use ltk_meta::property::PropertyValueEnum; +// +// // non-symmetric so we'd notice if it got transposed wrong +// // text layout (row-major): +// // 1 2 3 4 +// // 5 6 7 8 +// // 9 10 11 12 +// // 13 14 15 16 +// // +// // glam is column-major internally so: +// let expected = Mat4::from_cols_array(&[ +// 1.0, 5.0, 9.0, 13.0, // col0 +// 2.0, 6.0, 10.0, 14.0, // col1 +// 3.0, 7.0, 11.0, 15.0, // col2 +// 4.0, 8.0, 12.0, 16.0, // col3 +// ]); +// +// let input = r#"#PROP_text +// type: string = "PROP" +// version: u32 = 3 +// entries: map[hash,embed] = { +// "test/object" = TestClass { +// transform: mtx44 = { +// 1, 2, 3, 4 +// 5, 6, 7, 8 +// 9, 10, 11, 12 +// 13, 14, 15, 16 +// } +// } +// } +// "#; +// +// // 1) Parse and verify the Mat4 matches expected column-major layout +// let file = parse(input).expect("Failed to parse matrix input"); +// let tree = file.to_bin_tree(); +// let obj = tree.objects.values().next().expect("Expected one object"); +// let parsed_mat = match &obj.properties.values().next().unwrap().value { +// PropertyValueEnum::Matrix44(v) => v.value, +// other => panic!("Expected Matrix44, got {:?}", other), +// }; +// assert_eq!( +// parsed_mat, expected, +// "Parsed Mat4 should match expected column-major layout" +// ); +// +// // 2) Write back to text, parse again, verify values survive the round-trip +// let output = write(&tree).expect("Failed to write tree"); +// let file2 = parse(&output).expect("Failed to re-parse written output"); +// let tree2 = file2.to_bin_tree(); +// let obj2 = tree2 +// .objects +// .values() +// .next() +// .expect("Expected one object after round-trip"); +// let roundtrip_mat = match &obj2.properties.values().next().unwrap().value { +// PropertyValueEnum::Matrix44(v) => v.value, +// other => panic!("Expected Matrix44 after round-trip, got {:?}", other), +// }; +// assert_eq!( +// roundtrip_mat, expected, +// "Matrix44 should survive text round-trip unchanged" +// ); +// } +// +// #[test] +// fn test_error_is_miette_diagnostic() { +// use miette::Diagnostic; +// +// let input = "test: badtype = 42"; +// let err = parse(input).unwrap_err(); +// +// // ParseError implements Diagnostic +// let _code = err.code(); +// let _labels = err.labels(); +// let _source = err.source_code(); +// } // #[test] // fn test_parse_sample() { // let file = parse(SAMPLE_RITOBIN).expect("Failed to parse sample"); From cfc81fa6c8ede8eac4469fa95ed0ad12d630dd45 Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Thu, 5 Mar 2026 21:29:12 +0000 Subject: [PATCH 095/187] wip: build to Bin --- crates/ltk_ritobin/src/parse/mod.rs | 45 +++++++++++++++++++++++++++-- 1 file changed, 42 insertions(+), 3 deletions(-) diff --git a/crates/ltk_ritobin/src/parse/mod.rs b/crates/ltk_ritobin/src/parse/mod.rs index bde76dc2..e1bde7f1 100644 --- a/crates/ltk_ritobin/src/parse/mod.rs +++ b/crates/ltk_ritobin/src/parse/mod.rs @@ -24,14 +24,26 @@ pub fn parse(text: &str) -> cst::Cst { #[cfg(test)] mod test { + use ltk_meta::{property::values, Bin, BinObject, BinProperty, PropertyValueEnum}; + use crate::typecheck::visitor::TypeChecker; use super::*; #[test] fn smoke_test() { let text = r#" -a: list[vec4] = { { 1.5, 2.5, 6.9, -1000.21 } } - +entries: map[hash,embed] = { + "myPath" = VfxEmitter { + a: list[vec2] = { + {2 2} + } + e: list[embed] = { + Foo { + a: string = "" + } + } + } +} "#; let cst = parse(text); let errors = cst::FlatErrors::walk(&cst); @@ -47,7 +59,7 @@ a: list[vec4] = { { 1.5, 2.5, 6.9, -1000.21 } } let mut checker = TypeChecker::new(text); cst.walk(&mut checker); - let (roots, errors) = checker.into_parts(); + let (mut roots, errors) = checker.into_parts(); eprintln!("{str}\n====== type errors: ======\n"); for err in errors { @@ -55,5 +67,32 @@ a: list[vec4] = { { 1.5, 2.5, 6.9, -1000.21 } } } eprintln!("{roots:#?}"); + let objects = roots + .swap_remove("entries") + .map(|v| { + let PropertyValueEnum::Map(map) = v.inner else { + panic!("entries must be map"); + }; + map.into_entries().into_iter().filter_map(|(key, value)| { + let path_hash = match &key { + PropertyValueEnum::Hash(h) => **h, + _ => return None, + }; + + if let PropertyValueEnum::Embedded(values::Embedded(struct_val)) = value { + Some(BinObject { + path_hash, + class_hash: struct_val.class_hash, + properties: struct_val.properties.clone(), + }) + } else { + None + } + }) + }) + .expect("no 'entries' entry"); + + let tree = Bin::new(objects, [""]); + eprintln!("{tree:#?}"); } } From d295a4e9c5a40e3defd7bbeff6978aba9e78d770 Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Fri, 6 Mar 2026 20:01:10 +0000 Subject: [PATCH 096/187] wip: remove span --- crates/ltk_ritobin/src/parse/mod.rs | 2 +- crates/ltk_ritobin/src/typecheck/visitor.rs | 181 +++++++++----------- 2 files changed, 80 insertions(+), 103 deletions(-) diff --git a/crates/ltk_ritobin/src/parse/mod.rs b/crates/ltk_ritobin/src/parse/mod.rs index e1bde7f1..d9f66cf3 100644 --- a/crates/ltk_ritobin/src/parse/mod.rs +++ b/crates/ltk_ritobin/src/parse/mod.rs @@ -70,7 +70,7 @@ entries: map[hash,embed] = { let objects = roots .swap_remove("entries") .map(|v| { - let PropertyValueEnum::Map(map) = v.inner else { + let PropertyValueEnum::Map(map) = v else { panic!("entries must be map"); }; map.into_entries().into_iter().filter_map(|(key, value)| { diff --git a/crates/ltk_ritobin/src/typecheck/visitor.rs b/crates/ltk_ritobin/src/typecheck/visitor.rs index 275bd249..60182e05 100644 --- a/crates/ltk_ritobin/src/typecheck/visitor.rs +++ b/crates/ltk_ritobin/src/typecheck/visitor.rs @@ -7,6 +7,7 @@ use indexmap::IndexMap; use ltk_hash::fnv1a; use ltk_meta::{ property::{values, NoMeta}, + traits::PropertyExt, PropertyKind, PropertyValueEnum, }; @@ -18,41 +19,6 @@ use crate::{ typecheck::RitobinName, }; -pub trait SpannedExt { - fn with_span(self, span: Span) -> Spanned - where - Self: Sized, - { - Spanned::new(self, span) - } -} -impl SpannedExt for T {} - -#[derive(Debug, Clone, Copy)] -pub struct Spanned { - pub span: Span, - pub inner: T, -} - -impl Spanned { - pub fn new(item: T, span: Span) -> Self { - Self { inner: item, span } - } -} - -impl Deref for Spanned { - type Target = T; - - fn deref(&self) -> &Self::Target { - &self.inner - } -} -impl DerefMut for Spanned { - fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.inner - } -} - #[derive(Debug, Clone)] pub enum ClassKind { Str(String), @@ -61,12 +27,12 @@ pub enum ClassKind { #[derive(Debug, Clone)] pub struct IrEntry { - pub key: Spanned, - pub value: Spanned, + pub key: PropertyValueEnum, + pub value: PropertyValueEnum, } #[derive(Debug, Clone)] -pub struct IrListItem(pub Spanned); +pub struct IrListItem(pub PropertyValueEnum); #[derive(Debug, Clone)] pub enum IrItem { @@ -94,19 +60,19 @@ impl IrItem { _ => None, } } - pub fn value(&self) -> &Spanned { + pub fn value(&self) -> &PropertyValueEnum { match self { IrItem::Entry(i) => &i.value, IrItem::ListItem(i) => &i.0, } } - pub fn value_mut(&mut self) -> &mut Spanned { + pub fn value_mut(&mut self) -> &mut PropertyValueEnum { match self { IrItem::Entry(i) => &mut i.value, IrItem::ListItem(i) => &mut i.0, } } - pub fn into_value(self) -> Spanned { + pub fn into_value(self) -> PropertyValueEnum { match self { IrItem::Entry(i) => i.value, IrItem::ListItem(i) => i.0, @@ -116,7 +82,7 @@ impl IrItem { pub struct TypeChecker<'a> { ctx: Ctx<'a>, - pub root: IndexMap>, + pub root: IndexMap>, // current: Option<(PropertyValueEnum, PropertyValueEnum)>, stack: Vec<(u32, IrItem)>, list_queue: Vec, @@ -139,7 +105,7 @@ impl<'a> TypeChecker<'a> { pub fn into_parts( self, ) -> ( - IndexMap>, + IndexMap>, Vec, ) { (self.root, self.ctx.diagnostics) @@ -299,7 +265,7 @@ use Diagnostic::*; pub trait PropertyValueExt { fn rito_type(&self) -> RitoType; } -impl PropertyValueExt for PropertyValueEnum { +impl PropertyValueExt for PropertyValueEnum { fn rito_type(&self) -> RitoType { let base = self.kind(); let subtypes = match self { @@ -350,8 +316,8 @@ impl RitoType { self.subtypes[1].or(self.subtypes[0]) } - pub fn make_default(&self) -> PropertyValueEnum { - match self.base { + pub fn make_default(&self, span: Span) -> PropertyValueEnum { + let mut value = match self.base { PropertyKind::Map => { PropertyValueEnum::Map(values::Map::empty(self.subtype(0), self.subtype(1))) } @@ -368,7 +334,9 @@ impl RitoType { ), _ => self.base.default_value(), - } + }; + *value.meta_mut() = span; + value } } pub enum Statement { @@ -476,7 +444,7 @@ pub fn resolve_value( ctx: &mut Ctx, tree: &Cst, kind_hint: Option, -) -> Result>, Diagnostic> { +) -> Result>, Diagnostic> { use PropertyKind as K; use PropertyValueEnum as P; @@ -524,12 +492,12 @@ pub fn resolve_value( match kind_hint { K::Struct => P::Struct(values::Struct { class_hash, - meta: NoMeta, + meta: class.span, properties: Default::default(), }), K::Embedded => P::Embedded(values::Embedded(values::Struct { class_hash, - meta: NoMeta, + meta: class.span, properties: Default::default(), })), other => { @@ -542,7 +510,6 @@ pub fn resolve_value( }); } } - .with_span(class.span) } cst::Child::Tree(Cst { kind: Kind::Literal, @@ -556,7 +523,7 @@ pub fn resolve_value( cst::Child::Token(Token { kind: TokenKind::String, span, - }) => P::String(ctx.text[span].into()).with_span(*span), + }) => values::String::new_with_meta(ctx.text[span].into(), *span).into(), cst::Child::Token(Token { kind: TokenKind::Number, span, @@ -567,34 +534,41 @@ pub fn resolve_value( }; match kind_hint { - K::U8 => P::U8( - txt.parse::() - .map_err(|_| Diagnostic::ResolveLiteral)? - .into(), - ), - K::U16 => P::U16(values::U16::new( + K::U8 => P::U8(values::U8::new_with_meta( + txt.parse::().map_err(|_| Diagnostic::ResolveLiteral)?, + *span, + )), + K::U16 => P::U16(values::U16::new_with_meta( txt.parse().map_err(|_| Diagnostic::ResolveLiteral)?, + *span, )), - K::U32 => P::U32(values::U32::new( + K::U32 => P::U32(values::U32::new_with_meta( txt.parse().map_err(|_| Diagnostic::ResolveLiteral)?, + *span, )), - K::U64 => P::U64(values::U64::new( + K::U64 => P::U64(values::U64::new_with_meta( txt.parse().map_err(|_| Diagnostic::ResolveLiteral)?, + *span, )), - K::I8 => P::I8(values::I8::new( + K::I8 => P::I8(values::I8::new_with_meta( txt.parse().map_err(|_| Diagnostic::ResolveLiteral)?, + *span, )), - K::I16 => P::I16(values::I16::new( + K::I16 => P::I16(values::I16::new_with_meta( txt.parse().map_err(|_| Diagnostic::ResolveLiteral)?, + *span, )), - K::I32 => P::I32(values::I32::new( + K::I32 => P::I32(values::I32::new_with_meta( txt.parse().map_err(|_| Diagnostic::ResolveLiteral)?, + *span, )), - K::I64 => P::I64(values::I64::new( + K::I64 => P::I64(values::I64::new_with_meta( txt.parse().map_err(|_| Diagnostic::ResolveLiteral)?, + *span, )), - K::F32 => P::F32(values::F32::new( + K::F32 => P::F32(values::F32::new_with_meta( txt.parse().map_err(|_| Diagnostic::ResolveLiteral)?, + *span, )), _ => { return Err(TypeMismatch { @@ -605,7 +579,6 @@ pub fn resolve_value( }); } } - .with_span(*span) } _ => return Ok(None), } @@ -653,8 +626,8 @@ pub fn resolve_entry( .unwrap(), ); return Ok(IrEntry { - key: PropertyValueEnum::String(ctx.text[key.span].into()).with_span(key.span), - value: parent.make_default().with_span(value.span), + key: values::String::new_with_meta(ctx.text[key.span].into(), key.span).into(), + value: parent.make_default(value.span), }); } } @@ -671,7 +644,7 @@ pub fn resolve_entry( true => ivalue, false => { return Err(TypeMismatch { - span: ivalue.span, + span: *ivalue.meta(), expected: kind, expected_span: kind_span, got: ivalue.rito_type().into(), @@ -679,11 +652,11 @@ pub fn resolve_entry( .into()) } }, - (Some(kind), _) => kind.make_default().with_span(value_span), + (Some(kind), _) => kind.make_default(value_span), }; Ok(IrEntry { - key: PropertyValueEnum::String(ctx.text[key.span].into()).with_span(key.span), + key: values::String::new_with_meta(ctx.text[key.span].into(), key.span).into(), value, }) } @@ -694,17 +667,18 @@ pub fn resolve_list(ctx: &mut Ctx, tree: &Cst) -> Result<(), Diagnostic> { impl TypeChecker<'_> { fn merge_ir(&mut self, mut parent: IrItem, child: IrItem) -> IrItem { - match &mut parent.value_mut().inner { + match &mut parent.value_mut() { PropertyValueEnum::Container(list) | PropertyValueEnum::UnorderedContainer(values::UnorderedContainer(list)) => { match child { IrItem::ListItem(IrListItem(value)) => { - match list.push(value.inner) { + let span = *value.meta(); + match list.push(value) { Ok(_) => {} Err(ltk_meta::Error::MismatchedContainerTypes { expected, got }) => { self.ctx.diagnostics.push( TypeMismatch { - span: value.span, // FIXME: span info inside all containers + span, expected: RitoType::simple(expected), expected_span: None, // TODO: would be nice here got: RitoType::simple(got).into(), @@ -730,7 +704,7 @@ impl TypeChecker<'_> { return parent; }; - let key = match key.inner { + let key = match key { PropertyValueEnum::String(str) => fnv1a::hash_lower(&str), PropertyValueEnum::Hash(hash) => *hash, other => { @@ -743,7 +717,7 @@ impl TypeChecker<'_> { key, ltk_meta::BinProperty { name_hash: key, - value: value.inner, + value: value, }, ); } @@ -753,12 +727,13 @@ impl TypeChecker<'_> { eprintln!("map item must be entry"); return parent; }; - match map_value.push(key.inner, value.inner) { + let span = *value.meta(); + match map_value.push(key, value) { Ok(()) => {} Err(ltk_meta::Error::MismatchedContainerTypes { expected, got }) => { self.ctx.diagnostics.push( TypeMismatch { - span: value.span, + span, expected: RitoType::simple(expected), expected_span: None, // TODO: would be nice here got: RitoType::simple(got).into(), @@ -783,26 +758,29 @@ fn populate_vec_or_color( target: &mut IrItem, items: &mut Vec, ) -> Result<(), MaybeSpanDiag> { - let resolve_f32 = |n: Spanned| -> Result { - match n.inner { - PropertyValueEnum::F32(values::F32 { value: n, .. }) => Ok(n), + let resolve_f32 = |n: PropertyValueEnum| -> Result { + match n { + PropertyValueEnum::F32(values::F32 { + value: n, + meta: span, + }) => Ok(n), _ => Err(TypeMismatch { - span: n.span, + span: *n.meta(), expected: RitoType::simple(PropertyKind::F32), expected_span: None, // TODO: would be nice - got: RitoTypeOrVirtual::RitoType(RitoType::simple(n.inner.kind())), + got: RitoTypeOrVirtual::RitoType(RitoType::simple(n.kind())), } .into()), } }; - let resolve_u8 = |n: Spanned| -> Result { - match n.inner { + let resolve_u8 = |n: PropertyValueEnum| -> Result { + match n { PropertyValueEnum::U8(values::U8 { value: n, .. }) => Ok(n), _ => Err(TypeMismatch { - span: n.span, + span: *n.meta(), expected: RitoType::simple(PropertyKind::U8), expected_span: None, // TODO: would be nice - got: RitoTypeOrVirtual::RitoType(RitoType::simple(n.inner.kind())), + got: RitoTypeOrVirtual::RitoType(RitoType::simple(n.kind())), } .into()), } @@ -818,14 +796,14 @@ fn populate_vec_or_color( expected: ColorOrVec::Vec2, })? .0; - *span = item.span; + *span = *item.meta(); Ok(item) }; use PropertyValueEnum as V; let mut span = Span::new(0, 0); // FIXME: get a span in here stat let expected; - match &mut **target.value_mut() { + match target.value_mut() { V::Vector2(values::Vector2 { value: vec, .. }) => { vec.x = resolve_f32(get_next(&mut span)?)?; vec.y = resolve_f32(get_next(&mut span)?)?; @@ -859,7 +837,7 @@ fn populate_vec_or_color( if let Some(extra) = items.next() { let count = 1 + items.count(); return Err(TooManyItems { - span: extra.0.span, + span: *extra.0.meta(), extra: count as _, expected, } @@ -909,9 +887,11 @@ impl Visitor for TypeChecker<'_> { .expect("container must have value_subtype"); self.stack.push(( depth, - IrItem::ListItem(IrListItem( - value_type.default_value().with_span(tree.span), - )), + IrItem::ListItem(IrListItem({ + let mut v = value_type.default_value(); + *v.meta_mut() = tree.span; + v + })), )); } _ => {} @@ -1023,7 +1003,7 @@ impl Visitor for TypeChecker<'_> { if !self.list_queue.is_empty() { // let (d, mut ir) = &mut ir; if let Err(e) = populate_vec_or_color(&mut ir.1, &mut self.list_queue) { - self.ctx.diagnostics.push(e.fallback(ir.1.value().span)); + self.ctx.diagnostics.push(e.fallback(*ir.1.value().meta())); } // self.stack.push((d, ir)); // return Visit::Continue; @@ -1040,13 +1020,10 @@ impl Visitor for TypeChecker<'_> { _, IrItem::Entry(IrEntry { key: - Spanned { - span: key_span, - inner: - PropertyValueEnum::String(values::String { - value: key, .. - }), - }, + PropertyValueEnum::String(values::String { + value: key, + meta: key_span, + }), value, }), ) = ir.clone() @@ -1059,7 +1036,7 @@ impl Visitor for TypeChecker<'_> { if let Some(existing) = self.root.insert(key, value) { self.ctx.diagnostics.push( ShadowedEntry { - shadowee: existing.span, + shadowee: *existing.meta(), shadower: key_span, } .unwrap(), From cce2fb881f5ed5f7dc41895957a8e1e6e5fdc5ad Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Fri, 6 Mar 2026 21:02:51 +0000 Subject: [PATCH 097/187] fix: no_meta --- crates/ltk_ritobin/src/parse/mod.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/ltk_ritobin/src/parse/mod.rs b/crates/ltk_ritobin/src/parse/mod.rs index d9f66cf3..7d2fd02c 100644 --- a/crates/ltk_ritobin/src/parse/mod.rs +++ b/crates/ltk_ritobin/src/parse/mod.rs @@ -80,6 +80,7 @@ entries: map[hash,embed] = { }; if let PropertyValueEnum::Embedded(values::Embedded(struct_val)) = value { + let struct_val = struct_val.no_meta(); Some(BinObject { path_hash, class_hash: struct_val.class_hash, From dc5c9ae16e42a8ce933b69171976248bdb2b96c5 Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Sat, 7 Mar 2026 00:54:16 +0000 Subject: [PATCH 098/187] feat: type coercion method + collect to bin --- crates/ltk_ritobin/src/typecheck/visitor.rs | 108 ++++++++++++++++---- 1 file changed, 88 insertions(+), 20 deletions(-) diff --git a/crates/ltk_ritobin/src/typecheck/visitor.rs b/crates/ltk_ritobin/src/typecheck/visitor.rs index 60182e05..c806906f 100644 --- a/crates/ltk_ritobin/src/typecheck/visitor.rs +++ b/crates/ltk_ritobin/src/typecheck/visitor.rs @@ -8,7 +8,7 @@ use ltk_hash::fnv1a; use ltk_meta::{ property::{values, NoMeta}, traits::PropertyExt, - PropertyKind, PropertyValueEnum, + Bin, BinObject, PropertyKind, PropertyValueEnum, }; use crate::{ @@ -157,6 +157,12 @@ pub enum Diagnostic { UnknownType(Span), MissingType(Span), + MissingEntriesMap, + InvalidEntriesMap { + span: Span, + got: RitoType, + }, + TypeMismatch { span: Span, expected: RitoType, @@ -201,7 +207,8 @@ pub enum Diagnostic { impl Diagnostic { pub fn span(&self) -> Option<&Span> { match self { - MissingTree(_) | EmptyTree(_) | MissingToken(_) | RootNonEntry | ResolveLiteral => None, + MissingTree(_) | EmptyTree(_) | MissingToken(_) | RootNonEntry | ResolveLiteral + | MissingEntriesMap => None, UnknownType(span) | SubtypeCountMismatch { span, .. } | UnexpectedSubtypes { span, .. } @@ -211,7 +218,8 @@ impl Diagnostic { | InvalidHash(span) | AmbiguousNumeric(span) | NotEnoughItems { span, .. } - | TooManyItems { span, .. } => Some(span), + | TooManyItems { span, .. } + | InvalidEntriesMap { span, .. } => Some(span), } } @@ -371,6 +379,26 @@ pub struct Ctx<'a> { diagnostics: Vec, } +pub fn coerce_type( + value: PropertyValueEnum, + to: PropertyKind, +) -> Option> { + match to { + PropertyKind::Hash => Some(match value { + PropertyValueEnum::Hash(_) => return Some(value), + PropertyValueEnum::String(str) => { + values::Hash::new_with_meta(fnv1a::hash_lower(&str), str.meta).into() + } + other => { + eprintln!("\x1b[41mcannot coerce {other:?} to {to:?}\x1b[0m"); + return None; + } + }), + to if to == value.kind() => Some(value), + _ => None, + } +} + pub fn resolve_rito_type(ctx: &mut Ctx<'_>, tree: &Cst) -> Result { let mut c = tree.children.iter(); @@ -665,8 +693,50 @@ pub fn resolve_list(ctx: &mut Ctx, tree: &Cst) -> Result<(), Diagnostic> { Ok(()) } -impl TypeChecker<'_> { +impl<'a> TypeChecker<'a> { + pub fn collect_to_bin(mut self) -> (Bin, Vec) { + let objects = self + .root + .swap_remove("entries") + .and_then(|v| { + let PropertyValueEnum::Map(map) = v else { + self.ctx.diagnostics.push( + InvalidEntriesMap { + span: *v.meta(), + got: RitoType::simple(v.kind()), + } + .unwrap(), + ); + return None; + }; + Some(map.into_entries().into_iter().filter_map(|(key, value)| { + let PropertyValueEnum::Hash(path_hash) = coerce_type(key, PropertyKind::Hash)? + else { + return None; + }; + + if let PropertyValueEnum::Embedded(values::Embedded(struct_val)) = value { + let struct_val = struct_val.no_meta(); + eprintln!("struct_val: {struct_val:?}"); + Some(BinObject { + path_hash: *path_hash, + class_hash: struct_val.class_hash, + properties: struct_val.properties.clone(), + }) + } else { + None + } + })) + }) + .expect("no 'entries' entry"); + + let tree = Bin::new(objects, [""]); + + (tree, self.ctx.diagnostics) + } + fn merge_ir(&mut self, mut parent: IrItem, child: IrItem) -> IrItem { + eprintln!("\x1b[0;33mmerge {child:?}\n-----> {parent:?}\x1b[0m"); match &mut parent.value_mut() { PropertyValueEnum::Container(list) | PropertyValueEnum::UnorderedContainer(values::UnorderedContainer(list)) => { @@ -692,7 +762,7 @@ impl TypeChecker<'_> { } } IrItem::Entry(IrEntry { key, value }) => { - eprintln!("list item must be list item"); + eprintln!("\x1b[41mlist item must be list item\x1b[0m"); return parent; } } @@ -700,24 +770,21 @@ impl TypeChecker<'_> { PropertyValueEnum::Struct(struct_val) | PropertyValueEnum::Embedded(values::Embedded(struct_val)) => { let IrItem::Entry(IrEntry { key, value }) = child else { - eprintln!("struct item must be entry"); + eprintln!("\x1b[41mstruct item must be entry\x1b[0m"); return parent; }; - let key = match key { - PropertyValueEnum::String(str) => fnv1a::hash_lower(&str), - PropertyValueEnum::Hash(hash) => *hash, - other => { - eprintln!("{other:?} not valid hash"); - return parent; - } + let Some(PropertyValueEnum::Hash(key)) = coerce_type(key, PropertyKind::Hash) + else { + // eprintln!("\x1b[41m{other:?} not valid hash\x1b[0m"); + return parent; }; struct_val.properties.insert( - key, + *key, ltk_meta::BinProperty { - name_hash: key, - value: value, + name_hash: *key, + value, }, ); } @@ -728,6 +795,10 @@ impl TypeChecker<'_> { return parent; }; let span = *value.meta(); + let Some(key) = coerce_type(key, PropertyKind::Hash) else { + // eprintln!("\x1b[41m{other:?} not valid hash\x1b[0m"); + return parent; + }; match map_value.push(key, value) { Ok(()) => {} Err(ltk_meta::Error::MismatchedContainerTypes { expected, got }) => { @@ -760,10 +831,7 @@ fn populate_vec_or_color( ) -> Result<(), MaybeSpanDiag> { let resolve_f32 = |n: PropertyValueEnum| -> Result { match n { - PropertyValueEnum::F32(values::F32 { - value: n, - meta: span, - }) => Ok(n), + PropertyValueEnum::F32(values::F32 { value: n, .. }) => Ok(n), _ => Err(TypeMismatch { span: *n.meta(), expected: RitoType::simple(PropertyKind::F32), From 769146e4d0b78f449e146cf018998a0964d086c6 Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Sat, 7 Mar 2026 00:54:20 +0000 Subject: [PATCH 099/187] fix: update smoke test --- crates/ltk_ritobin/src/parse/mod.rs | 45 ++++------------------------- 1 file changed, 5 insertions(+), 40 deletions(-) diff --git a/crates/ltk_ritobin/src/parse/mod.rs b/crates/ltk_ritobin/src/parse/mod.rs index 7d2fd02c..be4e33f1 100644 --- a/crates/ltk_ritobin/src/parse/mod.rs +++ b/crates/ltk_ritobin/src/parse/mod.rs @@ -24,8 +24,6 @@ pub fn parse(text: &str) -> cst::Cst { #[cfg(test)] mod test { - use ltk_meta::{property::values, Bin, BinObject, BinProperty, PropertyValueEnum}; - use crate::typecheck::visitor::TypeChecker; use super::*; @@ -34,14 +32,8 @@ mod test { let text = r#" entries: map[hash,embed] = { "myPath" = VfxEmitter { - a: list[vec2] = { - {2 2} - } - e: list[embed] = { - Foo { - a: string = "" - } - } + a: string = "hello" + b: list[i8] = {3 6 1} } } "#; @@ -59,41 +51,14 @@ entries: map[hash,embed] = { let mut checker = TypeChecker::new(text); cst.walk(&mut checker); - let (mut roots, errors) = checker.into_parts(); + // let (mut roots, errors) = checker.into_parts(); + let (tree, errors) = checker.collect_to_bin(); eprintln!("{str}\n====== type errors: ======\n"); for err in errors { eprintln!("{:?}: {:#?}", &text[err.span], err.diagnostic); } - eprintln!("{roots:#?}"); - let objects = roots - .swap_remove("entries") - .map(|v| { - let PropertyValueEnum::Map(map) = v else { - panic!("entries must be map"); - }; - map.into_entries().into_iter().filter_map(|(key, value)| { - let path_hash = match &key { - PropertyValueEnum::Hash(h) => **h, - _ => return None, - }; - - if let PropertyValueEnum::Embedded(values::Embedded(struct_val)) = value { - let struct_val = struct_val.no_meta(); - Some(BinObject { - path_hash, - class_hash: struct_val.class_hash, - properties: struct_val.properties.clone(), - }) - } else { - None - } - }) - }) - .expect("no 'entries' entry"); - - let tree = Bin::new(objects, [""]); - eprintln!("{tree:#?}"); + eprintln!("==== FINAL TREE =====\n{tree:#?}"); } } From 5612381d1373d61badd0efb2aae2541ebdd218a3 Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Sat, 7 Mar 2026 01:05:18 +0000 Subject: [PATCH 100/187] feat: Cst::build_bin --- crates/ltk_ritobin/src/parse/cst/tree.rs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/crates/ltk_ritobin/src/parse/cst/tree.rs b/crates/ltk_ritobin/src/parse/cst/tree.rs index 90d46e5b..f1d63aa2 100644 --- a/crates/ltk_ritobin/src/parse/cst/tree.rs +++ b/crates/ltk_ritobin/src/parse/cst/tree.rs @@ -1,6 +1,9 @@ use std::fmt::Display; -use crate::parse::{self, tokenizer::Token, Span}; +use crate::{ + parse::{self, tokenizer::Token, Span}, + typecheck::visitor::DiagnosticWithSpan, +}; #[derive(Clone, Copy, PartialEq, Eq, Debug)] #[rustfmt::skip] @@ -81,6 +84,12 @@ macro_rules! format_to { }; } impl Cst { + pub fn build_bin(&self, text: &str) -> (ltk_meta::Bin, Vec) { + let mut checker = crate::typecheck::visitor::TypeChecker::new(text); + self.walk(&mut checker); + checker.collect_to_bin() + } + pub fn print(&self, buf: &mut String, level: usize, source: &str) { let parent_indent = "│ ".repeat(level.saturating_sub(1)); let indent = match level > 0 { From 0260f35bd0387ae95046e59759b5d8bdcc56038f Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Sat, 7 Mar 2026 01:05:22 +0000 Subject: [PATCH 101/187] wip: bring back tests --- crates/ltk_ritobin/tests/parse_sample.rs | 90 +++++++++++++----------- 1 file changed, 48 insertions(+), 42 deletions(-) diff --git a/crates/ltk_ritobin/tests/parse_sample.rs b/crates/ltk_ritobin/tests/parse_sample.rs index 334198b0..36246cd8 100644 --- a/crates/ltk_ritobin/tests/parse_sample.rs +++ b/crates/ltk_ritobin/tests/parse_sample.rs @@ -1,6 +1,6 @@ //! Integration test for parsing a sample ritobin file. -// use ltk_ritobin::{parse, write, ParseError}; +use ltk_ritobin::parse::parse; const SAMPLE_RITOBIN: &str = r#"#PROP_text type: string = "PROP" @@ -43,47 +43,53 @@ entries: map[hash,embed] = { } "#; -// #[test] -// fn test_parse_sample() { -// let file = parse(SAMPLE_RITOBIN).expect("Failed to parse sample"); -// -// // Verify basic fields -// assert_eq!(file.file_type(), Some("PROP")); -// assert_eq!(file.version(), Some(3)); -// -// // Verify dependencies -// let linked = file.linked(); -// assert_eq!(linked.len(), 2); -// assert!(linked[0].contains("Animations")); -// -// // Verify objects -// let objects = file.objects(); -// assert_eq!(objects.len(), 1); -// -// // Convert to BinTree -// let tree = file.to_bin_tree(); -// assert_eq!(tree.version, 3); -// assert_eq!(tree.dependencies.len(), 2); -// assert_eq!(tree.objects.len(), 1); -// } -// -// #[test] -// fn test_roundtrip() { -// let file = parse(SAMPLE_RITOBIN).expect("Failed to parse sample"); -// let tree = file.to_bin_tree(); -// -// // Write back to text -// let output = write(&tree).expect("Failed to write"); -// -// // Parse again -// let file2 = parse(&output).expect("Failed to parse output"); -// let tree2 = file2.to_bin_tree(); -// -// // Verify structure is preserved -// assert_eq!(tree.version, tree2.version); -// assert_eq!(tree.dependencies.len(), tree2.dependencies.len()); -// assert_eq!(tree.objects.len(), tree2.objects.len()); -// } +#[test] +fn test_parse_sample() { + let cst = parse(SAMPLE_RITOBIN); + + // Verify basic fields + // assert_eq!(file.file_type(), Some("PROP")); + // assert_eq!(file.version(), Some(3)); + + // Verify dependencies + // let linked = file.linked(); + // assert_eq!(linked.len(), 2); + // assert!(linked[0].contains("Animations")); + + // Verify objects + // let objects = file.objects(); + // assert_eq!(objects.len(), 1); + + // Convert to BinTree + let (tree, errors) = cst.build_bin(SAMPLE_RITOBIN); + + if !errors.is_empty() { + eprintln!("{errors:#?}"); + panic!("errors building bin tree"); + } + + assert_eq!(tree.version, 3); + assert_eq!(tree.dependencies.len(), 2); + assert_eq!(tree.objects.len(), 1); +} + +#[test] +fn test_roundtrip() { + let cst = parse(SAMPLE_RITOBIN); + let (tree, errors) = cst.build_bin(SAMPLE_RITOBIN); + + // Write back to text + // let output = write(&tree).expect("Failed to write"); + + // Parse again + // let file2 = parse(&output).expect("Failed to parse output"); + // let tree2 = file2.to_bin_tree(); + + // Verify structure is preserved + // assert_eq!(tree.version, tree2.version); + // assert_eq!(tree.dependencies.len(), tree2.dependencies.len()); + // assert_eq!(tree.objects.len(), tree2.objects.len()); +} // // #[test] // fn test_parse_primitives() { From 007df4a121fef9828f77a94a0d93054dbc850abb Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Sat, 7 Mar 2026 13:44:18 +0000 Subject: [PATCH 102/187] wip: print attempt 1 --- crates/ltk_ritobin/src/lib.rs | 1 + crates/ltk_ritobin/src/parse/mod.rs | 64 +++++++++++++++- crates/ltk_ritobin/src/print.rs | 113 ++++++++++++++++++++++++++++ 3 files changed, 177 insertions(+), 1 deletion(-) create mode 100644 crates/ltk_ritobin/src/print.rs diff --git a/crates/ltk_ritobin/src/lib.rs b/crates/ltk_ritobin/src/lib.rs index 9669079d..f346cc3d 100644 --- a/crates/ltk_ritobin/src/lib.rs +++ b/crates/ltk_ritobin/src/lib.rs @@ -47,6 +47,7 @@ pub mod error; pub mod hashes; pub mod parse; +pub mod print; pub mod typecheck; pub mod types; pub mod writer; diff --git a/crates/ltk_ritobin/src/parse/mod.rs b/crates/ltk_ritobin/src/parse/mod.rs index be4e33f1..e5f49674 100644 --- a/crates/ltk_ritobin/src/parse/mod.rs +++ b/crates/ltk_ritobin/src/parse/mod.rs @@ -24,7 +24,7 @@ pub fn parse(text: &str) -> cst::Cst { #[cfg(test)] mod test { - use crate::typecheck::visitor::TypeChecker; + use crate::{print::Printer, typecheck::visitor::TypeChecker}; use super::*; #[test] @@ -61,4 +61,66 @@ entries: map[hash,embed] = { eprintln!("==== FINAL TREE =====\n{tree:#?}"); } + + #[test] + fn writer_test() { + let text = r#" +entries: map[hash,embed] = { + "myPath" = VfxEmitter { + a: string = "hello" + b: list[i8] = {3 6 1} + } + "cock" = VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLinger: option[f32] = { + 2 + } + lifetime: option[f32] = { + 1 + } + emitterName: string = "JudgementCut" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mMeshName: string = "ASSETS/Characters/viego/Skins/base/judgementcut.skn" + mMeshSkeletonName: string = "ASSETS/Characters/viego/Skins/base/judgementcut.skl" + mAnimationName: string = "ASSETS/Characters/viego/Skins/base/judgementcut.anm" + } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 15, 15, 15 } + } + blendMode: u8 = 1 + disableBackfaceCull: bool = true + miscRenderFlags: u8 = 1 + texture: string = "ASSETS/Characters/viego/Skins/base/slashes.dds" + particleUVScrollRate: embed = IntegratedValueVector2 { + constantValue: vec2 = { 1, 0 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { + 0 + } + values: list[vec2] = { + { 1, 0 } + } + } + } + } +} +"#; + let cst = parse(text); + + let mut str = String::new(); + let mut printer = Printer::new(text, &mut str); + cst.walk(&mut printer); + + println!("========\n{str}"); + } } diff --git a/crates/ltk_ritobin/src/print.rs b/crates/ltk_ritobin/src/print.rs new file mode 100644 index 00000000..2079556f --- /dev/null +++ b/crates/ltk_ritobin/src/print.rs @@ -0,0 +1,113 @@ +use std::{ + cell::RefCell, + fmt::{self}, +}; + +use crate::parse::{ + cst::{visitor::Visit, Cst, Kind, Visitor}, + Span, TokenKind, +}; + +#[derive(Debug, thiserror::Error)] +pub enum PrintError { + #[error(transparent)] + FmtError(#[from] fmt::Error), +} + +#[derive(Default)] +struct Flags { + break_pre: bool, + break_post: bool, + space_pre: bool, + space_post: bool, +} + +pub struct Printer<'a, W: fmt::Write> { + source: &'a str, + out: &'a mut W, + error: Option, + indent: u32, + flags: Flags, + default_flags: Flags, +} + +impl<'a, W: fmt::Write> Printer<'a, W> { + pub fn new(source: &'a str, dest: &'a mut W) -> Self { + Self { + source, + out: dest, + error: None, + indent: 0, + flags: Flags::default(), + default_flags: Flags::default(), + } + } + + pub fn print(mut self, cst: &Cst) -> Result<(), PrintError> { + cst.walk(&mut self); + match self.error.take() { + Some(err) => Err(err), + None => Ok(()), + } + } + + fn visit_token_inner( + &mut self, + token: &crate::parse::Token, + context: &crate::parse::cst::Cst, + ) -> Result<(), PrintError> { + let token_txt = self.source[token.span].trim(); + if token_txt.is_empty() { + return Ok(()); + } + + match token.kind { + TokenKind::RCurly => { + self.indent -= 1; + self.flags.break_pre = true; + } + TokenKind::LCurly => { + self.flags.space_pre = true; + self.flags.break_post = true; + } + TokenKind::Colon => { + self.flags.space_post = true; + } + TokenKind::Eq => { + self.flags.space_pre = true; + self.flags.space_post = true; + } + TokenKind::Comma => { + self.flags.break_post = self.flags.break_pre; + self.flags.break_pre = false; + self.flags.space_post = true; + } + _ => { + eprintln!("{:?}", context.kind); + } + } + + if self.flags.break_pre { + self.out.write_char('\n')?; + for _ in 0..self.indent { + self.out.write_str(" ")?; + } + } else if self.flags.space_pre { + self.out.write_char(' ')?; + } + self.out.write_str(token_txt)?; + + self.flags.break_pre = self.flags.break_post; + self.flags.break_post = false; + + self.flags.space_pre = self.flags.space_post; + self.flags.space_post = false; + + if token.kind == TokenKind::LCurly { + self.indent += 1; + } + + Ok(()) + } +} + From afea2e9da09203c26ffedd012b8ad54110233f5c Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Sat, 7 Mar 2026 13:53:36 +0000 Subject: [PATCH 103/187] wip: printer v2 asdasd --- Cargo.toml | 2 + crates/ltk_ritobin/Cargo.toml | 3 +- crates/ltk_ritobin/src/parse/mod.rs | 11 +- crates/ltk_ritobin/src/parse/span.rs | 6 + crates/ltk_ritobin/src/print.rs | 135 +++----- crates/ltk_ritobin/src/print/visitor.rs | 407 ++++++++++++++++++++++++ 6 files changed, 478 insertions(+), 86 deletions(-) create mode 100644 crates/ltk_ritobin/src/print/visitor.rs diff --git a/Cargo.toml b/Cargo.toml index b21fb4fb..dc3f0dd4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -31,3 +31,5 @@ indexmap = "2.7.0" approx = "0.5.1" insta = { version = "1.39.0", features = ["ron"] } camino = "1.2.1" + +pretty_assertions = "1.4.1" diff --git a/crates/ltk_ritobin/Cargo.toml b/crates/ltk_ritobin/Cargo.toml index 7d067e24..0156721f 100644 --- a/crates/ltk_ritobin/Cargo.toml +++ b/crates/ltk_ritobin/Cargo.toml @@ -28,5 +28,6 @@ serde = { workspace = true, optional = true } salsa = "0.22.0" [dev-dependencies] -insta = { workspace = true } +insta.workspace = true +pretty_assertions.workspace = true diff --git a/crates/ltk_ritobin/src/parse/mod.rs b/crates/ltk_ritobin/src/parse/mod.rs index e5f49674..91347b01 100644 --- a/crates/ltk_ritobin/src/parse/mod.rs +++ b/crates/ltk_ritobin/src/parse/mod.rs @@ -118,9 +118,16 @@ entries: map[hash,embed] = { let cst = parse(text); let mut str = String::new(); - let mut printer = Printer::new(text, &mut str); - cst.walk(&mut printer); + cst.print(&mut str, 0, text); + + println!("============= CST ==========="); + println!("{str}"); + + let mut str = String::new(); + let size = 100; + Printer::new(text, &mut str, size).print(&cst).unwrap(); + println!("{}", "*".repeat(size)); println!("========\n{str}"); } } diff --git a/crates/ltk_ritobin/src/parse/span.rs b/crates/ltk_ritobin/src/parse/span.rs index 48eac9d6..54188868 100644 --- a/crates/ltk_ritobin/src/parse/span.rs +++ b/crates/ltk_ritobin/src/parse/span.rs @@ -23,6 +23,12 @@ impl Span { pub fn intersects(&self, other: &Span) -> bool { self.start < other.end && other.start < self.end } + + #[must_use] + #[inline] + pub fn len(&self) -> u32 { + self.end - self.start + } } impl std::ops::Index for str { diff --git a/crates/ltk_ritobin/src/print.rs b/crates/ltk_ritobin/src/print.rs index 2079556f..bf4c33bc 100644 --- a/crates/ltk_ritobin/src/print.rs +++ b/crates/ltk_ritobin/src/print.rs @@ -1,8 +1,3 @@ -use std::{ - cell::RefCell, - fmt::{self}, -}; - use crate::parse::{ cst::{visitor::Visit, Cst, Kind, Visitor}, Span, TokenKind, @@ -14,100 +9,74 @@ pub enum PrintError { FmtError(#[from] fmt::Error), } -#[derive(Default)] -struct Flags { - break_pre: bool, - break_post: bool, - space_pre: bool, - space_post: bool, -} +use std::fmt::{self, Write}; + +mod visitor; -pub struct Printer<'a, W: fmt::Write> { - source: &'a str, - out: &'a mut W, - error: Option, - indent: u32, - flags: Flags, - default_flags: Flags, +pub struct Printer<'a, W: Write> { + visitor: visitor::Printer<'a, W>, } -impl<'a, W: fmt::Write> Printer<'a, W> { - pub fn new(source: &'a str, dest: &'a mut W) -> Self { +impl<'a, W: Write> Printer<'a, W> { + pub fn new(src: &'a str, out: W, width: usize) -> Self { Self { - source, - out: dest, - error: None, - indent: 0, - flags: Flags::default(), - default_flags: Flags::default(), + visitor: visitor::Printer::new(src, out, width), } } pub fn print(mut self, cst: &Cst) -> Result<(), PrintError> { - cst.walk(&mut self); - match self.error.take() { - Some(err) => Err(err), - None => Ok(()), + cst.walk(&mut self.visitor); + self.visitor.flush()?; + if let Some(e) = self.visitor.error { + return Err(e); } + Ok(()) } +} - fn visit_token_inner( - &mut self, - token: &crate::parse::Token, - context: &crate::parse::cst::Cst, - ) -> Result<(), PrintError> { - let token_txt = self.source[token.span].trim(); - if token_txt.is_empty() { - return Ok(()); - } +#[cfg(test)] +mod test { + use crate::{parse::parse, print::Printer}; - match token.kind { - TokenKind::RCurly => { - self.indent -= 1; - self.flags.break_pre = true; - } - TokenKind::LCurly => { - self.flags.space_pre = true; - self.flags.break_post = true; - } - TokenKind::Colon => { - self.flags.space_post = true; - } - TokenKind::Eq => { - self.flags.space_pre = true; - self.flags.space_post = true; - } - TokenKind::Comma => { - self.flags.break_post = self.flags.break_pre; - self.flags.break_pre = false; - self.flags.space_post = true; - } - _ => { - eprintln!("{:?}", context.kind); - } - } + fn assert_pretty(input: &str, is: &str, size: usize) { + let cst = parse(input); - if self.flags.break_pre { - self.out.write_char('\n')?; - for _ in 0..self.indent { - self.out.write_str(" ")?; - } - } else if self.flags.space_pre { - self.out.write_char(' ')?; - } - self.out.write_str(token_txt)?; + let mut str = String::new(); + Printer::new(input, &mut str, size).print(&cst).unwrap(); - self.flags.break_pre = self.flags.break_post; - self.flags.break_post = false; + pretty_assertions::assert_eq!(str, is); + } - self.flags.space_pre = self.flags.space_post; - self.flags.space_post = false; + #[test] + fn simple_list() { + assert_pretty( + r#" b : list [ i8, ] = { 3, 6 1 }"#, + r#"b: list[i8] = { 3, 6, 1 }"#, + 80, + ); + } - if token.kind == TokenKind::LCurly { - self.indent += 1; - } + #[test] + fn nested_list() { + assert_pretty( + r#" nestedList : list [ vec2, ] = { {3, 6} {1 10000} }"#, + r#"nestedList: list[vec2] = { + { 3, 6 } + { 1, 10000 } +}"#, + 80, + ); + } - Ok(()) + #[test] + fn big_guy() { + assert_pretty( + r#" nestedList : list [ vec2, ] = { {3, 6} {1 10000} }"#, + r#"nestedList: list[vec2] = { + { 3, 6 } + { 1, 10000 } +}"#, + 80, + ); } } - diff --git a/crates/ltk_ritobin/src/print/visitor.rs b/crates/ltk_ritobin/src/print/visitor.rs new file mode 100644 index 00000000..9f9c769d --- /dev/null +++ b/crates/ltk_ritobin/src/print/visitor.rs @@ -0,0 +1,407 @@ +use std::{ + collections::VecDeque, + fmt::{self, Write}, +}; + +use crate::{ + parse::{ + cst::{visitor::Visit, Cst, Kind, Visitor}, + TokenKind, + }, + print::PrintError, +}; + +#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] +pub enum Mode { + Flat, + Break, +} + +#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] +struct GroupId(usize); + +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +pub enum Cmd<'a> { + Text(&'a str), + TextIf(&'a str, Mode), + Line, + SoftLine, + Space, + Begin(Option), + End, + Indent(usize), + Dedent(usize), +} + +#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] +struct ListContext { + len: u32, + idx: u32, + grp: GroupId, +} + +pub struct Printer<'a, W: Write> { + src: &'a str, + out: W, + width: usize, + col: usize, + indent: usize, + + pub queue: VecDeque>, + modes: Vec, + + list_stack: Vec, + + pub error: Option, +} + +impl<'a, W: Write> Printer<'a, W> { + pub fn new(src: &'a str, out: W, width: usize) -> Self { + Self { + src, + out, + width, + col: 0, + indent: 0, + queue: VecDeque::new(), + modes: vec![Mode::Break], + list_stack: Vec::new(), + + error: None, + } + } + + pub fn text(&mut self, txt: &'a str) { + self.queue.push_back(Cmd::Text(txt)); + } + + pub fn text_if(&mut self, txt: &'a str, mode: Mode) { + self.queue.push_back(Cmd::TextIf(txt, mode)); + } + + pub fn space(&mut self) { + self.queue.push_back(Cmd::Space); + } + + pub fn line(&mut self) { + if self.queue.is_empty() { + return; + } + self.queue.push_back(Cmd::Line); + } + pub fn softline(&mut self) { + if self.queue.is_empty() { + return; + } + self.queue.push_back(Cmd::SoftLine); + } + + pub fn begin_group(&mut self, mode: Option) -> GroupId { + let id = GroupId(self.queue.len()); + self.queue.push_back(Cmd::Begin(mode)); + id + } + + pub fn end_group(&mut self) { + self.queue.push_back(Cmd::End); + } + + pub fn indent(&mut self, n: usize) { + self.queue.push_back(Cmd::Indent(n)); + } + + pub fn dedent(&mut self, n: usize) { + self.queue.push_back(Cmd::Dedent(n)); + } + + fn fits(&self) -> bool { + let mut col = self.col; + let mut depth = 0; + + for cmd in &self.queue { + match cmd { + Cmd::Text(s) | Cmd::TextIf(s, Mode::Flat) => { + col += s.len(); + if col > self.width { + return false; + } + } + Cmd::Line => return true, + + Cmd::Begin(_) => depth += 1, + Cmd::End => { + if depth == 0 { + break; + } + depth -= 1; + } + + _ => {} + } + } + + true + } + + pub fn flush(&mut self) -> fmt::Result { + let mut block_space = false; + let mut block_line = false; + eprintln!("###### FLUSH ##"); + while let Some(cmd) = self.queue.pop_front() { + eprintln!("- {cmd:?}"); + match cmd { + Cmd::Text(s) => { + self.out.write_str(s)?; + self.col += s.len(); + block_space = false; + block_line = false; + } + Cmd::TextIf(s, mode) => { + if *self.modes.last().unwrap() == mode { + self.out.write_str(s)?; + self.col += s.len(); + block_space = false; + block_line = false; + } + } + Cmd::Space => { + if !block_space { + self.out.write_char(' ')?; + self.col += 1; + block_space = true; + block_line = false; + } + } + + Cmd::Line => { + self.out.write_char('\n')?; + for _ in 0..self.indent { + self.out.write_char(' ')?; + } + self.col = self.indent; + self.propagate_break(); + block_space = true; + block_line = true; + } + + Cmd::SoftLine => { + match self.modes.last().unwrap() { + Mode::Flat => { + if !block_space { + self.out.write_char(' ')?; + self.col += 1; + block_space = true; + block_line = false; + } + } + Mode::Break => { + if !block_line { + // eprintln!(" - not skipping"); + self.out.write_char('\n')?; + for _ in 0..self.indent { + self.out.write_char(' ')?; + } + self.col = self.indent; + self.propagate_break(); + block_space = true; + block_line = true; + } + } + } + } + + Cmd::Begin(mode) => { + self.modes.push(match mode { + Some(mode) => mode, + None => match self.fits() { + true => Mode::Flat, + false => Mode::Break, + }, + }); + } + Cmd::End => { + self.modes.pop(); + } + + Cmd::Indent(n) => { + self.indent += n; + } + Cmd::Dedent(n) => { + self.indent -= n; + } + } + } + + Ok(()) + } + + fn propagate_break(&mut self) { + for group in self.modes.iter_mut().rev() { + if *group == Mode::Flat { + *group = Mode::Break; + } else { + break; // stop once we hit an already broken group + } + } + } + + fn visit_token_inner( + &mut self, + token: &crate::parse::Token, + context: &Cst, + ) -> Result<(), PrintError> { + let txt = self.src[token.span].trim(); + + if txt.is_empty() { + return Ok(()); + } + + eprintln!("->{:?}", token.kind); + match token.kind { + TokenKind::LCurly => { + self.space(); + self.text("{"); + self.indent(4); + self.softline(); + } + + TokenKind::RCurly => { + if let Some(Cmd::SoftLine) = self.queue.back() { + self.queue.pop_back(); + } + self.dedent(4); + self.softline(); + self.text("}"); + } + + TokenKind::Comma => { + // self.text_if(",", Mode::Flat); + // self.softline(); + } + TokenKind::Colon => { + self.text(":"); + self.space(); + } + + TokenKind::Eq => { + self.space(); + self.text("="); + self.space(); + } + + _ => { + self.text(txt); + } + } + // self.flush()?; + Ok(()) + } +} + +impl<'a, W: fmt::Write> Visitor for Printer<'a, W> { + fn enter_tree(&mut self, tree: &Cst) -> Visit { + match tree.kind { + Kind::TypeArgList => { + let grp = self.begin_group(Some(Mode::Flat)); + // eprintln!("{:#?}", tree.children); + self.list_stack.push(ListContext { + len: tree + .children + .iter() + .filter(|n| n.tree().is_some_and(|t| t.kind == Kind::TypeArg)) + .count() + .try_into() + .unwrap(), + idx: 0, + grp, + }); + } + Kind::ListBlock => { + let grp = self.begin_group(None); + + let len = tree + .children + .iter() + .filter(|n| n.tree().is_some_and(|t| t.kind == Kind::ListItem)) + .count(); + if len > 0 { + self.list_stack.push(ListContext { + len: len.try_into().unwrap(), + idx: 0, + grp, + }); + } + } + Kind::Block => { + // eprintln!("BLOCK: {:#?}", tree.children); + let grp = self.begin_group(None); + let len = tree + .children + .iter() + .filter(|n| { + n.tree() + .is_some_and(|t| matches!(t.kind, Kind::ListItem | Kind::ListBlock)) + }) + .count(); + if len > 0 { + self.list_stack.push(ListContext { + len: len.try_into().unwrap(), + idx: 0, + grp, + }); + } + } + Kind::Entry => { + self.line(); + } + _ => {} + } + Visit::Continue + } + fn exit_tree(&mut self, tree: &Cst) -> Visit { + match tree.kind { + Kind::ListBlock | Kind::Block | Kind::TypeArgList => { + self.list_stack.pop(); + self.end_group(); + eprintln!("exit {} | stack: {}", tree.kind, self.list_stack.len()); + if let Some(list) = self.list_stack.last_mut() { + let Cmd::Begin(mode) = self.queue.get_mut(list.grp.0).unwrap() else { + unreachable!("grp pointing at non begin cmd"); + }; + mode.replace(Mode::Break); + self.softline(); + } + } + Kind::ListItem | Kind::TypeArg => { + if let Some(ctx) = self.list_stack.last() { + let last_item = ctx.idx + 1 == ctx.len; + + if !last_item { + self.text_if(",", Mode::Flat); + self.space(); + if tree.kind == Kind::ListItem { + self.softline(); + } + } + + self.list_stack.last_mut().unwrap(/* guaranteed by if let */).idx += 1; + } + } + _ => {} + } + Visit::Continue + } + fn visit_token( + &mut self, + token: &crate::parse::Token, + context: &crate::parse::cst::Cst, + ) -> Visit { + match self.visit_token_inner(token, context) { + Ok(_) => Visit::Continue, + Err(e) => { + self.error.replace(e); + Visit::Stop + } + } + } +} From 922e3b1ac32612ff7a32063438dba885680952a8 Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Sat, 7 Mar 2026 21:13:50 +0000 Subject: [PATCH 104/187] fix: disable spammy logs --- crates/ltk_ritobin/src/typecheck/visitor.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/crates/ltk_ritobin/src/typecheck/visitor.rs b/crates/ltk_ritobin/src/typecheck/visitor.rs index c806906f..748520a6 100644 --- a/crates/ltk_ritobin/src/typecheck/visitor.rs +++ b/crates/ltk_ritobin/src/typecheck/visitor.rs @@ -717,7 +717,7 @@ impl<'a> TypeChecker<'a> { if let PropertyValueEnum::Embedded(values::Embedded(struct_val)) = value { let struct_val = struct_val.no_meta(); - eprintln!("struct_val: {struct_val:?}"); + // eprintln!("struct_val: {struct_val:?}"); Some(BinObject { path_hash: *path_hash, class_hash: struct_val.class_hash, @@ -736,7 +736,7 @@ impl<'a> TypeChecker<'a> { } fn merge_ir(&mut self, mut parent: IrItem, child: IrItem) -> IrItem { - eprintln!("\x1b[0;33mmerge {child:?}\n-----> {parent:?}\x1b[0m"); + // eprintln!("\x1b[0;33mmerge {child:?}\n-----> {parent:?}\x1b[0m"); match &mut parent.value_mut() { PropertyValueEnum::Container(list) | PropertyValueEnum::UnorderedContainer(values::UnorderedContainer(list)) => { @@ -988,7 +988,7 @@ impl Visitor for TypeChecker<'_> { match resolve_value(&mut self.ctx, tree, value_hint) { Ok(Some(item)) => { - eprintln!("{indent} list item {item:?}"); + // eprintln!("{indent} list item {item:?}"); if color_vec_type.is_some() { self.list_queue.push(IrListItem(item)); } else { @@ -996,7 +996,7 @@ impl Visitor for TypeChecker<'_> { } } Ok(None) => { - eprintln!("{indent} ERROR empty item"); + // eprintln!("{indent} ERROR empty item"); } Err(e) => self.ctx.diagnostics.push(e.default_span(tree.span)), } @@ -1007,7 +1007,7 @@ impl Visitor for TypeChecker<'_> { .map_err(|e| e.fallback(tree.span)) { Ok(entry) => { - eprintln!("{indent} push {entry:?}"); + // eprintln!("{indent} push {entry:?}"); self.stack.push((depth, IrItem::Entry(entry))); } Err(e) => self.ctx.diagnostics.push(e), From 3a28f941ec8e9ca6c5c5abaa3e04632ab5fd97ed Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Sat, 7 Mar 2026 22:39:03 +0000 Subject: [PATCH 105/187] wip: fix some things --- crates/ltk_ritobin/src/parse/cst/tree.rs | 4 +-- crates/ltk_ritobin/src/parse/impls.rs | 18 +++++----- crates/ltk_ritobin/src/print.rs | 34 ++++++++++++++---- crates/ltk_ritobin/src/print/visitor.rs | 39 +++++++++++++++++---- crates/ltk_ritobin/src/typecheck/visitor.rs | 7 ++-- 5 files changed, 76 insertions(+), 26 deletions(-) diff --git a/crates/ltk_ritobin/src/parse/cst/tree.rs b/crates/ltk_ritobin/src/parse/cst/tree.rs index f1d63aa2..4458c66d 100644 --- a/crates/ltk_ritobin/src/parse/cst/tree.rs +++ b/crates/ltk_ritobin/src/parse/cst/tree.rs @@ -11,7 +11,7 @@ pub enum Kind { ErrorTree, File, TypeExpr, TypeArgList, TypeArg, - Block, BlockKey, Class, ListItem, ListBlock, + Block, BlockKey, Class, ListItem, ListItemBlock, Entry, EntryKey, EntryValue, EntryTerminator, Literal, @@ -35,7 +35,7 @@ impl Display for Kind { Self::BlockKey => "key", Self::Class => "bin class", Self::ListItem => "list item", - Self::ListBlock => "list item (block)", + Self::ListItemBlock => "list item (block)", Self::Comment => "comment", }) } diff --git a/crates/ltk_ritobin/src/parse/impls.rs b/crates/ltk_ritobin/src/parse/impls.rs index 5a8594af..55d84e09 100644 --- a/crates/ltk_ritobin/src/parse/impls.rs +++ b/crates/ltk_ritobin/src/parse/impls.rs @@ -33,7 +33,7 @@ pub fn stmt_or_list_item(p: &mut Parser) -> (MarkClosed, TreeKind) { } (LCurly, _, _) => { let m = block(p); - res = (p.close(m, TreeKind::ListBlock), TreeKind::ListBlock); + res = (p.close(m, TreeKind::ListItemBlock), TreeKind::ListItemBlock); p.eat(Comma); } (Name | HexLit | String | Number | True | False, _, _) => { @@ -104,15 +104,15 @@ pub fn entry_value(p: &mut Parser) -> bool { p.scope(TreeKind::EntryValue, |p| { match (p.nth(0), p.nth(1)) { (Name, _) | (HexLit, LCurly) => { - p.scope(TreeKind::ListItem, |p| { - p.scope(TreeKind::Class, |p| { - p.advance(); - if p.at(LCurly) { - let block = block(p); - p.close(block, TreeKind::Block); - } - }); + // p.scope(TreeKind::ListItem, |p| { + p.scope(TreeKind::Class, |p| { + p.advance(); + if p.at(LCurly) { + let block = block(p); + p.close(block, TreeKind::Block); + } }); + // }); } (UnterminatedString, _) => { p.advance_with_error(ErrorKind::UnterminatedString, None); diff --git a/crates/ltk_ritobin/src/print.rs b/crates/ltk_ritobin/src/print.rs index bf4c33bc..35577539 100644 --- a/crates/ltk_ritobin/src/print.rs +++ b/crates/ltk_ritobin/src/print.rs @@ -40,11 +40,15 @@ mod test { fn assert_pretty(input: &str, is: &str, size: usize) { let cst = parse(input); + let mut str = String::new(); + + cst.print(&mut str, 0, input); + eprintln!("#### CST:\n{str}"); let mut str = String::new(); Printer::new(input, &mut str, size).print(&cst).unwrap(); - pretty_assertions::assert_eq!(str, is); + pretty_assertions::assert_eq!(str.trim(), is.trim()); } #[test] @@ -69,12 +73,30 @@ mod test { } #[test] - fn big_guy() { + fn class_list() { assert_pretty( - r#" nestedList : list [ vec2, ] = { {3, 6} {1 10000} }"#, - r#"nestedList: list[vec2] = { - { 3, 6 } - { 1, 10000 } + r#" classList : list2[ embed] = { MyClass {a: string = "hello"} + FooClass {b: string = "foo"}}"#, + r#"classList: list2[embed] = { + MyClass { + a: string = "hello" + } + FooClass { + b: string = "foo" + } +}"#, + 80, + ); + } + + #[test] + fn simple_class_embed() { + assert_pretty( + r#"skinUpgradeData: embed = skinUpgradeData { + mGearSkinUpgrades: list[link] = { 0x3b9c7079, 0x17566805 } + }"#, + r#"skinUpgradeData: embed = skinUpgradeData { + mGearSkinUpgrades: list[link] = { 0x3b9c7079, 0x17566805 } }"#, 80, ); diff --git a/crates/ltk_ritobin/src/print/visitor.rs b/crates/ltk_ritobin/src/print/visitor.rs index 9f9c769d..1d81efc5 100644 --- a/crates/ltk_ritobin/src/print/visitor.rs +++ b/crates/ltk_ritobin/src/print/visitor.rs @@ -165,7 +165,12 @@ impl<'a, W: Write> Printer<'a, W> { } } Cmd::Space => { - if !block_space { + if !block_space + && self + .queue + .front() + .is_some_and(|c| !matches!(c, Cmd::SoftLine | Cmd::Line)) + { self.out.write_char(' ')?; self.col += 1; block_space = true; @@ -229,6 +234,8 @@ impl<'a, W: Write> Printer<'a, W> { Cmd::Dedent(n) => { self.indent -= n; } + + _ => {} } } @@ -256,13 +263,14 @@ impl<'a, W: Write> Printer<'a, W> { return Ok(()); } - eprintln!("->{:?}", token.kind); + // eprintln!("->{:?}", token.kind); match token.kind { TokenKind::LCurly => { self.space(); self.text("{"); self.indent(4); - self.softline(); + self.space(); + // self.softline(); } TokenKind::RCurly => { @@ -316,7 +324,8 @@ impl<'a, W: fmt::Write> Visitor for Printer<'a, W> { grp, }); } - Kind::ListBlock => { + Kind::ListItemBlock => { + self.softline(); let grp = self.begin_group(None); let len = tree @@ -340,7 +349,7 @@ impl<'a, W: fmt::Write> Visitor for Printer<'a, W> { .iter() .filter(|n| { n.tree() - .is_some_and(|t| matches!(t.kind, Kind::ListItem | Kind::ListBlock)) + .is_some_and(|t| matches!(t.kind, Kind::ListItem | Kind::ListItemBlock)) }) .count(); if len > 0 { @@ -351,6 +360,22 @@ impl<'a, W: fmt::Write> Visitor for Printer<'a, W> { }); } } + Kind::Class => {} + Kind::ListItem => { + if tree + .children + .first() + .is_some_and(|c| c.tree().is_some_and(|t| t.kind == Kind::Class)) + { + if let Some(list) = self.list_stack.last_mut() { + let Cmd::Begin(mode) = self.queue.get_mut(list.grp.0).unwrap() else { + unreachable!("grp pointing at non begin cmd"); + }; + mode.replace(Mode::Break); + } + self.softline(); + } + } Kind::Entry => { self.line(); } @@ -360,10 +385,10 @@ impl<'a, W: fmt::Write> Visitor for Printer<'a, W> { } fn exit_tree(&mut self, tree: &Cst) -> Visit { match tree.kind { - Kind::ListBlock | Kind::Block | Kind::TypeArgList => { + Kind::ListItemBlock | Kind::Block | Kind::TypeArgList => { self.list_stack.pop(); self.end_group(); - eprintln!("exit {} | stack: {}", tree.kind, self.list_stack.len()); + // eprintln!("exit {} | stack: {}", tree.kind, self.list_stack.len()); if let Some(list) = self.list_stack.last_mut() { let Cmd::Begin(mode) = self.queue.get_mut(list.grp.0).unwrap() else { unreachable!("grp pointing at non begin cmd"); diff --git a/crates/ltk_ritobin/src/typecheck/visitor.rs b/crates/ltk_ritobin/src/typecheck/visitor.rs index 748520a6..eec16354 100644 --- a/crates/ltk_ritobin/src/typecheck/visitor.rs +++ b/crates/ltk_ritobin/src/typecheck/visitor.rs @@ -937,7 +937,7 @@ impl Visitor for TypeChecker<'_> { match tree.kind { Kind::ErrorTree => return Visit::Skip, - Kind::ListBlock => { + Kind::ListItemBlock => { let Some((_, parent)) = parent else { self.ctx .diagnostics @@ -1083,7 +1083,10 @@ impl Visitor for TypeChecker<'_> { self.stack.push((d, parent)); } None => { - assert_eq!(depth, 2); + if depth != 2 { + eprintln!("ERROR: depth not 2???"); + } + // assert_eq!(depth, 2); let ( _, IrItem::Entry(IrEntry { From 194b9822521a2e630baabbab96486342fb93fc10 Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Sat, 7 Mar 2026 22:42:35 +0000 Subject: [PATCH 106/187] fix: string list fmt --- crates/ltk_ritobin/src/print.rs | 16 ++++++++++++++++ crates/ltk_ritobin/src/print/visitor.rs | 2 +- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/crates/ltk_ritobin/src/print.rs b/crates/ltk_ritobin/src/print.rs index 35577539..1bf241f8 100644 --- a/crates/ltk_ritobin/src/print.rs +++ b/crates/ltk_ritobin/src/print.rs @@ -97,6 +97,22 @@ mod test { }"#, r#"skinUpgradeData: embed = skinUpgradeData { mGearSkinUpgrades: list[link] = { 0x3b9c7079, 0x17566805 } +}"#, + 80, + ); + } + + #[test] + fn long_string_list() { + assert_pretty( + r#" +linked: list[string] = { "DATA/Characters/Viego/Viego.bin" + "DATA/Viego_Skins_Skin0_Skins_Skin1_Skins_Skin10_Skins_Skin11_Skins_Skin12_Skins_Skin13_Skins_Skin14_Skins_Skin15_Skins_Skin16_Skins_Skin17_Skins_Skin18_Skins_Skin2_Skins_Skin3_Skins_Skin4_Skins_Skin43_Skins_Skin5_Skins_Skin6_Skins_Skin7_Skins_Skin8.bin" +} +"#, + r#"linked: list[string] = { + "DATA/Characters/Viego/Viego.bin" + "DATA/Viego_Skins_Skin0_Skins_Skin1_Skins_Skin10_Skins_Skin11_Skins_Skin12_Skins_Skin13_Skins_Skin14_Skins_Skin15_Skins_Skin16_Skins_Skin17_Skins_Skin18_Skins_Skin2_Skins_Skin3_Skins_Skin4_Skins_Skin43_Skins_Skin5_Skins_Skin6_Skins_Skin7_Skins_Skin8.bin" }"#, 80, ); diff --git a/crates/ltk_ritobin/src/print/visitor.rs b/crates/ltk_ritobin/src/print/visitor.rs index 1d81efc5..6597c2fe 100644 --- a/crates/ltk_ritobin/src/print/visitor.rs +++ b/crates/ltk_ritobin/src/print/visitor.rs @@ -373,8 +373,8 @@ impl<'a, W: fmt::Write> Visitor for Printer<'a, W> { }; mode.replace(Mode::Break); } - self.softline(); } + self.softline(); } Kind::Entry => { self.line(); From da09e1c9f3fa853cfd082061705a513ea018d689 Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Thu, 12 Mar 2026 18:51:49 +0000 Subject: [PATCH 107/187] fix: don't add softlines after TypeArgList --- crates/ltk_ritobin/src/print/visitor.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/crates/ltk_ritobin/src/print/visitor.rs b/crates/ltk_ritobin/src/print/visitor.rs index 6597c2fe..1dbfc6fc 100644 --- a/crates/ltk_ritobin/src/print/visitor.rs +++ b/crates/ltk_ritobin/src/print/visitor.rs @@ -385,7 +385,11 @@ impl<'a, W: fmt::Write> Visitor for Printer<'a, W> { } fn exit_tree(&mut self, tree: &Cst) -> Visit { match tree.kind { - Kind::ListItemBlock | Kind::Block | Kind::TypeArgList => { + Kind::TypeArgList => { + self.list_stack.pop(); + self.end_group(); + } + Kind::ListItemBlock | Kind::Block => { self.list_stack.pop(); self.end_group(); // eprintln!("exit {} | stack: {}", tree.kind, self.list_stack.len()); From bd98bb5f04468fb403d5f7243c2fada4ab476f62 Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Thu, 12 Mar 2026 22:08:02 +0000 Subject: [PATCH 108/187] feat: more tests --- crates/ltk_ritobin/src/print.rs | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/crates/ltk_ritobin/src/print.rs b/crates/ltk_ritobin/src/print.rs index 1bf241f8..731cee57 100644 --- a/crates/ltk_ritobin/src/print.rs +++ b/crates/ltk_ritobin/src/print.rs @@ -61,12 +61,12 @@ mod test { } #[test] - fn nested_list() { + fn vec2_list() { assert_pretty( - r#" nestedList : list [ vec2, ] = { {3, 6} {1 10000} }"#, - r#"nestedList: list[vec2] = { - { 3, 6 } - { 1, 10000 } + r#" vec2List : list [ vec2, ] = { {3, 6} {1 10000} }"#, + r#"vec2List: list[vec2] = { + { 3, 6 } + { 1, 10000 } }"#, 80, ); @@ -113,6 +113,23 @@ linked: list[string] = { "DATA/Characters/Viego/Viego.bin" r#"linked: list[string] = { "DATA/Characters/Viego/Viego.bin" "DATA/Viego_Skins_Skin0_Skins_Skin1_Skins_Skin10_Skins_Skin11_Skins_Skin12_Skins_Skin13_Skins_Skin14_Skins_Skin15_Skins_Skin16_Skins_Skin17_Skins_Skin18_Skins_Skin2_Skins_Skin3_Skins_Skin4_Skins_Skin43_Skins_Skin5_Skins_Skin6_Skins_Skin7_Skins_Skin8.bin" +}"#, + 80, + ); + } + + #[test] + fn list_of_list_of_link() { + assert_pretty( + r#"BorderAugments: list2[embed] = { + 0x4a70b12c { + AugmentGroup: list2[link] = { 0x383e4602 } + } +}"#, + r#"BorderAugments: list2[embed] = { + 0x4a70b12c { + AugmentGroup: list2[link] = { 0x383e4602 } + } }"#, 80, ); From e0dbff895e8a9b3720afc2d835d40f145f4f3961 Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Thu, 12 Mar 2026 22:08:26 +0000 Subject: [PATCH 109/187] feat: queue flushing + safety mechanisms --- crates/ltk_ritobin/src/print/visitor.rs | 329 ++++++++++++++++-------- 1 file changed, 221 insertions(+), 108 deletions(-) diff --git a/crates/ltk_ritobin/src/print/visitor.rs b/crates/ltk_ritobin/src/print/visitor.rs index 1dbfc6fc..129cbf65 100644 --- a/crates/ltk_ritobin/src/print/visitor.rs +++ b/crates/ltk_ritobin/src/print/visitor.rs @@ -18,7 +18,7 @@ pub enum Mode { } #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] -struct GroupId(usize); +pub struct GroupId(usize); #[derive(Copy, Clone, PartialEq, Eq, Debug)] pub enum Cmd<'a> { @@ -40,6 +40,8 @@ struct ListContext { grp: GroupId, } +const MAX_QUEUE: usize = 4096; + pub struct Printer<'a, W: Write> { src: &'a str, out: W, @@ -47,12 +49,21 @@ pub struct Printer<'a, W: Write> { col: usize, indent: usize, + printed: usize, pub queue: VecDeque>, + pub queue_size_max: usize, modes: Vec, + /// group start indices + group_stack: Vec, list_stack: Vec, + /// running inline size for each group + size_stack: Vec, pub error: Option, + + block_space: bool, + block_line: bool, } impl<'a, W: Write> Printer<'a, W> { @@ -63,62 +74,139 @@ impl<'a, W: Write> Printer<'a, W> { width, col: 0, indent: 0, + printed: 0, queue: VecDeque::new(), + queue_size_max: 0, modes: vec![Mode::Break], + + group_stack: Vec::new(), list_stack: Vec::new(), + size_stack: Vec::new(), error: None, + + block_space: false, + block_line: false, + } + } + + fn push(&mut self, cmd: Cmd<'a>) { + // eprintln!("+ {cmd:?}"); + self.queue.push_back(cmd); + self.queue_size_max = self.queue_size_max.max(self.queue.len()); + if self.queue.len() > MAX_QUEUE { + eprintln!("[!!] hit hard queue limit - force breaking to save memory"); + self.break_first_group(); } } pub fn text(&mut self, txt: &'a str) { - self.queue.push_back(Cmd::Text(txt)); + for size in &mut self.size_stack { + *size += txt.len(); + } + self.check_running_size(); + self.push(Cmd::Text(txt)); } pub fn text_if(&mut self, txt: &'a str, mode: Mode) { - self.queue.push_back(Cmd::TextIf(txt, mode)); + self.push(Cmd::TextIf(txt, mode)); } pub fn space(&mut self) { - self.queue.push_back(Cmd::Space); + if matches!( + self.queue.back(), + Some(Cmd::Space) | Some(Cmd::Line) | Some(Cmd::SoftLine) + ) { + // eprintln!("# skipping Space! ({:?})", self.queue.back()); + return; + } + self.push(Cmd::Space); } pub fn line(&mut self) { - if self.queue.is_empty() { + if self.queue.is_empty() && self.printed == 0 { return; } - self.queue.push_back(Cmd::Line); + if matches!( + self.queue.back(), + Some(Cmd::Space) | Some(Cmd::Line) | Some(Cmd::SoftLine) + ) { + // eprintln!("# replacing ({:?}) w/ Line", self.queue.back()); + self.queue.pop_back(); + } + self.push(Cmd::Line); } pub fn softline(&mut self) { - if self.queue.is_empty() { + if self.queue.is_empty() && self.printed == 0 { return; } - self.queue.push_back(Cmd::SoftLine); + if matches!( + self.queue.back(), + Some(Cmd::Space) | Some(Cmd::Line) | Some(Cmd::SoftLine) + ) { + // eprintln!("# replacing ({:?}) w/ SoftLine", self.queue.back()); + self.queue.pop_back(); + } + self.push(Cmd::SoftLine); } pub fn begin_group(&mut self, mode: Option) -> GroupId { - let id = GroupId(self.queue.len()); - self.queue.push_back(Cmd::Begin(mode)); - id + let idx = self.queue.len() + self.printed; + + self.push(Cmd::Begin(mode)); + + self.group_stack.push(idx); + self.size_stack.push(0); + + GroupId(idx) } pub fn end_group(&mut self) { - self.queue.push_back(Cmd::End); + self.push(Cmd::End); + + self.group_stack.pop(); + self.size_stack.pop(); + + self.print_safe().unwrap(); } pub fn indent(&mut self, n: usize) { - self.queue.push_back(Cmd::Indent(n)); + self.push(Cmd::Indent(n)); } pub fn dedent(&mut self, n: usize) { - self.queue.push_back(Cmd::Dedent(n)); + self.push(Cmd::Dedent(n)); + } + + /// break the first/oldest group if running size is too big (bottom of the stack) + pub fn break_first_group(&mut self) { + if let Some(&idx) = self.group_stack.first() { + // eprintln!("[printer] breaking first group"); + self.force_group(GroupId(idx), Mode::Break); + + self.group_stack.remove(0); + self.size_stack.remove(0); + } + self.print_safe().unwrap(); + } + + /// break the first/oldest group if running size is too big (bottom of the stack) + pub fn check_running_size(&mut self) { + if let Some(size) = self.size_stack.last() { + if self.col + size > self.width { + self.break_first_group(); + } + } } fn fits(&self) -> bool { let mut col = self.col; let mut depth = 0; - for cmd in &self.queue { + for (i, cmd) in self.queue.iter().enumerate() { + if i > 512 { + panic!("fits too long"); + } match cmd { Cmd::Text(s) | Cmd::TextIf(s, Mode::Flat) => { col += s.len(); @@ -143,102 +231,134 @@ impl<'a, W: Write> Printer<'a, W> { true } - pub fn flush(&mut self) -> fmt::Result { - let mut block_space = false; - let mut block_line = false; - eprintln!("###### FLUSH ##"); - while let Some(cmd) = self.queue.pop_front() { - eprintln!("- {cmd:?}"); - match cmd { - Cmd::Text(s) => { + pub fn force_group(&mut self, group: GroupId, mode: Mode) { + if group.0 < self.printed { + // eprintln!("[!!] trying to mutate already printed group! {group:?}"); + return; + // panic!("trying to mutate already printed group!"); + } + let cmd = self.queue.get_mut(group.0 - self.printed).unwrap(); + let Cmd::Begin(grp_mode) = cmd else { + unreachable!("grp pointing at non begin cmd {cmd:?}"); + }; + grp_mode.replace(mode); + } + + fn print(&mut self, cmd: Cmd) -> fmt::Result { + match cmd { + Cmd::Text(s) => { + self.out.write_str(s)?; + self.col += s.len(); + self.block_space = false; + self.block_line = false; + } + Cmd::TextIf(s, mode) => { + if *self.modes.last().unwrap() == mode { self.out.write_str(s)?; self.col += s.len(); - block_space = false; - block_line = false; + self.block_space = false; + self.block_line = false; } - Cmd::TextIf(s, mode) => { - if *self.modes.last().unwrap() == mode { - self.out.write_str(s)?; - self.col += s.len(); - block_space = false; - block_line = false; - } + } + Cmd::Space => { + if !self.block_space { + self.out.write_char(' ')?; + self.col += 1; + self.block_space = true; + self.block_line = false; } - Cmd::Space => { - if !block_space - && self - .queue - .front() - .is_some_and(|c| !matches!(c, Cmd::SoftLine | Cmd::Line)) - { - self.out.write_char(' ')?; - self.col += 1; - block_space = true; - block_line = false; - } + } + + Cmd::Line => { + self.out.write_char('\n')?; + for _ in 0..self.indent { + self.out.write_char(' ')?; } + self.col = self.indent; + self.propagate_break(); + self.block_space = true; + self.block_line = true; + } - Cmd::Line => { - self.out.write_char('\n')?; - for _ in 0..self.indent { + Cmd::SoftLine => match self.modes.last().unwrap() { + Mode::Flat => { + if !self.block_space { + // eprintln!(" - not skipping -> space!"); self.out.write_char(' ')?; + self.col += 1; + self.block_space = true; + self.block_line = false; } - self.col = self.indent; - self.propagate_break(); - block_space = true; - block_line = true; } - - Cmd::SoftLine => { - match self.modes.last().unwrap() { - Mode::Flat => { - if !block_space { - self.out.write_char(' ')?; - self.col += 1; - block_space = true; - block_line = false; - } - } - Mode::Break => { - if !block_line { - // eprintln!(" - not skipping"); - self.out.write_char('\n')?; - for _ in 0..self.indent { - self.out.write_char(' ')?; - } - self.col = self.indent; - self.propagate_break(); - block_space = true; - block_line = true; - } + Mode::Break => { + if !self.block_line { + // eprintln!(" - not skipping -> line!"); + self.out.write_char('\n')?; + for _ in 0..self.indent { + self.out.write_char(' ')?; } + self.col = self.indent; + self.propagate_break(); + self.block_space = true; + self.block_line = true; } } + }, + + Cmd::Begin(mode) => { + self.modes.push(match mode { + Some(mode) => mode, + None => match self.fits() { + true => Mode::Flat, + false => Mode::Break, + }, + }); + } + Cmd::End => { + self.modes.pop(); + } - Cmd::Begin(mode) => { - self.modes.push(match mode { - Some(mode) => mode, - None => match self.fits() { - true => Mode::Flat, - false => Mode::Break, - }, - }); - } - Cmd::End => { - self.modes.pop(); - } + Cmd::Indent(n) => { + self.indent += n; + } + Cmd::Dedent(n) => { + self.indent = self.indent.saturating_sub(n); + } - Cmd::Indent(n) => { - self.indent += n; - } - Cmd::Dedent(n) => { - self.indent -= n; - } + _ => {} + } + Ok(()) + } - _ => {} - } + pub fn flush(&mut self) -> fmt::Result { + // eprintln!("###### FLUSH ##"); + while let Some(cmd) = self.queue.pop_front() { + self.printed += 1; + self.print(cmd)?; + // eprintln!("- {cmd:?}"); + } + + Ok(()) + } + + pub fn print_safe(&mut self) -> fmt::Result { + let limit = self + .group_stack + .first() + .copied() + .unwrap_or(self.queue.len() + self.printed); + + if limit > self.printed { + let count = limit - self.printed; + // eprintln!("[printer] printing {count}..."); } + while self.printed < limit { + let cmd = self.queue.pop_front().unwrap(); + // eprintln!("- {cmd:?}"); + self.printed += 1; + self.print(cmd)?; + } Ok(()) } @@ -274,9 +394,6 @@ impl<'a, W: Write> Printer<'a, W> { } TokenKind::RCurly => { - if let Some(Cmd::SoftLine) = self.queue.back() { - self.queue.pop_back(); - } self.dedent(4); self.softline(); self.text("}"); @@ -301,6 +418,7 @@ impl<'a, W: Write> Printer<'a, W> { self.text(txt); } } + self.print_safe()?; // self.flush()?; Ok(()) } @@ -367,17 +485,15 @@ impl<'a, W: fmt::Write> Visitor for Printer<'a, W> { .first() .is_some_and(|c| c.tree().is_some_and(|t| t.kind == Kind::Class)) { - if let Some(list) = self.list_stack.last_mut() { - let Cmd::Begin(mode) = self.queue.get_mut(list.grp.0).unwrap() else { - unreachable!("grp pointing at non begin cmd"); - }; - mode.replace(Mode::Break); + if let Some(list) = self.list_stack.last() { + self.force_group(list.grp, Mode::Break); } } self.softline(); } Kind::Entry => { self.line(); + // self.flush().unwrap(); } _ => {} } @@ -391,15 +507,12 @@ impl<'a, W: fmt::Write> Visitor for Printer<'a, W> { } Kind::ListItemBlock | Kind::Block => { self.list_stack.pop(); - self.end_group(); // eprintln!("exit {} | stack: {}", tree.kind, self.list_stack.len()); - if let Some(list) = self.list_stack.last_mut() { - let Cmd::Begin(mode) = self.queue.get_mut(list.grp.0).unwrap() else { - unreachable!("grp pointing at non begin cmd"); - }; - mode.replace(Mode::Break); + if let Some(list) = self.list_stack.last() { + self.force_group(list.grp, Mode::Break); self.softline(); } + self.end_group(); } Kind::ListItem | Kind::TypeArg => { if let Some(ctx) = self.list_stack.last() { From 4ed6ed700188b9a6d4b0dafbb374a39980192409 Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Thu, 12 Mar 2026 22:08:46 +0000 Subject: [PATCH 110/187] feat: formatter example --- crates/ltk_ritobin/examples/rito_fmt.rs | 30 +++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 crates/ltk_ritobin/examples/rito_fmt.rs diff --git a/crates/ltk_ritobin/examples/rito_fmt.rs b/crates/ltk_ritobin/examples/rito_fmt.rs new file mode 100644 index 00000000..6a91d4c0 --- /dev/null +++ b/crates/ltk_ritobin/examples/rito_fmt.rs @@ -0,0 +1,30 @@ +use std::{fs::File, io::BufReader, path::PathBuf, str::FromStr}; + +use ltk_ritobin::print::Printer; + +fn main() { + let mut args = std::env::args().skip(1); + let Some(input_path) = args.next().and_then(|p| PathBuf::from_str(&p).ok()) else { + eprintln!("Usage: './from_bin [PATH_TO_RITOBIN]'"); + return; + }; + + let size = args + .next() + .and_then(|p| usize::from_str(&p).ok()) + .unwrap_or(80); + eprintln!("Formatting {input_path:?}... (size {size})"); + + let input = std::fs::read_to_string(input_path).unwrap(); + + let cst = ltk_ritobin::parse::parse(&input); + + // let mut str = String::new(); + // cst.print(&mut str, 0, &input); + // eprintln!("#### CST:\n{str}"); + + let mut str = String::new(); + Printer::new(&input, &mut str, size).print(&cst).unwrap(); + + println!("{str}"); +} From 3a6858601c76f70333352001fcb1aabdb6126571 Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Wed, 18 Mar 2026 17:02:25 +0000 Subject: [PATCH 111/187] fix: replace mod.rs's --- crates/ltk_ritobin/src/{parse/mod.rs => parse.rs} | 0 crates/ltk_ritobin/src/parse/{cst/mod.rs => cst.rs} | 0 crates/ltk_ritobin/src/{typecheck/mod.rs => typecheck.rs} | 0 crates/ltk_ritobin/src/typecheck/visitor.rs | 8 ++++++-- 4 files changed, 6 insertions(+), 2 deletions(-) rename crates/ltk_ritobin/src/{parse/mod.rs => parse.rs} (100%) rename crates/ltk_ritobin/src/parse/{cst/mod.rs => cst.rs} (100%) rename crates/ltk_ritobin/src/{typecheck/mod.rs => typecheck.rs} (100%) diff --git a/crates/ltk_ritobin/src/parse/mod.rs b/crates/ltk_ritobin/src/parse.rs similarity index 100% rename from crates/ltk_ritobin/src/parse/mod.rs rename to crates/ltk_ritobin/src/parse.rs diff --git a/crates/ltk_ritobin/src/parse/cst/mod.rs b/crates/ltk_ritobin/src/parse/cst.rs similarity index 100% rename from crates/ltk_ritobin/src/parse/cst/mod.rs rename to crates/ltk_ritobin/src/parse/cst.rs diff --git a/crates/ltk_ritobin/src/typecheck/mod.rs b/crates/ltk_ritobin/src/typecheck.rs similarity index 100% rename from crates/ltk_ritobin/src/typecheck/mod.rs rename to crates/ltk_ritobin/src/typecheck.rs diff --git a/crates/ltk_ritobin/src/typecheck/visitor.rs b/crates/ltk_ritobin/src/typecheck/visitor.rs index eec16354..de7953c2 100644 --- a/crates/ltk_ritobin/src/typecheck/visitor.rs +++ b/crates/ltk_ritobin/src/typecheck/visitor.rs @@ -962,7 +962,9 @@ impl Visitor for TypeChecker<'_> { })), )); } - _ => {} + parent_type => { + eprintln!("[warn] got {parent_type:?} in ListItemBlock"); + } } } Kind::ListItem => { @@ -1084,7 +1086,9 @@ impl Visitor for TypeChecker<'_> { } None => { if depth != 2 { - eprintln!("ERROR: depth not 2???"); + // eprintln!("ERROR: depth not 2??? - {depth}"); + // eprintln!("{ir:?}"); + return Visit::Continue; } // assert_eq!(depth, 2); let ( From 659da2fb2f4e3e6f4e9e65949f12b028343bda3b Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Wed, 18 Mar 2026 20:47:54 +0000 Subject: [PATCH 112/187] fix (typecheck): hash parsing for entry key --- crates/ltk_ritobin/src/typecheck/visitor.rs | 50 ++++++++++++++++++--- 1 file changed, 43 insertions(+), 7 deletions(-) diff --git a/crates/ltk_ritobin/src/typecheck/visitor.rs b/crates/ltk_ritobin/src/typecheck/visitor.rs index de7953c2..cc248996 100644 --- a/crates/ltk_ritobin/src/typecheck/visitor.rs +++ b/crates/ltk_ritobin/src/typecheck/visitor.rs @@ -13,7 +13,7 @@ use ltk_meta::{ use crate::{ parse::{ - cst::{self, visitor::Visit, Cst, Kind, Visitor}, + cst::{self, visitor::Visit, Child, Cst, Kind, Visitor}, Span, Token, TokenKind, }, typecheck::RitobinName, @@ -624,6 +624,45 @@ pub fn resolve_entry( let key = c.expect_tree(Kind::EntryKey)?; + let (key, key_span) = match key.children.first().ok_or(InvalidHash(key.span))? { + Child::Token(Token { + kind: TokenKind::Name, + span, + }) => ( + PropertyValueEnum::from(values::String::from(&ctx.text[span])), + *span, + ), + Child::Token(Token { + kind: TokenKind::String, + span, + }) => ( + PropertyValueEnum::from(values::String::from(&ctx.text[span])), // TODO: trim quotes + *span, + ), + Child::Token(Token { + kind: TokenKind::HexLit, + span, + }) => { + // TODO: better err here? + ( + PropertyValueEnum::Hash( + u32::from_str_radix( + ctx.text[span] + .strip_prefix("0x") + .ok_or(InvalidHash(*span))?, + 16, + ) + .map_err(|_| InvalidHash(*span))? + .into(), + ), + *span, + ) + } + _ => { + return Err(InvalidHash(key.span).into()); + } + }; + let parent_value_kind = parent_value_kind .and_then(|p| p.value_subtype()) .map(RitoType::simple); @@ -654,7 +693,7 @@ pub fn resolve_entry( .unwrap(), ); return Ok(IrEntry { - key: values::String::new_with_meta(ctx.text[key.span].into(), key.span).into(), + key, value: parent.make_default(value.span), }); } @@ -667,7 +706,7 @@ pub fn resolve_entry( let value = match (kind, resolved_val) { (None, Some(value)) => value, - (None, None) => return Err(MissingType(key.span).into()), + (None, None) => return Err(MissingType(key_span).into()), (Some(kind), Some(ivalue)) => match ivalue.kind() == kind.base { true => ivalue, false => { @@ -683,10 +722,7 @@ pub fn resolve_entry( (Some(kind), _) => kind.make_default(value_span), }; - Ok(IrEntry { - key: values::String::new_with_meta(ctx.text[key.span].into(), key.span).into(), - value, - }) + Ok(IrEntry { key, value }) } pub fn resolve_list(ctx: &mut Ctx, tree: &Cst) -> Result<(), Diagnostic> { From eef0bb7e45be02d270f04c7c32ba97041f01514a Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Wed, 18 Mar 2026 20:53:27 +0000 Subject: [PATCH 113/187] feat: print fixed tokens regardless of span stuff like punctuation doesn't need to have a valid span to know what should be printed. this makes it cheaper to build arbitrary cst's without needing to allocate string space for known grammar symbols --- crates/ltk_ritobin/src/parse/tokenizer.rs | 29 +++++++++++++++++++++++ crates/ltk_ritobin/src/print/visitor.rs | 19 ++++++++++++++- 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/crates/ltk_ritobin/src/parse/tokenizer.rs b/crates/ltk_ritobin/src/parse/tokenizer.rs index cdd104f1..d77a3a49 100644 --- a/crates/ltk_ritobin/src/parse/tokenizer.rs +++ b/crates/ltk_ritobin/src/parse/tokenizer.rs @@ -27,6 +27,35 @@ impl TokenKind { pub fn is_string(&self) -> bool { matches!(self, Self::String | Self::UnterminatedString) } + + pub fn print_value(&self) -> Option<&'static str> { + match self { + TokenKind::Unknown => None, + TokenKind::Eof => None, + TokenKind::Newline => None, + TokenKind::LParen => Some("("), + TokenKind::RParen => Some(")"), + TokenKind::LCurly => Some("{"), + TokenKind::RCurly => Some("}"), + TokenKind::LBrack => Some("["), + TokenKind::RBrack => Some("]"), + TokenKind::Eq => Some("="), + TokenKind::Comma => Some(","), + TokenKind::Colon => Some(":"), + TokenKind::SemiColon => Some(";"), + TokenKind::Star => Some("*"), + TokenKind::Slash => Some("/"), + TokenKind::Quote => Some("\""), + TokenKind::String => None, + TokenKind::UnterminatedString => None, + TokenKind::Comment => None, + TokenKind::True => Some("true"), + TokenKind::False => Some("false"), + TokenKind::Name => None, + TokenKind::Number => None, + TokenKind::HexLit => None, + } + } } impl Display for TokenKind { diff --git a/crates/ltk_ritobin/src/print/visitor.rs b/crates/ltk_ritobin/src/print/visitor.rs index 129cbf65..75639361 100644 --- a/crates/ltk_ritobin/src/print/visitor.rs +++ b/crates/ltk_ritobin/src/print/visitor.rs @@ -378,8 +378,9 @@ impl<'a, W: Write> Printer<'a, W> { context: &Cst, ) -> Result<(), PrintError> { let txt = self.src[token.span].trim(); + let print_value = token.kind.print_value(); - if txt.is_empty() { + if txt.is_empty() && print_value.is_none() { return Ok(()); } @@ -414,6 +415,22 @@ impl<'a, W: Write> Printer<'a, W> { self.space(); } + TokenKind::LBrack => { + self.text("["); + } + TokenKind::RBrack => { + self.text("]"); + } + TokenKind::Quote => { + self.text("\""); + } + TokenKind::False => { + self.text("false"); + } + TokenKind::True => { + self.text("true"); + } + _ => { self.text(txt); } From d2f47937e95e1de90d663ade658907b9454284f2 Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Wed, 18 Mar 2026 20:54:13 +0000 Subject: [PATCH 114/187] fix: print token kind in Cst::print helper --- crates/ltk_ritobin/src/parse/cst/tree.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/crates/ltk_ritobin/src/parse/cst/tree.rs b/crates/ltk_ritobin/src/parse/cst/tree.rs index 4458c66d..42cdfc41 100644 --- a/crates/ltk_ritobin/src/parse/cst/tree.rs +++ b/crates/ltk_ritobin/src/parse/cst/tree.rs @@ -117,8 +117,9 @@ impl Cst { Child::Token(token) => { format_to!( buf, - "{parent_indent}│ {bar} {:?}\n", - &source[token.span.start as _..token.span.end as _] + "{parent_indent}│ {bar} {:?} ({:?})\n", + &source[token.span.start as _..token.span.end as _], + token.kind, ) } Child::Tree(tree) => tree.print(buf, level + 1, source), From 131fe2f76ca05d05ddc53d7d2769e5f9217ee651 Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Wed, 18 Mar 2026 20:54:31 +0000 Subject: [PATCH 115/187] wip: cst construction from bin tree --- crates/ltk_ritobin/src/parse/cst.rs | 2 + crates/ltk_ritobin/src/parse/cst/builder.rs | 315 ++++++++++++++++++++ crates/ltk_ritobin/src/print.rs | 19 +- 3 files changed, 335 insertions(+), 1 deletion(-) create mode 100644 crates/ltk_ritobin/src/parse/cst/builder.rs diff --git a/crates/ltk_ritobin/src/parse/cst.rs b/crates/ltk_ritobin/src/parse/cst.rs index fcb28b23..2106adc5 100644 --- a/crates/ltk_ritobin/src/parse/cst.rs +++ b/crates/ltk_ritobin/src/parse/cst.rs @@ -5,5 +5,7 @@ pub use tree::*; pub mod visitor; pub use visitor::Visitor; +pub mod builder; + mod flat_errors; pub use flat_errors::*; diff --git a/crates/ltk_ritobin/src/parse/cst/builder.rs b/crates/ltk_ritobin/src/parse/cst/builder.rs new file mode 100644 index 00000000..a4b66378 --- /dev/null +++ b/crates/ltk_ritobin/src/parse/cst/builder.rs @@ -0,0 +1,315 @@ +use std::fmt::Write; + +use ltk_meta::{property::values, Bin, BinObject, BinProperty, PropertyKind, PropertyValueEnum}; + +use crate::{ + kind_to_type_name, + parse::{ + cst::{Child, Cst, Kind}, + Span, Token, TokenKind as Tok, + }, + typecheck::visitor::{PropertyValueExt, RitoType}, +}; + +struct Builder { + buf: String, +} + +pub fn tree(kind: Kind, children: Vec) -> Child { + Child::Tree(Cst { + span: Span::default(), + kind, + children, + errors: vec![], + }) +} +pub fn token(kind: Tok) -> Child { + Child::Token(Token { + kind, + span: Span::default(), + }) +} + +impl Builder { + pub fn number(&mut self, v: impl AsRef) -> Child { + self.buf.write_str(v.as_ref()).unwrap(); + token(Tok::Number) + } + + pub fn spanned_token(&mut self, kind: Tok, str: impl AsRef) -> Child { + let start = self.buf.len() as u32; + self.buf.write_str(str.as_ref()).unwrap(); + let end = self.buf.len() as u32; + Child::Token(Token { + kind, + span: Span::new(start, end), + }) + } + + pub fn string(&mut self, v: impl AsRef) -> Child { + self.spanned_token(Tok::String, v) + } + + pub fn name(&mut self, v: impl AsRef) -> Child { + self.spanned_token(Tok::Name, v) + } + + pub fn hex_lit(&mut self, v: impl AsRef) -> Child { + self.spanned_token(Tok::HexLit, v) + } + + pub fn block(&self, children: Vec) -> Child { + tree( + Kind::Block, + [vec![token(Tok::LCurly)], children, vec![token(Tok::RCurly)]].concat(), + ) + } + + fn value_to_cst(&mut self, value: &PropertyValueEnum) -> Child { + match value { + PropertyValueEnum::Bool(b) => tree( + Kind::Literal, + vec![token(if **b { Tok::True } else { Tok::False })], + ), + PropertyValueEnum::None(_) => { + tree(Kind::Literal, vec![token(Tok::LCurly), token(Tok::RCurly)]) + } + PropertyValueEnum::U8(n) => tree(Kind::Literal, vec![token(Tok::Number)]), + PropertyValueEnum::U16(n) => tree(Kind::Literal, vec![token(Tok::Number)]), + PropertyValueEnum::U32(n) => tree(Kind::Literal, vec![token(Tok::Number)]), + PropertyValueEnum::U64(n) => tree(Kind::Literal, vec![token(Tok::Number)]), + PropertyValueEnum::I8(n) => tree(Kind::Literal, vec![token(Tok::Number)]), + PropertyValueEnum::I16(n) => tree(Kind::Literal, vec![token(Tok::Number)]), + PropertyValueEnum::I32(n) => tree(Kind::Literal, vec![token(Tok::Number)]), + PropertyValueEnum::I64(n) => tree(Kind::Literal, vec![token(Tok::Number)]), + PropertyValueEnum::F32(n) => tree(Kind::Literal, vec![token(Tok::Number)]), + PropertyValueEnum::Vector2(v) => tree(Kind::Literal, vec![token(Tok::Number)]), + PropertyValueEnum::Vector3(v) => tree(Kind::Literal, vec![token(Tok::Number)]), + PropertyValueEnum::Vector4(v) => tree(Kind::Literal, vec![token(Tok::Number)]), + PropertyValueEnum::String(s) => tree( + Kind::Literal, + vec![token(Tok::Quote), self.string(&**s), token(Tok::Quote)], + ), + PropertyValueEnum::Container(container) + | PropertyValueEnum::UnorderedContainer(values::UnorderedContainer(container)) => { + let mut children = vec![token(Tok::LBrack)]; + + for (i, item) in container.clone().into_items().enumerate() { + if i > 0 { + children.push(token(Tok::Comma)); + } + children.push(self.value_to_cst(&item)); + } + + children.push(token(Tok::RBrack)); + tree(Kind::TypeArgList, children) + } + PropertyValueEnum::Matrix44(matrix44) => todo!(), + PropertyValueEnum::Color(color) => todo!(), + PropertyValueEnum::Hash(hash) => todo!(), + PropertyValueEnum::WadChunkLink(wad_chunk_link) => todo!(), + PropertyValueEnum::Struct(_) => todo!(), + PropertyValueEnum::Embedded(embedded) => { + let children = embedded + .0 + .properties + .iter() + .map(|(k, v)| { + let k = self.spanned_token(Tok::HexLit, k.to_string()); + let t = self.rito_type(v.value.rito_type()); + let v = self.property_to_cst(v); + self.entry(k, Some(t), v) + }) + .collect(); + tree(Kind::Class, vec![token(Tok::HexLit), self.block(children)]) + } + PropertyValueEnum::ObjectLink(object_link) => todo!(), + PropertyValueEnum::BitBool(bit_bool) => todo!(), + PropertyValueEnum::Optional(optional) => { + let children = match optional.clone().into_inner() { + Some(v) => vec![self.value_to_cst(&v)], + None => vec![], + }; + self.block(children) + } + PropertyValueEnum::Map(map) => todo!(), + } + } + + fn entry(&self, key: Child, kind: Option, value: Child) -> Child { + tree( + Kind::Entry, + match kind { + Some(kind) => vec![key, token(Tok::Colon), kind, token(Tok::Eq), value], + None => vec![key, token(Tok::Eq), value], + }, + ) + } + + fn rito_type(&mut self, rito_type: RitoType) -> Child { + let mut children = vec![self.spanned_token(Tok::Name, kind_to_type_name(rito_type.base))]; + + if let Some(sub) = rito_type.subtypes[0] { + let mut args = vec![ + token(Tok::LBrack), + tree( + Kind::TypeArg, + vec![self.spanned_token(Tok::Name, kind_to_type_name(sub))], + ), + ]; + if let Some(sub) = rito_type.subtypes[1] { + args.push(token(Tok::Comma)); + args.push(tree( + Kind::TypeArg, + vec![self.spanned_token(Tok::Name, kind_to_type_name(sub))], + )); + } + args.push(token(Tok::RBrack)); + children.push(tree(Kind::TypeArgList, args)); + } + + tree(Kind::TypeExpr, children) + } + fn property_to_cst(&mut self, prop: &BinProperty) -> Child { + let k = self.spanned_token(Tok::HexLit, prop.name_hash.to_string()); + let t = self.rito_type(prop.value.rito_type()); + let v = self.value_to_cst(&prop.value); + self.entry(k, Some(t), v) + } + + fn object_block(&mut self, obj: &BinObject) -> Child { + let mut children = vec![token(Tok::LCurly)]; + + for prop in obj.properties.values() { + children.push(self.property_to_cst(prop)); + } + + children.push(token(Tok::RCurly)); + + tree(Kind::Block, children) + } + + fn class(&self, class_name: Child, items: Vec) -> Child { + tree(Kind::Class, vec![class_name, self.block(items)]) + } + + fn bin_object_to_cst(&mut self, obj: &BinObject) -> Child { + let k = self.hex_lit(format!("0x{:x}", obj.path_hash)); + + let class_hash = self.hex_lit(format!("0x{:x}", obj.class_hash)); + let class_values = obj + .properties + .iter() + .map(|(k, v)| { + let k = tree(Kind::EntryKey, vec![self.hex_lit(format!("0x{k:x}"))]); + let t = self.rito_type(v.value.rito_type()); + let v = self.value_to_cst(&v.value); + self.entry(k, Some(t), v) + }) + .collect(); + + let value = self.class(class_hash, class_values); + self.entry(k, None, value) + } + + fn bin_to_cst(&mut self, bin: &Bin) -> Cst { + let mut entries = Vec::new(); + + for obj in bin.objects.values() { + entries.push(self.bin_object_to_cst(obj)); + } + + let entries_key = self.spanned_token(Tok::Name, "entries"); + let entries_type = self.rito_type(RitoType { + base: ltk_meta::PropertyKind::Map, + subtypes: [Some(PropertyKind::Hash), Some(PropertyKind::Embedded)], + }); + let entries = self.entry( + tree(Kind::EntryKey, vec![entries_key]), + Some(entries_type), + tree(Kind::EntryValue, vec![self.block(entries)]), + ); + + Cst { + kind: Kind::File, + span: Span::default(), + children: vec![entries], + errors: vec![], + } + } +} + +pub fn bin_to_cst(bin: &Bin) -> (String, Cst) { + let mut builder = Builder { buf: String::new() }; + let cst = builder.bin_to_cst(bin); + + (builder.buf, cst) +} + +#[cfg(test)] +mod test { + use ltk_meta::{property::values, Bin, BinObject}; + + use crate::{ + parse::{cst::builder::bin_to_cst, parse}, + print::Printer, + }; + + fn roundtrip(bin: Bin) { + println!("bin: {bin:#?}"); + + let (buf, cst) = bin_to_cst(&bin); + + let mut str = String::new(); + cst.print(&mut str, 0, &buf); + + println!("cst:\n{str}"); + + let mut str = String::new(); + + Printer::new(&buf, &mut str, 80).print(&cst).unwrap(); + println!("RITOBIN:\n{str}"); + + let cst2 = parse(&str); + let (bin2, errors) = cst2.build_bin(&str); + + pretty_assertions::assert_eq!(bin2, bin); + } + + #[test] + fn simple() { + roundtrip( + Bin::builder() + .object( + BinObject::builder(0xDEADBEEF, 0x12344321) + .property(0x44444444, values::String::from("hello")) + .build(), + ) + .build(), + ); + + panic!(); + } + #[test] + fn list() { + roundtrip( + Bin::builder() + .object( + BinObject::builder(0xDEADBEEF, 0x12344321) + .property(0x44444444, values::String::from("hello")) + .property( + 0x9191919, + values::Container::new(vec![ + values::U64::new(5), + values::U64::new(6), + values::U64::new(7), + ]), + ) + .build(), + ) + .build(), + ); + + panic!(); + } +} diff --git a/crates/ltk_ritobin/src/print.rs b/crates/ltk_ritobin/src/print.rs index 731cee57..01571de9 100644 --- a/crates/ltk_ritobin/src/print.rs +++ b/crates/ltk_ritobin/src/print.rs @@ -1,5 +1,7 @@ +use ltk_meta::Bin; + use crate::parse::{ - cst::{visitor::Visit, Cst, Kind, Visitor}, + cst::{builder::bin_to_cst, visitor::Visit, Cst, Kind, Visitor}, Span, TokenKind, }; @@ -30,10 +32,25 @@ impl<'a, W: Write> Printer<'a, W> { if let Some(e) = self.visitor.error { return Err(e); } + eprintln!("max q size: {}", self.visitor.queue_size_max); Ok(()) } } +pub fn print_bin(bin: &Bin, width: usize) -> Result { + let mut str = String::new(); + + let (buf, cst) = bin_to_cst(bin); + + let mut tmp = String::new(); + cst.print(&mut tmp, 0, &buf); + println!("[print] cst:\n{tmp}"); + + Printer::new(&buf, &mut str, width).print(&cst)?; + + Ok(str) +} + #[cfg(test)] mod test { use crate::{parse::parse, print::Printer}; From 38073d21a3d3b485142b2ee09bbd0e54a8edb988 Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Wed, 18 Mar 2026 20:54:36 +0000 Subject: [PATCH 116/187] wip: round trip tests --- crates/ltk_ritobin/tests/parse_sample.rs | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/crates/ltk_ritobin/tests/parse_sample.rs b/crates/ltk_ritobin/tests/parse_sample.rs index 36246cd8..17633f1b 100644 --- a/crates/ltk_ritobin/tests/parse_sample.rs +++ b/crates/ltk_ritobin/tests/parse_sample.rs @@ -1,6 +1,6 @@ //! Integration test for parsing a sample ritobin file. -use ltk_ritobin::parse::parse; +use ltk_ritobin::{parse::parse, print::print_bin}; const SAMPLE_RITOBIN: &str = r#"#PROP_text type: string = "PROP" @@ -77,18 +77,25 @@ fn test_parse_sample() { fn test_roundtrip() { let cst = parse(SAMPLE_RITOBIN); let (tree, errors) = cst.build_bin(SAMPLE_RITOBIN); + // assert!(errors.is_empty()); // Write back to text - // let output = write(&tree).expect("Failed to write"); + let output = print_bin(&tree, 80).expect("Failed to write"); // Parse again - // let file2 = parse(&output).expect("Failed to parse output"); - // let tree2 = file2.to_bin_tree(); + let cst2 = parse(&output); + + let mut str = String::new(); + cst2.print(&mut str, 0, &output); + println!("reparsed:\n{str}"); + + let (tree2, errors) = cst2.build_bin(&output); + // assert!(errors.is_empty()); // Verify structure is preserved - // assert_eq!(tree.version, tree2.version); - // assert_eq!(tree.dependencies.len(), tree2.dependencies.len()); - // assert_eq!(tree.objects.len(), tree2.objects.len()); + assert_eq!(tree.version, tree2.version); + assert_eq!(tree.dependencies.len(), tree2.dependencies.len()); + assert_eq!(tree.objects.len(), tree2.objects.len()); } // // #[test] From 1d366cb4b1c84f53d6179fad5df41c4fc1bbca04 Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Thu, 19 Mar 2026 15:51:44 +0000 Subject: [PATCH 117/187] chore: reorganise --- crates/ltk_ritobin/examples/bin_to_rito.rs | 9 +- crates/ltk_ritobin/examples/rito_fmt.rs | 13 +- crates/ltk_ritobin/src/{parse => }/cst.rs | 0 .../src/{parse => }/cst/builder.rs | 15 +- .../src/{parse => }/cst/flat_errors.rs | 4 +- .../ltk_ritobin/src/{parse => }/cst/tree.rs | 0 .../src/{parse => }/cst/visitor.rs | 6 +- crates/ltk_ritobin/src/error.rs | 15 - crates/ltk_ritobin/src/hashes.rs | 12 +- crates/ltk_ritobin/src/lib.rs | 5 +- crates/ltk_ritobin/src/parse.rs | 13 +- crates/ltk_ritobin/src/print.rs | 116 ++-- crates/ltk_ritobin/src/print/command.rs | 26 + crates/ltk_ritobin/src/print/config.rs | 32 + crates/ltk_ritobin/src/print/printers.rs | 83 +++ crates/ltk_ritobin/src/print/visitor.rs | 252 +------- crates/ltk_ritobin/src/print/visitor/impl.rs | 225 +++++++ crates/ltk_ritobin/src/print/visitor/state.rs | 0 crates/ltk_ritobin/src/typecheck/visitor.rs | 6 +- crates/ltk_ritobin/src/writer.rs | 568 +----------------- crates/ltk_ritobin/tests/parse_sample.rs | 4 +- 21 files changed, 507 insertions(+), 897 deletions(-) rename crates/ltk_ritobin/src/{parse => }/cst.rs (100%) rename crates/ltk_ritobin/src/{parse => }/cst/builder.rs (97%) rename crates/ltk_ritobin/src/{parse => }/cst/flat_errors.rs (95%) rename crates/ltk_ritobin/src/{parse => }/cst/tree.rs (100%) rename crates/ltk_ritobin/src/{parse => }/cst/visitor.rs (96%) delete mode 100644 crates/ltk_ritobin/src/error.rs create mode 100644 crates/ltk_ritobin/src/print/command.rs create mode 100644 crates/ltk_ritobin/src/print/config.rs create mode 100644 crates/ltk_ritobin/src/print/printers.rs create mode 100644 crates/ltk_ritobin/src/print/visitor/impl.rs create mode 100644 crates/ltk_ritobin/src/print/visitor/state.rs diff --git a/crates/ltk_ritobin/examples/bin_to_rito.rs b/crates/ltk_ritobin/examples/bin_to_rito.rs index f7ed795e..81bb1bf8 100644 --- a/crates/ltk_ritobin/examples/bin_to_rito.rs +++ b/crates/ltk_ritobin/examples/bin_to_rito.rs @@ -1,4 +1,7 @@ -use ltk_ritobin::HashMapProvider; +use ltk_ritobin::{ + print::{Print, PrintConfig}, + HashMapProvider, +}; use std::{fs::File, io::BufReader, path::PathBuf, str::FromStr}; fn main() { @@ -25,6 +28,8 @@ fn main() { .and_then(|p| PathBuf::from_str(&p).ok()) .unwrap_or(std::env::current_dir().unwrap()), ); - let text = ltk_ritobin::write_with_hashes(&tree, &hashes).unwrap(); + let text = tree + .print_with_config(PrintConfig::default().with_hashes(hashes)) + .unwrap(); std::fs::write(output_path, text).unwrap(); } diff --git a/crates/ltk_ritobin/examples/rito_fmt.rs b/crates/ltk_ritobin/examples/rito_fmt.rs index 6a91d4c0..8f578bd2 100644 --- a/crates/ltk_ritobin/examples/rito_fmt.rs +++ b/crates/ltk_ritobin/examples/rito_fmt.rs @@ -1,6 +1,6 @@ use std::{fs::File, io::BufReader, path::PathBuf, str::FromStr}; -use ltk_ritobin::print::Printer; +use ltk_ritobin::print::{CstPrinter, PrintConfig}; fn main() { let mut args = std::env::args().skip(1); @@ -24,7 +24,16 @@ fn main() { // eprintln!("#### CST:\n{str}"); let mut str = String::new(); - Printer::new(&input, &mut str, size).print(&cst).unwrap(); + CstPrinter::new( + &input, + &mut str, + PrintConfig { + line_width: size, + ..Default::default() + }, + ) + .print(&cst) + .unwrap(); println!("{str}"); } diff --git a/crates/ltk_ritobin/src/parse/cst.rs b/crates/ltk_ritobin/src/cst.rs similarity index 100% rename from crates/ltk_ritobin/src/parse/cst.rs rename to crates/ltk_ritobin/src/cst.rs diff --git a/crates/ltk_ritobin/src/parse/cst/builder.rs b/crates/ltk_ritobin/src/cst/builder.rs similarity index 97% rename from crates/ltk_ritobin/src/parse/cst/builder.rs rename to crates/ltk_ritobin/src/cst/builder.rs index a4b66378..c25e839c 100644 --- a/crates/ltk_ritobin/src/parse/cst/builder.rs +++ b/crates/ltk_ritobin/src/cst/builder.rs @@ -3,11 +3,9 @@ use std::fmt::Write; use ltk_meta::{property::values, Bin, BinObject, BinProperty, PropertyKind, PropertyValueEnum}; use crate::{ + cst::{Child, Cst, Kind}, kind_to_type_name, - parse::{ - cst::{Child, Cst, Kind}, - Span, Token, TokenKind as Tok, - }, + parse::{Span, Token, TokenKind as Tok}, typecheck::visitor::{PropertyValueExt, RitoType}, }; @@ -250,10 +248,7 @@ pub fn bin_to_cst(bin: &Bin) -> (String, Cst) { mod test { use ltk_meta::{property::values, Bin, BinObject}; - use crate::{ - parse::{cst::builder::bin_to_cst, parse}, - print::Printer, - }; + use crate::{cst::builder::bin_to_cst, parse::parse, print::CstPrinter}; fn roundtrip(bin: Bin) { println!("bin: {bin:#?}"); @@ -267,7 +262,9 @@ mod test { let mut str = String::new(); - Printer::new(&buf, &mut str, 80).print(&cst).unwrap(); + CstPrinter::new(&buf, &mut str, Default::default()) + .print(&cst) + .unwrap(); println!("RITOBIN:\n{str}"); let cst2 = parse(&str); diff --git a/crates/ltk_ritobin/src/parse/cst/flat_errors.rs b/crates/ltk_ritobin/src/cst/flat_errors.rs similarity index 95% rename from crates/ltk_ritobin/src/parse/cst/flat_errors.rs rename to crates/ltk_ritobin/src/cst/flat_errors.rs index 58bcb809..598d8633 100644 --- a/crates/ltk_ritobin/src/parse/cst/flat_errors.rs +++ b/crates/ltk_ritobin/src/cst/flat_errors.rs @@ -1,9 +1,9 @@ -use crate::parse::{ +use crate::{ cst::{ visitor::{Visit, Visitor}, Cst, }, - Error, + parse::Error, }; #[derive(Default)] diff --git a/crates/ltk_ritobin/src/parse/cst/tree.rs b/crates/ltk_ritobin/src/cst/tree.rs similarity index 100% rename from crates/ltk_ritobin/src/parse/cst/tree.rs rename to crates/ltk_ritobin/src/cst/tree.rs diff --git a/crates/ltk_ritobin/src/parse/cst/visitor.rs b/crates/ltk_ritobin/src/cst/visitor.rs similarity index 96% rename from crates/ltk_ritobin/src/parse/cst/visitor.rs rename to crates/ltk_ritobin/src/cst/visitor.rs index ff4c92f0..91deb50e 100644 --- a/crates/ltk_ritobin/src/parse/cst/visitor.rs +++ b/crates/ltk_ritobin/src/cst/visitor.rs @@ -1,7 +1,5 @@ -use crate::parse::{ - cst::{tree::Child, Cst}, - tokenizer::Token, -}; +use super::{tree::Child, Cst}; +use crate::parse::tokenizer::Token; #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] pub enum Visit { diff --git a/crates/ltk_ritobin/src/error.rs b/crates/ltk_ritobin/src/error.rs deleted file mode 100644 index 720bfb61..00000000 --- a/crates/ltk_ritobin/src/error.rs +++ /dev/null @@ -1,15 +0,0 @@ -//! Error types for ritobin parsing and writing. - -// The miette Diagnostic derive macro generates code that triggers this warning -#![allow(unused_assignments)] - -use miette::{Diagnostic, SourceSpan}; -use thiserror::Error; - -/// Errors that can occur during ritobin writing. -#[derive(Debug, Error, Diagnostic)] -pub enum WriteError { - #[error("fmt error: {0}")] - #[diagnostic(code(ltk_ritobin::write::fmt))] - Fmt(#[from] std::fmt::Error), -} diff --git a/crates/ltk_ritobin/src/hashes.rs b/crates/ltk_ritobin/src/hashes.rs index 90a0af61..42ba87a8 100644 --- a/crates/ltk_ritobin/src/hashes.rs +++ b/crates/ltk_ritobin/src/hashes.rs @@ -28,13 +28,7 @@ pub trait HashProvider { fn lookup_type(&self, hash: u32) -> Option<&str>; } -/// A hash provider that always returns `None`, causing all hashes to be written as hex. -/// -/// This is the default provider and is useful when you don't have hash tables available. -#[derive(Debug, Clone, Copy, Default)] -pub struct HexHashProvider; - -impl HashProvider for HexHashProvider { +impl HashProvider for () { fn lookup_entry(&self, _hash: u32) -> Option<&str> { None } @@ -230,8 +224,8 @@ mod tests { use super::*; #[test] - fn test_hex_provider() { - let provider = HexHashProvider; + fn test_empty_provider() { + let provider = (); assert_eq!(provider.lookup_entry(0x12345678), None); assert_eq!(provider.lookup_field(0x12345678), None); assert_eq!(provider.lookup_hash(0x12345678), None); diff --git a/crates/ltk_ritobin/src/lib.rs b/crates/ltk_ritobin/src/lib.rs index f346cc3d..776c7ed7 100644 --- a/crates/ltk_ritobin/src/lib.rs +++ b/crates/ltk_ritobin/src/lib.rs @@ -44,15 +44,12 @@ // Nom-style parsers use elided lifetimes extensively #![allow(mismatched_lifetime_syntaxes)] -pub mod error; +pub mod cst; pub mod hashes; pub mod parse; pub mod print; pub mod typecheck; pub mod types; -pub mod writer; -pub use error::*; pub use hashes::*; pub use types::*; -pub use writer::*; diff --git a/crates/ltk_ritobin/src/parse.rs b/crates/ltk_ritobin/src/parse.rs index 91347b01..1bc338de 100644 --- a/crates/ltk_ritobin/src/parse.rs +++ b/crates/ltk_ritobin/src/parse.rs @@ -1,7 +1,5 @@ //! Parser for ritobin text format with CST output for better error reporting. -pub mod cst; - pub mod error; pub use error::*; @@ -15,6 +13,8 @@ pub mod impls; mod span; pub use span::Span; +use crate::cst; + pub fn parse(text: &str) -> cst::Cst { let tokens = tokenizer::lex(text); let mut p = parser::Parser::new(text, tokens); @@ -24,7 +24,7 @@ pub fn parse(text: &str) -> cst::Cst { #[cfg(test)] mod test { - use crate::{print::Printer, typecheck::visitor::TypeChecker}; + use crate::{print::CstPrinter, typecheck::visitor::TypeChecker}; use super::*; #[test] @@ -124,10 +124,11 @@ entries: map[hash,embed] = { println!("{str}"); let mut str = String::new(); - let size = 100; - Printer::new(text, &mut str, size).print(&cst).unwrap(); + CstPrinter::new(text, &mut str, Default::default()) + .print(&cst) + .unwrap(); - println!("{}", "*".repeat(size)); + println!("{}", "*".repeat(80)); println!("========\n{str}"); } } diff --git a/crates/ltk_ritobin/src/print.rs b/crates/ltk_ritobin/src/print.rs index 01571de9..27d7d3d6 100644 --- a/crates/ltk_ritobin/src/print.rs +++ b/crates/ltk_ritobin/src/print.rs @@ -1,59 +1,83 @@ -use ltk_meta::Bin; - -use crate::parse::{ - cst::{builder::bin_to_cst, visitor::Visit, Cst, Kind, Visitor}, - Span, TokenKind, -}; - #[derive(Debug, thiserror::Error)] pub enum PrintError { #[error(transparent)] FmtError(#[from] fmt::Error), } -use std::fmt::{self, Write}; - -mod visitor; +use std::fmt::{self}; -pub struct Printer<'a, W: Write> { - visitor: visitor::Printer<'a, W>, -} +use ltk_meta::Bin; -impl<'a, W: Write> Printer<'a, W> { - pub fn new(src: &'a str, out: W, width: usize) -> Self { - Self { - visitor: visitor::Printer::new(src, out, width), - } +use crate::hashes::HashProvider; + +pub mod command; +pub mod visitor; + +mod config; +pub use config::*; + +mod printers; +pub use printers::*; + +// pub fn print_bin(bin: &Bin, width: usize) -> Result { +// let mut str = String::new(); +// +// let (buf, cst) = bin_to_cst(bin); +// +// let mut tmp = String::new(); +// cst.print(&mut tmp, 0, &buf); +// println!("[print] cst:\n{tmp}"); +// +// Printer::new(&buf, &mut str, width).print(&cst)?; +// +// Ok(str) +// } + +pub trait Print { + /// Print as ritobin code to the given writer (using default config, which prints hashes as hex). + fn print_to_writer(&self, writer: &mut W) -> Result { + Self::print_to_writer_with_config::(self, writer, Default::default()) } - - pub fn print(mut self, cst: &Cst) -> Result<(), PrintError> { - cst.walk(&mut self.visitor); - self.visitor.flush()?; - if let Some(e) = self.visitor.error { - return Err(e); - } - eprintln!("max q size: {}", self.visitor.queue_size_max); - Ok(()) + /// Print as ritobin code to the given writer, using the given config. + fn print_to_writer_with_config( + &self, + writer: &mut W, + config: PrintConfig, + ) -> Result; + + /// Print as ritobin code to a string (using default config, which prints hashes as hex). + fn print(&self) -> Result { + let mut str = String::new(); + Self::print_to_writer(self, &mut str)?; + Ok(str) + } + /// Print as ritobin code to a string, using the given config. + fn print_with_config( + &self, + config: PrintConfig, + ) -> Result { + let mut str = String::new(); + Self::print_to_writer_with_config(self, &mut str, config)?; + Ok(str) } } -pub fn print_bin(bin: &Bin, width: usize) -> Result { - let mut str = String::new(); - - let (buf, cst) = bin_to_cst(bin); - - let mut tmp = String::new(); - cst.print(&mut tmp, 0, &buf); - println!("[print] cst:\n{tmp}"); - - Printer::new(&buf, &mut str, width).print(&cst)?; - - Ok(str) +impl Print for Bin { + fn print_to_writer_with_config( + &self, + writer: &mut W, + config: PrintConfig, + ) -> Result { + BinPrinter::new().with_config(config).print(self, writer) + } } #[cfg(test)] mod test { - use crate::{parse::parse, print::Printer}; + use crate::{ + parse::parse, + print::{config::PrintConfig, CstPrinter}, + }; fn assert_pretty(input: &str, is: &str, size: usize) { let cst = parse(input); @@ -63,7 +87,17 @@ mod test { eprintln!("#### CST:\n{str}"); let mut str = String::new(); - Printer::new(input, &mut str, size).print(&cst).unwrap(); + CstPrinter::new( + input, + &mut str, + PrintConfig { + indent_size: 4, + line_width: size, + hashes: (), + }, + ) + .print(&cst) + .unwrap(); pretty_assertions::assert_eq!(str.trim(), is.trim()); } diff --git a/crates/ltk_ritobin/src/print/command.rs b/crates/ltk_ritobin/src/print/command.rs new file mode 100644 index 00000000..5fb32de8 --- /dev/null +++ b/crates/ltk_ritobin/src/print/command.rs @@ -0,0 +1,26 @@ +#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] +pub enum Mode { + Flat, + Break, +} + +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +pub enum Cmd<'a> { + Text(&'a str), + TextIf(&'a str, Mode), + Line, + SoftLine, + Space, + Begin(Option), + End, + Indent(usize), + Dedent(usize), +} + +impl Cmd<'_> { + #[inline(always)] + #[must_use] + pub fn is_whitespace(&self) -> bool { + matches!(self, Self::Space | Self::Line | Self::SoftLine) + } +} diff --git a/crates/ltk_ritobin/src/print/config.rs b/crates/ltk_ritobin/src/print/config.rs new file mode 100644 index 00000000..216af9c3 --- /dev/null +++ b/crates/ltk_ritobin/src/print/config.rs @@ -0,0 +1,32 @@ +use crate::HashProvider; + +/// Configuration for the ritobin printer. +#[derive(Debug, Clone)] +pub struct PrintConfig { + /// Number of spaces per indent level. + pub indent_size: usize, + /// Maximum line width + pub line_width: usize, + + pub hashes: Hashes, +} + +impl Default for PrintConfig<()> { + fn default() -> Self { + Self { + indent_size: 4, + line_width: 80, + hashes: (), + } + } +} + +impl PrintConfig { + pub fn with_hashes(self, hashes: H2) -> PrintConfig

{ + PrintConfig { + indent_size: self.indent_size, + line_width: self.line_width, + hashes, + } + } +} diff --git a/crates/ltk_ritobin/src/print/printers.rs b/crates/ltk_ritobin/src/print/printers.rs new file mode 100644 index 00000000..1cbca3da --- /dev/null +++ b/crates/ltk_ritobin/src/print/printers.rs @@ -0,0 +1,83 @@ +use std::fmt::{self, Write}; + +use ltk_meta::{ + property::{ + values::{Embedded, Struct, UnorderedContainer}, + PropertyValueEnum, + }, + Bin, BinObject, BinProperty, +}; + +use crate::{ + cst::Cst, + hashes::HashProvider, + print::{PrintConfig, PrintError}, + types::kind_to_type_name, +}; + +pub struct CstPrinter<'a, W: Write, H: HashProvider> { + visitor: super::visitor::CstVisitor<'a, W, H>, +} + +impl<'a, W: Write, H: HashProvider> CstPrinter<'a, W, H> { + pub fn new(src: &'a str, out: W, config: PrintConfig) -> Self { + Self { + visitor: super::visitor::CstVisitor::new(src, out, config), + } + } + + pub fn print(mut self, cst: &Cst) -> Result<(), PrintError> { + cst.walk(&mut self.visitor); + self.visitor.flush()?; + if let Some(e) = self.visitor.error { + return Err(e); + } + eprintln!("max q size: {}", self.visitor.queue_size_max); + Ok(()) + } +} + +/// Text writer for ritobin format with hash provider support. +pub struct BinPrinter { + buffer: String, + config: PrintConfig, +} + +impl BinPrinter<()> { + /// Create a new text writer without hash lookup (all hashes written as hex). + pub fn new() -> Self { + Self::default() + } +} + +impl BinPrinter { + /// Create a new printer with custom configuration and hash provider. + pub fn with_config(self, config: PrintConfig

) -> BinPrinter

{ + BinPrinter { + buffer: self.buffer, + config, + } + } + + pub fn print( + &mut self, + tree: &Bin, + writer: &mut W, + ) -> Result { + Ok(0) + } + + pub fn print_to_string(&mut self, tree: &Bin) -> Result { + let mut str = String::new(); + self.print(tree, &mut str)?; + Ok(str) + } +} +impl Default for BinPrinter<()> { + fn default() -> Self { + Self { + buffer: String::new(), + config: PrintConfig::default(), + } + } +} diff --git a/crates/ltk_ritobin/src/print/visitor.rs b/crates/ltk_ritobin/src/print/visitor.rs index 75639361..65897f0c 100644 --- a/crates/ltk_ritobin/src/print/visitor.rs +++ b/crates/ltk_ritobin/src/print/visitor.rs @@ -4,35 +4,21 @@ use std::{ }; use crate::{ - parse::{ - cst::{visitor::Visit, Cst, Kind, Visitor}, - TokenKind, + cst::{visitor::Visit, Cst, Kind, Visitor}, + parse::TokenKind, + print::{ + command::{Cmd, Mode}, + PrintConfig, PrintError, }, - print::PrintError, + HashProvider, }; -#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] -pub enum Mode { - Flat, - Break, -} +mod r#impl; +pub mod state; #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] pub struct GroupId(usize); -#[derive(Copy, Clone, PartialEq, Eq, Debug)] -pub enum Cmd<'a> { - Text(&'a str), - TextIf(&'a str, Mode), - Line, - SoftLine, - Space, - Begin(Option), - End, - Indent(usize), - Dedent(usize), -} - #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] struct ListContext { len: u32, @@ -42,10 +28,11 @@ struct ListContext { const MAX_QUEUE: usize = 4096; -pub struct Printer<'a, W: Write> { +pub struct CstVisitor<'a, W: Write, H: HashProvider> { + config: PrintConfig, + src: &'a str, out: W, - width: usize, col: usize, indent: usize, @@ -66,12 +53,12 @@ pub struct Printer<'a, W: Write> { block_line: bool, } -impl<'a, W: Write> Printer<'a, W> { - pub fn new(src: &'a str, out: W, width: usize) -> Self { +impl<'a, W: Write, H: HashProvider> CstVisitor<'a, W, H> { + pub fn new(src: &'a str, out: W, config: PrintConfig) -> Self { Self { src, out, - width, + config, col: 0, indent: 0, printed: 0, @@ -113,10 +100,7 @@ impl<'a, W: Write> Printer<'a, W> { } pub fn space(&mut self) { - if matches!( - self.queue.back(), - Some(Cmd::Space) | Some(Cmd::Line) | Some(Cmd::SoftLine) - ) { + if self.queue.back().is_some_and(|c| c.is_whitespace()) { // eprintln!("# skipping Space! ({:?})", self.queue.back()); return; } @@ -127,10 +111,7 @@ impl<'a, W: Write> Printer<'a, W> { if self.queue.is_empty() && self.printed == 0 { return; } - if matches!( - self.queue.back(), - Some(Cmd::Space) | Some(Cmd::Line) | Some(Cmd::SoftLine) - ) { + if self.queue.back().is_some_and(|c| c.is_whitespace()) { // eprintln!("# replacing ({:?}) w/ Line", self.queue.back()); self.queue.pop_back(); } @@ -140,10 +121,7 @@ impl<'a, W: Write> Printer<'a, W> { if self.queue.is_empty() && self.printed == 0 { return; } - if matches!( - self.queue.back(), - Some(Cmd::Space) | Some(Cmd::Line) | Some(Cmd::SoftLine) - ) { + if self.queue.back().is_some_and(|c| c.is_whitespace()) { // eprintln!("# replacing ({:?}) w/ SoftLine", self.queue.back()); self.queue.pop_back(); } @@ -193,7 +171,7 @@ impl<'a, W: Write> Printer<'a, W> { /// break the first/oldest group if running size is too big (bottom of the stack) pub fn check_running_size(&mut self) { if let Some(size) = self.size_stack.last() { - if self.col + size > self.width { + if self.col + size > self.config.line_width { self.break_first_group(); } } @@ -210,7 +188,7 @@ impl<'a, W: Write> Printer<'a, W> { match cmd { Cmd::Text(s) | Cmd::TextIf(s, Mode::Flat) => { col += s.len(); - if col > self.width { + if col > self.config.line_width { return false; } } @@ -371,196 +349,4 @@ impl<'a, W: Write> Printer<'a, W> { } } } - - fn visit_token_inner( - &mut self, - token: &crate::parse::Token, - context: &Cst, - ) -> Result<(), PrintError> { - let txt = self.src[token.span].trim(); - let print_value = token.kind.print_value(); - - if txt.is_empty() && print_value.is_none() { - return Ok(()); - } - - // eprintln!("->{:?}", token.kind); - match token.kind { - TokenKind::LCurly => { - self.space(); - self.text("{"); - self.indent(4); - self.space(); - // self.softline(); - } - - TokenKind::RCurly => { - self.dedent(4); - self.softline(); - self.text("}"); - } - - TokenKind::Comma => { - // self.text_if(",", Mode::Flat); - // self.softline(); - } - TokenKind::Colon => { - self.text(":"); - self.space(); - } - - TokenKind::Eq => { - self.space(); - self.text("="); - self.space(); - } - - TokenKind::LBrack => { - self.text("["); - } - TokenKind::RBrack => { - self.text("]"); - } - TokenKind::Quote => { - self.text("\""); - } - TokenKind::False => { - self.text("false"); - } - TokenKind::True => { - self.text("true"); - } - - _ => { - self.text(txt); - } - } - self.print_safe()?; - // self.flush()?; - Ok(()) - } -} - -impl<'a, W: fmt::Write> Visitor for Printer<'a, W> { - fn enter_tree(&mut self, tree: &Cst) -> Visit { - match tree.kind { - Kind::TypeArgList => { - let grp = self.begin_group(Some(Mode::Flat)); - // eprintln!("{:#?}", tree.children); - self.list_stack.push(ListContext { - len: tree - .children - .iter() - .filter(|n| n.tree().is_some_and(|t| t.kind == Kind::TypeArg)) - .count() - .try_into() - .unwrap(), - idx: 0, - grp, - }); - } - Kind::ListItemBlock => { - self.softline(); - let grp = self.begin_group(None); - - let len = tree - .children - .iter() - .filter(|n| n.tree().is_some_and(|t| t.kind == Kind::ListItem)) - .count(); - if len > 0 { - self.list_stack.push(ListContext { - len: len.try_into().unwrap(), - idx: 0, - grp, - }); - } - } - Kind::Block => { - // eprintln!("BLOCK: {:#?}", tree.children); - let grp = self.begin_group(None); - let len = tree - .children - .iter() - .filter(|n| { - n.tree() - .is_some_and(|t| matches!(t.kind, Kind::ListItem | Kind::ListItemBlock)) - }) - .count(); - if len > 0 { - self.list_stack.push(ListContext { - len: len.try_into().unwrap(), - idx: 0, - grp, - }); - } - } - Kind::Class => {} - Kind::ListItem => { - if tree - .children - .first() - .is_some_and(|c| c.tree().is_some_and(|t| t.kind == Kind::Class)) - { - if let Some(list) = self.list_stack.last() { - self.force_group(list.grp, Mode::Break); - } - } - self.softline(); - } - Kind::Entry => { - self.line(); - // self.flush().unwrap(); - } - _ => {} - } - Visit::Continue - } - fn exit_tree(&mut self, tree: &Cst) -> Visit { - match tree.kind { - Kind::TypeArgList => { - self.list_stack.pop(); - self.end_group(); - } - Kind::ListItemBlock | Kind::Block => { - self.list_stack.pop(); - // eprintln!("exit {} | stack: {}", tree.kind, self.list_stack.len()); - if let Some(list) = self.list_stack.last() { - self.force_group(list.grp, Mode::Break); - self.softline(); - } - self.end_group(); - } - Kind::ListItem | Kind::TypeArg => { - if let Some(ctx) = self.list_stack.last() { - let last_item = ctx.idx + 1 == ctx.len; - - if !last_item { - self.text_if(",", Mode::Flat); - self.space(); - if tree.kind == Kind::ListItem { - self.softline(); - } - } - - self.list_stack.last_mut().unwrap(/* guaranteed by if let */).idx += 1; - } - } - _ => {} - } - Visit::Continue - } - fn visit_token( - &mut self, - token: &crate::parse::Token, - context: &crate::parse::cst::Cst, - ) -> Visit { - match self.visit_token_inner(token, context) { - Ok(_) => Visit::Continue, - Err(e) => { - self.error.replace(e); - Visit::Stop - } - } - } } diff --git a/crates/ltk_ritobin/src/print/visitor/impl.rs b/crates/ltk_ritobin/src/print/visitor/impl.rs new file mode 100644 index 00000000..ec67326f --- /dev/null +++ b/crates/ltk_ritobin/src/print/visitor/impl.rs @@ -0,0 +1,225 @@ +use std::{ + collections::VecDeque, + fmt::{self, Write}, +}; + +use crate::{ + cst::{visitor::Visit, Cst, Kind, Visitor}, + parse::TokenKind, + print::{ + command::Mode, + visitor::{CstVisitor, ListContext}, + PrintConfig, PrintError, + }, + HashProvider, +}; + +impl<'a, W: fmt::Write, H: HashProvider> CstVisitor<'a, W, H> { + fn enter_tree_inner(&mut self, tree: &Cst) -> Result<(), PrintError> { + match tree.kind { + Kind::TypeArgList => { + let grp = self.begin_group(Some(Mode::Flat)); + // eprintln!("{:#?}", tree.children); + self.list_stack.push(ListContext { + len: tree + .children + .iter() + .filter(|n| n.tree().is_some_and(|t| t.kind == Kind::TypeArg)) + .count() + .try_into() + .unwrap(), + idx: 0, + grp, + }); + } + Kind::ListItemBlock => { + self.softline(); + let grp = self.begin_group(None); + + let len = tree + .children + .iter() + .filter(|n| n.tree().is_some_and(|t| t.kind == Kind::ListItem)) + .count(); + if len > 0 { + self.list_stack.push(ListContext { + len: len.try_into().unwrap(), + idx: 0, + grp, + }); + } + } + Kind::Block => { + // eprintln!("BLOCK: {:#?}", tree.children); + let grp = self.begin_group(None); + let len = tree + .children + .iter() + .filter(|n| { + n.tree() + .is_some_and(|t| matches!(t.kind, Kind::ListItem | Kind::ListItemBlock)) + }) + .count(); + if len > 0 { + self.list_stack.push(ListContext { + len: len.try_into().unwrap(), + idx: 0, + grp, + }); + } + } + Kind::Class => {} + Kind::ListItem => { + if tree + .children + .first() + .is_some_and(|c| c.tree().is_some_and(|t| t.kind == Kind::Class)) + { + if let Some(list) = self.list_stack.last() { + self.force_group(list.grp, Mode::Break); + } + } + self.softline(); + } + Kind::Entry => { + self.line(); + // self.flush().unwrap(); + } + _ => {} + } + Ok(()) + } + + fn exit_tree_inner(&mut self, tree: &Cst) -> Result<(), PrintError> { + match tree.kind { + Kind::TypeArgList => { + self.list_stack.pop(); + self.end_group(); + } + Kind::ListItemBlock | Kind::Block => { + self.list_stack.pop(); + // eprintln!("exit {} | stack: {}", tree.kind, self.list_stack.len()); + if let Some(list) = self.list_stack.last() { + self.force_group(list.grp, Mode::Break); + self.softline(); + } + self.end_group(); + } + Kind::ListItem | Kind::TypeArg => { + if let Some(ctx) = self.list_stack.last() { + let last_item = ctx.idx + 1 == ctx.len; + + if !last_item { + self.text_if(",", Mode::Flat); + self.space(); + if tree.kind == Kind::ListItem { + self.softline(); + } + } + + self.list_stack.last_mut().unwrap(/* guaranteed by if let */).idx += 1; + } + } + _ => {} + } + Ok(()) + } + + fn visit_token_inner( + &mut self, + token: &crate::parse::Token, + context: &Cst, + ) -> Result<(), PrintError> { + let txt = self.src[token.span].trim(); + let print_value = token.kind.print_value(); + + if txt.is_empty() && print_value.is_none() { + return Ok(()); + } + + // eprintln!("->{:?}", token.kind); + match token.kind { + TokenKind::LCurly => { + self.space(); + self.text("{"); + self.indent(4); + self.space(); + // self.softline(); + } + + TokenKind::RCurly => { + self.dedent(4); + self.softline(); + self.text("}"); + } + + TokenKind::Comma => { + // self.text_if(",", Mode::Flat); + // self.softline(); + } + TokenKind::Colon => { + self.text(":"); + self.space(); + } + + TokenKind::Eq => { + self.space(); + self.text("="); + self.space(); + } + + TokenKind::LBrack => { + self.text("["); + } + TokenKind::RBrack => { + self.text("]"); + } + TokenKind::Quote => { + self.text("\""); + } + TokenKind::False => { + self.text("false"); + } + TokenKind::True => { + self.text("true"); + } + + _ => { + self.text(txt); + } + } + self.print_safe()?; + // self.flush()?; + Ok(()) + } +} + +impl<'a, W: fmt::Write, H: HashProvider> Visitor for CstVisitor<'a, W, H> { + fn enter_tree(&mut self, tree: &Cst) -> Visit { + match self.enter_tree_inner(tree) { + Ok(_) => Visit::Continue, + Err(e) => { + self.error.replace(e); + Visit::Stop + } + } + } + fn exit_tree(&mut self, tree: &Cst) -> Visit { + match self.exit_tree_inner(tree) { + Ok(_) => Visit::Continue, + Err(e) => { + self.error.replace(e); + Visit::Stop + } + } + } + fn visit_token(&mut self, token: &crate::parse::Token, context: &crate::cst::Cst) -> Visit { + match self.visit_token_inner(token, context) { + Ok(_) => Visit::Continue, + Err(e) => { + self.error.replace(e); + Visit::Stop + } + } + } +} diff --git a/crates/ltk_ritobin/src/print/visitor/state.rs b/crates/ltk_ritobin/src/print/visitor/state.rs new file mode 100644 index 00000000..e69de29b diff --git a/crates/ltk_ritobin/src/typecheck/visitor.rs b/crates/ltk_ritobin/src/typecheck/visitor.rs index cc248996..1691a4e9 100644 --- a/crates/ltk_ritobin/src/typecheck/visitor.rs +++ b/crates/ltk_ritobin/src/typecheck/visitor.rs @@ -12,10 +12,8 @@ use ltk_meta::{ }; use crate::{ - parse::{ - cst::{self, visitor::Visit, Child, Cst, Kind, Visitor}, - Span, Token, TokenKind, - }, + cst::{self, visitor::Visit, Child, Cst, Kind, Visitor}, + parse::{Span, Token, TokenKind}, typecheck::RitobinName, }; diff --git a/crates/ltk_ritobin/src/writer.rs b/crates/ltk_ritobin/src/writer.rs index 2281bf58..8ebbd53e 100644 --- a/crates/ltk_ritobin/src/writer.rs +++ b/crates/ltk_ritobin/src/writer.rs @@ -1,557 +1,5 @@ //! Text writer for ritobin format. -use std::fmt::Write; - -use ltk_meta::{ - property::{ - values::{Embedded, Struct, UnorderedContainer}, - NoMeta, PropertyValueEnum, - }, - Bin, BinObject, -}; - -use crate::{ - error::WriteError, - hashes::{HashMapProvider, HashProvider, HexHashProvider}, - types::kind_to_type_name, -}; - -/// Configuration for the text writer. -#[derive(Debug, Clone)] -pub struct WriterConfig { - /// Number of spaces per indent level. - pub indent_size: usize, -} - -impl Default for WriterConfig { - fn default() -> Self { - Self { indent_size: 4 } - } -} - -/// Text writer for ritobin format with hash provider support. -pub struct TextWriter<'a, H: HashProvider = HexHashProvider> { - buffer: String, - indent_level: usize, - config: WriterConfig, - hashes: &'a H, -} - -impl<'a> TextWriter<'a, HexHashProvider> { - /// Create a new text writer without hash lookup (all hashes written as hex). - pub fn new() -> Self { - static HEX_PROVIDER: HexHashProvider = HexHashProvider; - Self { - buffer: String::new(), - indent_level: 0, - config: WriterConfig::default(), - hashes: &HEX_PROVIDER, - } - } -} - -impl<'a, H: HashProvider> TextWriter<'a, H> { - /// Create a new text writer with a hash provider for name lookup. - pub fn with_hashes(hashes: &'a H) -> Self { - Self { - buffer: String::new(), - indent_level: 0, - config: WriterConfig::default(), - hashes, - } - } - - /// Create a new text writer with custom configuration and hash provider. - pub fn with_config_and_hashes(config: WriterConfig, hashes: &'a H) -> Self { - Self { - buffer: String::new(), - indent_level: 0, - config, - hashes, - } - } - - /// Consume the writer and return the generated string. - pub fn into_string(self) -> String { - self.buffer - } - - /// Get a reference to the generated string. - pub fn as_str(&self) -> &str { - &self.buffer - } - - fn indent(&mut self) { - self.indent_level += self.config.indent_size; - } - - fn dedent(&mut self) { - self.indent_level = self.indent_level.saturating_sub(self.config.indent_size); - } - - fn pad(&mut self) { - for _ in 0..self.indent_level { - self.buffer.push(' '); - } - } - - fn write_raw(&mut self, s: &str) { - self.buffer.push_str(s); - } - - fn write_type(&mut self, value: &PropertyValueEnum) { - let type_name = kind_to_type_name(value.kind()); - self.write_raw(type_name); - - match value { - PropertyValueEnum::Container(container) - | PropertyValueEnum::UnorderedContainer(UnorderedContainer(container)) => { - self.write_raw("["); - self.write_raw(kind_to_type_name(container.item_kind())); - self.write_raw("]"); - } - PropertyValueEnum::Optional(optional) => { - self.write_raw("["); - self.write_raw(kind_to_type_name(optional.item_kind())); - self.write_raw("]"); - } - PropertyValueEnum::Map(map) => { - self.write_raw("["); - self.write_raw(kind_to_type_name(map.key_kind())); - self.write_raw(","); - self.write_raw(kind_to_type_name(map.value_kind())); - self.write_raw("]"); - } - _ => {} - } - } - - /// Write an entry/object path hash (looks up in entries table). - fn write_entry_hash(&mut self, hash: u32) -> Result<(), WriteError> { - if let Some(name) = self.hashes.lookup_entry(hash) { - write!(self.buffer, "{:?}", name)?; - } else { - write!(self.buffer, "{:#x}", hash)?; - } - Ok(()) - } - - /// Write a field/property name hash (looks up in fields table). - fn write_field_hash(&mut self, hash: u32) -> Result<(), WriteError> { - if let Some(name) = self.hashes.lookup_field(hash) { - self.write_raw(name); - } else { - write!(self.buffer, "{:#x}", hash)?; - } - Ok(()) - } - - /// Write a hash property value (looks up in hashes table). - fn write_hash_value(&mut self, hash: u32) -> Result<(), WriteError> { - if let Some(name) = self.hashes.lookup_hash(hash) { - write!(self.buffer, "{:?}", name)?; - } else { - write!(self.buffer, "{:#x}", hash)?; - } - Ok(()) - } - - /// Write a type/class hash (looks up in types table). - fn write_type_hash(&mut self, hash: u32) -> Result<(), WriteError> { - if let Some(name) = self.hashes.lookup_type(hash) { - self.write_raw(name); - } else { - write!(self.buffer, "{:#x}", hash)?; - } - Ok(()) - } - - /// Write a link hash (looks up in entries table, same as entry paths). - fn write_link_hash(&mut self, hash: u32) -> Result<(), WriteError> { - if let Some(name) = self.hashes.lookup_entry(hash) { - write!(self.buffer, "{:?}", name)?; - } else { - write!(self.buffer, "{:#x}", hash)?; - } - Ok(()) - } - - fn write_value(&mut self, value: &PropertyValueEnum) -> Result<(), WriteError> { - match value { - PropertyValueEnum::None(_) => self.write_raw("null"), - PropertyValueEnum::Bool(v) => self.write_raw(if **v { "true" } else { "false" }), - PropertyValueEnum::I8(v) => write!(self.buffer, "{}", v.value)?, - PropertyValueEnum::U8(v) => write!(self.buffer, "{}", v.value)?, - PropertyValueEnum::I16(v) => write!(self.buffer, "{}", v.value)?, - PropertyValueEnum::U16(v) => write!(self.buffer, "{}", v.value)?, - PropertyValueEnum::I32(v) => write!(self.buffer, "{}", v.value)?, - PropertyValueEnum::U32(v) => write!(self.buffer, "{}", v.value)?, - PropertyValueEnum::I64(v) => write!(self.buffer, "{}", v.value)?, - PropertyValueEnum::U64(v) => write!(self.buffer, "{}", v.value)?, - PropertyValueEnum::F32(v) => write!(self.buffer, "{}", v.value)?, - PropertyValueEnum::Vector2(v) => { - write!(self.buffer, "{{ {}, {} }}", v.value.x, v.value.y)?; - } - PropertyValueEnum::Vector3(v) => { - write!( - self.buffer, - "{{ {}, {}, {} }}", - v.value.x, v.value.y, v.value.z - )?; - } - PropertyValueEnum::Vector4(v) => { - write!( - self.buffer, - "{{ {}, {}, {}, {} }}", - v.value.x, v.value.y, v.value.z, v.value.w - )?; - } - PropertyValueEnum::Matrix44(v) => { - self.write_raw("{\n"); - self.indent(); - // ritobin text stores matrices row-major, glam::Mat4 is column-major. - // transpose so to_cols_array() yields values in row-major order. - let arr = v.value.transpose().to_cols_array(); - for (i, val) in arr.iter().enumerate() { - if i % 4 == 0 { - self.pad(); - } - write!(self.buffer, "{}", val)?; - if i % 4 == 3 { - self.write_raw("\n"); - if i == 15 { - self.dedent(); - } - } else { - self.write_raw(", "); - } - } - self.pad(); - self.write_raw("}"); - } - PropertyValueEnum::Color(v) => { - write!( - self.buffer, - "{{ {}, {}, {}, {} }}", - v.value.r, v.value.g, v.value.b, v.value.a - )?; - } - PropertyValueEnum::String(v) => { - write!(self.buffer, "{:?}", v.value)?; - } - PropertyValueEnum::Hash(v) => { - self.write_hash_value(v.value)?; - } - PropertyValueEnum::WadChunkLink(v) => { - // WAD chunk links are u64 xxhash, we don't have lookup for these yet - write!(self.buffer, "{:#x}", v.value)?; - } - PropertyValueEnum::ObjectLink(v) => { - self.write_link_hash(v.value)?; - } - PropertyValueEnum::BitBool(v) => self.write_raw(if v.value { "true" } else { "false" }), - - PropertyValueEnum::Container(container) - | PropertyValueEnum::UnorderedContainer(UnorderedContainer(container)) => { - let items = container.clone().into_items().collect::>(); - if items.is_empty() { - self.write_raw("{}"); - } else { - self.write_raw("{\n"); - self.indent(); - for item in items { - self.pad(); - self.write_value(&item)?; - self.write_raw("\n"); - } - self.dedent(); - self.pad(); - self.write_raw("}"); - } - } - PropertyValueEnum::Optional(value) => { - if let Some(inner) = value.clone().into_inner() { - self.write_raw("{\n"); - self.indent(); - self.pad(); - self.write_value(&inner)?; - self.write_raw("\n"); - self.dedent(); - self.pad(); - self.write_raw("}"); - } else { - self.write_raw("{}"); - } - } - PropertyValueEnum::Map(map) => { - let entries = map.entries(); - if entries.is_empty() { - self.write_raw("{}"); - } else { - self.write_raw("{\n"); - self.indent(); - for (key, value) in entries { - self.pad(); - self.write_value(key)?; - self.write_raw(" = "); - self.write_value(value)?; - self.write_raw("\n"); - } - self.dedent(); - self.pad(); - self.write_raw("}"); - } - } - PropertyValueEnum::Struct(v) => { - self.write_struct_value(v)?; - } - PropertyValueEnum::Embedded(Embedded(v)) => { - self.write_struct_value(v)?; - } - } - Ok(()) - } - - fn write_struct_value(&mut self, v: &Struct) -> Result<(), WriteError> { - if v.class_hash == 0 && v.properties.is_empty() { - self.write_raw("null"); - } else { - self.write_type_hash(v.class_hash)?; - self.write_raw(" "); - if v.properties.is_empty() { - self.write_raw("{}"); - } else { - self.write_raw("{\n"); - self.indent(); - for (name_hash, value) in v.properties.iter() { - self.write_property(*name_hash, value)?; - } - self.dedent(); - self.pad(); - self.write_raw("}"); - } - } - Ok(()) - } - - fn write_property( - &mut self, - name_hash: u32, - value: &PropertyValueEnum, - ) -> Result<(), WriteError> { - self.pad(); - self.write_field_hash(name_hash)?; - self.write_raw(": "); - self.write_type(value); - self.write_raw(" = "); - self.write_value(value)?; - self.write_raw("\n"); - Ok(()) - } - - /// Write a Bin to the buffer. - pub fn write_tree(&mut self, tree: &Bin) -> Result<(), WriteError> { - // Header - self.write_raw("#PROP_text\n"); - - // Type - self.write_raw("type: string = \"PROP\"\n"); - - // Version - writeln!(self.buffer, "version: u32 = {}", tree.version)?; - - // Dependencies (linked) - if !tree.dependencies.is_empty() { - self.write_raw("linked: list[string] = {\n"); - self.indent(); - for dep in &tree.dependencies { - self.pad(); - writeln!(self.buffer, "{:?}", dep)?; - } - self.dedent(); - self.write_raw("}\n"); - } - - // Entries (objects) - if !tree.objects.is_empty() { - self.write_raw("entries: map[hash,embed] = {\n"); - self.indent(); - for obj in tree.objects.values() { - self.write_object(obj)?; - } - self.dedent(); - self.write_raw("}\n"); - } - - Ok(()) - } - - /// Write a single [`BinObject`]. - fn write_object(&mut self, obj: &BinObject) -> Result<(), WriteError> { - self.pad(); - self.write_entry_hash(obj.path_hash)?; - self.write_raw(" = "); - self.write_type_hash(obj.class_hash)?; - self.write_raw(" "); - - if obj.properties.is_empty() { - self.write_raw("{}\n"); - } else { - self.write_raw("{\n"); - self.indent(); - for (name_hash, value) in &obj.properties { - self.write_property(*name_hash, value)?; - } - self.dedent(); - self.pad(); - self.write_raw("}\n"); - } - - Ok(()) - } -} - -impl Default for TextWriter<'_, HexHashProvider> { - fn default() -> Self { - Self::new() - } -} - -// ============================================================================ -// Public API Functions -// ============================================================================ - -/// Write a [`Bin`] to ritobin text format (hashes as hex). -pub fn write(tree: &Bin) -> Result { - let mut writer = TextWriter::new(); - writer.write_tree(tree)?; - Ok(writer.into_string()) -} - -/// Write a [`Bin`] to ritobin text format with custom configuration. -pub fn write_with_config(tree: &Bin, config: WriterConfig) -> Result { - static HEX_PROVIDER: HexHashProvider = HexHashProvider; - let mut writer = TextWriter::with_config_and_hashes(config, &HEX_PROVIDER); - writer.write_tree(tree)?; - Ok(writer.into_string()) -} - -/// Write a [`Bin`] to ritobin text format with hash name lookup. -pub fn write_with_hashes(tree: &Bin, hashes: &H) -> Result { - let mut writer = TextWriter::with_hashes(hashes); - writer.write_tree(tree)?; - Ok(writer.into_string()) -} - -/// Write a [`Bin`] to ritobin text format with configuration and hash name lookup. -pub fn write_with_config_and_hashes( - tree: &Bin, - config: WriterConfig, - hashes: &H, -) -> Result { - let mut writer = TextWriter::with_config_and_hashes(config, hashes); - writer.write_tree(tree)?; - Ok(writer.into_string()) -} - -// ============================================================================ -// Builder -// ============================================================================ - -/// A builder for creating ritobin files programmatically and converting to text. -/// -/// This is a convenience wrapper around [`ltk_meta::Builder`] -/// that adds methods for direct text output. -/// -/// # Examples -/// -/// ``` -/// use ltk_ritobin::writer::RitobinBuilder; -/// use ltk_meta::BinObject; -/// -/// let text = RitobinBuilder::new() -/// .dependency("base.bin") -/// .object(BinObject::new(0x1234, 0x5678)) -/// .to_text() -/// .unwrap(); -/// ``` -#[derive(Debug, Default, Clone)] -pub struct RitobinBuilder { - is_override: bool, - dependencies: Vec, - objects: Vec, -} - -impl RitobinBuilder { - /// Creates a new [`RitobinBuilder`] with default values. - pub fn new() -> Self { - Self::default() - } - - /// Sets whether this is an override bin file. - /// - /// Default is `false`. - pub fn is_override(mut self, is_override: bool) -> Self { - self.is_override = is_override; - self - } - - /// Adds a single dependency. - pub fn dependency(mut self, dep: impl Into) -> Self { - self.dependencies.push(dep.into()); - self - } - - /// Adds multiple dependencies. - pub fn dependencies(mut self, deps: impl IntoIterator>) -> Self { - self.dependencies.extend(deps.into_iter().map(Into::into)); - self - } - - /// Adds a single object. - pub fn object(mut self, obj: BinObject) -> Self { - self.objects.push(obj); - self - } - - /// Adds multiple objects. - pub fn objects(mut self, objs: impl IntoIterator) -> Self { - self.objects.extend(objs); - self - } - - /// Builds the [`Bin`]. - /// - /// The resulting tree will have version 3, which is always used when writing. - pub fn build(self) -> Bin { - Bin::::builder() - .is_override(self.is_override) - .dependencies(self.dependencies) - .objects(self.objects) - .build() - } - - /// Build and write to ritobin text format (hashes as hex). - pub fn to_text(self) -> Result { - write(&self.build()) - } - - /// Build and write to ritobin text format with hash name lookup. - pub fn to_text_with_hashes(self, hashes: &H) -> Result { - write_with_hashes(&self.build(), hashes) - } -} - -// ============================================================================ -// Convenience type aliases -// ============================================================================ - -/// A pre-configured writer that outputs all hashes as hex values. -pub type HexWriter<'a> = TextWriter<'a, HexHashProvider>; - -/// A pre-configured writer that looks up hashes from HashMaps. -pub type NamedWriter<'a> = TextWriter<'a, HashMapProvider>; - #[cfg(test)] mod tests { use super::*; @@ -560,7 +8,7 @@ mod tests { #[test] fn test_write_simple() { let tree = Bin::new([], std::iter::empty::<&str>()); - let text = write(&tree).unwrap(); + let text = print(&tree).unwrap(); assert!(text.contains("#PROP_text")); assert!(text.contains("type: string = \"PROP\"")); assert!(text.contains("version: u32 = 3")); @@ -575,20 +23,12 @@ mod tests { "path/to/dep2.bin".to_string(), ], ); - let text = write(&tree).unwrap(); + let text = print(&tree).unwrap(); assert!(text.contains("linked: list[string] = {")); assert!(text.contains("\"path/to/dep1.bin\"")); assert!(text.contains("\"path/to/dep2.bin\"")); } - #[test] - fn test_builder() { - let tree = RitobinBuilder::new().dependency("path/to/dep.bin").build(); - - assert_eq!(tree.dependencies.len(), 1); - assert_eq!(tree.version, 3); // Version is always 3 - } - #[test] fn test_write_with_hash_lookup() { use indexmap::IndexMap; @@ -611,7 +51,7 @@ mod tests { let tree = Bin::new(std::iter::once(obj), std::iter::empty::<&str>()); // Without hash lookup - should have hex values - let text_hex = write(&tree).unwrap(); + let text_hex = print(&tree).unwrap(); assert!(text_hex.contains(&format!("{:#x}", path_hash))); // With hash lookup - should have named values @@ -620,7 +60,7 @@ mod tests { hashes.insert_field(name_hash, "testField"); hashes.insert_type(class_hash, "TestClass"); - let text_named = write_with_hashes(&tree, &hashes).unwrap(); + let text_named = print_with_hashes(&tree, &hashes).unwrap(); assert!(text_named.contains("\"Test/Path\"")); assert!(text_named.contains("testField:")); assert!(text_named.contains("TestClass {")); diff --git a/crates/ltk_ritobin/tests/parse_sample.rs b/crates/ltk_ritobin/tests/parse_sample.rs index 17633f1b..ec198e53 100644 --- a/crates/ltk_ritobin/tests/parse_sample.rs +++ b/crates/ltk_ritobin/tests/parse_sample.rs @@ -1,6 +1,6 @@ //! Integration test for parsing a sample ritobin file. -use ltk_ritobin::{parse::parse, print::print_bin}; +use ltk_ritobin::{parse::parse, print::Print as _}; const SAMPLE_RITOBIN: &str = r#"#PROP_text type: string = "PROP" @@ -80,7 +80,7 @@ fn test_roundtrip() { // assert!(errors.is_empty()); // Write back to text - let output = print_bin(&tree, 80).expect("Failed to write"); + let output = tree.print().expect("Failed to write"); // Parse again let cst2 = parse(&output); From 3d3746612eec3a951bbf716e3378e06d3511ee83 Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Thu, 19 Mar 2026 17:42:42 +0000 Subject: [PATCH 118/187] fix: use fixed token print value in print fallback arm --- crates/ltk_ritobin/src/print/visitor/impl.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/crates/ltk_ritobin/src/print/visitor/impl.rs b/crates/ltk_ritobin/src/print/visitor/impl.rs index ec67326f..b3a6f692 100644 --- a/crates/ltk_ritobin/src/print/visitor/impl.rs +++ b/crates/ltk_ritobin/src/print/visitor/impl.rs @@ -185,7 +185,11 @@ impl<'a, W: fmt::Write, H: HashProvider> CstVisitor<'a, W, H> { } _ => { - self.text(txt); + if let Some(print) = print_value { + self.text(print); + } else { + self.text(txt); + } } } self.print_safe()?; From 498abacd713b04c690bd6647604266ce9e5a5707 Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Thu, 19 Mar 2026 17:42:56 +0000 Subject: [PATCH 119/187] fix: number/vec/container cst building --- crates/ltk_ritobin/src/cst/builder.rs | 56 ++++++++++++++++++--------- 1 file changed, 38 insertions(+), 18 deletions(-) diff --git a/crates/ltk_ritobin/src/cst/builder.rs b/crates/ltk_ritobin/src/cst/builder.rs index c25e839c..9b5cf081 100644 --- a/crates/ltk_ritobin/src/cst/builder.rs +++ b/crates/ltk_ritobin/src/cst/builder.rs @@ -30,8 +30,7 @@ pub fn token(kind: Tok) -> Child { impl Builder { pub fn number(&mut self, v: impl AsRef) -> Child { - self.buf.write_str(v.as_ref()).unwrap(); - token(Tok::Number) + tree(Kind::Literal, vec![self.spanned_token(Tok::Number, v)]) } pub fn spanned_token(&mut self, kind: Tok, str: impl AsRef) -> Child { @@ -72,25 +71,46 @@ impl Builder { PropertyValueEnum::None(_) => { tree(Kind::Literal, vec![token(Tok::LCurly), token(Tok::RCurly)]) } - PropertyValueEnum::U8(n) => tree(Kind::Literal, vec![token(Tok::Number)]), - PropertyValueEnum::U16(n) => tree(Kind::Literal, vec![token(Tok::Number)]), - PropertyValueEnum::U32(n) => tree(Kind::Literal, vec![token(Tok::Number)]), - PropertyValueEnum::U64(n) => tree(Kind::Literal, vec![token(Tok::Number)]), - PropertyValueEnum::I8(n) => tree(Kind::Literal, vec![token(Tok::Number)]), - PropertyValueEnum::I16(n) => tree(Kind::Literal, vec![token(Tok::Number)]), - PropertyValueEnum::I32(n) => tree(Kind::Literal, vec![token(Tok::Number)]), - PropertyValueEnum::I64(n) => tree(Kind::Literal, vec![token(Tok::Number)]), - PropertyValueEnum::F32(n) => tree(Kind::Literal, vec![token(Tok::Number)]), - PropertyValueEnum::Vector2(v) => tree(Kind::Literal, vec![token(Tok::Number)]), - PropertyValueEnum::Vector3(v) => tree(Kind::Literal, vec![token(Tok::Number)]), - PropertyValueEnum::Vector4(v) => tree(Kind::Literal, vec![token(Tok::Number)]), + PropertyValueEnum::U8(n) => self.number(n.to_string()), + PropertyValueEnum::U16(n) => self.number(n.to_string()), + PropertyValueEnum::U32(n) => self.number(n.to_string()), + PropertyValueEnum::U64(n) => self.number(n.to_string()), + PropertyValueEnum::I8(n) => self.number(n.to_string()), + PropertyValueEnum::I16(n) => self.number(n.to_string()), + PropertyValueEnum::I32(n) => self.number(n.to_string()), + PropertyValueEnum::I64(n) => self.number(n.to_string()), + PropertyValueEnum::F32(n) => self.number(n.to_string()), + PropertyValueEnum::Vector2(v) => { + let items = v + .to_array() + .iter() + .flat_map(|v| [self.number(v.to_string()), token(Tok::Comma)]) + .collect(); + self.block(items) + } + PropertyValueEnum::Vector3(v) => { + let items = v + .to_array() + .iter() + .map(|v| self.number(v.to_string())) + .collect(); + self.block(items) + } + PropertyValueEnum::Vector4(v) => { + let items = v + .to_array() + .iter() + .map(|v| self.number(v.to_string())) + .collect(); + self.block(items) + } PropertyValueEnum::String(s) => tree( Kind::Literal, vec![token(Tok::Quote), self.string(&**s), token(Tok::Quote)], ), PropertyValueEnum::Container(container) | PropertyValueEnum::UnorderedContainer(values::UnorderedContainer(container)) => { - let mut children = vec![token(Tok::LBrack)]; + let mut children = vec![token(Tok::LCurly)]; for (i, item) in container.clone().into_items().enumerate() { if i > 0 { @@ -99,7 +119,7 @@ impl Builder { children.push(self.value_to_cst(&item)); } - children.push(token(Tok::RBrack)); + children.push(token(Tok::RCurly)); tree(Kind::TypeArgList, children) } PropertyValueEnum::Matrix44(matrix44) => todo!(), @@ -156,7 +176,6 @@ impl Builder { ), ]; if let Some(sub) = rito_type.subtypes[1] { - args.push(token(Tok::Comma)); args.push(tree( Kind::TypeArg, vec![self.spanned_token(Tok::Name, kind_to_type_name(sub))], @@ -293,7 +312,8 @@ mod test { Bin::builder() .object( BinObject::builder(0xDEADBEEF, 0x12344321) - .property(0x44444444, values::String::from("hello")) + .property(0x1, values::String::from("hello")) + .property(0x2, values::U64::new(9)) .property( 0x9191919, values::Container::new(vec![ From 0d8c5bedf4ab4ca665e8c3373fd05547d05f62d0 Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Thu, 19 Mar 2026 17:46:02 +0000 Subject: [PATCH 120/187] fix: set empty dependencies in typecheck --- crates/ltk_ritobin/src/typecheck/visitor.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/ltk_ritobin/src/typecheck/visitor.rs b/crates/ltk_ritobin/src/typecheck/visitor.rs index 1691a4e9..b341ae87 100644 --- a/crates/ltk_ritobin/src/typecheck/visitor.rs +++ b/crates/ltk_ritobin/src/typecheck/visitor.rs @@ -764,7 +764,7 @@ impl<'a> TypeChecker<'a> { }) .expect("no 'entries' entry"); - let tree = Bin::new(objects, [""]); + let tree = Bin::new(objects, Vec::::new()); (tree, self.ctx.diagnostics) } From df0b7beea65ba204ba906ab315b2ffee830d9092 Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Thu, 19 Mar 2026 18:19:30 +0000 Subject: [PATCH 121/187] fix: don't include quotes when building strings for bin --- crates/ltk_ritobin/src/typecheck/visitor.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/crates/ltk_ritobin/src/typecheck/visitor.rs b/crates/ltk_ritobin/src/typecheck/visitor.rs index b341ae87..87aab4bf 100644 --- a/crates/ltk_ritobin/src/typecheck/visitor.rs +++ b/crates/ltk_ritobin/src/typecheck/visitor.rs @@ -549,7 +549,11 @@ pub fn resolve_value( cst::Child::Token(Token { kind: TokenKind::String, span, - }) => values::String::new_with_meta(ctx.text[span].into(), *span).into(), + }) => values::String::new_with_meta( + ctx.text[Span::new(span.start + 1, span.end - 1)].into(), + *span, + ) + .into(), cst::Child::Token(Token { kind: TokenKind::Number, span, @@ -634,7 +638,9 @@ pub fn resolve_entry( kind: TokenKind::String, span, }) => ( - PropertyValueEnum::from(values::String::from(&ctx.text[span])), // TODO: trim quotes + PropertyValueEnum::from(values::String::from( + &ctx.text[Span::new(span.start + 1, span.end - 1)], + )), *span, ), Child::Token(Token { From 1ee227e779bcdea8cfef9b47d008a9ce7b28ec20 Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Thu, 19 Mar 2026 18:19:43 +0000 Subject: [PATCH 122/187] feat (typecheck): build mat44 --- crates/ltk_ritobin/src/typecheck/visitor.rs | 32 ++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/crates/ltk_ritobin/src/typecheck/visitor.rs b/crates/ltk_ritobin/src/typecheck/visitor.rs index 87aab4bf..3c34eb2b 100644 --- a/crates/ltk_ritobin/src/typecheck/visitor.rs +++ b/crates/ltk_ritobin/src/typecheck/visitor.rs @@ -3,6 +3,7 @@ use std::{ ops::{Deref, DerefMut}, }; +use glam::Vec4; use indexmap::IndexMap; use ltk_hash::fnv1a; use ltk_meta::{ @@ -145,6 +146,7 @@ pub enum ColorOrVec { Vec2, Vec3, Vec4, + Mat44, } #[derive(Debug, Clone, Copy)] @@ -937,6 +939,34 @@ fn populate_vec_or_color( color.a = resolve_u8(get_next(&mut span)?)?; expected = ColorOrVec::Color; } + V::Matrix44(values::Matrix44 { value: mat, .. }) => { + mat.x_axis = Vec4::new( + resolve_f32(get_next(&mut span)?)?, + resolve_f32(get_next(&mut span)?)?, + resolve_f32(get_next(&mut span)?)?, + resolve_f32(get_next(&mut span)?)?, + ); + mat.y_axis = Vec4::new( + resolve_f32(get_next(&mut span)?)?, + resolve_f32(get_next(&mut span)?)?, + resolve_f32(get_next(&mut span)?)?, + resolve_f32(get_next(&mut span)?)?, + ); + mat.z_axis = Vec4::new( + resolve_f32(get_next(&mut span)?)?, + resolve_f32(get_next(&mut span)?)?, + resolve_f32(get_next(&mut span)?)?, + resolve_f32(get_next(&mut span)?)?, + ); + mat.w_axis = Vec4::new( + resolve_f32(get_next(&mut span)?)?, + resolve_f32(get_next(&mut span)?)?, + resolve_f32(get_next(&mut span)?)?, + resolve_f32(get_next(&mut span)?)?, + ); + *mat = mat.transpose(); + expected = ColorOrVec::Mat44; + } _ => { unreachable!("non-empty list queue with non color/vec type receiver?"); } @@ -1019,7 +1049,7 @@ impl Visitor for TypeChecker<'_> { use PropertyKind as K; let color_vec_type = match parent_type.base { - K::Vector2 | K::Vector3 | K::Vector4 => Some(K::F32), + K::Vector2 | K::Vector3 | K::Vector4 | K::Matrix44 => Some(K::F32), K::Color => Some(K::U8), _ => None, }; From 54b87c2a951656900b78b75f648d4a933801002f Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Thu, 19 Mar 2026 18:20:06 +0000 Subject: [PATCH 123/187] feat: impl serde traits for cst stuff --- crates/ltk_ritobin/src/cst/tree.rs | 4 ++++ crates/ltk_ritobin/src/parse/error.rs | 2 ++ crates/ltk_ritobin/src/parse/span.rs | 1 + crates/ltk_ritobin/src/parse/tokenizer.rs | 2 ++ 4 files changed, 9 insertions(+) diff --git a/crates/ltk_ritobin/src/cst/tree.rs b/crates/ltk_ritobin/src/cst/tree.rs index 42cdfc41..46d3d47e 100644 --- a/crates/ltk_ritobin/src/cst/tree.rs +++ b/crates/ltk_ritobin/src/cst/tree.rs @@ -5,6 +5,7 @@ use crate::{ typecheck::visitor::DiagnosticWithSpan, }; +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] #[derive(Clone, Copy, PartialEq, Eq, Debug)] #[rustfmt::skip] pub enum Kind { @@ -41,14 +42,17 @@ impl Display for Kind { } } +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] #[derive(Clone, Debug)] pub struct Cst { pub span: Span, pub kind: Kind, pub children: Vec, + #[cfg_attr(feature = "serde", serde(skip_deserializing))] pub errors: Vec, } +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] #[derive(Clone, Debug)] pub enum Child { Token(Token), diff --git a/crates/ltk_ritobin/src/parse/error.rs b/crates/ltk_ritobin/src/parse/error.rs index af15b8e2..f6c68980 100644 --- a/crates/ltk_ritobin/src/parse/error.rs +++ b/crates/ltk_ritobin/src/parse/error.rs @@ -1,5 +1,6 @@ use crate::parse::{cst, tokenizer::TokenKind, Span}; +#[cfg_attr(feature = "serde", derive(serde::Serialize))] #[derive(Debug, Clone, Copy)] pub enum ErrorKind { Expected { @@ -19,6 +20,7 @@ pub enum ErrorKind { Custom(&'static str), } +#[cfg_attr(feature = "serde", derive(serde::Serialize))] #[derive(Debug, Clone, Copy)] pub struct Error { pub span: Span, diff --git a/crates/ltk_ritobin/src/parse/span.rs b/crates/ltk_ritobin/src/parse/span.rs index 54188868..fd053be8 100644 --- a/crates/ltk_ritobin/src/parse/span.rs +++ b/crates/ltk_ritobin/src/parse/span.rs @@ -1,4 +1,5 @@ /// A span in the source text (offset and length). +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] #[derive(Debug, Clone, Copy, Default)] pub struct Span { pub start: u32, diff --git a/crates/ltk_ritobin/src/parse/tokenizer.rs b/crates/ltk_ritobin/src/parse/tokenizer.rs index d77a3a49..36f2f63b 100644 --- a/crates/ltk_ritobin/src/parse/tokenizer.rs +++ b/crates/ltk_ritobin/src/parse/tokenizer.rs @@ -2,6 +2,7 @@ use std::fmt::Display; use crate::parse::Span; +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] #[derive(Clone, Copy, PartialEq, Eq, Debug)] #[rustfmt::skip] pub enum TokenKind { @@ -89,6 +90,7 @@ impl Display for TokenKind { } } +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] #[derive(Clone, Copy, Debug)] pub struct Token { pub kind: TokenKind, From c824660e12ceaa4314ccc0f2010c8b944d90a2d4 Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Thu, 19 Mar 2026 18:20:14 +0000 Subject: [PATCH 124/187] feat: impl Span::is_empty --- crates/ltk_ritobin/src/parse/span.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/crates/ltk_ritobin/src/parse/span.rs b/crates/ltk_ritobin/src/parse/span.rs index fd053be8..7d008f5d 100644 --- a/crates/ltk_ritobin/src/parse/span.rs +++ b/crates/ltk_ritobin/src/parse/span.rs @@ -30,6 +30,12 @@ impl Span { pub fn len(&self) -> u32 { self.end - self.start } + + #[must_use] + #[inline] + pub fn is_empty(&self) -> bool { + self.end <= self.start + } } impl std::ops::Index for str { From 85442e54f72620a192ad47df05b33a9ccd61c67b Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Thu, 19 Mar 2026 18:20:34 +0000 Subject: [PATCH 125/187] feat: fix list item stuff + more cst builder tests --- crates/ltk_ritobin/src/cst/builder.rs | 81 ++++++++++++++++++++++----- 1 file changed, 67 insertions(+), 14 deletions(-) diff --git a/crates/ltk_ritobin/src/cst/builder.rs b/crates/ltk_ritobin/src/cst/builder.rs index 9b5cf081..0c650bca 100644 --- a/crates/ltk_ritobin/src/cst/builder.rs +++ b/crates/ltk_ritobin/src/cst/builder.rs @@ -84,7 +84,7 @@ impl Builder { let items = v .to_array() .iter() - .flat_map(|v| [self.number(v.to_string()), token(Tok::Comma)]) + .map(|v| tree(Kind::ListItem, vec![self.number(v.to_string())])) .collect(); self.block(items) } @@ -92,7 +92,7 @@ impl Builder { let items = v .to_array() .iter() - .map(|v| self.number(v.to_string())) + .map(|v| tree(Kind::ListItem, vec![self.number(v.to_string())])) .collect(); self.block(items) } @@ -100,7 +100,23 @@ impl Builder { let items = v .to_array() .iter() - .map(|v| self.number(v.to_string())) + .map(|v| tree(Kind::ListItem, vec![self.number(v.to_string())])) + .collect(); + self.block(items) + } + PropertyValueEnum::Matrix44(v) => { + let items = v + .transpose() // ritobin text stores matrices row-major, glam::Mat4 is column-major. + .to_cols_array_2d() + .iter() + .flat_map(|v| { + [ + tree(Kind::ListItem, vec![self.number(v[0].to_string())]), + tree(Kind::ListItem, vec![self.number(v[1].to_string())]), + tree(Kind::ListItem, vec![self.number(v[2].to_string())]), + tree(Kind::ListItem, vec![self.number(v[3].to_string())]), + ] + }) .collect(); self.block(items) } @@ -112,17 +128,13 @@ impl Builder { | PropertyValueEnum::UnorderedContainer(values::UnorderedContainer(container)) => { let mut children = vec![token(Tok::LCurly)]; - for (i, item) in container.clone().into_items().enumerate() { - if i > 0 { - children.push(token(Tok::Comma)); - } - children.push(self.value_to_cst(&item)); + for item in container.clone().into_items() { + children.push(tree(Kind::ListItem, vec![self.value_to_cst(&item)])); } children.push(token(Tok::RCurly)); tree(Kind::TypeArgList, children) } - PropertyValueEnum::Matrix44(matrix44) => todo!(), PropertyValueEnum::Color(color) => todo!(), PropertyValueEnum::Hash(hash) => todo!(), PropertyValueEnum::WadChunkLink(wad_chunk_link) => todo!(), @@ -293,7 +305,7 @@ mod test { } #[test] - fn simple() { + fn string() { roundtrip( Bin::builder() .object( @@ -303,8 +315,51 @@ mod test { ) .build(), ); - - panic!(); + } + #[test] + fn numerics() { + roundtrip( + Bin::builder() + .object( + BinObject::builder(0xDEADBEEF, 0x12344321) + .property(0x1, values::U64::new(12)) + .property(0x2, values::U32::new(23)) + .property(0x3, values::U16::new(34)) + .property(0x4, values::U8::new(45)) + .property(0x11, values::I64::new(-12)) + .property(0x22, values::I32::new(-23)) + .property(0x33, values::I16::new(-34)) + .property(0x44, values::I8::new(45)) + .property(0x99, values::F32::new(-45.45345)) + .property(0x98, values::F32::new(199999.)) + .build(), + ) + .build(), + ); + } + #[test] + fn vectors_and_matrix() { + roundtrip( + Bin::builder() + .object( + BinObject::builder(0xDEADBEEF, 0x12344321) + .property(0x1, values::Vector2::new(glam::Vec2::new(0.1, -65.0))) + .property(0x2, values::Vector3::new(glam::Vec3::new(1000., -0.0, 2.))) + .property( + 0x3, + values::Vector4::new(glam::Vec4::new(0.1, -65.0, 100.0, 481.)), + ) + .property( + 0x4, + values::Matrix44::new(glam::Mat4::from_cols_array(&[ + 0.1, 0.5, 0.7, 0.9, 10.0, 11.2, 13.8, 15.3, 19.52, -0.123, -55.11, + -13.005, 23.0, 99.02, 101.1, 500.0, + ])), + ) + .build(), + ) + .build(), + ); } #[test] fn list() { @@ -326,7 +381,5 @@ mod test { ) .build(), ); - - panic!(); } } From 2d0ee30d4fe5f2e14a0f4c8f765500d04922a8c2 Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Thu, 19 Mar 2026 18:25:34 +0000 Subject: [PATCH 126/187] fix: remove bars in Cst::print --- crates/ltk_ritobin/src/cst/tree.rs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/crates/ltk_ritobin/src/cst/tree.rs b/crates/ltk_ritobin/src/cst/tree.rs index 46d3d47e..56d2b489 100644 --- a/crates/ltk_ritobin/src/cst/tree.rs +++ b/crates/ltk_ritobin/src/cst/tree.rs @@ -95,9 +95,10 @@ impl Cst { } pub fn print(&self, buf: &mut String, level: usize, source: &str) { - let parent_indent = "│ ".repeat(level.saturating_sub(1)); + // let parent_indent = "│ ".repeat(level.saturating_sub(1)); + let parent_indent = " ".repeat(level.saturating_sub(1)); let indent = match level > 0 { - true => "├ ", + true => " ", // "├ " false => "", }; let safe_span = match self.span.end >= self.span.start { @@ -114,14 +115,15 @@ impl Cst { ); for (i, child) in self.children.iter().enumerate() { let bar = match i + 1 == self.children.len() { - true => '└', - false => '├', + true => ' ', // '└' + false => ' ', // '├' }; match child { Child::Token(token) => { format_to!( buf, - "{parent_indent}│ {bar} {:?} ({:?})\n", + // "{parent_indent}│ {bar} {:?} ({:?})\n", + "{parent_indent} {bar} {:?} ({:?})\n", &source[token.span.start as _..token.span.end as _], token.kind, ) From 278a919b0da3cde01853044c784dc6c21898c17b Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Thu, 19 Mar 2026 19:27:06 +0000 Subject: [PATCH 127/187] fix: bring back some tests --- crates/ltk_ritobin/Cargo.toml | 2 + crates/ltk_ritobin/tests/parse_sample.rs | 484 ++++-------------- .../parse_sample__parse_containers.snap | 143 ++++++ ...arse_sample__parse_hex_property_names.snap | 62 +++ .../parse_sample__parse_nested_embeds.snap | 86 ++++ .../parse_sample__parse_primitives.snap | 249 +++++++++ .../snapshots/parse_sample__parse_sample.snap | 319 ++++++++++++ .../parse_sample__tree_snapshot-2.snap | 143 ++++++ .../parse_sample__tree_snapshot-3.snap | 319 ++++++++++++ .../parse_sample__tree_snapshot-4.snap | 143 ++++++ .../parse_sample__tree_snapshot-5.snap | 249 +++++++++ .../parse_sample__tree_snapshot.snap | 62 +++ 12 files changed, 1871 insertions(+), 390 deletions(-) create mode 100644 crates/ltk_ritobin/tests/snapshots/parse_sample__parse_containers.snap create mode 100644 crates/ltk_ritobin/tests/snapshots/parse_sample__parse_hex_property_names.snap create mode 100644 crates/ltk_ritobin/tests/snapshots/parse_sample__parse_nested_embeds.snap create mode 100644 crates/ltk_ritobin/tests/snapshots/parse_sample__parse_primitives.snap create mode 100644 crates/ltk_ritobin/tests/snapshots/parse_sample__parse_sample.snap create mode 100644 crates/ltk_ritobin/tests/snapshots/parse_sample__tree_snapshot-2.snap create mode 100644 crates/ltk_ritobin/tests/snapshots/parse_sample__tree_snapshot-3.snap create mode 100644 crates/ltk_ritobin/tests/snapshots/parse_sample__tree_snapshot-4.snap create mode 100644 crates/ltk_ritobin/tests/snapshots/parse_sample__tree_snapshot-5.snap create mode 100644 crates/ltk_ritobin/tests/snapshots/parse_sample__tree_snapshot.snap diff --git a/crates/ltk_ritobin/Cargo.toml b/crates/ltk_ritobin/Cargo.toml index 0156721f..ff614211 100644 --- a/crates/ltk_ritobin/Cargo.toml +++ b/crates/ltk_ritobin/Cargo.toml @@ -30,4 +30,6 @@ salsa = "0.22.0" [dev-dependencies] insta.workspace = true pretty_assertions.workspace = true +serde.workspace = true +ltk_ritobin = { path = ".", features = ["serde"] } diff --git a/crates/ltk_ritobin/tests/parse_sample.rs b/crates/ltk_ritobin/tests/parse_sample.rs index ec198e53..d1b50365 100644 --- a/crates/ltk_ritobin/tests/parse_sample.rs +++ b/crates/ltk_ritobin/tests/parse_sample.rs @@ -43,41 +43,22 @@ entries: map[hash,embed] = { } "#; -#[test] -fn test_parse_sample() { - let cst = parse(SAMPLE_RITOBIN); - - // Verify basic fields - // assert_eq!(file.file_type(), Some("PROP")); - // assert_eq!(file.version(), Some(3)); - - // Verify dependencies - // let linked = file.linked(); - // assert_eq!(linked.len(), 2); - // assert!(linked[0].contains("Animations")); - - // Verify objects - // let objects = file.objects(); - // assert_eq!(objects.len(), 1); +fn tree(input: &str) -> String { + let cst = parse(input); + assert!(cst.errors.is_empty()); - // Convert to BinTree - let (tree, errors) = cst.build_bin(SAMPLE_RITOBIN); - - if !errors.is_empty() { - eprintln!("{errors:#?}"); - panic!("errors building bin tree"); - } + let mut debug = String::new(); + cst.print(&mut debug, 0, input); - assert_eq!(tree.version, 3); - assert_eq!(tree.dependencies.len(), 2); - assert_eq!(tree.objects.len(), 1); + // debug); + debug } #[test] fn test_roundtrip() { let cst = parse(SAMPLE_RITOBIN); let (tree, errors) = cst.build_bin(SAMPLE_RITOBIN); - // assert!(errors.is_empty()); + assert!(errors.is_empty()); // Write back to text let output = tree.print().expect("Failed to write"); @@ -97,352 +78,72 @@ fn test_roundtrip() { assert_eq!(tree.dependencies.len(), tree2.dependencies.len()); assert_eq!(tree.objects.len(), tree2.objects.len()); } -// -// #[test] -// fn test_parse_primitives() { -// let input = r#" -// test_bool: bool = true -// test_i8: i8 = -128 -// test_u8: u8 = 255 -// test_i16: i16 = -32768 -// test_u16: u16 = 65535 -// test_i32: i32 = -2147483648 -// test_u32: u32 = 4294967295 -// test_f32: f32 = 3.14159 -// test_vec2: vec2 = { 1.0, 2.0 } -// test_vec3: vec3 = { 1.0, 2.0, 3.0 } -// test_vec4: vec4 = { 1.0, 2.0, 3.0, 4.0 } -// test_rgba: rgba = { 255, 128, 64, 255 } -// test_string: string = "Hello, World!" -// test_hash: hash = 0xdeadbeef -// test_link: link = "path/to/object" -// test_flag: flag = false -// "#; -// -// let file = parse(input).expect("Failed to parse primitives"); -// assert!(file.entries.contains_key("test_bool")); -// assert!(file.entries.contains_key("test_f32")); -// assert!(file.entries.contains_key("test_vec3")); -// assert!(file.entries.contains_key("test_rgba")); -// assert!(file.entries.contains_key("test_string")); -// } -// -// #[test] -// fn test_parse_containers() { -// let input = r#" -// test_list: list[string] = { -// "item1" -// "item2" -// "item3" -// } -// test_list2: list2[u32] = { -// 1 -// 2 -// 3 -// } -// test_option_some: option[string] = { -// "value" -// } -// test_option_none: option[string] = {} -// test_map: map[hash,string] = { -// 0x12345678 = "value1" -// 0xdeadbeef = "value2" -// } -// "#; -// -// let file = parse(input).expect("Failed to parse containers"); -// assert!(file.entries.contains_key("test_list")); -// assert!(file.entries.contains_key("test_list2")); -// assert!(file.entries.contains_key("test_option_some")); -// assert!(file.entries.contains_key("test_option_none")); -// assert!(file.entries.contains_key("test_map")); -// } -// -// #[test] -// fn test_parse_nested_embeds() { -// let input = r#" -// data: embed = OuterClass { -// name: string = "outer" -// inner: embed = InnerClass { -// value: u32 = 42 -// nested: embed = DeepClass { -// deep_value: f32 = 1.5 -// } -// } -// } -// "#; -// -// let file = parse(input).expect("Failed to parse nested embeds"); -// assert!(file.entries.contains_key("data")); -// } -// -// #[test] -// fn test_parse_pointer_null() { -// let input = r#" -// null_ptr: pointer = null -// "#; -// -// let file = parse(input).expect("Failed to parse null pointer"); -// assert!(file.entries.contains_key("null_ptr")); -// } -// -// #[test] -// fn test_parse_hex_property_names() { -// let input = r#" -// entries: map[hash,embed] = { -// "Test/Path" = TestClass { -// 0xcb13aff1: f32 = -40 -// normalName: string = "test" -// } -// } -// "#; -// -// let file = parse(input).expect("Failed to parse hex property names"); -// assert!(file.entries.contains_key("entries")); -// } -// -// #[test] -// fn test_error_span_unknown_type() { -// let input = "test: badtype = 42"; -// let err = parse(input).unwrap_err(); -// -// // Verify we get an UnknownType error with correct span -// match err { -// ParseError::UnknownType { -// type_name, span, .. -// } => { -// assert_eq!(type_name, "badtype"); -// // "badtype" starts at position 6 (after "test: ") -// assert_eq!(span.offset(), 6); -// assert_eq!(span.len(), 7); // "badtype" is 7 chars -// } -// _ => panic!("Expected UnknownType error, got: {:?}", err), -// } -// } -// -// #[test] -// fn test_error_span_multiline() { -// let input = r#" -// valid: string = "hello" -// broken: unknowntype = 123 -// "#; -// let err = parse(input).unwrap_err(); -// -// match err { -// ParseError::UnknownType { -// type_name, span, .. -// } => { -// assert_eq!(type_name, "unknowntype"); -// // The span offset should point into the second line -// assert!(span.offset() > 20); // After first line -// } -// _ => panic!("Expected UnknownType error, got: {:?}", err), -// } -// } -// -// /// Make sure mtx44 values don't get mangled during a text round-trip. -// /// uh the text format is row-major but glam stores column-major so we -// /// transpose on write and on parse, i guess this just makes sure that -// /// doesn't break anything and the values come out right. -// #[test] -// fn test_matrix44_roundtrip_ordering() { -// use glam::Mat4; -// use ltk_meta::property::PropertyValueEnum; -// -// // non-symmetric so we'd notice if it got transposed wrong -// // text layout (row-major): -// // 1 2 3 4 -// // 5 6 7 8 -// // 9 10 11 12 -// // 13 14 15 16 -// // -// // glam is column-major internally so: -// let expected = Mat4::from_cols_array(&[ -// 1.0, 5.0, 9.0, 13.0, // col0 -// 2.0, 6.0, 10.0, 14.0, // col1 -// 3.0, 7.0, 11.0, 15.0, // col2 -// 4.0, 8.0, 12.0, 16.0, // col3 -// ]); -// -// let input = r#"#PROP_text -// type: string = "PROP" -// version: u32 = 3 -// entries: map[hash,embed] = { -// "test/object" = TestClass { -// transform: mtx44 = { -// 1, 2, 3, 4 -// 5, 6, 7, 8 -// 9, 10, 11, 12 -// 13, 14, 15, 16 -// } -// } -// } -// "#; -// -// // 1) Parse and verify the Mat4 matches expected column-major layout -// let file = parse(input).expect("Failed to parse matrix input"); -// let tree = file.to_bin_tree(); -// let obj = tree.objects.values().next().expect("Expected one object"); -// let parsed_mat = match &obj.properties.values().next().unwrap().value { -// PropertyValueEnum::Matrix44(v) => v.value, -// other => panic!("Expected Matrix44, got {:?}", other), -// }; -// assert_eq!( -// parsed_mat, expected, -// "Parsed Mat4 should match expected column-major layout" -// ); -// -// // 2) Write back to text, parse again, verify values survive the round-trip -// let output = write(&tree).expect("Failed to write tree"); -// let file2 = parse(&output).expect("Failed to re-parse written output"); -// let tree2 = file2.to_bin_tree(); -// let obj2 = tree2 -// .objects -// .values() -// .next() -// .expect("Expected one object after round-trip"); -// let roundtrip_mat = match &obj2.properties.values().next().unwrap().value { -// PropertyValueEnum::Matrix44(v) => v.value, -// other => panic!("Expected Matrix44 after round-trip, got {:?}", other), -// }; -// assert_eq!( -// roundtrip_mat, expected, -// "Matrix44 should survive text round-trip unchanged" -// ); -// } -// -// #[test] -// fn test_error_is_miette_diagnostic() { -// use miette::Diagnostic; -// -// let input = "test: badtype = 42"; -// let err = parse(input).unwrap_err(); -// -// // ParseError implements Diagnostic -// let _code = err.code(); -// let _labels = err.labels(); -// let _source = err.source_code(); -// } -// #[test] -// fn test_parse_sample() { -// let file = parse(SAMPLE_RITOBIN).expect("Failed to parse sample"); -// -// // Verify basic fields -// assert_eq!(file.file_type(), Some("PROP")); -// assert_eq!(file.version(), Some(3)); -// -// // Verify dependencies -// let linked = file.linked(); -// assert_eq!(linked.len(), 2); -// assert!(linked[0].contains("Animations")); -// -// // Verify objects -// let objects = file.objects(); -// assert_eq!(objects.len(), 1); -// -// // Convert to BinTree -// let tree = file.to_bin_tree(); -// assert_eq!(tree.version, 3); -// assert_eq!(tree.dependencies.len(), 2); -// assert_eq!(tree.objects.len(), 1); -// } -// -// #[test] -// fn test_roundtrip() { -// let file = parse(SAMPLE_RITOBIN).expect("Failed to parse sample"); -// let tree = file.to_bin_tree(); -// -// // Write back to text -// let output = write(&tree).expect("Failed to write"); -// -// // Parse again -// let file2 = parse(&output).expect("Failed to parse output"); -// let tree2 = file2.to_bin_tree(); -// -// // Verify structure is preserved -// assert_eq!(tree.version, tree2.version); -// assert_eq!(tree.dependencies.len(), tree2.dependencies.len()); -// assert_eq!(tree.objects.len(), tree2.objects.len()); -// } -// -// #[test] -// fn test_parse_primitives() { -// let input = r#" -// test_bool: bool = true -// test_i8: i8 = -128 -// test_u8: u8 = 255 -// test_i16: i16 = -32768 -// test_u16: u16 = 65535 -// test_i32: i32 = -2147483648 -// test_u32: u32 = 4294967295 -// test_f32: f32 = 3.14159 -// test_vec2: vec2 = { 1.0, 2.0 } -// test_vec3: vec3 = { 1.0, 2.0, 3.0 } -// test_vec4: vec4 = { 1.0, 2.0, 3.0, 4.0 } -// test_rgba: rgba = { 255, 128, 64, 255 } -// test_string: string = "Hello, World!" -// test_hash: hash = 0xdeadbeef -// test_link: link = "path/to/object" -// test_flag: flag = false -// "#; -// -// let file = parse(input).expect("Failed to parse primitives"); -// assert!(file.entries.contains_key("test_bool")); -// assert!(file.entries.contains_key("test_f32")); -// assert!(file.entries.contains_key("test_vec3")); -// assert!(file.entries.contains_key("test_rgba")); -// assert!(file.entries.contains_key("test_string")); -// } -// -// #[test] -// fn test_parse_containers() { -// let input = r#" -// test_list: list[string] = { -// "item1" -// "item2" -// "item3" -// } -// test_list2: list2[u32] = { -// 1 -// 2 -// 3 -// } -// test_option_some: option[string] = { -// "value" -// } -// test_option_none: option[string] = {} -// test_map: map[hash,string] = { -// 0x12345678 = "value1" -// 0xdeadbeef = "value2" -// } -// "#; -// -// let file = parse(input).expect("Failed to parse containers"); -// assert!(file.entries.contains_key("test_list")); -// assert!(file.entries.contains_key("test_list2")); -// assert!(file.entries.contains_key("test_option_some")); -// assert!(file.entries.contains_key("test_option_none")); -// assert!(file.entries.contains_key("test_map")); -// } -// -// #[test] -// fn test_parse_nested_embeds() { -// let input = r#" -// data: embed = OuterClass { -// name: string = "outer" -// inner: embed = InnerClass { -// value: u32 = 42 -// nested: embed = DeepClass { -// deep_value: f32 = 1.5 -// } -// } -// } -// "#; -// -// let file = parse(input).expect("Failed to parse nested embeds"); -// assert!(file.entries.contains_key("data")); -// } -// +#[test] +fn test_parse_primitives() { + insta::assert_snapshot!(tree( + r#" +test_bool: bool = true +test_i8: i8 = -128 +test_u8: u8 = 255 +test_i16: i16 = -32768 +test_u16: u16 = 65535 +test_i32: i32 = -2147483648 +test_u32: u32 = 4294967295 +test_f32: f32 = 3.14159 +test_vec2: vec2 = { 1.0, 2.0 } +test_vec3: vec3 = { 1.0, 2.0, 3.0 } +test_vec4: vec4 = { 1.0, 2.0, 3.0, 4.0 } +test_rgba: rgba = { 255, 128, 64, 255 } +test_string: string = "Hello, World!" +test_hash: hash = 0xdeadbeef +test_link: link = "path/to/object" +test_flag: flag = false +"#, + )); +} + +#[test] +fn test_parse_containers() { + insta::assert_snapshot!(tree( + r#" +test_list: list[string] = { + "item1" + "item2" + "item3" +} +test_list2: list2[u32] = { + 1 + 2 + 3 +} +test_option_some: option[string] = { + "value" +} +test_option_none: option[string] = {} +test_map: map[hash,string] = { + 0x12345678 = "value1" + 0xdeadbeef = "value2" +}"#, + )); +} + +#[test] +fn test_parse_nested_embeds() { + insta::assert_snapshot!(tree( + r#" +data: embed = OuterClass { + name: string = "outer" + inner: embed = InnerClass { + value: u32 = 42 + nested: embed = DeepClass { + deep_value: f32 = 1.5 + } + } +} +"#, + )); +} + // #[test] // fn test_parse_pointer_null() { // let input = r#" @@ -452,22 +153,21 @@ fn test_roundtrip() { // let file = parse(input).expect("Failed to parse null pointer"); // assert!(file.entries.contains_key("null_ptr")); // } -// -// #[test] -// fn test_parse_hex_property_names() { -// let input = r#" -// entries: map[hash,embed] = { -// "Test/Path" = TestClass { -// 0xcb13aff1: f32 = -40 -// normalName: string = "test" -// } -// } -// "#; -// -// let file = parse(input).expect("Failed to parse hex property names"); -// assert!(file.entries.contains_key("entries")); -// } -// + +#[test] +fn test_parse_hex_property_names() { + insta::assert_snapshot!(tree( + r#" +entries: map[hash,embed] = { + "Test/Path" = TestClass { + 0xcb13aff1: f32 = -40 + normalName: string = "test" + } +} +"#, + )); +} + // #[test] // fn test_error_span_unknown_type() { // let input = "test: badtype = 42"; @@ -486,7 +186,7 @@ fn test_roundtrip() { // _ => panic!("Expected UnknownType error, got: {:?}", err), // } // } -// + // #[test] // fn test_error_span_multiline() { // let input = r#" @@ -519,3 +219,7 @@ fn test_roundtrip() { // let _labels = err.labels(); // let _source = err.source_code(); // } +#[test] +fn test_parse_sample() { + insta::assert_snapshot!(tree(SAMPLE_RITOBIN)); +} diff --git a/crates/ltk_ritobin/tests/snapshots/parse_sample__parse_containers.snap b/crates/ltk_ritobin/tests/snapshots/parse_sample__parse_containers.snap new file mode 100644 index 00000000..c84b6d40 --- /dev/null +++ b/crates/ltk_ritobin/tests/snapshots/parse_sample__parse_containers.snap @@ -0,0 +1,143 @@ +--- +source: crates/ltk_ritobin/tests/parse_sample.rs +expression: "tree(r#\"\ntest_list: list[string] = {\n \"item1\"\n \"item2\"\n \"item3\"\n}\ntest_list2: list2[u32] = {\n 1\n 2\n 3\n}\ntest_option_some: option[string] = {\n \"value\"\n}\ntest_option_none: option[string] = {}\ntest_map: map[hash,string] = {\n 0x12345678 = \"value1\"\n 0xdeadbeef = \"value2\"\n}\"#,)" +--- +File - (0..287): "\ntest_list: list[string] = {\n \"item1\"\n \"item2\"\n \"item3\"\n}\ntest_list2: list2[u32] = {\n 1\n 2\n 3\n}\ntest_option_some: option[string] = {\n \"value\"\n}\ntest_option_none: option[string] = {}\ntest_map: map[hash,string] = {\n 0x12345678 = \"value1\"\n 0xdeadbeef = \"value2\"\n}" + Entry - (0..67): "\ntest_list: list[string] = {\n \"item1\"\n \"item2\"\n \"item3\"\n}\n" + EntryKey - (1..10): "test_list" + "test_list" (Name) + ":" (Colon) + TypeExpr - (12..24): "list[string]" + "list" (Name) + "[" (LBrack) + TypeArgList - (17..23): "string" + TypeArg - (17..23): "string" + "string" (Name) + "]" (RBrack) + "=" (Eq) + EntryValue - (26..66): " {\n \"item1\"\n \"item2\"\n \"item3\"\n}" + Block - (27..66): "{\n \"item1\"\n \"item2\"\n \"item3\"\n}" + "{" (LCurly) + ListItem - (28..40): "\n \"item1\"" + Literal - (33..40): "\"item1\"" + "\"item1\"" (String) + "\n " (Newline) + ListItem - (45..52): "\"item2\"" + Literal - (45..52): "\"item2\"" + "\"item2\"" (String) + "\n " (Newline) + ListItem - (57..64): "\"item3\"" + Literal - (57..64): "\"item3\"" + "\"item3\"" (String) + "\n" (Newline) + "}" (RCurly) + EntryTerminator - (66..67): "\n" + "\n" (Newline) + Entry - (67..114): "test_list2: list2[u32] = {\n 1\n 2\n 3\n}\n" + EntryKey - (67..77): "test_list2" + "test_list2" (Name) + ":" (Colon) + TypeExpr - (79..89): "list2[u32]" + "list2" (Name) + "[" (LBrack) + TypeArgList - (85..88): "u32" + TypeArg - (85..88): "u32" + "u32" (Name) + "]" (RBrack) + "=" (Eq) + EntryValue - (91..113): " {\n 1\n 2\n 3\n}" + Block - (92..113): "{\n 1\n 2\n 3\n}" + "{" (LCurly) + ListItem - (93..99): "\n 1" + Literal - (98..99): "1" + "1" (Number) + "\n " (Newline) + ListItem - (104..105): "2" + Literal - (104..105): "2" + "2" (Number) + "\n " (Newline) + ListItem - (110..111): "3" + Literal - (110..111): "3" + "3" (Number) + "\n" (Newline) + "}" (RCurly) + EntryTerminator - (113..114): "\n" + "\n" (Newline) + Entry - (114..165): "test_option_some: option[string] = {\n \"value\"\n}\n" + EntryKey - (114..130): "test_option_some" + "test_option_some" (Name) + ":" (Colon) + TypeExpr - (132..146): "option[string]" + "option" (Name) + "[" (LBrack) + TypeArgList - (139..145): "string" + TypeArg - (139..145): "string" + "string" (Name) + "]" (RBrack) + "=" (Eq) + EntryValue - (148..164): " {\n \"value\"\n}" + Block - (149..164): "{\n \"value\"\n}" + "{" (LCurly) + ListItem - (150..162): "\n \"value\"" + Literal - (155..162): "\"value\"" + "\"value\"" (String) + "\n" (Newline) + "}" (RCurly) + EntryTerminator - (164..165): "\n" + "\n" (Newline) + Entry - (165..203): "test_option_none: option[string] = {}\n" + EntryKey - (165..181): "test_option_none" + "test_option_none" (Name) + ":" (Colon) + TypeExpr - (183..197): "option[string]" + "option" (Name) + "[" (LBrack) + TypeArgList - (190..196): "string" + TypeArg - (190..196): "string" + "string" (Name) + "]" (RBrack) + "=" (Eq) + EntryValue - (199..202): " {}" + Block - (200..202): "{}" + "{" (LCurly) + "}" (RCurly) + EntryTerminator - (202..203): "\n" + "\n" (Newline) + Entry - (203..287): "test_map: map[hash,string] = {\n 0x12345678 = \"value1\"\n 0xdeadbeef = \"value2\"\n}" + EntryKey - (203..211): "test_map" + "test_map" (Name) + ":" (Colon) + TypeExpr - (213..229): "map[hash,string]" + "map" (Name) + "[" (LBrack) + TypeArgList - (217..228): "hash,string" + TypeArg - (217..221): "hash" + "hash" (Name) + "," (Comma) + TypeArg - (222..228): "string" + "string" (Name) + "]" (RBrack) + "=" (Eq) + EntryValue - (231..287): " {\n 0x12345678 = \"value1\"\n 0xdeadbeef = \"value2\"\n}" + Block - (232..287): "{\n 0x12345678 = \"value1\"\n 0xdeadbeef = \"value2\"\n}" + "{" (LCurly) + Entry - (233..264): "\n 0x12345678 = \"value1\"\n " + EntryKey - (238..248): "0x12345678" + "0x12345678" (HexLit) + "=" (Eq) + EntryValue - (250..259): " \"value1\"" + Literal - (251..259): "\"value1\"" + "\"value1\"" (String) + EntryTerminator - (259..264): "\n " + "\n " (Newline) + Entry - (264..286): "0xdeadbeef = \"value2\"\n" + EntryKey - (264..274): "0xdeadbeef" + "0xdeadbeef" (HexLit) + "=" (Eq) + EntryValue - (276..285): " \"value2\"" + Literal - (277..285): "\"value2\"" + "\"value2\"" (String) + EntryTerminator - (285..286): "\n" + "\n" (Newline) + "}" (RCurly) + EntryTerminator - (287..287): "" diff --git a/crates/ltk_ritobin/tests/snapshots/parse_sample__parse_hex_property_names.snap b/crates/ltk_ritobin/tests/snapshots/parse_sample__parse_hex_property_names.snap new file mode 100644 index 00000000..a4ab0885 --- /dev/null +++ b/crates/ltk_ritobin/tests/snapshots/parse_sample__parse_hex_property_names.snap @@ -0,0 +1,62 @@ +--- +source: crates/ltk_ritobin/tests/parse_sample.rs +expression: "tree(r#\"\nentries: map[hash,embed] = {\n \"Test/Path\" = TestClass {\n 0xcb13aff1: f32 = -40\n normalName: string = \"test\"\n }\n}\n\"#,)" +--- +File - (0..134): "\nentries: map[hash,embed] = {\n \"Test/Path\" = TestClass {\n 0xcb13aff1: f32 = -40\n normalName: string = \"test\"\n }\n}\n" + Entry - (0..134): "\nentries: map[hash,embed] = {\n \"Test/Path\" = TestClass {\n 0xcb13aff1: f32 = -40\n normalName: string = \"test\"\n }\n}\n" + EntryKey - (1..8): "entries" + "entries" (Name) + ":" (Colon) + TypeExpr - (10..25): "map[hash,embed]" + "map" (Name) + "[" (LBrack) + TypeArgList - (14..24): "hash,embed" + TypeArg - (14..18): "hash" + "hash" (Name) + "," (Comma) + TypeArg - (19..24): "embed" + "embed" (Name) + "]" (RBrack) + "=" (Eq) + EntryValue - (27..133): " {\n \"Test/Path\" = TestClass {\n 0xcb13aff1: f32 = -40\n normalName: string = \"test\"\n }\n}" + Block - (28..133): "{\n \"Test/Path\" = TestClass {\n 0xcb13aff1: f32 = -40\n normalName: string = \"test\"\n }\n}" + "{" (LCurly) + Entry - (29..132): "\n \"Test/Path\" = TestClass {\n 0xcb13aff1: f32 = -40\n normalName: string = \"test\"\n }\n" + EntryKey - (34..45): "\"Test/Path\"" + "\"Test/Path\"" (String) + "=" (Eq) + EntryValue - (47..131): " TestClass {\n 0xcb13aff1: f32 = -40\n normalName: string = \"test\"\n }" + Class - (48..131): "TestClass {\n 0xcb13aff1: f32 = -40\n normalName: string = \"test\"\n }" + "TestClass" (Name) + Block - (58..131): "{\n 0xcb13aff1: f32 = -40\n normalName: string = \"test\"\n }" + "{" (LCurly) + Entry - (59..98): "\n 0xcb13aff1: f32 = -40\n " + EntryKey - (68..78): "0xcb13aff1" + "0xcb13aff1" (HexLit) + ":" (Colon) + TypeExpr - (80..83): "f32" + "f32" (Name) + "=" (Eq) + EntryValue - (85..89): " -40" + Literal - (86..89): "-40" + "-40" (Number) + EntryTerminator - (89..98): "\n " + "\n " (Newline) + Entry - (98..130): "normalName: string = \"test\"\n " + EntryKey - (98..108): "normalName" + "normalName" (Name) + ":" (Colon) + TypeExpr - (110..116): "string" + "string" (Name) + "=" (Eq) + EntryValue - (118..125): " \"test\"" + Literal - (119..125): "\"test\"" + "\"test\"" (String) + EntryTerminator - (125..130): "\n " + "\n " (Newline) + "}" (RCurly) + EntryTerminator - (131..132): "\n" + "\n" (Newline) + "}" (RCurly) + EntryTerminator - (133..134): "\n" + "\n" (Newline) diff --git a/crates/ltk_ritobin/tests/snapshots/parse_sample__parse_nested_embeds.snap b/crates/ltk_ritobin/tests/snapshots/parse_sample__parse_nested_embeds.snap new file mode 100644 index 00000000..ca063771 --- /dev/null +++ b/crates/ltk_ritobin/tests/snapshots/parse_sample__parse_nested_embeds.snap @@ -0,0 +1,86 @@ +--- +source: crates/ltk_ritobin/tests/parse_sample.rs +expression: "tree(r#\"\ndata: embed = OuterClass {\n name: string = \"outer\"\n inner: embed = InnerClass {\n value: u32 = 42\n nested: embed = DeepClass {\n deep_value: f32 = 1.5\n }\n }\n}\n\"#,)" +--- +File - (0..199): "\ndata: embed = OuterClass {\n name: string = \"outer\"\n inner: embed = InnerClass {\n value: u32 = 42\n nested: embed = DeepClass {\n deep_value: f32 = 1.5\n }\n }\n}\n" + Entry - (0..199): "\ndata: embed = OuterClass {\n name: string = \"outer\"\n inner: embed = InnerClass {\n value: u32 = 42\n nested: embed = DeepClass {\n deep_value: f32 = 1.5\n }\n }\n}\n" + EntryKey - (1..5): "data" + "data" (Name) + ":" (Colon) + TypeExpr - (7..12): "embed" + "embed" (Name) + "=" (Eq) + EntryValue - (14..198): " OuterClass {\n name: string = \"outer\"\n inner: embed = InnerClass {\n value: u32 = 42\n nested: embed = DeepClass {\n deep_value: f32 = 1.5\n }\n }\n}" + Class - (15..198): "OuterClass {\n name: string = \"outer\"\n inner: embed = InnerClass {\n value: u32 = 42\n nested: embed = DeepClass {\n deep_value: f32 = 1.5\n }\n }\n}" + "OuterClass" (Name) + Block - (26..198): "{\n name: string = \"outer\"\n inner: embed = InnerClass {\n value: u32 = 42\n nested: embed = DeepClass {\n deep_value: f32 = 1.5\n }\n }\n}" + "{" (LCurly) + Entry - (27..59): "\n name: string = \"outer\"\n " + EntryKey - (32..36): "name" + "name" (Name) + ":" (Colon) + TypeExpr - (38..44): "string" + "string" (Name) + "=" (Eq) + EntryValue - (46..54): " \"outer\"" + Literal - (47..54): "\"outer\"" + "\"outer\"" (String) + EntryTerminator - (54..59): "\n " + "\n " (Newline) + Entry - (59..197): "inner: embed = InnerClass {\n value: u32 = 42\n nested: embed = DeepClass {\n deep_value: f32 = 1.5\n }\n }\n" + EntryKey - (59..64): "inner" + "inner" (Name) + ":" (Colon) + TypeExpr - (66..71): "embed" + "embed" (Name) + "=" (Eq) + EntryValue - (73..196): " InnerClass {\n value: u32 = 42\n nested: embed = DeepClass {\n deep_value: f32 = 1.5\n }\n }" + Class - (74..196): "InnerClass {\n value: u32 = 42\n nested: embed = DeepClass {\n deep_value: f32 = 1.5\n }\n }" + "InnerClass" (Name) + Block - (85..196): "{\n value: u32 = 42\n nested: embed = DeepClass {\n deep_value: f32 = 1.5\n }\n }" + "{" (LCurly) + Entry - (86..119): "\n value: u32 = 42\n " + EntryKey - (95..100): "value" + "value" (Name) + ":" (Colon) + TypeExpr - (102..105): "u32" + "u32" (Name) + "=" (Eq) + EntryValue - (107..110): " 42" + Literal - (108..110): "42" + "42" (Number) + EntryTerminator - (110..119): "\n " + "\n " (Newline) + Entry - (119..195): "nested: embed = DeepClass {\n deep_value: f32 = 1.5\n }\n " + EntryKey - (119..125): "nested" + "nested" (Name) + ":" (Colon) + TypeExpr - (127..132): "embed" + "embed" (Name) + "=" (Eq) + EntryValue - (134..190): " DeepClass {\n deep_value: f32 = 1.5\n }" + Class - (135..190): "DeepClass {\n deep_value: f32 = 1.5\n }" + "DeepClass" (Name) + Block - (145..190): "{\n deep_value: f32 = 1.5\n }" + "{" (LCurly) + Entry - (146..189): "\n deep_value: f32 = 1.5\n " + EntryKey - (159..169): "deep_value" + "deep_value" (Name) + ":" (Colon) + TypeExpr - (171..174): "f32" + "f32" (Name) + "=" (Eq) + EntryValue - (176..180): " 1.5" + Literal - (177..180): "1.5" + "1.5" (Number) + EntryTerminator - (180..189): "\n " + "\n " (Newline) + "}" (RCurly) + EntryTerminator - (190..195): "\n " + "\n " (Newline) + "}" (RCurly) + EntryTerminator - (196..197): "\n" + "\n" (Newline) + "}" (RCurly) + EntryTerminator - (198..199): "\n" + "\n" (Newline) diff --git a/crates/ltk_ritobin/tests/snapshots/parse_sample__parse_primitives.snap b/crates/ltk_ritobin/tests/snapshots/parse_sample__parse_primitives.snap new file mode 100644 index 00000000..59932165 --- /dev/null +++ b/crates/ltk_ritobin/tests/snapshots/parse_sample__parse_primitives.snap @@ -0,0 +1,249 @@ +--- +source: crates/ltk_ritobin/tests/parse_sample.rs +expression: debug +--- +File - (0..459): "\ntest_bool: bool = true\ntest_i8: i8 = -128\ntest_u8: u8 = 255\ntest_i16: i16 = -32768\ntest_u16: u16 = 65535\ntest_i32: i32 = -2147483648\ntest_u32: u32 = 4294967295\ntest_f32: f32 = 3.14159\ntest_vec2: vec2 = { 1.0, 2.0 }\ntest_vec3: vec3 = { 1.0, 2.0, 3.0 }\ntest_vec4: vec4 = { 1.0, 2.0, 3.0, 4.0 }\ntest_rgba: rgba = { 255, 128, 64, 255 }\ntest_string: string = \"Hello, World!\"\ntest_hash: hash = 0xdeadbeef\ntest_link: link = \"path/to/object\"\ntest_flag: flag = false\n" + Entry - (0..24): "\ntest_bool: bool = true\n" + EntryKey - (1..10): "test_bool" + "test_bool" (Name) + ":" (Colon) + TypeExpr - (12..16): "bool" + "bool" (Name) + "=" (Eq) + EntryValue - (18..23): " true" + Literal - (19..23): "true" + "true" (True) + EntryTerminator - (23..24): "\n" + "\n" (Newline) + Entry - (24..43): "test_i8: i8 = -128\n" + EntryKey - (24..31): "test_i8" + "test_i8" (Name) + ":" (Colon) + TypeExpr - (33..35): "i8" + "i8" (Name) + "=" (Eq) + EntryValue - (37..42): " -128" + Literal - (38..42): "-128" + "-128" (Number) + EntryTerminator - (42..43): "\n" + "\n" (Newline) + Entry - (43..61): "test_u8: u8 = 255\n" + EntryKey - (43..50): "test_u8" + "test_u8" (Name) + ":" (Colon) + TypeExpr - (52..54): "u8" + "u8" (Name) + "=" (Eq) + EntryValue - (56..60): " 255" + Literal - (57..60): "255" + "255" (Number) + EntryTerminator - (60..61): "\n" + "\n" (Newline) + Entry - (61..84): "test_i16: i16 = -32768\n" + EntryKey - (61..69): "test_i16" + "test_i16" (Name) + ":" (Colon) + TypeExpr - (71..74): "i16" + "i16" (Name) + "=" (Eq) + EntryValue - (76..83): " -32768" + Literal - (77..83): "-32768" + "-32768" (Number) + EntryTerminator - (83..84): "\n" + "\n" (Newline) + Entry - (84..106): "test_u16: u16 = 65535\n" + EntryKey - (84..92): "test_u16" + "test_u16" (Name) + ":" (Colon) + TypeExpr - (94..97): "u16" + "u16" (Name) + "=" (Eq) + EntryValue - (99..105): " 65535" + Literal - (100..105): "65535" + "65535" (Number) + EntryTerminator - (105..106): "\n" + "\n" (Newline) + Entry - (106..134): "test_i32: i32 = -2147483648\n" + EntryKey - (106..114): "test_i32" + "test_i32" (Name) + ":" (Colon) + TypeExpr - (116..119): "i32" + "i32" (Name) + "=" (Eq) + EntryValue - (121..133): " -2147483648" + Literal - (122..133): "-2147483648" + "-2147483648" (Number) + EntryTerminator - (133..134): "\n" + "\n" (Newline) + Entry - (134..161): "test_u32: u32 = 4294967295\n" + EntryKey - (134..142): "test_u32" + "test_u32" (Name) + ":" (Colon) + TypeExpr - (144..147): "u32" + "u32" (Name) + "=" (Eq) + EntryValue - (149..160): " 4294967295" + Literal - (150..160): "4294967295" + "4294967295" (Number) + EntryTerminator - (160..161): "\n" + "\n" (Newline) + Entry - (161..185): "test_f32: f32 = 3.14159\n" + EntryKey - (161..169): "test_f32" + "test_f32" (Name) + ":" (Colon) + TypeExpr - (171..174): "f32" + "f32" (Name) + "=" (Eq) + EntryValue - (176..184): " 3.14159" + Literal - (177..184): "3.14159" + "3.14159" (Number) + EntryTerminator - (184..185): "\n" + "\n" (Newline) + Entry - (185..216): "test_vec2: vec2 = { 1.0, 2.0 }\n" + EntryKey - (185..194): "test_vec2" + "test_vec2" (Name) + ":" (Colon) + TypeExpr - (196..200): "vec2" + "vec2" (Name) + "=" (Eq) + EntryValue - (202..215): " { 1.0, 2.0 }" + Block - (203..215): "{ 1.0, 2.0 }" + "{" (LCurly) + ListItem - (204..208): " 1.0" + Literal - (205..208): "1.0" + "1.0" (Number) + "," (Comma) + ListItem - (209..213): " 2.0" + Literal - (210..213): "2.0" + "2.0" (Number) + "}" (RCurly) + EntryTerminator - (215..216): "\n" + "\n" (Newline) + Entry - (216..252): "test_vec3: vec3 = { 1.0, 2.0, 3.0 }\n" + EntryKey - (216..225): "test_vec3" + "test_vec3" (Name) + ":" (Colon) + TypeExpr - (227..231): "vec3" + "vec3" (Name) + "=" (Eq) + EntryValue - (233..251): " { 1.0, 2.0, 3.0 }" + Block - (234..251): "{ 1.0, 2.0, 3.0 }" + "{" (LCurly) + ListItem - (235..239): " 1.0" + Literal - (236..239): "1.0" + "1.0" (Number) + "," (Comma) + ListItem - (240..244): " 2.0" + Literal - (241..244): "2.0" + "2.0" (Number) + "," (Comma) + ListItem - (245..249): " 3.0" + Literal - (246..249): "3.0" + "3.0" (Number) + "}" (RCurly) + EntryTerminator - (251..252): "\n" + "\n" (Newline) + Entry - (252..293): "test_vec4: vec4 = { 1.0, 2.0, 3.0, 4.0 }\n" + EntryKey - (252..261): "test_vec4" + "test_vec4" (Name) + ":" (Colon) + TypeExpr - (263..267): "vec4" + "vec4" (Name) + "=" (Eq) + EntryValue - (269..292): " { 1.0, 2.0, 3.0, 4.0 }" + Block - (270..292): "{ 1.0, 2.0, 3.0, 4.0 }" + "{" (LCurly) + ListItem - (271..275): " 1.0" + Literal - (272..275): "1.0" + "1.0" (Number) + "," (Comma) + ListItem - (276..280): " 2.0" + Literal - (277..280): "2.0" + "2.0" (Number) + "," (Comma) + ListItem - (281..285): " 3.0" + Literal - (282..285): "3.0" + "3.0" (Number) + "," (Comma) + ListItem - (286..290): " 4.0" + Literal - (287..290): "4.0" + "4.0" (Number) + "}" (RCurly) + EntryTerminator - (292..293): "\n" + "\n" (Newline) + Entry - (293..333): "test_rgba: rgba = { 255, 128, 64, 255 }\n" + EntryKey - (293..302): "test_rgba" + "test_rgba" (Name) + ":" (Colon) + TypeExpr - (304..308): "rgba" + "rgba" (Name) + "=" (Eq) + EntryValue - (310..332): " { 255, 128, 64, 255 }" + Block - (311..332): "{ 255, 128, 64, 255 }" + "{" (LCurly) + ListItem - (312..316): " 255" + Literal - (313..316): "255" + "255" (Number) + "," (Comma) + ListItem - (317..321): " 128" + Literal - (318..321): "128" + "128" (Number) + "," (Comma) + ListItem - (322..325): " 64" + Literal - (323..325): "64" + "64" (Number) + "," (Comma) + ListItem - (326..330): " 255" + Literal - (327..330): "255" + "255" (Number) + "}" (RCurly) + EntryTerminator - (332..333): "\n" + "\n" (Newline) + Entry - (333..371): "test_string: string = \"Hello, World!\"\n" + EntryKey - (333..344): "test_string" + "test_string" (Name) + ":" (Colon) + TypeExpr - (346..352): "string" + "string" (Name) + "=" (Eq) + EntryValue - (354..370): " \"Hello, World!\"" + Literal - (355..370): "\"Hello, World!\"" + "\"Hello, World!\"" (String) + EntryTerminator - (370..371): "\n" + "\n" (Newline) + Entry - (371..400): "test_hash: hash = 0xdeadbeef\n" + EntryKey - (371..380): "test_hash" + "test_hash" (Name) + ":" (Colon) + TypeExpr - (382..386): "hash" + "hash" (Name) + "=" (Eq) + EntryValue - (388..399): " 0xdeadbeef" + Literal - (389..399): "0xdeadbeef" + "0xdeadbeef" (HexLit) + EntryTerminator - (399..400): "\n" + "\n" (Newline) + Entry - (400..435): "test_link: link = \"path/to/object\"\n" + EntryKey - (400..409): "test_link" + "test_link" (Name) + ":" (Colon) + TypeExpr - (411..415): "link" + "link" (Name) + "=" (Eq) + EntryValue - (417..434): " \"path/to/object\"" + Literal - (418..434): "\"path/to/object\"" + "\"path/to/object\"" (String) + EntryTerminator - (434..435): "\n" + "\n" (Newline) + Entry - (435..459): "test_flag: flag = false\n" + EntryKey - (435..444): "test_flag" + "test_flag" (Name) + ":" (Colon) + TypeExpr - (446..450): "flag" + "flag" (Name) + "=" (Eq) + EntryValue - (452..458): " false" + Literal - (453..458): "false" + "false" (False) + EntryTerminator - (458..459): "\n" + "\n" (Newline) diff --git a/crates/ltk_ritobin/tests/snapshots/parse_sample__parse_sample.snap b/crates/ltk_ritobin/tests/snapshots/parse_sample__parse_sample.snap new file mode 100644 index 00000000..cc4e896d --- /dev/null +++ b/crates/ltk_ritobin/tests/snapshots/parse_sample__parse_sample.snap @@ -0,0 +1,319 @@ +--- +source: crates/ltk_ritobin/tests/parse_sample.rs +expression: tree(SAMPLE_RITOBIN) +--- +File - (0..1310): "#PROP_text\ntype: string = \"PROP\"\nversion: u32 = 3\nlinked: list[string] = {\n \"DATA/Characters/Test/Animations/Skin0.bin\"\n \"DATA/Characters/Test/Test.bin\"\n}\nentries: map[hash,embed] = {\n \"Characters/Test/Skins/Skin0\" = SkinCharacterDataProperties {\n skinClassification: u32 = 1\n championSkinName: string = \"TestBase\"\n metaDataTags: string = \"gender:male\"\n loadscreen: embed = CensoredImage {\n image: string = \"ASSETS/Characters/Test/Skins/Base/TestLoadScreen.tex\"\n }\n skinAudioProperties: embed = skinAudioProperties {\n tagEventList: list[string] = {\n \"Test\"\n }\n bankUnits: list2[embed] = {\n BankUnit {\n name: string = \"Test_Base_SFX\"\n bankPath: list[string] = {\n \"ASSETS/Sounds/Test/audio.bnk\"\n \"ASSETS/Sounds/Test/events.bnk\"\n }\n events: list[string] = {\n \"Play_sfx_Test_Attack\"\n \"Play_sfx_Test_Death\"\n }\n }\n }\n }\n iconCircle: option[string] = {\n \"ASSETS/Characters/Test/Icons/Circle.tex\"\n }\n iconSquare: option[string] = {}\n }\n}\n" + Comment - (0..10): "#PROP_text" + "#PROP_text" (Comment) + Entry - (10..33): "\ntype: string = \"PROP\"\n" + EntryKey - (11..15): "type" + "type" (Name) + ":" (Colon) + TypeExpr - (17..23): "string" + "string" (Name) + "=" (Eq) + EntryValue - (25..32): " \"PROP\"" + Literal - (26..32): "\"PROP\"" + "\"PROP\"" (String) + EntryTerminator - (32..33): "\n" + "\n" (Newline) + Entry - (33..50): "version: u32 = 3\n" + EntryKey - (33..40): "version" + "version" (Name) + ":" (Colon) + TypeExpr - (42..45): "u32" + "u32" (Name) + "=" (Eq) + EntryValue - (47..49): " 3" + Literal - (48..49): "3" + "3" (Number) + EntryTerminator - (49..50): "\n" + "\n" (Newline) + Entry - (50..161): "linked: list[string] = {\n \"DATA/Characters/Test/Animations/Skin0.bin\"\n \"DATA/Characters/Test/Test.bin\"\n}\n" + EntryKey - (50..56): "linked" + "linked" (Name) + ":" (Colon) + TypeExpr - (58..70): "list[string]" + "list" (Name) + "[" (LBrack) + TypeArgList - (63..69): "string" + TypeArg - (63..69): "string" + "string" (Name) + "]" (RBrack) + "=" (Eq) + EntryValue - (72..160): " {\n \"DATA/Characters/Test/Animations/Skin0.bin\"\n \"DATA/Characters/Test/Test.bin\"\n}" + Block - (73..160): "{\n \"DATA/Characters/Test/Animations/Skin0.bin\"\n \"DATA/Characters/Test/Test.bin\"\n}" + "{" (LCurly) + ListItem - (74..122): "\n \"DATA/Characters/Test/Animations/Skin0.bin\"" + Literal - (79..122): "\"DATA/Characters/Test/Animations/Skin0.bin\"" + "\"DATA/Characters/Test/Animations/Skin0.bin\"" (String) + "\n " (Newline) + ListItem - (127..158): "\"DATA/Characters/Test/Test.bin\"" + Literal - (127..158): "\"DATA/Characters/Test/Test.bin\"" + "\"DATA/Characters/Test/Test.bin\"" (String) + "\n" (Newline) + "}" (RCurly) + EntryTerminator - (160..161): "\n" + "\n" (Newline) + Entry - (161..1310): "entries: map[hash,embed] = {\n \"Characters/Test/Skins/Skin0\" = SkinCharacterDataProperties {\n skinClassification: u32 = 1\n championSkinName: string = \"TestBase\"\n metaDataTags: string = \"gender:male\"\n loadscreen: embed = CensoredImage {\n image: string = \"ASSETS/Characters/Test/Skins/Base/TestLoadScreen.tex\"\n }\n skinAudioProperties: embed = skinAudioProperties {\n tagEventList: list[string] = {\n \"Test\"\n }\n bankUnits: list2[embed] = {\n BankUnit {\n name: string = \"Test_Base_SFX\"\n bankPath: list[string] = {\n \"ASSETS/Sounds/Test/audio.bnk\"\n \"ASSETS/Sounds/Test/events.bnk\"\n }\n events: list[string] = {\n \"Play_sfx_Test_Attack\"\n \"Play_sfx_Test_Death\"\n }\n }\n }\n }\n iconCircle: option[string] = {\n \"ASSETS/Characters/Test/Icons/Circle.tex\"\n }\n iconSquare: option[string] = {}\n }\n}\n" + EntryKey - (161..168): "entries" + "entries" (Name) + ":" (Colon) + TypeExpr - (170..185): "map[hash,embed]" + "map" (Name) + "[" (LBrack) + TypeArgList - (174..184): "hash,embed" + TypeArg - (174..178): "hash" + "hash" (Name) + "," (Comma) + TypeArg - (179..184): "embed" + "embed" (Name) + "]" (RBrack) + "=" (Eq) + EntryValue - (187..1309): " {\n \"Characters/Test/Skins/Skin0\" = SkinCharacterDataProperties {\n skinClassification: u32 = 1\n championSkinName: string = \"TestBase\"\n metaDataTags: string = \"gender:male\"\n loadscreen: embed = CensoredImage {\n image: string = \"ASSETS/Characters/Test/Skins/Base/TestLoadScreen.tex\"\n }\n skinAudioProperties: embed = skinAudioProperties {\n tagEventList: list[string] = {\n \"Test\"\n }\n bankUnits: list2[embed] = {\n BankUnit {\n name: string = \"Test_Base_SFX\"\n bankPath: list[string] = {\n \"ASSETS/Sounds/Test/audio.bnk\"\n \"ASSETS/Sounds/Test/events.bnk\"\n }\n events: list[string] = {\n \"Play_sfx_Test_Attack\"\n \"Play_sfx_Test_Death\"\n }\n }\n }\n }\n iconCircle: option[string] = {\n \"ASSETS/Characters/Test/Icons/Circle.tex\"\n }\n iconSquare: option[string] = {}\n }\n}" + Block - (188..1309): "{\n \"Characters/Test/Skins/Skin0\" = SkinCharacterDataProperties {\n skinClassification: u32 = 1\n championSkinName: string = \"TestBase\"\n metaDataTags: string = \"gender:male\"\n loadscreen: embed = CensoredImage {\n image: string = \"ASSETS/Characters/Test/Skins/Base/TestLoadScreen.tex\"\n }\n skinAudioProperties: embed = skinAudioProperties {\n tagEventList: list[string] = {\n \"Test\"\n }\n bankUnits: list2[embed] = {\n BankUnit {\n name: string = \"Test_Base_SFX\"\n bankPath: list[string] = {\n \"ASSETS/Sounds/Test/audio.bnk\"\n \"ASSETS/Sounds/Test/events.bnk\"\n }\n events: list[string] = {\n \"Play_sfx_Test_Attack\"\n \"Play_sfx_Test_Death\"\n }\n }\n }\n }\n iconCircle: option[string] = {\n \"ASSETS/Characters/Test/Icons/Circle.tex\"\n }\n iconSquare: option[string] = {}\n }\n}" + "{" (LCurly) + Entry - (189..1308): "\n \"Characters/Test/Skins/Skin0\" = SkinCharacterDataProperties {\n skinClassification: u32 = 1\n championSkinName: string = \"TestBase\"\n metaDataTags: string = \"gender:male\"\n loadscreen: embed = CensoredImage {\n image: string = \"ASSETS/Characters/Test/Skins/Base/TestLoadScreen.tex\"\n }\n skinAudioProperties: embed = skinAudioProperties {\n tagEventList: list[string] = {\n \"Test\"\n }\n bankUnits: list2[embed] = {\n BankUnit {\n name: string = \"Test_Base_SFX\"\n bankPath: list[string] = {\n \"ASSETS/Sounds/Test/audio.bnk\"\n \"ASSETS/Sounds/Test/events.bnk\"\n }\n events: list[string] = {\n \"Play_sfx_Test_Attack\"\n \"Play_sfx_Test_Death\"\n }\n }\n }\n }\n iconCircle: option[string] = {\n \"ASSETS/Characters/Test/Icons/Circle.tex\"\n }\n iconSquare: option[string] = {}\n }\n" + EntryKey - (194..223): "\"Characters/Test/Skins/Skin0\"" + "\"Characters/Test/Skins/Skin0\"" (String) + "=" (Eq) + EntryValue - (225..1307): " SkinCharacterDataProperties {\n skinClassification: u32 = 1\n championSkinName: string = \"TestBase\"\n metaDataTags: string = \"gender:male\"\n loadscreen: embed = CensoredImage {\n image: string = \"ASSETS/Characters/Test/Skins/Base/TestLoadScreen.tex\"\n }\n skinAudioProperties: embed = skinAudioProperties {\n tagEventList: list[string] = {\n \"Test\"\n }\n bankUnits: list2[embed] = {\n BankUnit {\n name: string = \"Test_Base_SFX\"\n bankPath: list[string] = {\n \"ASSETS/Sounds/Test/audio.bnk\"\n \"ASSETS/Sounds/Test/events.bnk\"\n }\n events: list[string] = {\n \"Play_sfx_Test_Attack\"\n \"Play_sfx_Test_Death\"\n }\n }\n }\n }\n iconCircle: option[string] = {\n \"ASSETS/Characters/Test/Icons/Circle.tex\"\n }\n iconSquare: option[string] = {}\n }" + Class - (226..1307): "SkinCharacterDataProperties {\n skinClassification: u32 = 1\n championSkinName: string = \"TestBase\"\n metaDataTags: string = \"gender:male\"\n loadscreen: embed = CensoredImage {\n image: string = \"ASSETS/Characters/Test/Skins/Base/TestLoadScreen.tex\"\n }\n skinAudioProperties: embed = skinAudioProperties {\n tagEventList: list[string] = {\n \"Test\"\n }\n bankUnits: list2[embed] = {\n BankUnit {\n name: string = \"Test_Base_SFX\"\n bankPath: list[string] = {\n \"ASSETS/Sounds/Test/audio.bnk\"\n \"ASSETS/Sounds/Test/events.bnk\"\n }\n events: list[string] = {\n \"Play_sfx_Test_Attack\"\n \"Play_sfx_Test_Death\"\n }\n }\n }\n }\n iconCircle: option[string] = {\n \"ASSETS/Characters/Test/Icons/Circle.tex\"\n }\n iconSquare: option[string] = {}\n }" + "SkinCharacterDataProperties" (Name) + Block - (254..1307): "{\n skinClassification: u32 = 1\n championSkinName: string = \"TestBase\"\n metaDataTags: string = \"gender:male\"\n loadscreen: embed = CensoredImage {\n image: string = \"ASSETS/Characters/Test/Skins/Base/TestLoadScreen.tex\"\n }\n skinAudioProperties: embed = skinAudioProperties {\n tagEventList: list[string] = {\n \"Test\"\n }\n bankUnits: list2[embed] = {\n BankUnit {\n name: string = \"Test_Base_SFX\"\n bankPath: list[string] = {\n \"ASSETS/Sounds/Test/audio.bnk\"\n \"ASSETS/Sounds/Test/events.bnk\"\n }\n events: list[string] = {\n \"Play_sfx_Test_Attack\"\n \"Play_sfx_Test_Death\"\n }\n }\n }\n }\n iconCircle: option[string] = {\n \"ASSETS/Characters/Test/Icons/Circle.tex\"\n }\n iconSquare: option[string] = {}\n }" + "{" (LCurly) + Entry - (255..300): "\n skinClassification: u32 = 1\n " + EntryKey - (264..282): "skinClassification" + "skinClassification" (Name) + ":" (Colon) + TypeExpr - (284..287): "u32" + "u32" (Name) + "=" (Eq) + EntryValue - (289..291): " 1" + Literal - (290..291): "1" + "1" (Number) + EntryTerminator - (291..300): "\n " + "\n " (Newline) + Entry - (300..346): "championSkinName: string = \"TestBase\"\n " + EntryKey - (300..316): "championSkinName" + "championSkinName" (Name) + ":" (Colon) + TypeExpr - (318..324): "string" + "string" (Name) + "=" (Eq) + EntryValue - (326..337): " \"TestBase\"" + Literal - (327..337): "\"TestBase\"" + "\"TestBase\"" (String) + EntryTerminator - (337..346): "\n " + "\n " (Newline) + Entry - (346..391): "metaDataTags: string = \"gender:male\"\n " + EntryKey - (346..358): "metaDataTags" + "metaDataTags" (Name) + ":" (Colon) + TypeExpr - (360..366): "string" + "string" (Name) + "=" (Eq) + EntryValue - (368..382): " \"gender:male\"" + Literal - (369..382): "\"gender:male\"" + "\"gender:male\"" (String) + EntryTerminator - (382..391): "\n " + "\n " (Newline) + Entry - (391..528): "loadscreen: embed = CensoredImage {\n image: string = \"ASSETS/Characters/Test/Skins/Base/TestLoadScreen.tex\"\n }\n " + EntryKey - (391..401): "loadscreen" + "loadscreen" (Name) + ":" (Colon) + TypeExpr - (403..408): "embed" + "embed" (Name) + "=" (Eq) + EntryValue - (410..519): " CensoredImage {\n image: string = \"ASSETS/Characters/Test/Skins/Base/TestLoadScreen.tex\"\n }" + Class - (411..519): "CensoredImage {\n image: string = \"ASSETS/Characters/Test/Skins/Base/TestLoadScreen.tex\"\n }" + "CensoredImage" (Name) + Block - (425..519): "{\n image: string = \"ASSETS/Characters/Test/Skins/Base/TestLoadScreen.tex\"\n }" + "{" (LCurly) + Entry - (426..518): "\n image: string = \"ASSETS/Characters/Test/Skins/Base/TestLoadScreen.tex\"\n " + EntryKey - (439..444): "image" + "image" (Name) + ":" (Colon) + TypeExpr - (446..452): "string" + "string" (Name) + "=" (Eq) + EntryValue - (454..509): " \"ASSETS/Characters/Test/Skins/Base/TestLoadScreen.tex\"" + Literal - (455..509): "\"ASSETS/Characters/Test/Skins/Base/TestLoadScreen.tex\"" + "\"ASSETS/Characters/Test/Skins/Base/TestLoadScreen.tex\"" (String) + EntryTerminator - (509..518): "\n " + "\n " (Newline) + "}" (RCurly) + EntryTerminator - (519..528): "\n " + "\n " (Newline) + Entry - (528..1167): "skinAudioProperties: embed = skinAudioProperties {\n tagEventList: list[string] = {\n \"Test\"\n }\n bankUnits: list2[embed] = {\n BankUnit {\n name: string = \"Test_Base_SFX\"\n bankPath: list[string] = {\n \"ASSETS/Sounds/Test/audio.bnk\"\n \"ASSETS/Sounds/Test/events.bnk\"\n }\n events: list[string] = {\n \"Play_sfx_Test_Attack\"\n \"Play_sfx_Test_Death\"\n }\n }\n }\n }\n " + EntryKey - (528..547): "skinAudioProperties" + "skinAudioProperties" (Name) + ":" (Colon) + TypeExpr - (549..554): "embed" + "embed" (Name) + "=" (Eq) + EntryValue - (556..1158): " skinAudioProperties {\n tagEventList: list[string] = {\n \"Test\"\n }\n bankUnits: list2[embed] = {\n BankUnit {\n name: string = \"Test_Base_SFX\"\n bankPath: list[string] = {\n \"ASSETS/Sounds/Test/audio.bnk\"\n \"ASSETS/Sounds/Test/events.bnk\"\n }\n events: list[string] = {\n \"Play_sfx_Test_Attack\"\n \"Play_sfx_Test_Death\"\n }\n }\n }\n }" + Class - (557..1158): "skinAudioProperties {\n tagEventList: list[string] = {\n \"Test\"\n }\n bankUnits: list2[embed] = {\n BankUnit {\n name: string = \"Test_Base_SFX\"\n bankPath: list[string] = {\n \"ASSETS/Sounds/Test/audio.bnk\"\n \"ASSETS/Sounds/Test/events.bnk\"\n }\n events: list[string] = {\n \"Play_sfx_Test_Attack\"\n \"Play_sfx_Test_Death\"\n }\n }\n }\n }" + "skinAudioProperties" (Name) + Block - (577..1158): "{\n tagEventList: list[string] = {\n \"Test\"\n }\n bankUnits: list2[embed] = {\n BankUnit {\n name: string = \"Test_Base_SFX\"\n bankPath: list[string] = {\n \"ASSETS/Sounds/Test/audio.bnk\"\n \"ASSETS/Sounds/Test/events.bnk\"\n }\n events: list[string] = {\n \"Play_sfx_Test_Attack\"\n \"Play_sfx_Test_Death\"\n }\n }\n }\n }" + "{" (LCurly) + Entry - (578..671): "\n tagEventList: list[string] = {\n \"Test\"\n }\n " + EntryKey - (591..603): "tagEventList" + "tagEventList" (Name) + ":" (Colon) + TypeExpr - (605..617): "list[string]" + "list" (Name) + "[" (LBrack) + TypeArgList - (610..616): "string" + TypeArg - (610..616): "string" + "string" (Name) + "]" (RBrack) + "=" (Eq) + EntryValue - (619..658): " {\n \"Test\"\n }" + Block - (620..658): "{\n \"Test\"\n }" + "{" (LCurly) + ListItem - (621..644): "\n \"Test\"" + Literal - (638..644): "\"Test\"" + "\"Test\"" (String) + "\n " (Newline) + "}" (RCurly) + EntryTerminator - (658..671): "\n " + "\n " (Newline) + Entry - (671..1157): "bankUnits: list2[embed] = {\n BankUnit {\n name: string = \"Test_Base_SFX\"\n bankPath: list[string] = {\n \"ASSETS/Sounds/Test/audio.bnk\"\n \"ASSETS/Sounds/Test/events.bnk\"\n }\n events: list[string] = {\n \"Play_sfx_Test_Attack\"\n \"Play_sfx_Test_Death\"\n }\n }\n }\n " + EntryKey - (671..680): "bankUnits" + "bankUnits" (Name) + ":" (Colon) + TypeExpr - (682..694): "list2[embed]" + "list2" (Name) + "[" (LBrack) + TypeArgList - (688..693): "embed" + TypeArg - (688..693): "embed" + "embed" (Name) + "]" (RBrack) + "=" (Eq) + EntryValue - (696..1148): " {\n BankUnit {\n name: string = \"Test_Base_SFX\"\n bankPath: list[string] = {\n \"ASSETS/Sounds/Test/audio.bnk\"\n \"ASSETS/Sounds/Test/events.bnk\"\n }\n events: list[string] = {\n \"Play_sfx_Test_Attack\"\n \"Play_sfx_Test_Death\"\n }\n }\n }" + Block - (697..1148): "{\n BankUnit {\n name: string = \"Test_Base_SFX\"\n bankPath: list[string] = {\n \"ASSETS/Sounds/Test/audio.bnk\"\n \"ASSETS/Sounds/Test/events.bnk\"\n }\n events: list[string] = {\n \"Play_sfx_Test_Attack\"\n \"Play_sfx_Test_Death\"\n }\n }\n }" + "{" (LCurly) + ListItem - (698..1147): "\n BankUnit {\n name: string = \"Test_Base_SFX\"\n bankPath: list[string] = {\n \"ASSETS/Sounds/Test/audio.bnk\"\n \"ASSETS/Sounds/Test/events.bnk\"\n }\n events: list[string] = {\n \"Play_sfx_Test_Attack\"\n \"Play_sfx_Test_Death\"\n }\n }\n " + Class - (715..1134): "BankUnit {\n name: string = \"Test_Base_SFX\"\n bankPath: list[string] = {\n \"ASSETS/Sounds/Test/audio.bnk\"\n \"ASSETS/Sounds/Test/events.bnk\"\n }\n events: list[string] = {\n \"Play_sfx_Test_Attack\"\n \"Play_sfx_Test_Death\"\n }\n }" + "BankUnit" (Name) + Block - (724..1134): "{\n name: string = \"Test_Base_SFX\"\n bankPath: list[string] = {\n \"ASSETS/Sounds/Test/audio.bnk\"\n \"ASSETS/Sounds/Test/events.bnk\"\n }\n events: list[string] = {\n \"Play_sfx_Test_Attack\"\n \"Play_sfx_Test_Death\"\n }\n }" + "{" (LCurly) + Entry - (725..797): "\n name: string = \"Test_Base_SFX\"\n " + EntryKey - (746..750): "name" + "name" (Name) + ":" (Colon) + TypeExpr - (752..758): "string" + "string" (Name) + "=" (Eq) + EntryValue - (760..776): " \"Test_Base_SFX\"" + Literal - (761..776): "\"Test_Base_SFX\"" + "\"Test_Base_SFX\"" (String) + EntryTerminator - (776..797): "\n " + "\n " (Newline) + Entry - (797..977): "bankPath: list[string] = {\n \"ASSETS/Sounds/Test/audio.bnk\"\n \"ASSETS/Sounds/Test/events.bnk\"\n }\n " + EntryKey - (797..805): "bankPath" + "bankPath" (Name) + ":" (Colon) + TypeExpr - (807..819): "list[string]" + "list" (Name) + "[" (LBrack) + TypeArgList - (812..818): "string" + TypeArg - (812..818): "string" + "string" (Name) + "]" (RBrack) + "=" (Eq) + EntryValue - (821..956): " {\n \"ASSETS/Sounds/Test/audio.bnk\"\n \"ASSETS/Sounds/Test/events.bnk\"\n }" + Block - (822..956): "{\n \"ASSETS/Sounds/Test/audio.bnk\"\n \"ASSETS/Sounds/Test/events.bnk\"\n }" + "{" (LCurly) + ListItem - (823..878): "\n \"ASSETS/Sounds/Test/audio.bnk\"" + Literal - (848..878): "\"ASSETS/Sounds/Test/audio.bnk\"" + "\"ASSETS/Sounds/Test/audio.bnk\"" (String) + "\n " (Newline) + ListItem - (903..934): "\"ASSETS/Sounds/Test/events.bnk\"" + Literal - (903..934): "\"ASSETS/Sounds/Test/events.bnk\"" + "\"ASSETS/Sounds/Test/events.bnk\"" (String) + "\n " (Newline) + "}" (RCurly) + EntryTerminator - (956..977): "\n " + "\n " (Newline) + Entry - (977..1133): "events: list[string] = {\n \"Play_sfx_Test_Attack\"\n \"Play_sfx_Test_Death\"\n }\n " + EntryKey - (977..983): "events" + "events" (Name) + ":" (Colon) + TypeExpr - (985..997): "list[string]" + "list" (Name) + "[" (LBrack) + TypeArgList - (990..996): "string" + TypeArg - (990..996): "string" + "string" (Name) + "]" (RBrack) + "=" (Eq) + EntryValue - (999..1116): " {\n \"Play_sfx_Test_Attack\"\n \"Play_sfx_Test_Death\"\n }" + Block - (1000..1116): "{\n \"Play_sfx_Test_Attack\"\n \"Play_sfx_Test_Death\"\n }" + "{" (LCurly) + ListItem - (1001..1048): "\n \"Play_sfx_Test_Attack\"" + Literal - (1026..1048): "\"Play_sfx_Test_Attack\"" + "\"Play_sfx_Test_Attack\"" (String) + "\n " (Newline) + ListItem - (1073..1094): "\"Play_sfx_Test_Death\"" + Literal - (1073..1094): "\"Play_sfx_Test_Death\"" + "\"Play_sfx_Test_Death\"" (String) + "\n " (Newline) + "}" (RCurly) + EntryTerminator - (1116..1133): "\n " + "\n " (Newline) + "}" (RCurly) + "\n " (Newline) + "}" (RCurly) + EntryTerminator - (1148..1157): "\n " + "\n " (Newline) + "}" (RCurly) + EntryTerminator - (1158..1167): "\n " + "\n " (Newline) + Entry - (1167..1270): "iconCircle: option[string] = {\n \"ASSETS/Characters/Test/Icons/Circle.tex\"\n }\n " + EntryKey - (1167..1177): "iconCircle" + "iconCircle" (Name) + ":" (Colon) + TypeExpr - (1179..1193): "option[string]" + "option" (Name) + "[" (LBrack) + TypeArgList - (1186..1192): "string" + TypeArg - (1186..1192): "string" + "string" (Name) + "]" (RBrack) + "=" (Eq) + EntryValue - (1195..1261): " {\n \"ASSETS/Characters/Test/Icons/Circle.tex\"\n }" + Block - (1196..1261): "{\n \"ASSETS/Characters/Test/Icons/Circle.tex\"\n }" + "{" (LCurly) + ListItem - (1197..1251): "\n \"ASSETS/Characters/Test/Icons/Circle.tex\"" + Literal - (1210..1251): "\"ASSETS/Characters/Test/Icons/Circle.tex\"" + "\"ASSETS/Characters/Test/Icons/Circle.tex\"" (String) + "\n " (Newline) + "}" (RCurly) + EntryTerminator - (1261..1270): "\n " + "\n " (Newline) + Entry - (1270..1306): "iconSquare: option[string] = {}\n " + EntryKey - (1270..1280): "iconSquare" + "iconSquare" (Name) + ":" (Colon) + TypeExpr - (1282..1296): "option[string]" + "option" (Name) + "[" (LBrack) + TypeArgList - (1289..1295): "string" + TypeArg - (1289..1295): "string" + "string" (Name) + "]" (RBrack) + "=" (Eq) + EntryValue - (1298..1301): " {}" + Block - (1299..1301): "{}" + "{" (LCurly) + "}" (RCurly) + EntryTerminator - (1301..1306): "\n " + "\n " (Newline) + "}" (RCurly) + EntryTerminator - (1307..1308): "\n" + "\n" (Newline) + "}" (RCurly) + EntryTerminator - (1309..1310): "\n" + "\n" (Newline) diff --git a/crates/ltk_ritobin/tests/snapshots/parse_sample__tree_snapshot-2.snap b/crates/ltk_ritobin/tests/snapshots/parse_sample__tree_snapshot-2.snap new file mode 100644 index 00000000..2ed7a2f9 --- /dev/null +++ b/crates/ltk_ritobin/tests/snapshots/parse_sample__tree_snapshot-2.snap @@ -0,0 +1,143 @@ +--- +source: crates/ltk_ritobin/tests/parse_sample.rs +expression: debug +--- +File - (0..287): "\ntest_list: list[string] = {\n \"item1\"\n \"item2\"\n \"item3\"\n}\ntest_list2: list2[u32] = {\n 1\n 2\n 3\n}\ntest_option_some: option[string] = {\n \"value\"\n}\ntest_option_none: option[string] = {}\ntest_map: map[hash,string] = {\n 0x12345678 = \"value1\"\n 0xdeadbeef = \"value2\"\n}" + Entry - (0..67): "\ntest_list: list[string] = {\n \"item1\"\n \"item2\"\n \"item3\"\n}\n" + EntryKey - (1..10): "test_list" + "test_list" (Name) + ":" (Colon) + TypeExpr - (12..24): "list[string]" + "list" (Name) + "[" (LBrack) + TypeArgList - (17..23): "string" + TypeArg - (17..23): "string" + "string" (Name) + "]" (RBrack) + "=" (Eq) + EntryValue - (26..66): " {\n \"item1\"\n \"item2\"\n \"item3\"\n}" + Block - (27..66): "{\n \"item1\"\n \"item2\"\n \"item3\"\n}" + "{" (LCurly) + ListItem - (28..40): "\n \"item1\"" + Literal - (33..40): "\"item1\"" + "\"item1\"" (String) + "\n " (Newline) + ListItem - (45..52): "\"item2\"" + Literal - (45..52): "\"item2\"" + "\"item2\"" (String) + "\n " (Newline) + ListItem - (57..64): "\"item3\"" + Literal - (57..64): "\"item3\"" + "\"item3\"" (String) + "\n" (Newline) + "}" (RCurly) + EntryTerminator - (66..67): "\n" + "\n" (Newline) + Entry - (67..114): "test_list2: list2[u32] = {\n 1\n 2\n 3\n}\n" + EntryKey - (67..77): "test_list2" + "test_list2" (Name) + ":" (Colon) + TypeExpr - (79..89): "list2[u32]" + "list2" (Name) + "[" (LBrack) + TypeArgList - (85..88): "u32" + TypeArg - (85..88): "u32" + "u32" (Name) + "]" (RBrack) + "=" (Eq) + EntryValue - (91..113): " {\n 1\n 2\n 3\n}" + Block - (92..113): "{\n 1\n 2\n 3\n}" + "{" (LCurly) + ListItem - (93..99): "\n 1" + Literal - (98..99): "1" + "1" (Number) + "\n " (Newline) + ListItem - (104..105): "2" + Literal - (104..105): "2" + "2" (Number) + "\n " (Newline) + ListItem - (110..111): "3" + Literal - (110..111): "3" + "3" (Number) + "\n" (Newline) + "}" (RCurly) + EntryTerminator - (113..114): "\n" + "\n" (Newline) + Entry - (114..165): "test_option_some: option[string] = {\n \"value\"\n}\n" + EntryKey - (114..130): "test_option_some" + "test_option_some" (Name) + ":" (Colon) + TypeExpr - (132..146): "option[string]" + "option" (Name) + "[" (LBrack) + TypeArgList - (139..145): "string" + TypeArg - (139..145): "string" + "string" (Name) + "]" (RBrack) + "=" (Eq) + EntryValue - (148..164): " {\n \"value\"\n}" + Block - (149..164): "{\n \"value\"\n}" + "{" (LCurly) + ListItem - (150..162): "\n \"value\"" + Literal - (155..162): "\"value\"" + "\"value\"" (String) + "\n" (Newline) + "}" (RCurly) + EntryTerminator - (164..165): "\n" + "\n" (Newline) + Entry - (165..203): "test_option_none: option[string] = {}\n" + EntryKey - (165..181): "test_option_none" + "test_option_none" (Name) + ":" (Colon) + TypeExpr - (183..197): "option[string]" + "option" (Name) + "[" (LBrack) + TypeArgList - (190..196): "string" + TypeArg - (190..196): "string" + "string" (Name) + "]" (RBrack) + "=" (Eq) + EntryValue - (199..202): " {}" + Block - (200..202): "{}" + "{" (LCurly) + "}" (RCurly) + EntryTerminator - (202..203): "\n" + "\n" (Newline) + Entry - (203..287): "test_map: map[hash,string] = {\n 0x12345678 = \"value1\"\n 0xdeadbeef = \"value2\"\n}" + EntryKey - (203..211): "test_map" + "test_map" (Name) + ":" (Colon) + TypeExpr - (213..229): "map[hash,string]" + "map" (Name) + "[" (LBrack) + TypeArgList - (217..228): "hash,string" + TypeArg - (217..221): "hash" + "hash" (Name) + "," (Comma) + TypeArg - (222..228): "string" + "string" (Name) + "]" (RBrack) + "=" (Eq) + EntryValue - (231..287): " {\n 0x12345678 = \"value1\"\n 0xdeadbeef = \"value2\"\n}" + Block - (232..287): "{\n 0x12345678 = \"value1\"\n 0xdeadbeef = \"value2\"\n}" + "{" (LCurly) + Entry - (233..264): "\n 0x12345678 = \"value1\"\n " + EntryKey - (238..248): "0x12345678" + "0x12345678" (HexLit) + "=" (Eq) + EntryValue - (250..259): " \"value1\"" + Literal - (251..259): "\"value1\"" + "\"value1\"" (String) + EntryTerminator - (259..264): "\n " + "\n " (Newline) + Entry - (264..286): "0xdeadbeef = \"value2\"\n" + EntryKey - (264..274): "0xdeadbeef" + "0xdeadbeef" (HexLit) + "=" (Eq) + EntryValue - (276..285): " \"value2\"" + Literal - (277..285): "\"value2\"" + "\"value2\"" (String) + EntryTerminator - (285..286): "\n" + "\n" (Newline) + "}" (RCurly) + EntryTerminator - (287..287): "" diff --git a/crates/ltk_ritobin/tests/snapshots/parse_sample__tree_snapshot-3.snap b/crates/ltk_ritobin/tests/snapshots/parse_sample__tree_snapshot-3.snap new file mode 100644 index 00000000..61e77213 --- /dev/null +++ b/crates/ltk_ritobin/tests/snapshots/parse_sample__tree_snapshot-3.snap @@ -0,0 +1,319 @@ +--- +source: crates/ltk_ritobin/tests/parse_sample.rs +expression: debug +--- +File - (0..1310): "#PROP_text\ntype: string = \"PROP\"\nversion: u32 = 3\nlinked: list[string] = {\n \"DATA/Characters/Test/Animations/Skin0.bin\"\n \"DATA/Characters/Test/Test.bin\"\n}\nentries: map[hash,embed] = {\n \"Characters/Test/Skins/Skin0\" = SkinCharacterDataProperties {\n skinClassification: u32 = 1\n championSkinName: string = \"TestBase\"\n metaDataTags: string = \"gender:male\"\n loadscreen: embed = CensoredImage {\n image: string = \"ASSETS/Characters/Test/Skins/Base/TestLoadScreen.tex\"\n }\n skinAudioProperties: embed = skinAudioProperties {\n tagEventList: list[string] = {\n \"Test\"\n }\n bankUnits: list2[embed] = {\n BankUnit {\n name: string = \"Test_Base_SFX\"\n bankPath: list[string] = {\n \"ASSETS/Sounds/Test/audio.bnk\"\n \"ASSETS/Sounds/Test/events.bnk\"\n }\n events: list[string] = {\n \"Play_sfx_Test_Attack\"\n \"Play_sfx_Test_Death\"\n }\n }\n }\n }\n iconCircle: option[string] = {\n \"ASSETS/Characters/Test/Icons/Circle.tex\"\n }\n iconSquare: option[string] = {}\n }\n}\n" + Comment - (0..10): "#PROP_text" + "#PROP_text" (Comment) + Entry - (10..33): "\ntype: string = \"PROP\"\n" + EntryKey - (11..15): "type" + "type" (Name) + ":" (Colon) + TypeExpr - (17..23): "string" + "string" (Name) + "=" (Eq) + EntryValue - (25..32): " \"PROP\"" + Literal - (26..32): "\"PROP\"" + "\"PROP\"" (String) + EntryTerminator - (32..33): "\n" + "\n" (Newline) + Entry - (33..50): "version: u32 = 3\n" + EntryKey - (33..40): "version" + "version" (Name) + ":" (Colon) + TypeExpr - (42..45): "u32" + "u32" (Name) + "=" (Eq) + EntryValue - (47..49): " 3" + Literal - (48..49): "3" + "3" (Number) + EntryTerminator - (49..50): "\n" + "\n" (Newline) + Entry - (50..161): "linked: list[string] = {\n \"DATA/Characters/Test/Animations/Skin0.bin\"\n \"DATA/Characters/Test/Test.bin\"\n}\n" + EntryKey - (50..56): "linked" + "linked" (Name) + ":" (Colon) + TypeExpr - (58..70): "list[string]" + "list" (Name) + "[" (LBrack) + TypeArgList - (63..69): "string" + TypeArg - (63..69): "string" + "string" (Name) + "]" (RBrack) + "=" (Eq) + EntryValue - (72..160): " {\n \"DATA/Characters/Test/Animations/Skin0.bin\"\n \"DATA/Characters/Test/Test.bin\"\n}" + Block - (73..160): "{\n \"DATA/Characters/Test/Animations/Skin0.bin\"\n \"DATA/Characters/Test/Test.bin\"\n}" + "{" (LCurly) + ListItem - (74..122): "\n \"DATA/Characters/Test/Animations/Skin0.bin\"" + Literal - (79..122): "\"DATA/Characters/Test/Animations/Skin0.bin\"" + "\"DATA/Characters/Test/Animations/Skin0.bin\"" (String) + "\n " (Newline) + ListItem - (127..158): "\"DATA/Characters/Test/Test.bin\"" + Literal - (127..158): "\"DATA/Characters/Test/Test.bin\"" + "\"DATA/Characters/Test/Test.bin\"" (String) + "\n" (Newline) + "}" (RCurly) + EntryTerminator - (160..161): "\n" + "\n" (Newline) + Entry - (161..1310): "entries: map[hash,embed] = {\n \"Characters/Test/Skins/Skin0\" = SkinCharacterDataProperties {\n skinClassification: u32 = 1\n championSkinName: string = \"TestBase\"\n metaDataTags: string = \"gender:male\"\n loadscreen: embed = CensoredImage {\n image: string = \"ASSETS/Characters/Test/Skins/Base/TestLoadScreen.tex\"\n }\n skinAudioProperties: embed = skinAudioProperties {\n tagEventList: list[string] = {\n \"Test\"\n }\n bankUnits: list2[embed] = {\n BankUnit {\n name: string = \"Test_Base_SFX\"\n bankPath: list[string] = {\n \"ASSETS/Sounds/Test/audio.bnk\"\n \"ASSETS/Sounds/Test/events.bnk\"\n }\n events: list[string] = {\n \"Play_sfx_Test_Attack\"\n \"Play_sfx_Test_Death\"\n }\n }\n }\n }\n iconCircle: option[string] = {\n \"ASSETS/Characters/Test/Icons/Circle.tex\"\n }\n iconSquare: option[string] = {}\n }\n}\n" + EntryKey - (161..168): "entries" + "entries" (Name) + ":" (Colon) + TypeExpr - (170..185): "map[hash,embed]" + "map" (Name) + "[" (LBrack) + TypeArgList - (174..184): "hash,embed" + TypeArg - (174..178): "hash" + "hash" (Name) + "," (Comma) + TypeArg - (179..184): "embed" + "embed" (Name) + "]" (RBrack) + "=" (Eq) + EntryValue - (187..1309): " {\n \"Characters/Test/Skins/Skin0\" = SkinCharacterDataProperties {\n skinClassification: u32 = 1\n championSkinName: string = \"TestBase\"\n metaDataTags: string = \"gender:male\"\n loadscreen: embed = CensoredImage {\n image: string = \"ASSETS/Characters/Test/Skins/Base/TestLoadScreen.tex\"\n }\n skinAudioProperties: embed = skinAudioProperties {\n tagEventList: list[string] = {\n \"Test\"\n }\n bankUnits: list2[embed] = {\n BankUnit {\n name: string = \"Test_Base_SFX\"\n bankPath: list[string] = {\n \"ASSETS/Sounds/Test/audio.bnk\"\n \"ASSETS/Sounds/Test/events.bnk\"\n }\n events: list[string] = {\n \"Play_sfx_Test_Attack\"\n \"Play_sfx_Test_Death\"\n }\n }\n }\n }\n iconCircle: option[string] = {\n \"ASSETS/Characters/Test/Icons/Circle.tex\"\n }\n iconSquare: option[string] = {}\n }\n}" + Block - (188..1309): "{\n \"Characters/Test/Skins/Skin0\" = SkinCharacterDataProperties {\n skinClassification: u32 = 1\n championSkinName: string = \"TestBase\"\n metaDataTags: string = \"gender:male\"\n loadscreen: embed = CensoredImage {\n image: string = \"ASSETS/Characters/Test/Skins/Base/TestLoadScreen.tex\"\n }\n skinAudioProperties: embed = skinAudioProperties {\n tagEventList: list[string] = {\n \"Test\"\n }\n bankUnits: list2[embed] = {\n BankUnit {\n name: string = \"Test_Base_SFX\"\n bankPath: list[string] = {\n \"ASSETS/Sounds/Test/audio.bnk\"\n \"ASSETS/Sounds/Test/events.bnk\"\n }\n events: list[string] = {\n \"Play_sfx_Test_Attack\"\n \"Play_sfx_Test_Death\"\n }\n }\n }\n }\n iconCircle: option[string] = {\n \"ASSETS/Characters/Test/Icons/Circle.tex\"\n }\n iconSquare: option[string] = {}\n }\n}" + "{" (LCurly) + Entry - (189..1308): "\n \"Characters/Test/Skins/Skin0\" = SkinCharacterDataProperties {\n skinClassification: u32 = 1\n championSkinName: string = \"TestBase\"\n metaDataTags: string = \"gender:male\"\n loadscreen: embed = CensoredImage {\n image: string = \"ASSETS/Characters/Test/Skins/Base/TestLoadScreen.tex\"\n }\n skinAudioProperties: embed = skinAudioProperties {\n tagEventList: list[string] = {\n \"Test\"\n }\n bankUnits: list2[embed] = {\n BankUnit {\n name: string = \"Test_Base_SFX\"\n bankPath: list[string] = {\n \"ASSETS/Sounds/Test/audio.bnk\"\n \"ASSETS/Sounds/Test/events.bnk\"\n }\n events: list[string] = {\n \"Play_sfx_Test_Attack\"\n \"Play_sfx_Test_Death\"\n }\n }\n }\n }\n iconCircle: option[string] = {\n \"ASSETS/Characters/Test/Icons/Circle.tex\"\n }\n iconSquare: option[string] = {}\n }\n" + EntryKey - (194..223): "\"Characters/Test/Skins/Skin0\"" + "\"Characters/Test/Skins/Skin0\"" (String) + "=" (Eq) + EntryValue - (225..1307): " SkinCharacterDataProperties {\n skinClassification: u32 = 1\n championSkinName: string = \"TestBase\"\n metaDataTags: string = \"gender:male\"\n loadscreen: embed = CensoredImage {\n image: string = \"ASSETS/Characters/Test/Skins/Base/TestLoadScreen.tex\"\n }\n skinAudioProperties: embed = skinAudioProperties {\n tagEventList: list[string] = {\n \"Test\"\n }\n bankUnits: list2[embed] = {\n BankUnit {\n name: string = \"Test_Base_SFX\"\n bankPath: list[string] = {\n \"ASSETS/Sounds/Test/audio.bnk\"\n \"ASSETS/Sounds/Test/events.bnk\"\n }\n events: list[string] = {\n \"Play_sfx_Test_Attack\"\n \"Play_sfx_Test_Death\"\n }\n }\n }\n }\n iconCircle: option[string] = {\n \"ASSETS/Characters/Test/Icons/Circle.tex\"\n }\n iconSquare: option[string] = {}\n }" + Class - (226..1307): "SkinCharacterDataProperties {\n skinClassification: u32 = 1\n championSkinName: string = \"TestBase\"\n metaDataTags: string = \"gender:male\"\n loadscreen: embed = CensoredImage {\n image: string = \"ASSETS/Characters/Test/Skins/Base/TestLoadScreen.tex\"\n }\n skinAudioProperties: embed = skinAudioProperties {\n tagEventList: list[string] = {\n \"Test\"\n }\n bankUnits: list2[embed] = {\n BankUnit {\n name: string = \"Test_Base_SFX\"\n bankPath: list[string] = {\n \"ASSETS/Sounds/Test/audio.bnk\"\n \"ASSETS/Sounds/Test/events.bnk\"\n }\n events: list[string] = {\n \"Play_sfx_Test_Attack\"\n \"Play_sfx_Test_Death\"\n }\n }\n }\n }\n iconCircle: option[string] = {\n \"ASSETS/Characters/Test/Icons/Circle.tex\"\n }\n iconSquare: option[string] = {}\n }" + "SkinCharacterDataProperties" (Name) + Block - (254..1307): "{\n skinClassification: u32 = 1\n championSkinName: string = \"TestBase\"\n metaDataTags: string = \"gender:male\"\n loadscreen: embed = CensoredImage {\n image: string = \"ASSETS/Characters/Test/Skins/Base/TestLoadScreen.tex\"\n }\n skinAudioProperties: embed = skinAudioProperties {\n tagEventList: list[string] = {\n \"Test\"\n }\n bankUnits: list2[embed] = {\n BankUnit {\n name: string = \"Test_Base_SFX\"\n bankPath: list[string] = {\n \"ASSETS/Sounds/Test/audio.bnk\"\n \"ASSETS/Sounds/Test/events.bnk\"\n }\n events: list[string] = {\n \"Play_sfx_Test_Attack\"\n \"Play_sfx_Test_Death\"\n }\n }\n }\n }\n iconCircle: option[string] = {\n \"ASSETS/Characters/Test/Icons/Circle.tex\"\n }\n iconSquare: option[string] = {}\n }" + "{" (LCurly) + Entry - (255..300): "\n skinClassification: u32 = 1\n " + EntryKey - (264..282): "skinClassification" + "skinClassification" (Name) + ":" (Colon) + TypeExpr - (284..287): "u32" + "u32" (Name) + "=" (Eq) + EntryValue - (289..291): " 1" + Literal - (290..291): "1" + "1" (Number) + EntryTerminator - (291..300): "\n " + "\n " (Newline) + Entry - (300..346): "championSkinName: string = \"TestBase\"\n " + EntryKey - (300..316): "championSkinName" + "championSkinName" (Name) + ":" (Colon) + TypeExpr - (318..324): "string" + "string" (Name) + "=" (Eq) + EntryValue - (326..337): " \"TestBase\"" + Literal - (327..337): "\"TestBase\"" + "\"TestBase\"" (String) + EntryTerminator - (337..346): "\n " + "\n " (Newline) + Entry - (346..391): "metaDataTags: string = \"gender:male\"\n " + EntryKey - (346..358): "metaDataTags" + "metaDataTags" (Name) + ":" (Colon) + TypeExpr - (360..366): "string" + "string" (Name) + "=" (Eq) + EntryValue - (368..382): " \"gender:male\"" + Literal - (369..382): "\"gender:male\"" + "\"gender:male\"" (String) + EntryTerminator - (382..391): "\n " + "\n " (Newline) + Entry - (391..528): "loadscreen: embed = CensoredImage {\n image: string = \"ASSETS/Characters/Test/Skins/Base/TestLoadScreen.tex\"\n }\n " + EntryKey - (391..401): "loadscreen" + "loadscreen" (Name) + ":" (Colon) + TypeExpr - (403..408): "embed" + "embed" (Name) + "=" (Eq) + EntryValue - (410..519): " CensoredImage {\n image: string = \"ASSETS/Characters/Test/Skins/Base/TestLoadScreen.tex\"\n }" + Class - (411..519): "CensoredImage {\n image: string = \"ASSETS/Characters/Test/Skins/Base/TestLoadScreen.tex\"\n }" + "CensoredImage" (Name) + Block - (425..519): "{\n image: string = \"ASSETS/Characters/Test/Skins/Base/TestLoadScreen.tex\"\n }" + "{" (LCurly) + Entry - (426..518): "\n image: string = \"ASSETS/Characters/Test/Skins/Base/TestLoadScreen.tex\"\n " + EntryKey - (439..444): "image" + "image" (Name) + ":" (Colon) + TypeExpr - (446..452): "string" + "string" (Name) + "=" (Eq) + EntryValue - (454..509): " \"ASSETS/Characters/Test/Skins/Base/TestLoadScreen.tex\"" + Literal - (455..509): "\"ASSETS/Characters/Test/Skins/Base/TestLoadScreen.tex\"" + "\"ASSETS/Characters/Test/Skins/Base/TestLoadScreen.tex\"" (String) + EntryTerminator - (509..518): "\n " + "\n " (Newline) + "}" (RCurly) + EntryTerminator - (519..528): "\n " + "\n " (Newline) + Entry - (528..1167): "skinAudioProperties: embed = skinAudioProperties {\n tagEventList: list[string] = {\n \"Test\"\n }\n bankUnits: list2[embed] = {\n BankUnit {\n name: string = \"Test_Base_SFX\"\n bankPath: list[string] = {\n \"ASSETS/Sounds/Test/audio.bnk\"\n \"ASSETS/Sounds/Test/events.bnk\"\n }\n events: list[string] = {\n \"Play_sfx_Test_Attack\"\n \"Play_sfx_Test_Death\"\n }\n }\n }\n }\n " + EntryKey - (528..547): "skinAudioProperties" + "skinAudioProperties" (Name) + ":" (Colon) + TypeExpr - (549..554): "embed" + "embed" (Name) + "=" (Eq) + EntryValue - (556..1158): " skinAudioProperties {\n tagEventList: list[string] = {\n \"Test\"\n }\n bankUnits: list2[embed] = {\n BankUnit {\n name: string = \"Test_Base_SFX\"\n bankPath: list[string] = {\n \"ASSETS/Sounds/Test/audio.bnk\"\n \"ASSETS/Sounds/Test/events.bnk\"\n }\n events: list[string] = {\n \"Play_sfx_Test_Attack\"\n \"Play_sfx_Test_Death\"\n }\n }\n }\n }" + Class - (557..1158): "skinAudioProperties {\n tagEventList: list[string] = {\n \"Test\"\n }\n bankUnits: list2[embed] = {\n BankUnit {\n name: string = \"Test_Base_SFX\"\n bankPath: list[string] = {\n \"ASSETS/Sounds/Test/audio.bnk\"\n \"ASSETS/Sounds/Test/events.bnk\"\n }\n events: list[string] = {\n \"Play_sfx_Test_Attack\"\n \"Play_sfx_Test_Death\"\n }\n }\n }\n }" + "skinAudioProperties" (Name) + Block - (577..1158): "{\n tagEventList: list[string] = {\n \"Test\"\n }\n bankUnits: list2[embed] = {\n BankUnit {\n name: string = \"Test_Base_SFX\"\n bankPath: list[string] = {\n \"ASSETS/Sounds/Test/audio.bnk\"\n \"ASSETS/Sounds/Test/events.bnk\"\n }\n events: list[string] = {\n \"Play_sfx_Test_Attack\"\n \"Play_sfx_Test_Death\"\n }\n }\n }\n }" + "{" (LCurly) + Entry - (578..671): "\n tagEventList: list[string] = {\n \"Test\"\n }\n " + EntryKey - (591..603): "tagEventList" + "tagEventList" (Name) + ":" (Colon) + TypeExpr - (605..617): "list[string]" + "list" (Name) + "[" (LBrack) + TypeArgList - (610..616): "string" + TypeArg - (610..616): "string" + "string" (Name) + "]" (RBrack) + "=" (Eq) + EntryValue - (619..658): " {\n \"Test\"\n }" + Block - (620..658): "{\n \"Test\"\n }" + "{" (LCurly) + ListItem - (621..644): "\n \"Test\"" + Literal - (638..644): "\"Test\"" + "\"Test\"" (String) + "\n " (Newline) + "}" (RCurly) + EntryTerminator - (658..671): "\n " + "\n " (Newline) + Entry - (671..1157): "bankUnits: list2[embed] = {\n BankUnit {\n name: string = \"Test_Base_SFX\"\n bankPath: list[string] = {\n \"ASSETS/Sounds/Test/audio.bnk\"\n \"ASSETS/Sounds/Test/events.bnk\"\n }\n events: list[string] = {\n \"Play_sfx_Test_Attack\"\n \"Play_sfx_Test_Death\"\n }\n }\n }\n " + EntryKey - (671..680): "bankUnits" + "bankUnits" (Name) + ":" (Colon) + TypeExpr - (682..694): "list2[embed]" + "list2" (Name) + "[" (LBrack) + TypeArgList - (688..693): "embed" + TypeArg - (688..693): "embed" + "embed" (Name) + "]" (RBrack) + "=" (Eq) + EntryValue - (696..1148): " {\n BankUnit {\n name: string = \"Test_Base_SFX\"\n bankPath: list[string] = {\n \"ASSETS/Sounds/Test/audio.bnk\"\n \"ASSETS/Sounds/Test/events.bnk\"\n }\n events: list[string] = {\n \"Play_sfx_Test_Attack\"\n \"Play_sfx_Test_Death\"\n }\n }\n }" + Block - (697..1148): "{\n BankUnit {\n name: string = \"Test_Base_SFX\"\n bankPath: list[string] = {\n \"ASSETS/Sounds/Test/audio.bnk\"\n \"ASSETS/Sounds/Test/events.bnk\"\n }\n events: list[string] = {\n \"Play_sfx_Test_Attack\"\n \"Play_sfx_Test_Death\"\n }\n }\n }" + "{" (LCurly) + ListItem - (698..1147): "\n BankUnit {\n name: string = \"Test_Base_SFX\"\n bankPath: list[string] = {\n \"ASSETS/Sounds/Test/audio.bnk\"\n \"ASSETS/Sounds/Test/events.bnk\"\n }\n events: list[string] = {\n \"Play_sfx_Test_Attack\"\n \"Play_sfx_Test_Death\"\n }\n }\n " + Class - (715..1134): "BankUnit {\n name: string = \"Test_Base_SFX\"\n bankPath: list[string] = {\n \"ASSETS/Sounds/Test/audio.bnk\"\n \"ASSETS/Sounds/Test/events.bnk\"\n }\n events: list[string] = {\n \"Play_sfx_Test_Attack\"\n \"Play_sfx_Test_Death\"\n }\n }" + "BankUnit" (Name) + Block - (724..1134): "{\n name: string = \"Test_Base_SFX\"\n bankPath: list[string] = {\n \"ASSETS/Sounds/Test/audio.bnk\"\n \"ASSETS/Sounds/Test/events.bnk\"\n }\n events: list[string] = {\n \"Play_sfx_Test_Attack\"\n \"Play_sfx_Test_Death\"\n }\n }" + "{" (LCurly) + Entry - (725..797): "\n name: string = \"Test_Base_SFX\"\n " + EntryKey - (746..750): "name" + "name" (Name) + ":" (Colon) + TypeExpr - (752..758): "string" + "string" (Name) + "=" (Eq) + EntryValue - (760..776): " \"Test_Base_SFX\"" + Literal - (761..776): "\"Test_Base_SFX\"" + "\"Test_Base_SFX\"" (String) + EntryTerminator - (776..797): "\n " + "\n " (Newline) + Entry - (797..977): "bankPath: list[string] = {\n \"ASSETS/Sounds/Test/audio.bnk\"\n \"ASSETS/Sounds/Test/events.bnk\"\n }\n " + EntryKey - (797..805): "bankPath" + "bankPath" (Name) + ":" (Colon) + TypeExpr - (807..819): "list[string]" + "list" (Name) + "[" (LBrack) + TypeArgList - (812..818): "string" + TypeArg - (812..818): "string" + "string" (Name) + "]" (RBrack) + "=" (Eq) + EntryValue - (821..956): " {\n \"ASSETS/Sounds/Test/audio.bnk\"\n \"ASSETS/Sounds/Test/events.bnk\"\n }" + Block - (822..956): "{\n \"ASSETS/Sounds/Test/audio.bnk\"\n \"ASSETS/Sounds/Test/events.bnk\"\n }" + "{" (LCurly) + ListItem - (823..878): "\n \"ASSETS/Sounds/Test/audio.bnk\"" + Literal - (848..878): "\"ASSETS/Sounds/Test/audio.bnk\"" + "\"ASSETS/Sounds/Test/audio.bnk\"" (String) + "\n " (Newline) + ListItem - (903..934): "\"ASSETS/Sounds/Test/events.bnk\"" + Literal - (903..934): "\"ASSETS/Sounds/Test/events.bnk\"" + "\"ASSETS/Sounds/Test/events.bnk\"" (String) + "\n " (Newline) + "}" (RCurly) + EntryTerminator - (956..977): "\n " + "\n " (Newline) + Entry - (977..1133): "events: list[string] = {\n \"Play_sfx_Test_Attack\"\n \"Play_sfx_Test_Death\"\n }\n " + EntryKey - (977..983): "events" + "events" (Name) + ":" (Colon) + TypeExpr - (985..997): "list[string]" + "list" (Name) + "[" (LBrack) + TypeArgList - (990..996): "string" + TypeArg - (990..996): "string" + "string" (Name) + "]" (RBrack) + "=" (Eq) + EntryValue - (999..1116): " {\n \"Play_sfx_Test_Attack\"\n \"Play_sfx_Test_Death\"\n }" + Block - (1000..1116): "{\n \"Play_sfx_Test_Attack\"\n \"Play_sfx_Test_Death\"\n }" + "{" (LCurly) + ListItem - (1001..1048): "\n \"Play_sfx_Test_Attack\"" + Literal - (1026..1048): "\"Play_sfx_Test_Attack\"" + "\"Play_sfx_Test_Attack\"" (String) + "\n " (Newline) + ListItem - (1073..1094): "\"Play_sfx_Test_Death\"" + Literal - (1073..1094): "\"Play_sfx_Test_Death\"" + "\"Play_sfx_Test_Death\"" (String) + "\n " (Newline) + "}" (RCurly) + EntryTerminator - (1116..1133): "\n " + "\n " (Newline) + "}" (RCurly) + "\n " (Newline) + "}" (RCurly) + EntryTerminator - (1148..1157): "\n " + "\n " (Newline) + "}" (RCurly) + EntryTerminator - (1158..1167): "\n " + "\n " (Newline) + Entry - (1167..1270): "iconCircle: option[string] = {\n \"ASSETS/Characters/Test/Icons/Circle.tex\"\n }\n " + EntryKey - (1167..1177): "iconCircle" + "iconCircle" (Name) + ":" (Colon) + TypeExpr - (1179..1193): "option[string]" + "option" (Name) + "[" (LBrack) + TypeArgList - (1186..1192): "string" + TypeArg - (1186..1192): "string" + "string" (Name) + "]" (RBrack) + "=" (Eq) + EntryValue - (1195..1261): " {\n \"ASSETS/Characters/Test/Icons/Circle.tex\"\n }" + Block - (1196..1261): "{\n \"ASSETS/Characters/Test/Icons/Circle.tex\"\n }" + "{" (LCurly) + ListItem - (1197..1251): "\n \"ASSETS/Characters/Test/Icons/Circle.tex\"" + Literal - (1210..1251): "\"ASSETS/Characters/Test/Icons/Circle.tex\"" + "\"ASSETS/Characters/Test/Icons/Circle.tex\"" (String) + "\n " (Newline) + "}" (RCurly) + EntryTerminator - (1261..1270): "\n " + "\n " (Newline) + Entry - (1270..1306): "iconSquare: option[string] = {}\n " + EntryKey - (1270..1280): "iconSquare" + "iconSquare" (Name) + ":" (Colon) + TypeExpr - (1282..1296): "option[string]" + "option" (Name) + "[" (LBrack) + TypeArgList - (1289..1295): "string" + TypeArg - (1289..1295): "string" + "string" (Name) + "]" (RBrack) + "=" (Eq) + EntryValue - (1298..1301): " {}" + Block - (1299..1301): "{}" + "{" (LCurly) + "}" (RCurly) + EntryTerminator - (1301..1306): "\n " + "\n " (Newline) + "}" (RCurly) + EntryTerminator - (1307..1308): "\n" + "\n" (Newline) + "}" (RCurly) + EntryTerminator - (1309..1310): "\n" + "\n" (Newline) diff --git a/crates/ltk_ritobin/tests/snapshots/parse_sample__tree_snapshot-4.snap b/crates/ltk_ritobin/tests/snapshots/parse_sample__tree_snapshot-4.snap new file mode 100644 index 00000000..2ed7a2f9 --- /dev/null +++ b/crates/ltk_ritobin/tests/snapshots/parse_sample__tree_snapshot-4.snap @@ -0,0 +1,143 @@ +--- +source: crates/ltk_ritobin/tests/parse_sample.rs +expression: debug +--- +File - (0..287): "\ntest_list: list[string] = {\n \"item1\"\n \"item2\"\n \"item3\"\n}\ntest_list2: list2[u32] = {\n 1\n 2\n 3\n}\ntest_option_some: option[string] = {\n \"value\"\n}\ntest_option_none: option[string] = {}\ntest_map: map[hash,string] = {\n 0x12345678 = \"value1\"\n 0xdeadbeef = \"value2\"\n}" + Entry - (0..67): "\ntest_list: list[string] = {\n \"item1\"\n \"item2\"\n \"item3\"\n}\n" + EntryKey - (1..10): "test_list" + "test_list" (Name) + ":" (Colon) + TypeExpr - (12..24): "list[string]" + "list" (Name) + "[" (LBrack) + TypeArgList - (17..23): "string" + TypeArg - (17..23): "string" + "string" (Name) + "]" (RBrack) + "=" (Eq) + EntryValue - (26..66): " {\n \"item1\"\n \"item2\"\n \"item3\"\n}" + Block - (27..66): "{\n \"item1\"\n \"item2\"\n \"item3\"\n}" + "{" (LCurly) + ListItem - (28..40): "\n \"item1\"" + Literal - (33..40): "\"item1\"" + "\"item1\"" (String) + "\n " (Newline) + ListItem - (45..52): "\"item2\"" + Literal - (45..52): "\"item2\"" + "\"item2\"" (String) + "\n " (Newline) + ListItem - (57..64): "\"item3\"" + Literal - (57..64): "\"item3\"" + "\"item3\"" (String) + "\n" (Newline) + "}" (RCurly) + EntryTerminator - (66..67): "\n" + "\n" (Newline) + Entry - (67..114): "test_list2: list2[u32] = {\n 1\n 2\n 3\n}\n" + EntryKey - (67..77): "test_list2" + "test_list2" (Name) + ":" (Colon) + TypeExpr - (79..89): "list2[u32]" + "list2" (Name) + "[" (LBrack) + TypeArgList - (85..88): "u32" + TypeArg - (85..88): "u32" + "u32" (Name) + "]" (RBrack) + "=" (Eq) + EntryValue - (91..113): " {\n 1\n 2\n 3\n}" + Block - (92..113): "{\n 1\n 2\n 3\n}" + "{" (LCurly) + ListItem - (93..99): "\n 1" + Literal - (98..99): "1" + "1" (Number) + "\n " (Newline) + ListItem - (104..105): "2" + Literal - (104..105): "2" + "2" (Number) + "\n " (Newline) + ListItem - (110..111): "3" + Literal - (110..111): "3" + "3" (Number) + "\n" (Newline) + "}" (RCurly) + EntryTerminator - (113..114): "\n" + "\n" (Newline) + Entry - (114..165): "test_option_some: option[string] = {\n \"value\"\n}\n" + EntryKey - (114..130): "test_option_some" + "test_option_some" (Name) + ":" (Colon) + TypeExpr - (132..146): "option[string]" + "option" (Name) + "[" (LBrack) + TypeArgList - (139..145): "string" + TypeArg - (139..145): "string" + "string" (Name) + "]" (RBrack) + "=" (Eq) + EntryValue - (148..164): " {\n \"value\"\n}" + Block - (149..164): "{\n \"value\"\n}" + "{" (LCurly) + ListItem - (150..162): "\n \"value\"" + Literal - (155..162): "\"value\"" + "\"value\"" (String) + "\n" (Newline) + "}" (RCurly) + EntryTerminator - (164..165): "\n" + "\n" (Newline) + Entry - (165..203): "test_option_none: option[string] = {}\n" + EntryKey - (165..181): "test_option_none" + "test_option_none" (Name) + ":" (Colon) + TypeExpr - (183..197): "option[string]" + "option" (Name) + "[" (LBrack) + TypeArgList - (190..196): "string" + TypeArg - (190..196): "string" + "string" (Name) + "]" (RBrack) + "=" (Eq) + EntryValue - (199..202): " {}" + Block - (200..202): "{}" + "{" (LCurly) + "}" (RCurly) + EntryTerminator - (202..203): "\n" + "\n" (Newline) + Entry - (203..287): "test_map: map[hash,string] = {\n 0x12345678 = \"value1\"\n 0xdeadbeef = \"value2\"\n}" + EntryKey - (203..211): "test_map" + "test_map" (Name) + ":" (Colon) + TypeExpr - (213..229): "map[hash,string]" + "map" (Name) + "[" (LBrack) + TypeArgList - (217..228): "hash,string" + TypeArg - (217..221): "hash" + "hash" (Name) + "," (Comma) + TypeArg - (222..228): "string" + "string" (Name) + "]" (RBrack) + "=" (Eq) + EntryValue - (231..287): " {\n 0x12345678 = \"value1\"\n 0xdeadbeef = \"value2\"\n}" + Block - (232..287): "{\n 0x12345678 = \"value1\"\n 0xdeadbeef = \"value2\"\n}" + "{" (LCurly) + Entry - (233..264): "\n 0x12345678 = \"value1\"\n " + EntryKey - (238..248): "0x12345678" + "0x12345678" (HexLit) + "=" (Eq) + EntryValue - (250..259): " \"value1\"" + Literal - (251..259): "\"value1\"" + "\"value1\"" (String) + EntryTerminator - (259..264): "\n " + "\n " (Newline) + Entry - (264..286): "0xdeadbeef = \"value2\"\n" + EntryKey - (264..274): "0xdeadbeef" + "0xdeadbeef" (HexLit) + "=" (Eq) + EntryValue - (276..285): " \"value2\"" + Literal - (277..285): "\"value2\"" + "\"value2\"" (String) + EntryTerminator - (285..286): "\n" + "\n" (Newline) + "}" (RCurly) + EntryTerminator - (287..287): "" diff --git a/crates/ltk_ritobin/tests/snapshots/parse_sample__tree_snapshot-5.snap b/crates/ltk_ritobin/tests/snapshots/parse_sample__tree_snapshot-5.snap new file mode 100644 index 00000000..59932165 --- /dev/null +++ b/crates/ltk_ritobin/tests/snapshots/parse_sample__tree_snapshot-5.snap @@ -0,0 +1,249 @@ +--- +source: crates/ltk_ritobin/tests/parse_sample.rs +expression: debug +--- +File - (0..459): "\ntest_bool: bool = true\ntest_i8: i8 = -128\ntest_u8: u8 = 255\ntest_i16: i16 = -32768\ntest_u16: u16 = 65535\ntest_i32: i32 = -2147483648\ntest_u32: u32 = 4294967295\ntest_f32: f32 = 3.14159\ntest_vec2: vec2 = { 1.0, 2.0 }\ntest_vec3: vec3 = { 1.0, 2.0, 3.0 }\ntest_vec4: vec4 = { 1.0, 2.0, 3.0, 4.0 }\ntest_rgba: rgba = { 255, 128, 64, 255 }\ntest_string: string = \"Hello, World!\"\ntest_hash: hash = 0xdeadbeef\ntest_link: link = \"path/to/object\"\ntest_flag: flag = false\n" + Entry - (0..24): "\ntest_bool: bool = true\n" + EntryKey - (1..10): "test_bool" + "test_bool" (Name) + ":" (Colon) + TypeExpr - (12..16): "bool" + "bool" (Name) + "=" (Eq) + EntryValue - (18..23): " true" + Literal - (19..23): "true" + "true" (True) + EntryTerminator - (23..24): "\n" + "\n" (Newline) + Entry - (24..43): "test_i8: i8 = -128\n" + EntryKey - (24..31): "test_i8" + "test_i8" (Name) + ":" (Colon) + TypeExpr - (33..35): "i8" + "i8" (Name) + "=" (Eq) + EntryValue - (37..42): " -128" + Literal - (38..42): "-128" + "-128" (Number) + EntryTerminator - (42..43): "\n" + "\n" (Newline) + Entry - (43..61): "test_u8: u8 = 255\n" + EntryKey - (43..50): "test_u8" + "test_u8" (Name) + ":" (Colon) + TypeExpr - (52..54): "u8" + "u8" (Name) + "=" (Eq) + EntryValue - (56..60): " 255" + Literal - (57..60): "255" + "255" (Number) + EntryTerminator - (60..61): "\n" + "\n" (Newline) + Entry - (61..84): "test_i16: i16 = -32768\n" + EntryKey - (61..69): "test_i16" + "test_i16" (Name) + ":" (Colon) + TypeExpr - (71..74): "i16" + "i16" (Name) + "=" (Eq) + EntryValue - (76..83): " -32768" + Literal - (77..83): "-32768" + "-32768" (Number) + EntryTerminator - (83..84): "\n" + "\n" (Newline) + Entry - (84..106): "test_u16: u16 = 65535\n" + EntryKey - (84..92): "test_u16" + "test_u16" (Name) + ":" (Colon) + TypeExpr - (94..97): "u16" + "u16" (Name) + "=" (Eq) + EntryValue - (99..105): " 65535" + Literal - (100..105): "65535" + "65535" (Number) + EntryTerminator - (105..106): "\n" + "\n" (Newline) + Entry - (106..134): "test_i32: i32 = -2147483648\n" + EntryKey - (106..114): "test_i32" + "test_i32" (Name) + ":" (Colon) + TypeExpr - (116..119): "i32" + "i32" (Name) + "=" (Eq) + EntryValue - (121..133): " -2147483648" + Literal - (122..133): "-2147483648" + "-2147483648" (Number) + EntryTerminator - (133..134): "\n" + "\n" (Newline) + Entry - (134..161): "test_u32: u32 = 4294967295\n" + EntryKey - (134..142): "test_u32" + "test_u32" (Name) + ":" (Colon) + TypeExpr - (144..147): "u32" + "u32" (Name) + "=" (Eq) + EntryValue - (149..160): " 4294967295" + Literal - (150..160): "4294967295" + "4294967295" (Number) + EntryTerminator - (160..161): "\n" + "\n" (Newline) + Entry - (161..185): "test_f32: f32 = 3.14159\n" + EntryKey - (161..169): "test_f32" + "test_f32" (Name) + ":" (Colon) + TypeExpr - (171..174): "f32" + "f32" (Name) + "=" (Eq) + EntryValue - (176..184): " 3.14159" + Literal - (177..184): "3.14159" + "3.14159" (Number) + EntryTerminator - (184..185): "\n" + "\n" (Newline) + Entry - (185..216): "test_vec2: vec2 = { 1.0, 2.0 }\n" + EntryKey - (185..194): "test_vec2" + "test_vec2" (Name) + ":" (Colon) + TypeExpr - (196..200): "vec2" + "vec2" (Name) + "=" (Eq) + EntryValue - (202..215): " { 1.0, 2.0 }" + Block - (203..215): "{ 1.0, 2.0 }" + "{" (LCurly) + ListItem - (204..208): " 1.0" + Literal - (205..208): "1.0" + "1.0" (Number) + "," (Comma) + ListItem - (209..213): " 2.0" + Literal - (210..213): "2.0" + "2.0" (Number) + "}" (RCurly) + EntryTerminator - (215..216): "\n" + "\n" (Newline) + Entry - (216..252): "test_vec3: vec3 = { 1.0, 2.0, 3.0 }\n" + EntryKey - (216..225): "test_vec3" + "test_vec3" (Name) + ":" (Colon) + TypeExpr - (227..231): "vec3" + "vec3" (Name) + "=" (Eq) + EntryValue - (233..251): " { 1.0, 2.0, 3.0 }" + Block - (234..251): "{ 1.0, 2.0, 3.0 }" + "{" (LCurly) + ListItem - (235..239): " 1.0" + Literal - (236..239): "1.0" + "1.0" (Number) + "," (Comma) + ListItem - (240..244): " 2.0" + Literal - (241..244): "2.0" + "2.0" (Number) + "," (Comma) + ListItem - (245..249): " 3.0" + Literal - (246..249): "3.0" + "3.0" (Number) + "}" (RCurly) + EntryTerminator - (251..252): "\n" + "\n" (Newline) + Entry - (252..293): "test_vec4: vec4 = { 1.0, 2.0, 3.0, 4.0 }\n" + EntryKey - (252..261): "test_vec4" + "test_vec4" (Name) + ":" (Colon) + TypeExpr - (263..267): "vec4" + "vec4" (Name) + "=" (Eq) + EntryValue - (269..292): " { 1.0, 2.0, 3.0, 4.0 }" + Block - (270..292): "{ 1.0, 2.0, 3.0, 4.0 }" + "{" (LCurly) + ListItem - (271..275): " 1.0" + Literal - (272..275): "1.0" + "1.0" (Number) + "," (Comma) + ListItem - (276..280): " 2.0" + Literal - (277..280): "2.0" + "2.0" (Number) + "," (Comma) + ListItem - (281..285): " 3.0" + Literal - (282..285): "3.0" + "3.0" (Number) + "," (Comma) + ListItem - (286..290): " 4.0" + Literal - (287..290): "4.0" + "4.0" (Number) + "}" (RCurly) + EntryTerminator - (292..293): "\n" + "\n" (Newline) + Entry - (293..333): "test_rgba: rgba = { 255, 128, 64, 255 }\n" + EntryKey - (293..302): "test_rgba" + "test_rgba" (Name) + ":" (Colon) + TypeExpr - (304..308): "rgba" + "rgba" (Name) + "=" (Eq) + EntryValue - (310..332): " { 255, 128, 64, 255 }" + Block - (311..332): "{ 255, 128, 64, 255 }" + "{" (LCurly) + ListItem - (312..316): " 255" + Literal - (313..316): "255" + "255" (Number) + "," (Comma) + ListItem - (317..321): " 128" + Literal - (318..321): "128" + "128" (Number) + "," (Comma) + ListItem - (322..325): " 64" + Literal - (323..325): "64" + "64" (Number) + "," (Comma) + ListItem - (326..330): " 255" + Literal - (327..330): "255" + "255" (Number) + "}" (RCurly) + EntryTerminator - (332..333): "\n" + "\n" (Newline) + Entry - (333..371): "test_string: string = \"Hello, World!\"\n" + EntryKey - (333..344): "test_string" + "test_string" (Name) + ":" (Colon) + TypeExpr - (346..352): "string" + "string" (Name) + "=" (Eq) + EntryValue - (354..370): " \"Hello, World!\"" + Literal - (355..370): "\"Hello, World!\"" + "\"Hello, World!\"" (String) + EntryTerminator - (370..371): "\n" + "\n" (Newline) + Entry - (371..400): "test_hash: hash = 0xdeadbeef\n" + EntryKey - (371..380): "test_hash" + "test_hash" (Name) + ":" (Colon) + TypeExpr - (382..386): "hash" + "hash" (Name) + "=" (Eq) + EntryValue - (388..399): " 0xdeadbeef" + Literal - (389..399): "0xdeadbeef" + "0xdeadbeef" (HexLit) + EntryTerminator - (399..400): "\n" + "\n" (Newline) + Entry - (400..435): "test_link: link = \"path/to/object\"\n" + EntryKey - (400..409): "test_link" + "test_link" (Name) + ":" (Colon) + TypeExpr - (411..415): "link" + "link" (Name) + "=" (Eq) + EntryValue - (417..434): " \"path/to/object\"" + Literal - (418..434): "\"path/to/object\"" + "\"path/to/object\"" (String) + EntryTerminator - (434..435): "\n" + "\n" (Newline) + Entry - (435..459): "test_flag: flag = false\n" + EntryKey - (435..444): "test_flag" + "test_flag" (Name) + ":" (Colon) + TypeExpr - (446..450): "flag" + "flag" (Name) + "=" (Eq) + EntryValue - (452..458): " false" + Literal - (453..458): "false" + "false" (False) + EntryTerminator - (458..459): "\n" + "\n" (Newline) diff --git a/crates/ltk_ritobin/tests/snapshots/parse_sample__tree_snapshot.snap b/crates/ltk_ritobin/tests/snapshots/parse_sample__tree_snapshot.snap new file mode 100644 index 00000000..a142b440 --- /dev/null +++ b/crates/ltk_ritobin/tests/snapshots/parse_sample__tree_snapshot.snap @@ -0,0 +1,62 @@ +--- +source: crates/ltk_ritobin/tests/parse_sample.rs +expression: debug +--- +File - (0..134): "\nentries: map[hash,embed] = {\n \"Test/Path\" = TestClass {\n 0xcb13aff1: f32 = -40\n normalName: string = \"test\"\n }\n}\n" + Entry - (0..134): "\nentries: map[hash,embed] = {\n \"Test/Path\" = TestClass {\n 0xcb13aff1: f32 = -40\n normalName: string = \"test\"\n }\n}\n" + EntryKey - (1..8): "entries" + "entries" (Name) + ":" (Colon) + TypeExpr - (10..25): "map[hash,embed]" + "map" (Name) + "[" (LBrack) + TypeArgList - (14..24): "hash,embed" + TypeArg - (14..18): "hash" + "hash" (Name) + "," (Comma) + TypeArg - (19..24): "embed" + "embed" (Name) + "]" (RBrack) + "=" (Eq) + EntryValue - (27..133): " {\n \"Test/Path\" = TestClass {\n 0xcb13aff1: f32 = -40\n normalName: string = \"test\"\n }\n}" + Block - (28..133): "{\n \"Test/Path\" = TestClass {\n 0xcb13aff1: f32 = -40\n normalName: string = \"test\"\n }\n}" + "{" (LCurly) + Entry - (29..132): "\n \"Test/Path\" = TestClass {\n 0xcb13aff1: f32 = -40\n normalName: string = \"test\"\n }\n" + EntryKey - (34..45): "\"Test/Path\"" + "\"Test/Path\"" (String) + "=" (Eq) + EntryValue - (47..131): " TestClass {\n 0xcb13aff1: f32 = -40\n normalName: string = \"test\"\n }" + Class - (48..131): "TestClass {\n 0xcb13aff1: f32 = -40\n normalName: string = \"test\"\n }" + "TestClass" (Name) + Block - (58..131): "{\n 0xcb13aff1: f32 = -40\n normalName: string = \"test\"\n }" + "{" (LCurly) + Entry - (59..98): "\n 0xcb13aff1: f32 = -40\n " + EntryKey - (68..78): "0xcb13aff1" + "0xcb13aff1" (HexLit) + ":" (Colon) + TypeExpr - (80..83): "f32" + "f32" (Name) + "=" (Eq) + EntryValue - (85..89): " -40" + Literal - (86..89): "-40" + "-40" (Number) + EntryTerminator - (89..98): "\n " + "\n " (Newline) + Entry - (98..130): "normalName: string = \"test\"\n " + EntryKey - (98..108): "normalName" + "normalName" (Name) + ":" (Colon) + TypeExpr - (110..116): "string" + "string" (Name) + "=" (Eq) + EntryValue - (118..125): " \"test\"" + Literal - (119..125): "\"test\"" + "\"test\"" (String) + EntryTerminator - (125..130): "\n " + "\n " (Newline) + "}" (RCurly) + EntryTerminator - (131..132): "\n" + "\n" (Newline) + "}" (RCurly) + EntryTerminator - (133..134): "\n" + "\n" (Newline) From f2c98e750725e2f94ce349357a1b406a56b32979 Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Thu, 19 Mar 2026 19:47:43 +0000 Subject: [PATCH 128/187] feat (typecheck): inject into Optionals --- crates/ltk_ritobin/src/typecheck/visitor.rs | 27 ++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/crates/ltk_ritobin/src/typecheck/visitor.rs b/crates/ltk_ritobin/src/typecheck/visitor.rs index 3c34eb2b..d86449ba 100644 --- a/crates/ltk_ritobin/src/typecheck/visitor.rs +++ b/crates/ltk_ritobin/src/typecheck/visitor.rs @@ -859,6 +859,31 @@ impl<'a> TypeChecker<'a> { } } } + PropertyValueEnum::Optional(option) => { + let IrItem::ListItem(IrListItem(child)) = child else { + eprintln!("\x1b[41moptional value must be list item\x1b[0m"); + return parent; + }; + if child.kind() != option.item_kind() { + self.ctx.diagnostics.push( + TypeMismatch { + span: *child.meta(), + expected: RitoType::simple(option.item_kind()), + expected_span: None, // TODO: would be nice here + got: child.rito_type().into(), + } + .unwrap(), + ); + return parent; + } + + *option = values::Optional::new_with_meta( + option.item_kind(), + Some(child), + *option.meta(), + ) + .unwrap(); + } other => { eprintln!("cant inject into {:?}", other.kind()) } @@ -1019,7 +1044,7 @@ impl Visitor for TypeChecker<'_> { use PropertyKind as K; match parent_type.base { - K::Container | K::UnorderedContainer => { + K::Container | K::UnorderedContainer | K::Optional => { let value_type = parent_type .value_subtype() .expect("container must have value_subtype"); From 3b70613deb2dc44bb80aca9033bcd4cba0775713 Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Thu, 19 Mar 2026 20:16:12 +0000 Subject: [PATCH 129/187] fix: cst builder public api --- crates/ltk_ritobin/src/cst/builder.rs | 62 +++++++++++++++++++-------- 1 file changed, 43 insertions(+), 19 deletions(-) diff --git a/crates/ltk_ritobin/src/cst/builder.rs b/crates/ltk_ritobin/src/cst/builder.rs index 0c650bca..e38bb0b9 100644 --- a/crates/ltk_ritobin/src/cst/builder.rs +++ b/crates/ltk_ritobin/src/cst/builder.rs @@ -7,10 +7,12 @@ use crate::{ kind_to_type_name, parse::{Span, Token, TokenKind as Tok}, typecheck::visitor::{PropertyValueExt, RitoType}, + HashProvider, }; -struct Builder { +pub struct Builder { buf: String, + hashes: H, } pub fn tree(kind: Kind, children: Vec) -> Child { @@ -28,12 +30,38 @@ pub fn token(kind: Tok) -> Child { }) } -impl Builder { - pub fn number(&mut self, v: impl AsRef) -> Child { +impl Builder<()> { + pub fn new() -> Self { + Self { + buf: String::new(), + hashes: (), + } + } +} + +impl Builder { + pub fn build(&mut self, bin: &Bin) -> Cst { + self.bin_to_cst(bin) + } + + /// Get a reference to the underlying text buffer all Cst's built by this builder reference in + /// their spans. + pub fn text_buffer(&self) -> &str { + &self.buf + } + /// Get the underlying text buffer all Cst's built by this builder reference in + /// their spans. + pub fn into_text_buffer(self) -> String { + self.buf + } +} + +impl Builder { + fn number(&mut self, v: impl AsRef) -> Child { tree(Kind::Literal, vec![self.spanned_token(Tok::Number, v)]) } - pub fn spanned_token(&mut self, kind: Tok, str: impl AsRef) -> Child { + fn spanned_token(&mut self, kind: Tok, str: impl AsRef) -> Child { let start = self.buf.len() as u32; self.buf.write_str(str.as_ref()).unwrap(); let end = self.buf.len() as u32; @@ -43,19 +71,19 @@ impl Builder { }) } - pub fn string(&mut self, v: impl AsRef) -> Child { + fn string(&mut self, v: impl AsRef) -> Child { self.spanned_token(Tok::String, v) } - pub fn name(&mut self, v: impl AsRef) -> Child { + fn name(&mut self, v: impl AsRef) -> Child { self.spanned_token(Tok::Name, v) } - pub fn hex_lit(&mut self, v: impl AsRef) -> Child { + fn hex_lit(&mut self, v: impl AsRef) -> Child { self.spanned_token(Tok::HexLit, v) } - pub fn block(&self, children: Vec) -> Child { + fn block(&self, children: Vec) -> Child { tree( Kind::Block, [vec![token(Tok::LCurly)], children, vec![token(Tok::RCurly)]].concat(), @@ -268,32 +296,28 @@ impl Builder { } } -pub fn bin_to_cst(bin: &Bin) -> (String, Cst) { - let mut builder = Builder { buf: String::new() }; - let cst = builder.bin_to_cst(bin); - - (builder.buf, cst) -} - #[cfg(test)] mod test { use ltk_meta::{property::values, Bin, BinObject}; - use crate::{cst::builder::bin_to_cst, parse::parse, print::CstPrinter}; + use super::*; + use crate::{parse::parse, print::CstPrinter}; fn roundtrip(bin: Bin) { println!("bin: {bin:#?}"); - let (buf, cst) = bin_to_cst(&bin); + let mut builder = Builder::new(); + let cst = builder.build(&bin); + let buf = builder.text_buffer(); let mut str = String::new(); - cst.print(&mut str, 0, &buf); + cst.print(&mut str, 0, buf); println!("cst:\n{str}"); let mut str = String::new(); - CstPrinter::new(&buf, &mut str, Default::default()) + CstPrinter::new(buf, &mut str, Default::default()) .print(&cst) .unwrap(); println!("RITOBIN:\n{str}"); From 82d254ee30545aae36ea94344e30aeb8080ed593 Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Thu, 19 Mar 2026 20:16:25 +0000 Subject: [PATCH 130/187] fix: support more types in cst builder --- crates/ltk_ritobin/src/cst/builder.rs | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/crates/ltk_ritobin/src/cst/builder.rs b/crates/ltk_ritobin/src/cst/builder.rs index e38bb0b9..8ef72385 100644 --- a/crates/ltk_ritobin/src/cst/builder.rs +++ b/crates/ltk_ritobin/src/cst/builder.rs @@ -90,12 +90,21 @@ impl Builder { ) } + fn bool(&self, v: bool) -> Child { + tree( + Kind::Literal, + vec![token(match v { + true => Tok::True, + false => Tok::False, + })], + ) + } + fn value_to_cst(&mut self, value: &PropertyValueEnum) -> Child { match value { - PropertyValueEnum::Bool(b) => tree( - Kind::Literal, - vec![token(if **b { Tok::True } else { Tok::False })], - ), + PropertyValueEnum::Bool(b) => self.bool(**b), + PropertyValueEnum::BitBool(b) => self.bool(**b), + PropertyValueEnum::None(_) => { tree(Kind::Literal, vec![token(Tok::LCurly), token(Tok::RCurly)]) } @@ -166,10 +175,8 @@ impl Builder { PropertyValueEnum::Color(color) => todo!(), PropertyValueEnum::Hash(hash) => todo!(), PropertyValueEnum::WadChunkLink(wad_chunk_link) => todo!(), - PropertyValueEnum::Struct(_) => todo!(), - PropertyValueEnum::Embedded(embedded) => { - let children = embedded - .0 + PropertyValueEnum::Embedded(values::Embedded(s)) | PropertyValueEnum::Struct(s) => { + let children = s .properties .iter() .map(|(k, v)| { @@ -182,7 +189,6 @@ impl Builder { tree(Kind::Class, vec![token(Tok::HexLit), self.block(children)]) } PropertyValueEnum::ObjectLink(object_link) => todo!(), - PropertyValueEnum::BitBool(bit_bool) => todo!(), PropertyValueEnum::Optional(optional) => { let children = match optional.clone().into_inner() { Some(v) => vec![self.value_to_cst(&v)], From 1faef683ce754b7a2c0f00ddeef773785dbaf24a Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Thu, 19 Mar 2026 20:16:43 +0000 Subject: [PATCH 131/187] fix: print impl --- crates/ltk_ritobin/src/print/printers.rs | 11 +++++++---- crates/ltk_ritobin/src/print/visitor.rs | 8 ++++++++ 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/crates/ltk_ritobin/src/print/printers.rs b/crates/ltk_ritobin/src/print/printers.rs index 1cbca3da..ef77bfa5 100644 --- a/crates/ltk_ritobin/src/print/printers.rs +++ b/crates/ltk_ritobin/src/print/printers.rs @@ -9,7 +9,7 @@ use ltk_meta::{ }; use crate::{ - cst::Cst, + cst::{self, Cst}, hashes::HashProvider, print::{PrintConfig, PrintError}, types::kind_to_type_name, @@ -26,14 +26,14 @@ impl<'a, W: Write, H: HashProvider> CstPrinter<'a, W, H> { } } - pub fn print(mut self, cst: &Cst) -> Result<(), PrintError> { + pub fn print(mut self, cst: &Cst) -> Result { cst.walk(&mut self.visitor); self.visitor.flush()?; if let Some(e) = self.visitor.error { return Err(e); } eprintln!("max q size: {}", self.visitor.queue_size_max); - Ok(()) + Ok(self.visitor.printed_bytes) } } @@ -64,7 +64,10 @@ impl BinPrinter { tree: &Bin, writer: &mut W, ) -> Result { - Ok(0) + let mut builder = cst::builder::Builder::new(); + let cst = builder.build(tree); + let buf = builder.into_text_buffer(); + CstPrinter::new(&buf, writer, Default::default()).print(&cst) } pub fn print_to_string(&mut self, tree: &Bin) -> Result { diff --git a/crates/ltk_ritobin/src/print/visitor.rs b/crates/ltk_ritobin/src/print/visitor.rs index 65897f0c..978cf647 100644 --- a/crates/ltk_ritobin/src/print/visitor.rs +++ b/crates/ltk_ritobin/src/print/visitor.rs @@ -36,6 +36,7 @@ pub struct CstVisitor<'a, W: Write, H: HashProvider> { col: usize, indent: usize, + pub printed_bytes: usize, printed: usize, pub queue: VecDeque>, pub queue_size_max: usize, @@ -62,6 +63,7 @@ impl<'a, W: Write, H: HashProvider> CstVisitor<'a, W, H> { col: 0, indent: 0, printed: 0, + printed_bytes: 0, queue: VecDeque::new(), queue_size_max: 0, modes: vec![Mode::Break], @@ -226,6 +228,7 @@ impl<'a, W: Write, H: HashProvider> CstVisitor<'a, W, H> { match cmd { Cmd::Text(s) => { self.out.write_str(s)?; + self.printed_bytes += s.len(); self.col += s.len(); self.block_space = false; self.block_line = false; @@ -233,6 +236,7 @@ impl<'a, W: Write, H: HashProvider> CstVisitor<'a, W, H> { Cmd::TextIf(s, mode) => { if *self.modes.last().unwrap() == mode { self.out.write_str(s)?; + self.printed_bytes += s.len(); self.col += s.len(); self.block_space = false; self.block_line = false; @@ -241,6 +245,7 @@ impl<'a, W: Write, H: HashProvider> CstVisitor<'a, W, H> { Cmd::Space => { if !self.block_space { self.out.write_char(' ')?; + self.printed_bytes += 1; self.col += 1; self.block_space = true; self.block_line = false; @@ -252,6 +257,7 @@ impl<'a, W: Write, H: HashProvider> CstVisitor<'a, W, H> { for _ in 0..self.indent { self.out.write_char(' ')?; } + self.printed_bytes += self.indent + 1; self.col = self.indent; self.propagate_break(); self.block_space = true; @@ -263,6 +269,7 @@ impl<'a, W: Write, H: HashProvider> CstVisitor<'a, W, H> { if !self.block_space { // eprintln!(" - not skipping -> space!"); self.out.write_char(' ')?; + self.printed_bytes += 1; self.col += 1; self.block_space = true; self.block_line = false; @@ -275,6 +282,7 @@ impl<'a, W: Write, H: HashProvider> CstVisitor<'a, W, H> { for _ in 0..self.indent { self.out.write_char(' ')?; } + self.printed_bytes += self.indent + 1; self.col = self.indent; self.propagate_break(); self.block_space = true; From 3e44f26d41d8375c4452bd0913e11d57830c73f2 Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Thu, 19 Mar 2026 20:17:03 +0000 Subject: [PATCH 132/187] fix (typecheck): coerce values when resolving entries --- crates/ltk_ritobin/src/typecheck/visitor.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/crates/ltk_ritobin/src/typecheck/visitor.rs b/crates/ltk_ritobin/src/typecheck/visitor.rs index d86449ba..7fca7615 100644 --- a/crates/ltk_ritobin/src/typecheck/visitor.rs +++ b/crates/ltk_ritobin/src/typecheck/visitor.rs @@ -708,7 +708,11 @@ pub fn resolve_entry( let kind = kind.or(parent_value_kind); - let resolved_val = resolve_value(ctx, value, kind.map(|k| k.base))?; + let resolved_val = + resolve_value(ctx, value, kind.map(|k| k.base))?.and_then(|value| match kind { + Some(kind) => coerce_type(value, kind.base), + None => Some(value), + }); let value = match (kind, resolved_val) { (None, Some(value)) => value, From 447577c62bda0ff25002519884c17cfc4f1a5b08 Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Thu, 19 Mar 2026 20:38:20 +0000 Subject: [PATCH 133/187] fix: coerce value types in lists --- crates/ltk_ritobin/src/typecheck/visitor.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/crates/ltk_ritobin/src/typecheck/visitor.rs b/crates/ltk_ritobin/src/typecheck/visitor.rs index 7fca7615..13d7b582 100644 --- a/crates/ltk_ritobin/src/typecheck/visitor.rs +++ b/crates/ltk_ritobin/src/typecheck/visitor.rs @@ -788,6 +788,7 @@ impl<'a> TypeChecker<'a> { | PropertyValueEnum::UnorderedContainer(values::UnorderedContainer(list)) => { match child { IrItem::ListItem(IrListItem(value)) => { + let value = coerce_type(value.clone(), list.item_kind()).unwrap_or(value); let span = *value.meta(); match list.push(value) { Ok(_) => {} @@ -1062,7 +1063,10 @@ impl Visitor for TypeChecker<'_> { )); } parent_type => { - eprintln!("[warn] got {parent_type:?} in ListItemBlock"); + eprintln!( + "[warn] got {parent_type:?} in ListItemBlock - {:?}", + &self.ctx.text[tree.span] + ); } } } From b62fdbcc7e4f12276e38475b1f9a5f67b35822d4 Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Thu, 19 Mar 2026 20:38:41 +0000 Subject: [PATCH 134/187] fix: cst builder struct/embedded building + other hash printing --- crates/ltk_ritobin/src/cst/builder.rs | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/crates/ltk_ritobin/src/cst/builder.rs b/crates/ltk_ritobin/src/cst/builder.rs index 8ef72385..ae0798ba 100644 --- a/crates/ltk_ritobin/src/cst/builder.rs +++ b/crates/ltk_ritobin/src/cst/builder.rs @@ -176,17 +176,13 @@ impl Builder { PropertyValueEnum::Hash(hash) => todo!(), PropertyValueEnum::WadChunkLink(wad_chunk_link) => todo!(), PropertyValueEnum::Embedded(values::Embedded(s)) | PropertyValueEnum::Struct(s) => { + let k = self.spanned_token(Tok::HexLit, format!("0x{:x}", s.class_hash)); let children = s .properties .iter() - .map(|(k, v)| { - let k = self.spanned_token(Tok::HexLit, k.to_string()); - let t = self.rito_type(v.value.rito_type()); - let v = self.property_to_cst(v); - self.entry(k, Some(t), v) - }) + .map(|(k, v)| self.property_to_cst(v)) .collect(); - tree(Kind::Class, vec![token(Tok::HexLit), self.block(children)]) + tree(Kind::Class, vec![k, self.block(children)]) } PropertyValueEnum::ObjectLink(object_link) => todo!(), PropertyValueEnum::Optional(optional) => { @@ -234,7 +230,7 @@ impl Builder { tree(Kind::TypeExpr, children) } fn property_to_cst(&mut self, prop: &BinProperty) -> Child { - let k = self.spanned_token(Tok::HexLit, prop.name_hash.to_string()); + let k = self.spanned_token(Tok::HexLit, format!("0x{:x}", prop.name_hash)); let t = self.rito_type(prop.value.rito_type()); let v = self.value_to_cst(&prop.value); self.entry(k, Some(t), v) From 88ad59c9dbe6e836101537260e8bce6d5884c0ff Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Thu, 19 Mar 2026 20:53:58 +0000 Subject: [PATCH 135/187] feat (print): only break nested lists if the parent list has >1 item --- crates/ltk_ritobin/src/print/visitor/impl.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/crates/ltk_ritobin/src/print/visitor/impl.rs b/crates/ltk_ritobin/src/print/visitor/impl.rs index b3a6f692..18420433 100644 --- a/crates/ltk_ritobin/src/print/visitor/impl.rs +++ b/crates/ltk_ritobin/src/print/visitor/impl.rs @@ -100,8 +100,10 @@ impl<'a, W: fmt::Write, H: HashProvider> CstVisitor<'a, W, H> { self.list_stack.pop(); // eprintln!("exit {} | stack: {}", tree.kind, self.list_stack.len()); if let Some(list) = self.list_stack.last() { - self.force_group(list.grp, Mode::Break); - self.softline(); + if list.len > 1 { + self.force_group(list.grp, Mode::Break); + self.softline(); + } } self.end_group(); } From e456cf7324bed83acc1fe7ad86a9ffbfc59991b7 Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Thu, 19 Mar 2026 20:54:08 +0000 Subject: [PATCH 136/187] fix (print): increase default line width -> 120 --- crates/ltk_ritobin/src/print/config.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/ltk_ritobin/src/print/config.rs b/crates/ltk_ritobin/src/print/config.rs index 216af9c3..610c454e 100644 --- a/crates/ltk_ritobin/src/print/config.rs +++ b/crates/ltk_ritobin/src/print/config.rs @@ -15,7 +15,7 @@ impl Default for PrintConfig<()> { fn default() -> Self { Self { indent_size: 4, - line_width: 80, + line_width: 120, hashes: (), } } From 0982b0ace15d6ac5ee8ec7fdbf3c11e1f9eccbbe Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Thu, 19 Mar 2026 20:54:18 +0000 Subject: [PATCH 137/187] fix: coerce map key values to the map key type --- crates/ltk_ritobin/src/typecheck/visitor.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/ltk_ritobin/src/typecheck/visitor.rs b/crates/ltk_ritobin/src/typecheck/visitor.rs index 13d7b582..fa97bc71 100644 --- a/crates/ltk_ritobin/src/typecheck/visitor.rs +++ b/crates/ltk_ritobin/src/typecheck/visitor.rs @@ -842,7 +842,7 @@ impl<'a> TypeChecker<'a> { return parent; }; let span = *value.meta(); - let Some(key) = coerce_type(key, PropertyKind::Hash) else { + let Some(key) = coerce_type(key, map_value.key_kind()) else { // eprintln!("\x1b[41m{other:?} not valid hash\x1b[0m"); return parent; }; From e6722ac804245b4743f2eef205450731825603fd Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Thu, 19 Mar 2026 21:24:28 +0000 Subject: [PATCH 138/187] fix: entry value coercion --- crates/ltk_ritobin/src/typecheck/visitor.rs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/crates/ltk_ritobin/src/typecheck/visitor.rs b/crates/ltk_ritobin/src/typecheck/visitor.rs index fa97bc71..7979b057 100644 --- a/crates/ltk_ritobin/src/typecheck/visitor.rs +++ b/crates/ltk_ritobin/src/typecheck/visitor.rs @@ -708,11 +708,10 @@ pub fn resolve_entry( let kind = kind.or(parent_value_kind); - let resolved_val = - resolve_value(ctx, value, kind.map(|k| k.base))?.and_then(|value| match kind { - Some(kind) => coerce_type(value, kind.base), - None => Some(value), - }); + let resolved_val = resolve_value(ctx, value, kind.map(|k| k.base))?.map(|value| match kind { + Some(kind) => coerce_type(value.clone(), kind.base).unwrap_or(value), + None => value, + }); let value = match (kind, resolved_val) { (None, Some(value)) => value, From 02cea0a792bc97504daf1166c7d380438b7578bc Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Thu, 19 Mar 2026 22:49:50 +0000 Subject: [PATCH 139/187] feat (typecheck): coerce to ObjectLink/WadChunkLink --- crates/ltk_ritobin/src/typecheck/visitor.rs | 25 +++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/crates/ltk_ritobin/src/typecheck/visitor.rs b/crates/ltk_ritobin/src/typecheck/visitor.rs index 7979b057..a604f29f 100644 --- a/crates/ltk_ritobin/src/typecheck/visitor.rs +++ b/crates/ltk_ritobin/src/typecheck/visitor.rs @@ -11,6 +11,7 @@ use ltk_meta::{ traits::PropertyExt, Bin, BinObject, PropertyKind, PropertyValueEnum, }; +use xxhash_rust::xxh64::xxh64; use crate::{ cst::{self, visitor::Visit, Child, Cst, Kind, Visitor}, @@ -394,6 +395,30 @@ pub fn coerce_type( return None; } }), + PropertyKind::ObjectLink => Some(match value { + PropertyValueEnum::Hash(hash) => { + values::ObjectLink::new_with_meta(*hash, hash.meta).into() + } + PropertyValueEnum::ObjectLink(_) => return Some(value), + PropertyValueEnum::String(str) => { + values::ObjectLink::new_with_meta(fnv1a::hash_lower(&str), str.meta).into() + } + other => { + eprintln!("\x1b[41mcannot coerce {other:?} to {to:?}\x1b[0m"); + return None; + } + }), + PropertyKind::WadChunkLink => Some(match value { + // FIXME: does the lexer give Hash when u64? if so we are cooked + PropertyValueEnum::WadChunkLink(_) => return Some(value), + PropertyValueEnum::String(str) => { + values::WadChunkLink::new_with_meta(xxh64(str.as_bytes(), 0), str.meta).into() + } + other => { + eprintln!("\x1b[41mcannot coerce {other:?} to {to:?}\x1b[0m"); + return None; + } + }), to if to == value.kind() => Some(value), _ => None, } From 5a1d516aec3fd87e68e14b3d5685db934d69edfa Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Thu, 19 Mar 2026 22:51:54 +0000 Subject: [PATCH 140/187] test: nicer assertion messages in roundtrip test --- crates/ltk_ritobin/tests/parse_sample.rs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/crates/ltk_ritobin/tests/parse_sample.rs b/crates/ltk_ritobin/tests/parse_sample.rs index d1b50365..5ce63b57 100644 --- a/crates/ltk_ritobin/tests/parse_sample.rs +++ b/crates/ltk_ritobin/tests/parse_sample.rs @@ -58,20 +58,27 @@ fn tree(input: &str) -> String { fn test_roundtrip() { let cst = parse(SAMPLE_RITOBIN); let (tree, errors) = cst.build_bin(SAMPLE_RITOBIN); - assert!(errors.is_empty()); + assert!(errors.is_empty(), "errors = {errors:#?}"); // Write back to text let output = tree.print().expect("Failed to write"); + println!("output:\n{output}"); + // Parse again let cst2 = parse(&output); + assert!( + cst2.errors.is_empty(), + "reparse errors = {:#?}", + cst2.errors + ); let mut str = String::new(); cst2.print(&mut str, 0, &output); println!("reparsed:\n{str}"); let (tree2, errors) = cst2.build_bin(&output); - // assert!(errors.is_empty()); + assert!(errors.is_empty(), "build bin errors = {errors:#?}"); // Verify structure is preserved assert_eq!(tree.version, tree2.version); From acca479b35bedd052b3333dec9f456a5bc4e49b3 Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Mon, 23 Mar 2026 17:15:39 +0000 Subject: [PATCH 141/187] fix: print visitor org --- crates/ltk_ritobin/src/print/printers.rs | 4 +- crates/ltk_ritobin/src/print/visitor.rs | 269 ++++++++++++++++-- crates/ltk_ritobin/src/print/visitor/impl.rs | 231 --------------- crates/ltk_ritobin/src/print/visitor/state.rs | 0 4 files changed, 252 insertions(+), 252 deletions(-) delete mode 100644 crates/ltk_ritobin/src/print/visitor/impl.rs delete mode 100644 crates/ltk_ritobin/src/print/visitor/state.rs diff --git a/crates/ltk_ritobin/src/print/printers.rs b/crates/ltk_ritobin/src/print/printers.rs index ef77bfa5..d71dd506 100644 --- a/crates/ltk_ritobin/src/print/printers.rs +++ b/crates/ltk_ritobin/src/print/printers.rs @@ -32,8 +32,8 @@ impl<'a, W: Write, H: HashProvider> CstPrinter<'a, W, H> { if let Some(e) = self.visitor.error { return Err(e); } - eprintln!("max q size: {}", self.visitor.queue_size_max); - Ok(self.visitor.printed_bytes) + eprintln!("max q size: {}", self.visitor.queue_size_max()); + Ok(self.visitor.printed_bytes()) } } diff --git a/crates/ltk_ritobin/src/print/visitor.rs b/crates/ltk_ritobin/src/print/visitor.rs index 978cf647..ce337a51 100644 --- a/crates/ltk_ritobin/src/print/visitor.rs +++ b/crates/ltk_ritobin/src/print/visitor.rs @@ -13,9 +13,6 @@ use crate::{ HashProvider, }; -mod r#impl; -pub mod state; - #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] pub struct GroupId(usize); @@ -36,10 +33,10 @@ pub struct CstVisitor<'a, W: Write, H: HashProvider> { col: usize, indent: usize, - pub printed_bytes: usize, - printed: usize, - pub queue: VecDeque>, - pub queue_size_max: usize, + printed_bytes: usize, + printed_commands: usize, + queue: VecDeque>, + queue_size_max: usize, modes: Vec, /// group start indices @@ -54,6 +51,26 @@ pub struct CstVisitor<'a, W: Write, H: HashProvider> { block_line: bool, } +impl<'a, W: Write, H: HashProvider> CstVisitor<'a, W, H> { + #[inline(always)] + #[must_use] + pub fn queue_size_max(&self) -> usize { + self.queue_size_max + } + + #[inline(always)] + #[must_use] + pub fn printed_bytes(&self) -> usize { + self.printed_bytes + } + + #[inline(always)] + #[must_use] + pub fn printed_commands(&self) -> usize { + self.printed_commands + } +} + impl<'a, W: Write, H: HashProvider> CstVisitor<'a, W, H> { pub fn new(src: &'a str, out: W, config: PrintConfig) -> Self { Self { @@ -62,7 +79,7 @@ impl<'a, W: Write, H: HashProvider> CstVisitor<'a, W, H> { config, col: 0, indent: 0, - printed: 0, + printed_commands: 0, printed_bytes: 0, queue: VecDeque::new(), queue_size_max: 0, @@ -110,7 +127,7 @@ impl<'a, W: Write, H: HashProvider> CstVisitor<'a, W, H> { } pub fn line(&mut self) { - if self.queue.is_empty() && self.printed == 0 { + if self.queue.is_empty() && self.printed_commands == 0 { return; } if self.queue.back().is_some_and(|c| c.is_whitespace()) { @@ -120,7 +137,7 @@ impl<'a, W: Write, H: HashProvider> CstVisitor<'a, W, H> { self.push(Cmd::Line); } pub fn softline(&mut self) { - if self.queue.is_empty() && self.printed == 0 { + if self.queue.is_empty() && self.printed_commands == 0 { return; } if self.queue.back().is_some_and(|c| c.is_whitespace()) { @@ -131,7 +148,7 @@ impl<'a, W: Write, H: HashProvider> CstVisitor<'a, W, H> { } pub fn begin_group(&mut self, mode: Option) -> GroupId { - let idx = self.queue.len() + self.printed; + let idx = self.queue.len() + self.printed_commands; self.push(Cmd::Begin(mode)); @@ -212,12 +229,12 @@ impl<'a, W: Write, H: HashProvider> CstVisitor<'a, W, H> { } pub fn force_group(&mut self, group: GroupId, mode: Mode) { - if group.0 < self.printed { + if group.0 < self.printed_commands { // eprintln!("[!!] trying to mutate already printed group! {group:?}"); return; // panic!("trying to mutate already printed group!"); } - let cmd = self.queue.get_mut(group.0 - self.printed).unwrap(); + let cmd = self.queue.get_mut(group.0 - self.printed_commands).unwrap(); let Cmd::Begin(grp_mode) = cmd else { unreachable!("grp pointing at non begin cmd {cmd:?}"); }; @@ -319,7 +336,7 @@ impl<'a, W: Write, H: HashProvider> CstVisitor<'a, W, H> { pub fn flush(&mut self) -> fmt::Result { // eprintln!("###### FLUSH ##"); while let Some(cmd) = self.queue.pop_front() { - self.printed += 1; + self.printed_commands += 1; self.print(cmd)?; // eprintln!("- {cmd:?}"); } @@ -332,17 +349,17 @@ impl<'a, W: Write, H: HashProvider> CstVisitor<'a, W, H> { .group_stack .first() .copied() - .unwrap_or(self.queue.len() + self.printed); + .unwrap_or(self.queue.len() + self.printed_commands); - if limit > self.printed { - let count = limit - self.printed; + if limit > self.printed_commands { + let count = limit - self.printed_commands; // eprintln!("[printer] printing {count}..."); } - while self.printed < limit { + while self.printed_commands < limit { let cmd = self.queue.pop_front().unwrap(); // eprintln!("- {cmd:?}"); - self.printed += 1; + self.printed_commands += 1; self.print(cmd)?; } Ok(()) @@ -357,4 +374,218 @@ impl<'a, W: Write, H: HashProvider> CstVisitor<'a, W, H> { } } } + + fn enter_tree_inner(&mut self, tree: &Cst) -> Result<(), PrintError> { + match tree.kind { + Kind::TypeArgList => { + let grp = self.begin_group(Some(Mode::Flat)); + // eprintln!("{:#?}", tree.children); + self.list_stack.push(ListContext { + len: tree + .children + .iter() + .filter(|n| n.tree().is_some_and(|t| t.kind == Kind::TypeArg)) + .count() + .try_into() + .unwrap(), + idx: 0, + grp, + }); + } + Kind::ListItemBlock => { + self.softline(); + let grp = self.begin_group(None); + + let len = tree + .children + .iter() + .filter(|n| n.tree().is_some_and(|t| t.kind == Kind::ListItem)) + .count(); + if len > 0 { + self.list_stack.push(ListContext { + len: len.try_into().unwrap(), + idx: 0, + grp, + }); + } + } + Kind::Block => { + // eprintln!("BLOCK: {:#?}", tree.children); + let grp = self.begin_group(None); + let len = tree + .children + .iter() + .filter(|n| { + n.tree() + .is_some_and(|t| matches!(t.kind, Kind::ListItem | Kind::ListItemBlock)) + }) + .count(); + if len > 0 { + self.list_stack.push(ListContext { + len: len.try_into().unwrap(), + idx: 0, + grp, + }); + } + } + Kind::Class => {} + Kind::ListItem => { + if tree + .children + .first() + .is_some_and(|c| c.tree().is_some_and(|t| t.kind == Kind::Class)) + { + if let Some(list) = self.list_stack.last() { + self.force_group(list.grp, Mode::Break); + } + } + self.softline(); + } + Kind::Entry => { + self.line(); + // self.flush().unwrap(); + } + _ => {} + } + Ok(()) + } + + fn exit_tree_inner(&mut self, tree: &Cst) -> Result<(), PrintError> { + match tree.kind { + Kind::TypeArgList => { + self.list_stack.pop(); + self.end_group(); + } + Kind::ListItemBlock | Kind::Block => { + self.list_stack.pop(); + // eprintln!("exit {} | stack: {}", tree.kind, self.list_stack.len()); + if let Some(list) = self.list_stack.last() { + if list.len > 1 { + self.force_group(list.grp, Mode::Break); + self.softline(); + } + } + self.end_group(); + } + Kind::ListItem | Kind::TypeArg => { + if let Some(ctx) = self.list_stack.last() { + let last_item = ctx.idx + 1 == ctx.len; + + if !last_item { + self.text_if(",", Mode::Flat); + self.space(); + if tree.kind == Kind::ListItem { + self.softline(); + } + } + + self.list_stack.last_mut().unwrap(/* guaranteed by if let */).idx += 1; + } + } + _ => {} + } + Ok(()) + } + + fn visit_token_inner( + &mut self, + token: &crate::parse::Token, + context: &Cst, + ) -> Result<(), PrintError> { + let txt = self.src[token.span].trim(); + let print_value = token.kind.print_value(); + + if txt.is_empty() && print_value.is_none() { + return Ok(()); + } + + // eprintln!("->{:?}", token.kind); + match token.kind { + TokenKind::LCurly => { + self.space(); + self.text("{"); + self.indent(4); + self.space(); + // self.softline(); + } + + TokenKind::RCurly => { + self.dedent(4); + self.softline(); + self.text("}"); + } + + TokenKind::Comma => { + // self.text_if(",", Mode::Flat); + // self.softline(); + } + TokenKind::Colon => { + self.text(":"); + self.space(); + } + + TokenKind::Eq => { + self.space(); + self.text("="); + self.space(); + } + + TokenKind::LBrack => { + self.text("["); + } + TokenKind::RBrack => { + self.text("]"); + } + TokenKind::Quote => { + self.text("\""); + } + TokenKind::False => { + self.text("false"); + } + TokenKind::True => { + self.text("true"); + } + + _ => { + if let Some(print) = print_value { + self.text(print); + } else { + self.text(txt); + } + } + } + self.print_safe()?; + // self.flush()?; + Ok(()) + } +} + +impl<'a, W: fmt::Write, H: HashProvider> Visitor for CstVisitor<'a, W, H> { + fn enter_tree(&mut self, tree: &Cst) -> Visit { + match self.enter_tree_inner(tree) { + Ok(_) => Visit::Continue, + Err(e) => { + self.error.replace(e); + Visit::Stop + } + } + } + fn exit_tree(&mut self, tree: &Cst) -> Visit { + match self.exit_tree_inner(tree) { + Ok(_) => Visit::Continue, + Err(e) => { + self.error.replace(e); + Visit::Stop + } + } + } + fn visit_token(&mut self, token: &crate::parse::Token, context: &crate::cst::Cst) -> Visit { + match self.visit_token_inner(token, context) { + Ok(_) => Visit::Continue, + Err(e) => { + self.error.replace(e); + Visit::Stop + } + } + } } diff --git a/crates/ltk_ritobin/src/print/visitor/impl.rs b/crates/ltk_ritobin/src/print/visitor/impl.rs deleted file mode 100644 index 18420433..00000000 --- a/crates/ltk_ritobin/src/print/visitor/impl.rs +++ /dev/null @@ -1,231 +0,0 @@ -use std::{ - collections::VecDeque, - fmt::{self, Write}, -}; - -use crate::{ - cst::{visitor::Visit, Cst, Kind, Visitor}, - parse::TokenKind, - print::{ - command::Mode, - visitor::{CstVisitor, ListContext}, - PrintConfig, PrintError, - }, - HashProvider, -}; - -impl<'a, W: fmt::Write, H: HashProvider> CstVisitor<'a, W, H> { - fn enter_tree_inner(&mut self, tree: &Cst) -> Result<(), PrintError> { - match tree.kind { - Kind::TypeArgList => { - let grp = self.begin_group(Some(Mode::Flat)); - // eprintln!("{:#?}", tree.children); - self.list_stack.push(ListContext { - len: tree - .children - .iter() - .filter(|n| n.tree().is_some_and(|t| t.kind == Kind::TypeArg)) - .count() - .try_into() - .unwrap(), - idx: 0, - grp, - }); - } - Kind::ListItemBlock => { - self.softline(); - let grp = self.begin_group(None); - - let len = tree - .children - .iter() - .filter(|n| n.tree().is_some_and(|t| t.kind == Kind::ListItem)) - .count(); - if len > 0 { - self.list_stack.push(ListContext { - len: len.try_into().unwrap(), - idx: 0, - grp, - }); - } - } - Kind::Block => { - // eprintln!("BLOCK: {:#?}", tree.children); - let grp = self.begin_group(None); - let len = tree - .children - .iter() - .filter(|n| { - n.tree() - .is_some_and(|t| matches!(t.kind, Kind::ListItem | Kind::ListItemBlock)) - }) - .count(); - if len > 0 { - self.list_stack.push(ListContext { - len: len.try_into().unwrap(), - idx: 0, - grp, - }); - } - } - Kind::Class => {} - Kind::ListItem => { - if tree - .children - .first() - .is_some_and(|c| c.tree().is_some_and(|t| t.kind == Kind::Class)) - { - if let Some(list) = self.list_stack.last() { - self.force_group(list.grp, Mode::Break); - } - } - self.softline(); - } - Kind::Entry => { - self.line(); - // self.flush().unwrap(); - } - _ => {} - } - Ok(()) - } - - fn exit_tree_inner(&mut self, tree: &Cst) -> Result<(), PrintError> { - match tree.kind { - Kind::TypeArgList => { - self.list_stack.pop(); - self.end_group(); - } - Kind::ListItemBlock | Kind::Block => { - self.list_stack.pop(); - // eprintln!("exit {} | stack: {}", tree.kind, self.list_stack.len()); - if let Some(list) = self.list_stack.last() { - if list.len > 1 { - self.force_group(list.grp, Mode::Break); - self.softline(); - } - } - self.end_group(); - } - Kind::ListItem | Kind::TypeArg => { - if let Some(ctx) = self.list_stack.last() { - let last_item = ctx.idx + 1 == ctx.len; - - if !last_item { - self.text_if(",", Mode::Flat); - self.space(); - if tree.kind == Kind::ListItem { - self.softline(); - } - } - - self.list_stack.last_mut().unwrap(/* guaranteed by if let */).idx += 1; - } - } - _ => {} - } - Ok(()) - } - - fn visit_token_inner( - &mut self, - token: &crate::parse::Token, - context: &Cst, - ) -> Result<(), PrintError> { - let txt = self.src[token.span].trim(); - let print_value = token.kind.print_value(); - - if txt.is_empty() && print_value.is_none() { - return Ok(()); - } - - // eprintln!("->{:?}", token.kind); - match token.kind { - TokenKind::LCurly => { - self.space(); - self.text("{"); - self.indent(4); - self.space(); - // self.softline(); - } - - TokenKind::RCurly => { - self.dedent(4); - self.softline(); - self.text("}"); - } - - TokenKind::Comma => { - // self.text_if(",", Mode::Flat); - // self.softline(); - } - TokenKind::Colon => { - self.text(":"); - self.space(); - } - - TokenKind::Eq => { - self.space(); - self.text("="); - self.space(); - } - - TokenKind::LBrack => { - self.text("["); - } - TokenKind::RBrack => { - self.text("]"); - } - TokenKind::Quote => { - self.text("\""); - } - TokenKind::False => { - self.text("false"); - } - TokenKind::True => { - self.text("true"); - } - - _ => { - if let Some(print) = print_value { - self.text(print); - } else { - self.text(txt); - } - } - } - self.print_safe()?; - // self.flush()?; - Ok(()) - } -} - -impl<'a, W: fmt::Write, H: HashProvider> Visitor for CstVisitor<'a, W, H> { - fn enter_tree(&mut self, tree: &Cst) -> Visit { - match self.enter_tree_inner(tree) { - Ok(_) => Visit::Continue, - Err(e) => { - self.error.replace(e); - Visit::Stop - } - } - } - fn exit_tree(&mut self, tree: &Cst) -> Visit { - match self.exit_tree_inner(tree) { - Ok(_) => Visit::Continue, - Err(e) => { - self.error.replace(e); - Visit::Stop - } - } - } - fn visit_token(&mut self, token: &crate::parse::Token, context: &crate::cst::Cst) -> Visit { - match self.visit_token_inner(token, context) { - Ok(_) => Visit::Continue, - Err(e) => { - self.error.replace(e); - Visit::Stop - } - } - } -} diff --git a/crates/ltk_ritobin/src/print/visitor/state.rs b/crates/ltk_ritobin/src/print/visitor/state.rs deleted file mode 100644 index e69de29b..00000000 From 143e80f528a8f6cf1ff933cbfa25356e63ecd071 Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Mon, 23 Mar 2026 17:15:47 +0000 Subject: [PATCH 142/187] chore: fmt --- crates/ltk_ritobin/src/parse.rs | 7 +++---- crates/ltk_ritobin/src/print.rs | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/crates/ltk_ritobin/src/parse.rs b/crates/ltk_ritobin/src/parse.rs index 1bc338de..9caa4d82 100644 --- a/crates/ltk_ritobin/src/parse.rs +++ b/crates/ltk_ritobin/src/parse.rs @@ -30,10 +30,9 @@ mod test { #[test] fn smoke_test() { let text = r#" -entries: map[hash,embed] = { - "myPath" = VfxEmitter { - a: string = "hello" - b: list[i8] = {3 6 1} +entries: map[hash, embed] = { + "foo" = Foo { + guy: u32 = "asdasd" } } "#; diff --git a/crates/ltk_ritobin/src/print.rs b/crates/ltk_ritobin/src/print.rs index 27d7d3d6..53e81fc0 100644 --- a/crates/ltk_ritobin/src/print.rs +++ b/crates/ltk_ritobin/src/print.rs @@ -179,7 +179,7 @@ linked: list[string] = { "DATA/Characters/Viego/Viego.bin" }"#, r#"BorderAugments: list2[embed] = { 0x4a70b12c { - AugmentGroup: list2[link] = { 0x383e4602 } + AugmentGroup: list2[link] = { 0x383e4602 } } }"#, 80, From 3da463e961eeff6d1348c51f68249c46faa06bc1 Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Mon, 23 Mar 2026 17:17:22 +0000 Subject: [PATCH 143/187] chore: cargo fix --- crates/ltk_ritobin/src/cst/builder.rs | 12 ++++++------ crates/ltk_ritobin/src/parse/real.rs | 5 ----- crates/ltk_ritobin/src/print.rs | 14 -------------- crates/ltk_ritobin/src/print/printers.rs | 9 +-------- crates/ltk_ritobin/src/print/visitor.rs | 10 +--------- crates/ltk_ritobin/src/typecheck/visitor.rs | 21 ++++++--------------- 6 files changed, 14 insertions(+), 57 deletions(-) diff --git a/crates/ltk_ritobin/src/cst/builder.rs b/crates/ltk_ritobin/src/cst/builder.rs index ae0798ba..c06920bc 100644 --- a/crates/ltk_ritobin/src/cst/builder.rs +++ b/crates/ltk_ritobin/src/cst/builder.rs @@ -172,19 +172,19 @@ impl Builder { children.push(token(Tok::RCurly)); tree(Kind::TypeArgList, children) } - PropertyValueEnum::Color(color) => todo!(), - PropertyValueEnum::Hash(hash) => todo!(), - PropertyValueEnum::WadChunkLink(wad_chunk_link) => todo!(), + PropertyValueEnum::Color(_color) => todo!(), + PropertyValueEnum::Hash(_hash) => todo!(), + PropertyValueEnum::WadChunkLink(_wad_chunk_link) => todo!(), PropertyValueEnum::Embedded(values::Embedded(s)) | PropertyValueEnum::Struct(s) => { let k = self.spanned_token(Tok::HexLit, format!("0x{:x}", s.class_hash)); let children = s .properties .iter() - .map(|(k, v)| self.property_to_cst(v)) + .map(|(_k, v)| self.property_to_cst(v)) .collect(); tree(Kind::Class, vec![k, self.block(children)]) } - PropertyValueEnum::ObjectLink(object_link) => todo!(), + PropertyValueEnum::ObjectLink(_object_link) => todo!(), PropertyValueEnum::Optional(optional) => { let children = match optional.clone().into_inner() { Some(v) => vec![self.value_to_cst(&v)], @@ -192,7 +192,7 @@ impl Builder { }; self.block(children) } - PropertyValueEnum::Map(map) => todo!(), + PropertyValueEnum::Map(_map) => todo!(), } } diff --git a/crates/ltk_ritobin/src/parse/real.rs b/crates/ltk_ritobin/src/parse/real.rs index c72fbe76..d1b511ac 100644 --- a/crates/ltk_ritobin/src/parse/real.rs +++ b/crates/ltk_ritobin/src/parse/real.rs @@ -1,8 +1,3 @@ -use std::{ - cell::Cell, - fmt::{self, Display}, - sync::{Arc, Mutex}, -}; #[salsa::db] #[derive(Clone)] diff --git a/crates/ltk_ritobin/src/print.rs b/crates/ltk_ritobin/src/print.rs index 53e81fc0..c0ec31ef 100644 --- a/crates/ltk_ritobin/src/print.rs +++ b/crates/ltk_ritobin/src/print.rs @@ -19,20 +19,6 @@ pub use config::*; mod printers; pub use printers::*; -// pub fn print_bin(bin: &Bin, width: usize) -> Result { -// let mut str = String::new(); -// -// let (buf, cst) = bin_to_cst(bin); -// -// let mut tmp = String::new(); -// cst.print(&mut tmp, 0, &buf); -// println!("[print] cst:\n{tmp}"); -// -// Printer::new(&buf, &mut str, width).print(&cst)?; -// -// Ok(str) -// } - pub trait Print { /// Print as ritobin code to the given writer (using default config, which prints hashes as hex). fn print_to_writer(&self, writer: &mut W) -> Result { diff --git a/crates/ltk_ritobin/src/print/printers.rs b/crates/ltk_ritobin/src/print/printers.rs index d71dd506..664e0bd6 100644 --- a/crates/ltk_ritobin/src/print/printers.rs +++ b/crates/ltk_ritobin/src/print/printers.rs @@ -1,18 +1,11 @@ use std::fmt::{self, Write}; -use ltk_meta::{ - property::{ - values::{Embedded, Struct, UnorderedContainer}, - PropertyValueEnum, - }, - Bin, BinObject, BinProperty, -}; +use ltk_meta::Bin; use crate::{ cst::{self, Cst}, hashes::HashProvider, print::{PrintConfig, PrintError}, - types::kind_to_type_name, }; pub struct CstPrinter<'a, W: Write, H: HashProvider> { diff --git a/crates/ltk_ritobin/src/print/visitor.rs b/crates/ltk_ritobin/src/print/visitor.rs index ce337a51..7ed643e1 100644 --- a/crates/ltk_ritobin/src/print/visitor.rs +++ b/crates/ltk_ritobin/src/print/visitor.rs @@ -327,8 +327,6 @@ impl<'a, W: Write, H: HashProvider> CstVisitor<'a, W, H> { Cmd::Dedent(n) => { self.indent = self.indent.saturating_sub(n); } - - _ => {} } Ok(()) } @@ -351,14 +349,8 @@ impl<'a, W: Write, H: HashProvider> CstVisitor<'a, W, H> { .copied() .unwrap_or(self.queue.len() + self.printed_commands); - if limit > self.printed_commands { - let count = limit - self.printed_commands; - // eprintln!("[printer] printing {count}..."); - } - while self.printed_commands < limit { let cmd = self.queue.pop_front().unwrap(); - // eprintln!("- {cmd:?}"); self.printed_commands += 1; self.print(cmd)?; } @@ -490,7 +482,7 @@ impl<'a, W: Write, H: HashProvider> CstVisitor<'a, W, H> { fn visit_token_inner( &mut self, token: &crate::parse::Token, - context: &Cst, + _context: &Cst, ) -> Result<(), PrintError> { let txt = self.src[token.span].trim(); let print_value = token.kind.print_value(); diff --git a/crates/ltk_ritobin/src/typecheck/visitor.rs b/crates/ltk_ritobin/src/typecheck/visitor.rs index a604f29f..471fd9a9 100644 --- a/crates/ltk_ritobin/src/typecheck/visitor.rs +++ b/crates/ltk_ritobin/src/typecheck/visitor.rs @@ -1,15 +1,10 @@ -use std::{ - fmt::{Debug, Display}, - ops::{Deref, DerefMut}, -}; +use std::fmt::{Debug, Display}; use glam::Vec4; use indexmap::IndexMap; use ltk_hash::fnv1a; use ltk_meta::{ - property::{values, NoMeta}, - traits::PropertyExt, - Bin, BinObject, PropertyKind, PropertyValueEnum, + property::values, traits::PropertyExt, Bin, BinObject, PropertyKind, PropertyValueEnum, }; use xxhash_rust::xxh64::xxh64; @@ -759,10 +754,6 @@ pub fn resolve_entry( Ok(IrEntry { key, value }) } -pub fn resolve_list(ctx: &mut Ctx, tree: &Cst) -> Result<(), Diagnostic> { - Ok(()) -} - impl<'a> TypeChecker<'a> { pub fn collect_to_bin(mut self) -> (Bin, Vec) { let objects = self @@ -827,12 +818,12 @@ impl<'a> TypeChecker<'a> { .unwrap(), ); } - Err(e) => { + Err(_e) => { todo!("handle unexpected error"); } } } - IrItem::Entry(IrEntry { key, value }) => { + IrItem::Entry(IrEntry { key: _, value: _ }) => { eprintln!("\x1b[41mlist item must be list item\x1b[0m"); return parent; } @@ -859,7 +850,7 @@ impl<'a> TypeChecker<'a> { }, ); } - PropertyValueEnum::ObjectLink(object_link_value) => todo!(), + PropertyValueEnum::ObjectLink(_object_link_value) => todo!(), PropertyValueEnum::Map(map_value) => { let IrItem::Entry(IrEntry { key, value }) = child else { eprintln!("map item must be entry"); @@ -883,7 +874,7 @@ impl<'a> TypeChecker<'a> { .unwrap(), ); } - Err(e) => { + Err(_e) => { todo!("handle unexpected err"); } } From 35a7ef0ba710ec94f38163c1b01efbf4b3e1ef4a Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Mon, 23 Mar 2026 17:21:13 +0000 Subject: [PATCH 144/187] fix: remove garbage --- crates/ltk_ritobin/src/parse.rs | 1 - crates/ltk_ritobin/src/parse/real.rs | 114 --------------------------- 2 files changed, 115 deletions(-) delete mode 100644 crates/ltk_ritobin/src/parse/real.rs diff --git a/crates/ltk_ritobin/src/parse.rs b/crates/ltk_ritobin/src/parse.rs index 9caa4d82..cbf51055 100644 --- a/crates/ltk_ritobin/src/parse.rs +++ b/crates/ltk_ritobin/src/parse.rs @@ -4,7 +4,6 @@ pub mod error; pub use error::*; pub mod parser; -pub mod real; pub mod tokenizer; pub use tokenizer::{Token, TokenKind}; diff --git a/crates/ltk_ritobin/src/parse/real.rs b/crates/ltk_ritobin/src/parse/real.rs deleted file mode 100644 index d1b511ac..00000000 --- a/crates/ltk_ritobin/src/parse/real.rs +++ /dev/null @@ -1,114 +0,0 @@ - -#[salsa::db] -#[derive(Clone)] -#[cfg_attr(not(test), derive(Default))] -pub struct CalcDatabaseImpl { - storage: salsa::Storage, - - // The logs are only used for testing and demonstrating reuse: - #[cfg(test)] - logs: Arc>>>, -} - -#[cfg(test)] -impl Default for CalcDatabaseImpl { - fn default() -> Self { - let logs = >>>>::default(); - Self { - storage: salsa::Storage::new(Some(Box::new({ - let logs = logs.clone(); - move |event| { - eprintln!("Event: {event:?}"); - // Log interesting events, if logging is enabled - if let Some(logs) = &mut *logs.lock().unwrap() { - // only log interesting events - if let salsa::EventKind::WillExecute { .. } = event.kind { - logs.push(format!("Event: {event:?}")); - } - } - } - }))), - logs, - } - } -} - -#[salsa::db] -impl salsa::Database for CalcDatabaseImpl {} - -#[salsa::input(debug)] -pub struct SourceProgram { - #[returns(ref)] - pub text: String, -} - -#[salsa::tracked(debug)] -pub struct RitobinFile<'db> { - #[tracked] - #[returns(ref)] - pub statements: Vec>, -} - -#[salsa::interned(debug)] -pub struct PropertyName<'db> { - #[returns(ref)] - pub text: String, -} - -#[derive(PartialEq, Debug, Hash, salsa::Update)] -pub struct Statement<'db> { - pub span: Span<'db>, - pub name: PropertyName<'db>, - pub value: BinProperty, -} - -#[salsa::accumulator] -#[derive(Debug)] -#[allow(dead_code)] // Debug impl uses them -pub struct Diagnostic { - pub start: usize, - pub end: usize, - pub message: String, -} -impl Diagnostic { - pub fn new(start: usize, end: usize, message: String) -> Self { - Diagnostic { - start, - end, - message, - } - } - - // #[cfg(test)] - // pub fn render(&self, db: &dyn crate::Db, src: SourceProgram) -> String { - // use annotate_snippets::*; - // let line_start = src.text(db)[..self.start].lines().count() + 1; - // Renderer::plain() - // .render( - // Level::Error.title(&self.message).snippet( - // Snippet::source(src.text(db)) - // .line_start(line_start) - // .origin("input") - // .fold(true) - // .annotation(Level::Error.span(self.start..self.end).label("here")), - // ), - // ) - // .to_string() - // } -} - -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] -#[derive(Clone, PartialEq, Debug, Hash, salsa::Update)] -pub struct BinProperty { - pub name_hash: u32, - #[cfg_attr(feature = "serde", serde(flatten))] - pub value: ltk_meta::PropertyValueEnum, -} - -#[salsa::tracked(debug)] -pub struct Span<'db> { - #[tracked] - pub start: usize, - #[tracked] - pub end: usize, -} From ad0f21d8dcaa791b8694ae0dab386031d4cc30a5 Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Mon, 23 Mar 2026 18:05:28 +0000 Subject: [PATCH 145/187] fix: remove hashprovider from cst printer --- crates/ltk_ritobin/src/cst/builder.rs | 16 ++++++++++------ crates/ltk_ritobin/src/print.rs | 6 +++--- crates/ltk_ritobin/src/print/printers.rs | 20 +++++++++++++------- crates/ltk_ritobin/src/print/visitor.rs | 13 ++++++------- 4 files changed, 32 insertions(+), 23 deletions(-) diff --git a/crates/ltk_ritobin/src/cst/builder.rs b/crates/ltk_ritobin/src/cst/builder.rs index c06920bc..b19cdc7c 100644 --- a/crates/ltk_ritobin/src/cst/builder.rs +++ b/crates/ltk_ritobin/src/cst/builder.rs @@ -30,16 +30,20 @@ pub fn token(kind: Tok) -> Child { }) } -impl Builder<()> { - pub fn new() -> Self { +impl Default for Builder<()> { + fn default() -> Self { + Self::new(()) + } +} + +impl Builder { + pub fn new(hashes: H) -> Self { Self { buf: String::new(), - hashes: (), + hashes, } } -} -impl Builder { pub fn build(&mut self, bin: &Bin) -> Cst { self.bin_to_cst(bin) } @@ -308,7 +312,7 @@ mod test { fn roundtrip(bin: Bin) { println!("bin: {bin:#?}"); - let mut builder = Builder::new(); + let mut builder = Builder::default(); let cst = builder.build(&bin); let buf = builder.text_buffer(); diff --git a/crates/ltk_ritobin/src/print.rs b/crates/ltk_ritobin/src/print.rs index c0ec31ef..a30ae4fa 100644 --- a/crates/ltk_ritobin/src/print.rs +++ b/crates/ltk_ritobin/src/print.rs @@ -25,7 +25,7 @@ pub trait Print { Self::print_to_writer_with_config::(self, writer, Default::default()) } /// Print as ritobin code to the given writer, using the given config. - fn print_to_writer_with_config( + fn print_to_writer_with_config( &self, writer: &mut W, config: PrintConfig, @@ -38,7 +38,7 @@ pub trait Print { Ok(str) } /// Print as ritobin code to a string, using the given config. - fn print_with_config( + fn print_with_config( &self, config: PrintConfig, ) -> Result { @@ -49,7 +49,7 @@ pub trait Print { } impl Print for Bin { - fn print_to_writer_with_config( + fn print_to_writer_with_config( &self, writer: &mut W, config: PrintConfig, diff --git a/crates/ltk_ritobin/src/print/printers.rs b/crates/ltk_ritobin/src/print/printers.rs index 664e0bd6..a7477409 100644 --- a/crates/ltk_ritobin/src/print/printers.rs +++ b/crates/ltk_ritobin/src/print/printers.rs @@ -8,12 +8,12 @@ use crate::{ print::{PrintConfig, PrintError}, }; -pub struct CstPrinter<'a, W: Write, H: HashProvider> { - visitor: super::visitor::CstVisitor<'a, W, H>, +pub struct CstPrinter<'a, W: Write> { + visitor: super::visitor::CstVisitor<'a, W>, } -impl<'a, W: Write, H: HashProvider> CstPrinter<'a, W, H> { - pub fn new(src: &'a str, out: W, config: PrintConfig) -> Self { +impl<'a, W: Write> CstPrinter<'a, W> { + pub fn new(src: &'a str, out: W, config: PrintConfig<()>) -> Self { Self { visitor: super::visitor::CstVisitor::new(src, out, config), } @@ -56,14 +56,20 @@ impl BinPrinter { &mut self, tree: &Bin, writer: &mut W, - ) -> Result { - let mut builder = cst::builder::Builder::new(); + ) -> Result + where + H: Clone, + { + let mut builder = cst::builder::Builder::new(self.config.hashes.clone()); let cst = builder.build(tree); let buf = builder.into_text_buffer(); CstPrinter::new(&buf, writer, Default::default()).print(&cst) } - pub fn print_to_string(&mut self, tree: &Bin) -> Result { + pub fn print_to_string(&mut self, tree: &Bin) -> Result + where + H: Clone, + { let mut str = String::new(); self.print(tree, &mut str)?; Ok(str) diff --git a/crates/ltk_ritobin/src/print/visitor.rs b/crates/ltk_ritobin/src/print/visitor.rs index 7ed643e1..d015df66 100644 --- a/crates/ltk_ritobin/src/print/visitor.rs +++ b/crates/ltk_ritobin/src/print/visitor.rs @@ -10,7 +10,6 @@ use crate::{ command::{Cmd, Mode}, PrintConfig, PrintError, }, - HashProvider, }; #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] @@ -25,8 +24,8 @@ struct ListContext { const MAX_QUEUE: usize = 4096; -pub struct CstVisitor<'a, W: Write, H: HashProvider> { - config: PrintConfig, +pub struct CstVisitor<'a, W: Write> { + config: PrintConfig<()>, src: &'a str, out: W, @@ -51,7 +50,7 @@ pub struct CstVisitor<'a, W: Write, H: HashProvider> { block_line: bool, } -impl<'a, W: Write, H: HashProvider> CstVisitor<'a, W, H> { +impl<'a, W: Write> CstVisitor<'a, W> { #[inline(always)] #[must_use] pub fn queue_size_max(&self) -> usize { @@ -71,8 +70,8 @@ impl<'a, W: Write, H: HashProvider> CstVisitor<'a, W, H> { } } -impl<'a, W: Write, H: HashProvider> CstVisitor<'a, W, H> { - pub fn new(src: &'a str, out: W, config: PrintConfig) -> Self { +impl<'a, W: Write> CstVisitor<'a, W> { + pub fn new(src: &'a str, out: W, config: PrintConfig<()>) -> Self { Self { src, out, @@ -552,7 +551,7 @@ impl<'a, W: Write, H: HashProvider> CstVisitor<'a, W, H> { } } -impl<'a, W: fmt::Write, H: HashProvider> Visitor for CstVisitor<'a, W, H> { +impl<'a, W: fmt::Write> Visitor for CstVisitor<'a, W> { fn enter_tree(&mut self, tree: &Cst) -> Visit { match self.enter_tree_inner(tree) { Ok(_) => Visit::Continue, From b294c1db933ee558c3cb88fda98f0ddb2e6a0d5b Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Mon, 23 Mar 2026 18:44:21 +0000 Subject: [PATCH 146/187] feat: impl cst building of color/hash/wadchunklink --- crates/ltk_ritobin/src/cst/builder.rs | 38 +++++++++++++++++++++------ 1 file changed, 30 insertions(+), 8 deletions(-) diff --git a/crates/ltk_ritobin/src/cst/builder.rs b/crates/ltk_ritobin/src/cst/builder.rs index b19cdc7c..7b67ba1b 100644 --- a/crates/ltk_ritobin/src/cst/builder.rs +++ b/crates/ltk_ritobin/src/cst/builder.rs @@ -109,9 +109,6 @@ impl Builder { PropertyValueEnum::Bool(b) => self.bool(**b), PropertyValueEnum::BitBool(b) => self.bool(**b), - PropertyValueEnum::None(_) => { - tree(Kind::Literal, vec![token(Tok::LCurly), token(Tok::RCurly)]) - } PropertyValueEnum::U8(n) => self.number(n.to_string()), PropertyValueEnum::U16(n) => self.number(n.to_string()), PropertyValueEnum::U32(n) => self.number(n.to_string()), @@ -161,10 +158,24 @@ impl Builder { .collect(); self.block(items) } + PropertyValueEnum::Color(v) => { + let items = v + .to_array() + .iter() + .map(|v| tree(Kind::ListItem, vec![self.number(v.to_string())])) + .collect(); + self.block(items) + } PropertyValueEnum::String(s) => tree( Kind::Literal, vec![token(Tok::Quote), self.string(&**s), token(Tok::Quote)], ), + + // hash/hash-likes + PropertyValueEnum::Hash(v) => self.hex_lit(format!("0x{:x}", **v)), + PropertyValueEnum::WadChunkLink(v) => self.hex_lit(format!("0x{:x}", **v)), + PropertyValueEnum::ObjectLink(v) => self.hex_lit(format!("0x{:x}", **v)), + PropertyValueEnum::Container(container) | PropertyValueEnum::UnorderedContainer(values::UnorderedContainer(container)) => { let mut children = vec![token(Tok::LCurly)]; @@ -176,9 +187,6 @@ impl Builder { children.push(token(Tok::RCurly)); tree(Kind::TypeArgList, children) } - PropertyValueEnum::Color(_color) => todo!(), - PropertyValueEnum::Hash(_hash) => todo!(), - PropertyValueEnum::WadChunkLink(_wad_chunk_link) => todo!(), PropertyValueEnum::Embedded(values::Embedded(s)) | PropertyValueEnum::Struct(s) => { let k = self.spanned_token(Tok::HexLit, format!("0x{:x}", s.class_hash)); let children = s @@ -188,7 +196,7 @@ impl Builder { .collect(); tree(Kind::Class, vec![k, self.block(children)]) } - PropertyValueEnum::ObjectLink(_object_link) => todo!(), + PropertyValueEnum::Optional(optional) => { let children = match optional.clone().into_inner() { Some(v) => vec![self.value_to_cst(&v)], @@ -196,6 +204,10 @@ impl Builder { }; self.block(children) } + PropertyValueEnum::None(_) => { + tree(Kind::Literal, vec![token(Tok::LCurly), token(Tok::RCurly)]) + } + PropertyValueEnum::Map(_map) => todo!(), } } @@ -360,6 +372,7 @@ mod test { .property(0x22, values::I32::new(-23)) .property(0x33, values::I16::new(-34)) .property(0x44, values::I8::new(45)) + .property(0x66, values::Hash::new(123123)) .property(0x99, values::F32::new(-45.45345)) .property(0x98, values::F32::new(199999.)) .build(), @@ -368,7 +381,7 @@ mod test { ); } #[test] - fn vectors_and_matrix() { + fn vectors_colors_and_matrices() { roundtrip( Bin::builder() .object( @@ -381,6 +394,15 @@ mod test { ) .property( 0x4, + values::Color::new(ltk_primitives::Color { + r: 123, + g: 255, + b: 2, + a: 5, + }), + ) + .property( + 0x5, values::Matrix44::new(glam::Mat4::from_cols_array(&[ 0.1, 0.5, 0.7, 0.9, 10.0, 11.2, 13.8, 15.3, 19.52, -0.123, -55.11, -13.005, 23.0, 99.02, 101.1, 500.0, From 18c0257d6b7e2c381fd940e289fb70675370da82 Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Mon, 23 Mar 2026 19:33:52 +0000 Subject: [PATCH 147/187] feat(primitives): Color::to_array --- crates/ltk_primitives/src/color.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/crates/ltk_primitives/src/color.rs b/crates/ltk_primitives/src/color.rs index 3677cc82..824984f6 100644 --- a/crates/ltk_primitives/src/color.rs +++ b/crates/ltk_primitives/src/color.rs @@ -21,6 +21,13 @@ impl Color { pub const fn new(r: T, g: T, b: T, a: T) -> Self { Self { r, g, b, a } } + + pub const fn to_array(&self) -> [T; 4] + where + T: Copy, + { + [self.r, self.g, self.b, self.a] + } } impl Color { From 597af296488c9f355b4ea4a3094e05e92ec694cc Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Mon, 23 Mar 2026 19:43:09 +0000 Subject: [PATCH 148/187] feat: impl cst building of maps --- crates/ltk_ritobin/src/cst/builder.rs | 33 ++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/crates/ltk_ritobin/src/cst/builder.rs b/crates/ltk_ritobin/src/cst/builder.rs index 7b67ba1b..7a8568ce 100644 --- a/crates/ltk_ritobin/src/cst/builder.rs +++ b/crates/ltk_ritobin/src/cst/builder.rs @@ -208,7 +208,14 @@ impl Builder { tree(Kind::Literal, vec![token(Tok::LCurly), token(Tok::RCurly)]) } - PropertyValueEnum::Map(_map) => todo!(), + PropertyValueEnum::Map(map) => { + let children = map + .entries() + .iter() + .flat_map(|(k, v)| [self.value_to_cst(k), token(Tok::Eq), self.value_to_cst(v)]) + .collect(); + self.block(children) + } } } @@ -434,4 +441,28 @@ mod test { .build(), ); } + + #[test] + fn map() { + roundtrip( + Bin::builder() + .object( + BinObject::builder(0xfeeb1e, 0x111) + .property( + 0x1, + values::Map::new( + PropertyKind::String, + PropertyKind::U64, + vec![( + values::String::from("asdasd").into(), + values::U64::new(1).into(), + )], + ) + .unwrap(), + ) + .build(), + ) + .build(), + ); + } } From 5056a19e26f33be1108c67436ecc81718d29d1df Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Mon, 23 Mar 2026 19:47:51 +0000 Subject: [PATCH 149/187] fix: unused --- crates/ltk_ritobin/examples/rito_fmt.rs | 2 +- crates/ltk_ritobin/src/cst/builder.rs | 12 ------------ crates/ltk_ritobin/src/parse/parser.rs | 1 + 3 files changed, 2 insertions(+), 13 deletions(-) diff --git a/crates/ltk_ritobin/examples/rito_fmt.rs b/crates/ltk_ritobin/examples/rito_fmt.rs index 8f578bd2..bcb6b405 100644 --- a/crates/ltk_ritobin/examples/rito_fmt.rs +++ b/crates/ltk_ritobin/examples/rito_fmt.rs @@ -1,4 +1,4 @@ -use std::{fs::File, io::BufReader, path::PathBuf, str::FromStr}; +use std::{path::PathBuf, str::FromStr}; use ltk_ritobin::print::{CstPrinter, PrintConfig}; diff --git a/crates/ltk_ritobin/src/cst/builder.rs b/crates/ltk_ritobin/src/cst/builder.rs index 7a8568ce..9ed5a1e0 100644 --- a/crates/ltk_ritobin/src/cst/builder.rs +++ b/crates/ltk_ritobin/src/cst/builder.rs @@ -259,18 +259,6 @@ impl Builder { self.entry(k, Some(t), v) } - fn object_block(&mut self, obj: &BinObject) -> Child { - let mut children = vec![token(Tok::LCurly)]; - - for prop in obj.properties.values() { - children.push(self.property_to_cst(prop)); - } - - children.push(token(Tok::RCurly)); - - tree(Kind::Block, children) - } - fn class(&self, class_name: Child, items: Vec) -> Child { tree(Kind::Class, vec![class_name, self.block(items)]) } diff --git a/crates/ltk_ritobin/src/parse/parser.rs b/crates/ltk_ritobin/src/parse/parser.rs index bacdedee..65c8d46a 100644 --- a/crates/ltk_ritobin/src/parse/parser.rs +++ b/crates/ltk_ritobin/src/parse/parser.rs @@ -255,6 +255,7 @@ impl<'a> Parser<'a> { false } + #[allow(unused)] pub(crate) fn expect_fallable(&mut self, kind: TokenKind) -> Result<(), ()> { match self.expect(kind) { true => Ok(()), From 5b3870be550873c9898035bfd48489b067584247 Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Mon, 23 Mar 2026 20:00:51 +0000 Subject: [PATCH 150/187] feat: typecheck hex lit values --- crates/ltk_ritobin/src/typecheck/visitor.rs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/crates/ltk_ritobin/src/typecheck/visitor.rs b/crates/ltk_ritobin/src/typecheck/visitor.rs index 471fd9a9..5800e7be 100644 --- a/crates/ltk_ritobin/src/typecheck/visitor.rs +++ b/crates/ltk_ritobin/src/typecheck/visitor.rs @@ -576,6 +576,19 @@ pub fn resolve_value( *span, ) .into(), + cst::Child::Token(Token { + kind: TokenKind::HexLit, + span, + }) => { + let txt = &ctx.text[span] + .strip_prefix("0x") + .ok_or(Diagnostic::InvalidHash(*span))?; + values::Hash::new_with_meta( + u32::from_str_radix(txt, 16).map_err(|_| Diagnostic::InvalidHash(*span))?, + *span, + ) + .into() + } cst::Child::Token(Token { kind: TokenKind::Number, span, From 6493f3fa6d4e0915f701d0e80e2fa39628788d9a Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Mon, 23 Mar 2026 20:01:00 +0000 Subject: [PATCH 151/187] fix: add error checks to roundtrip tests --- crates/ltk_ritobin/src/cst/builder.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/crates/ltk_ritobin/src/cst/builder.rs b/crates/ltk_ritobin/src/cst/builder.rs index 9ed5a1e0..098bd10e 100644 --- a/crates/ltk_ritobin/src/cst/builder.rs +++ b/crates/ltk_ritobin/src/cst/builder.rs @@ -316,6 +316,7 @@ mod test { use super::*; use crate::{parse::parse, print::CstPrinter}; + // bin -> cst -> txt -> cst -> bin fn roundtrip(bin: Bin) { println!("bin: {bin:#?}"); @@ -336,8 +337,18 @@ mod test { println!("RITOBIN:\n{str}"); let cst2 = parse(&str); + assert!( + cst2.errors.is_empty(), + "errors parsing ritobin - {:#?}", + cst2.errors + ); let (bin2, errors) = cst2.build_bin(&str); + assert!( + errors.is_empty(), + "errors building tree from reparsed ritobin - {errors:#?}" + ); + pretty_assertions::assert_eq!(bin2, bin); } From aad70b301c9f8b05cd2e726298df0b61e53bb0f7 Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Mon, 23 Mar 2026 20:34:24 +0000 Subject: [PATCH 152/187] feat: cst builder hash lookups --- crates/ltk_ritobin/src/cst/builder.rs | 51 ++++++++++++++++++++------- 1 file changed, 38 insertions(+), 13 deletions(-) diff --git a/crates/ltk_ritobin/src/cst/builder.rs b/crates/ltk_ritobin/src/cst/builder.rs index 098bd10e..d4307e54 100644 --- a/crates/ltk_ritobin/src/cst/builder.rs +++ b/crates/ltk_ritobin/src/cst/builder.rs @@ -1,4 +1,4 @@ -use std::fmt::Write; +use std::fmt::{LowerHex, Write}; use ltk_meta::{property::values, Bin, BinObject, BinProperty, PropertyKind, PropertyValueEnum}; @@ -60,6 +60,10 @@ impl Builder { } } +fn hex_fmt(v: T) -> String { + format!("0x{v:x}") +} + impl Builder { fn number(&mut self, v: impl AsRef) -> Child { tree(Kind::Literal, vec![self.spanned_token(Tok::Number, v)]) @@ -79,14 +83,35 @@ impl Builder { self.spanned_token(Tok::String, v) } - fn name(&mut self, v: impl AsRef) -> Child { - self.spanned_token(Tok::Name, v) - } - fn hex_lit(&mut self, v: impl AsRef) -> Child { self.spanned_token(Tok::HexLit, v) } + fn hash_hash_lit(&mut self, h: u32) -> Child { + match self.hashes.lookup_hash(h).map(|h| format!("\"{h}\"")) { + Some(h) => self.spanned_token(Tok::String, h), + None => self.spanned_token(Tok::HexLit, hex_fmt(h)), + } + } + fn hash_type_lit(&mut self, h: u32) -> Child { + match self.hashes.lookup_type(h).map(|h| format!("\"{h}\"")) { + Some(h) => self.spanned_token(Tok::String, h), + None => self.spanned_token(Tok::HexLit, hex_fmt(h)), + } + } + fn hash_field_lit(&mut self, h: u32) -> Child { + match self.hashes.lookup_field(h).map(|h| format!("\"{h}\"")) { + Some(h) => self.spanned_token(Tok::String, h), + None => self.spanned_token(Tok::HexLit, hex_fmt(h)), + } + } + fn hash_entry_lit(&mut self, h: u32) -> Child { + match self.hashes.lookup_entry(h).map(|h| format!("\"{h}\"")) { + Some(h) => self.spanned_token(Tok::String, h), + None => self.spanned_token(Tok::HexLit, hex_fmt(h)), + } + } + fn block(&self, children: Vec) -> Child { tree( Kind::Block, @@ -172,9 +197,9 @@ impl Builder { ), // hash/hash-likes - PropertyValueEnum::Hash(v) => self.hex_lit(format!("0x{:x}", **v)), - PropertyValueEnum::WadChunkLink(v) => self.hex_lit(format!("0x{:x}", **v)), - PropertyValueEnum::ObjectLink(v) => self.hex_lit(format!("0x{:x}", **v)), + PropertyValueEnum::Hash(h) => self.hash_hash_lit(**h), + PropertyValueEnum::WadChunkLink(h) => self.hex_lit(hex_fmt(**h)), + PropertyValueEnum::ObjectLink(h) => self.hash_hash_lit(**h), PropertyValueEnum::Container(container) | PropertyValueEnum::UnorderedContainer(values::UnorderedContainer(container)) => { @@ -188,7 +213,7 @@ impl Builder { tree(Kind::TypeArgList, children) } PropertyValueEnum::Embedded(values::Embedded(s)) | PropertyValueEnum::Struct(s) => { - let k = self.spanned_token(Tok::HexLit, format!("0x{:x}", s.class_hash)); + let k = self.hash_type_lit(s.class_hash); let children = s .properties .iter() @@ -253,7 +278,7 @@ impl Builder { tree(Kind::TypeExpr, children) } fn property_to_cst(&mut self, prop: &BinProperty) -> Child { - let k = self.spanned_token(Tok::HexLit, format!("0x{:x}", prop.name_hash)); + let k = self.hash_field_lit(prop.name_hash); let t = self.rito_type(prop.value.rito_type()); let v = self.value_to_cst(&prop.value); self.entry(k, Some(t), v) @@ -264,14 +289,14 @@ impl Builder { } fn bin_object_to_cst(&mut self, obj: &BinObject) -> Child { - let k = self.hex_lit(format!("0x{:x}", obj.path_hash)); + let k = self.hash_entry_lit(obj.path_hash); - let class_hash = self.hex_lit(format!("0x{:x}", obj.class_hash)); + let class_hash = self.hash_type_lit(obj.class_hash); let class_values = obj .properties .iter() .map(|(k, v)| { - let k = tree(Kind::EntryKey, vec![self.hex_lit(format!("0x{k:x}"))]); + let k = tree(Kind::EntryKey, vec![self.hash_field_lit(*k)]); let t = self.rito_type(v.value.rito_type()); let v = self.value_to_cst(&v.value); self.entry(k, Some(t), v) From f4b201f38b31b7e21c83995a4bf9d09b939d7467 Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Mon, 23 Mar 2026 21:07:03 +0000 Subject: [PATCH 153/187] chore!: public api reorg --- crates/ltk_ritobin/examples/rito_fmt.rs | 7 +++++-- crates/ltk_ritobin/src/cst/builder.rs | 4 ++-- crates/ltk_ritobin/src/cst/tree.rs | 13 ++++++++++++- crates/ltk_ritobin/src/parse.rs | 19 +++++++------------ crates/ltk_ritobin/src/print.rs | 4 ++-- crates/ltk_ritobin/tests/parse_sample.rs | 9 ++++----- 6 files changed, 32 insertions(+), 24 deletions(-) diff --git a/crates/ltk_ritobin/examples/rito_fmt.rs b/crates/ltk_ritobin/examples/rito_fmt.rs index bcb6b405..1eb0a99e 100644 --- a/crates/ltk_ritobin/examples/rito_fmt.rs +++ b/crates/ltk_ritobin/examples/rito_fmt.rs @@ -1,6 +1,9 @@ use std::{path::PathBuf, str::FromStr}; -use ltk_ritobin::print::{CstPrinter, PrintConfig}; +use ltk_ritobin::{ + cst::Cst, + print::{CstPrinter, PrintConfig}, +}; fn main() { let mut args = std::env::args().skip(1); @@ -17,7 +20,7 @@ fn main() { let input = std::fs::read_to_string(input_path).unwrap(); - let cst = ltk_ritobin::parse::parse(&input); + let cst = Cst::parse(&input); // let mut str = String::new(); // cst.print(&mut str, 0, &input); diff --git a/crates/ltk_ritobin/src/cst/builder.rs b/crates/ltk_ritobin/src/cst/builder.rs index d4307e54..f9945093 100644 --- a/crates/ltk_ritobin/src/cst/builder.rs +++ b/crates/ltk_ritobin/src/cst/builder.rs @@ -339,7 +339,7 @@ mod test { use ltk_meta::{property::values, Bin, BinObject}; use super::*; - use crate::{parse::parse, print::CstPrinter}; + use crate::print::CstPrinter; // bin -> cst -> txt -> cst -> bin fn roundtrip(bin: Bin) { @@ -361,7 +361,7 @@ mod test { .unwrap(); println!("RITOBIN:\n{str}"); - let cst2 = parse(&str); + let cst2 = Cst::parse(&str); assert!( cst2.errors.is_empty(), "errors parsing ritobin - {:#?}", diff --git a/crates/ltk_ritobin/src/cst/tree.rs b/crates/ltk_ritobin/src/cst/tree.rs index 56d2b489..288c31d1 100644 --- a/crates/ltk_ritobin/src/cst/tree.rs +++ b/crates/ltk_ritobin/src/cst/tree.rs @@ -1,7 +1,11 @@ use std::fmt::Display; use crate::{ - parse::{self, tokenizer::Token, Span}, + parse::{ + self, impls, + tokenizer::{self, Token}, + Parser, Span, + }, typecheck::visitor::DiagnosticWithSpan, }; @@ -88,6 +92,13 @@ macro_rules! format_to { }; } impl Cst { + pub fn parse(text: &str) -> Self { + let tokens = tokenizer::lex(text); + let mut p = Parser::new(text, tokens); + impls::file(&mut p); + p.build_tree() + } + pub fn build_bin(&self, text: &str) -> (ltk_meta::Bin, Vec) { let mut checker = crate::typecheck::visitor::TypeChecker::new(text); self.walk(&mut checker); diff --git a/crates/ltk_ritobin/src/parse.rs b/crates/ltk_ritobin/src/parse.rs index cbf51055..7dec4b48 100644 --- a/crates/ltk_ritobin/src/parse.rs +++ b/crates/ltk_ritobin/src/parse.rs @@ -1,9 +1,11 @@ //! Parser for ritobin text format with CST output for better error reporting. -pub mod error; +mod error; pub use error::*; -pub mod parser; +mod parser; +pub use parser::*; + pub mod tokenizer; pub use tokenizer::{Token, TokenKind}; @@ -14,16 +16,9 @@ pub use span::Span; use crate::cst; -pub fn parse(text: &str) -> cst::Cst { - let tokens = tokenizer::lex(text); - let mut p = parser::Parser::new(text, tokens); - impls::file(&mut p); - p.build_tree() -} - #[cfg(test)] mod test { - use crate::{print::CstPrinter, typecheck::visitor::TypeChecker}; + use crate::{cst::Cst, print::CstPrinter, typecheck::visitor::TypeChecker}; use super::*; #[test] @@ -35,7 +30,7 @@ entries: map[hash, embed] = { } } "#; - let cst = parse(text); + let cst = Cst::parse(text); let errors = cst::FlatErrors::walk(&cst); let mut str = String::new(); @@ -113,7 +108,7 @@ entries: map[hash,embed] = { } } "#; - let cst = parse(text); + let cst = Cst::parse(text); let mut str = String::new(); cst.print(&mut str, 0, text); diff --git a/crates/ltk_ritobin/src/print.rs b/crates/ltk_ritobin/src/print.rs index a30ae4fa..4d98be2f 100644 --- a/crates/ltk_ritobin/src/print.rs +++ b/crates/ltk_ritobin/src/print.rs @@ -61,12 +61,12 @@ impl Print for Bin { #[cfg(test)] mod test { use crate::{ - parse::parse, + cst::Cst, print::{config::PrintConfig, CstPrinter}, }; fn assert_pretty(input: &str, is: &str, size: usize) { - let cst = parse(input); + let cst = Cst::parse(input); let mut str = String::new(); cst.print(&mut str, 0, input); diff --git a/crates/ltk_ritobin/tests/parse_sample.rs b/crates/ltk_ritobin/tests/parse_sample.rs index 5ce63b57..af7aadd1 100644 --- a/crates/ltk_ritobin/tests/parse_sample.rs +++ b/crates/ltk_ritobin/tests/parse_sample.rs @@ -1,6 +1,6 @@ //! Integration test for parsing a sample ritobin file. -use ltk_ritobin::{parse::parse, print::Print as _}; +use ltk_ritobin::{cst::Cst, print::Print as _}; const SAMPLE_RITOBIN: &str = r#"#PROP_text type: string = "PROP" @@ -44,19 +44,18 @@ entries: map[hash,embed] = { "#; fn tree(input: &str) -> String { - let cst = parse(input); + let cst = Cst::parse(input); assert!(cst.errors.is_empty()); let mut debug = String::new(); cst.print(&mut debug, 0, input); - // debug); debug } #[test] fn test_roundtrip() { - let cst = parse(SAMPLE_RITOBIN); + let cst = Cst::parse(SAMPLE_RITOBIN); let (tree, errors) = cst.build_bin(SAMPLE_RITOBIN); assert!(errors.is_empty(), "errors = {errors:#?}"); @@ -66,7 +65,7 @@ fn test_roundtrip() { println!("output:\n{output}"); // Parse again - let cst2 = parse(&output); + let cst2 = Cst::parse(&output); assert!( cst2.errors.is_empty(), "reparse errors = {:#?}", From 32073bec0fb5c5da4c9758935a4dcf121c53448a Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Mon, 23 Mar 2026 21:19:07 +0000 Subject: [PATCH 154/187] fix: consolidate rito type related traits --- crates/ltk_ritobin/src/cst/builder.rs | 9 +- crates/ltk_ritobin/src/typecheck.rs | 3 - crates/ltk_ritobin/src/typecheck/name_ext.rs | 73 ---------- crates/ltk_ritobin/src/typecheck/visitor.rs | 13 +- crates/ltk_ritobin/src/types.rs | 140 ++++++++++--------- 5 files changed, 87 insertions(+), 151 deletions(-) delete mode 100644 crates/ltk_ritobin/src/typecheck/name_ext.rs diff --git a/crates/ltk_ritobin/src/cst/builder.rs b/crates/ltk_ritobin/src/cst/builder.rs index f9945093..b35d27a3 100644 --- a/crates/ltk_ritobin/src/cst/builder.rs +++ b/crates/ltk_ritobin/src/cst/builder.rs @@ -4,10 +4,9 @@ use ltk_meta::{property::values, Bin, BinObject, BinProperty, PropertyKind, Prop use crate::{ cst::{Child, Cst, Kind}, - kind_to_type_name, parse::{Span, Token, TokenKind as Tok}, typecheck::visitor::{PropertyValueExt, RitoType}, - HashProvider, + HashProvider, RitobinName as _, }; pub struct Builder { @@ -255,20 +254,20 @@ impl Builder { } fn rito_type(&mut self, rito_type: RitoType) -> Child { - let mut children = vec![self.spanned_token(Tok::Name, kind_to_type_name(rito_type.base))]; + let mut children = vec![self.spanned_token(Tok::Name, rito_type.base.to_rito_name())]; if let Some(sub) = rito_type.subtypes[0] { let mut args = vec![ token(Tok::LBrack), tree( Kind::TypeArg, - vec![self.spanned_token(Tok::Name, kind_to_type_name(sub))], + vec![self.spanned_token(Tok::Name, sub.to_rito_name())], ), ]; if let Some(sub) = rito_type.subtypes[1] { args.push(tree( Kind::TypeArg, - vec![self.spanned_token(Tok::Name, kind_to_type_name(sub))], + vec![self.spanned_token(Tok::Name, sub.to_rito_name())], )); } args.push(token(Tok::RBrack)); diff --git a/crates/ltk_ritobin/src/typecheck.rs b/crates/ltk_ritobin/src/typecheck.rs index 942097ca..1a49dced 100644 --- a/crates/ltk_ritobin/src/typecheck.rs +++ b/crates/ltk_ritobin/src/typecheck.rs @@ -1,4 +1 @@ -mod name_ext; -pub use name_ext::*; - pub mod visitor; diff --git a/crates/ltk_ritobin/src/typecheck/name_ext.rs b/crates/ltk_ritobin/src/typecheck/name_ext.rs deleted file mode 100644 index 58cb8c33..00000000 --- a/crates/ltk_ritobin/src/typecheck/name_ext.rs +++ /dev/null @@ -1,73 +0,0 @@ -use ltk_meta::PropertyKind; - -pub trait RitobinName: Sized { - fn from_ritobin_name(name: &str) -> Option; - fn to_ritobin_name(self) -> &'static str; -} - -impl RitobinName for PropertyKind { - fn from_ritobin_name(name: &str) -> Option { - match name { - "none" => Some(Self::None), - "bool" => Some(Self::Bool), - "i8" => Some(Self::I8), - "u8" => Some(Self::U8), - "i16" => Some(Self::I16), - "u16" => Some(Self::U16), - "i32" => Some(Self::I32), - "u32" => Some(Self::U32), - "i64" => Some(Self::I64), - "u64" => Some(Self::U64), - "f32" => Some(Self::F32), - "vec2" => Some(Self::Vector2), - "vec3" => Some(Self::Vector3), - "vec4" => Some(Self::Vector4), - "mtx44" => Some(Self::Matrix44), - "rgba" => Some(Self::Color), - "string" => Some(Self::String), - "hash" => Some(Self::Hash), - "file" => Some(Self::WadChunkLink), - "list" => Some(Self::Container), - "list2" => Some(Self::UnorderedContainer), - "pointer" => Some(Self::Struct), - "embed" => Some(Self::Embedded), - "link" => Some(Self::ObjectLink), - "option" => Some(Self::Optional), - "map" => Some(Self::Map), - "flag" => Some(Self::BitBool), - _ => None, - } - } - - fn to_ritobin_name(self) -> &'static str { - match self { - Self::None => "none", - Self::Bool => "bool", - Self::I8 => "i8", - Self::U8 => "u8", - Self::I16 => "i16", - Self::U16 => "u16", - Self::I32 => "i32", - Self::U32 => "u32", - Self::I64 => "i64", - Self::U64 => "u64", - Self::F32 => "f32", - Self::Vector2 => "vec2", - Self::Vector3 => "vec3", - Self::Vector4 => "vec4", - Self::Matrix44 => "mtx44", - Self::Color => "rgba", - Self::String => "string", - Self::Hash => "hash", - Self::WadChunkLink => "file", - Self::Container => "list", - Self::UnorderedContainer => "list2", - Self::Struct => "pointer", - Self::Embedded => "embed", - Self::ObjectLink => "link", - Self::Optional => "option", - Self::Map => "map", - Self::BitBool => "flag", - } - } -} diff --git a/crates/ltk_ritobin/src/typecheck/visitor.rs b/crates/ltk_ritobin/src/typecheck/visitor.rs index 5800e7be..4572c5ae 100644 --- a/crates/ltk_ritobin/src/typecheck/visitor.rs +++ b/crates/ltk_ritobin/src/typecheck/visitor.rs @@ -11,7 +11,7 @@ use xxhash_rust::xxh64::xxh64; use crate::{ cst::{self, visitor::Visit, Child, Cst, Kind, Visitor}, parse::{Span, Token, TokenKind}, - typecheck::RitobinName, + RitobinName, }; #[derive(Debug, Clone)] @@ -292,12 +292,12 @@ pub struct RitoType { impl Display for RitoType { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - let base = self.base.to_ritobin_name(); + let base = self.base.to_rito_name(); match self.subtypes { [None, None] => f.write_str(base), - [Some(a), None] => write!(f, "{base}[{}]", a.to_ritobin_name()), + [Some(a), None] => write!(f, "{base}[{}]", a.to_rito_name()), [Some(a), Some(b)] => { - write!(f, "{base}[{},{}]", a.to_ritobin_name(), b.to_ritobin_name()) + write!(f, "{base}[{},{}]", a.to_rito_name(), b.to_rito_name()) } _ => write!(f, "{base}[!!]"), } @@ -425,8 +425,7 @@ pub fn resolve_rito_type(ctx: &mut Ctx<'_>, tree: &Cst) -> Result, tree: &Cst) -> Result Option { - match name { - "none" => Some(PropertyKind::None), - "bool" => Some(PropertyKind::Bool), - "i8" => Some(PropertyKind::I8), - "u8" => Some(PropertyKind::U8), - "i16" => Some(PropertyKind::I16), - "u16" => Some(PropertyKind::U16), - "i32" => Some(PropertyKind::I32), - "u32" => Some(PropertyKind::U32), - "i64" => Some(PropertyKind::I64), - "u64" => Some(PropertyKind::U64), - "f32" => Some(PropertyKind::F32), - "vec2" => Some(PropertyKind::Vector2), - "vec3" => Some(PropertyKind::Vector3), - "vec4" => Some(PropertyKind::Vector4), - "mtx44" => Some(PropertyKind::Matrix44), - "rgba" => Some(PropertyKind::Color), - "string" => Some(PropertyKind::String), - "hash" => Some(PropertyKind::Hash), - "file" => Some(PropertyKind::WadChunkLink), - "list" => Some(PropertyKind::Container), - "list2" => Some(PropertyKind::UnorderedContainer), - "pointer" => Some(PropertyKind::Struct), - "embed" => Some(PropertyKind::Embedded), - "link" => Some(PropertyKind::ObjectLink), - "option" => Some(PropertyKind::Optional), - "map" => Some(PropertyKind::Map), - "flag" => Some(PropertyKind::BitBool), - _ => None, - } +/// Extension trait for mapping ritobin type names to/from [`PropertyKind`]'s +pub trait RitobinName { + /// Maps a ritobin type name string to a [`ltk_meta::PropertyKind`]. + /// **NOTE:** Case sensitive. + fn from_rito_name(name: &str) -> Option + where + Self: Sized; + + /// Maps a [`ltk_meta::PropertyKind`] to its ritobin type name string. + fn to_rito_name(&self) -> &'static str; } -/// Maps a [`ltk_meta::PropertyKind`] to its ritobin type name string. -pub fn kind_to_type_name(kind: PropertyKind) -> &'static str { - match kind { - PropertyKind::None => "none", - PropertyKind::Bool => "bool", - PropertyKind::I8 => "i8", - PropertyKind::U8 => "u8", - PropertyKind::I16 => "i16", - PropertyKind::U16 => "u16", - PropertyKind::I32 => "i32", - PropertyKind::U32 => "u32", - PropertyKind::I64 => "i64", - PropertyKind::U64 => "u64", - PropertyKind::F32 => "f32", - PropertyKind::Vector2 => "vec2", - PropertyKind::Vector3 => "vec3", - PropertyKind::Vector4 => "vec4", - PropertyKind::Matrix44 => "mtx44", - PropertyKind::Color => "rgba", - PropertyKind::String => "string", - PropertyKind::Hash => "hash", - PropertyKind::WadChunkLink => "file", - PropertyKind::Container => "list", - PropertyKind::UnorderedContainer => "list2", - PropertyKind::Struct => "pointer", - PropertyKind::Embedded => "embed", - PropertyKind::ObjectLink => "link", - PropertyKind::Optional => "option", - PropertyKind::Map => "map", - PropertyKind::BitBool => "flag", +impl RitobinName for PropertyKind { + fn from_rito_name(name: &str) -> Option { + match name { + "none" => Some(Self::None), + "bool" => Some(Self::Bool), + "i8" => Some(Self::I8), + "u8" => Some(Self::U8), + "i16" => Some(Self::I16), + "u16" => Some(Self::U16), + "i32" => Some(Self::I32), + "u32" => Some(Self::U32), + "i64" => Some(Self::I64), + "u64" => Some(Self::U64), + "f32" => Some(Self::F32), + "vec2" => Some(Self::Vector2), + "vec3" => Some(Self::Vector3), + "vec4" => Some(Self::Vector4), + "mtx44" => Some(Self::Matrix44), + "rgba" => Some(Self::Color), + "string" => Some(Self::String), + "hash" => Some(Self::Hash), + "file" => Some(Self::WadChunkLink), + "list" => Some(Self::Container), + "list2" => Some(Self::UnorderedContainer), + "pointer" => Some(Self::Struct), + "embed" => Some(Self::Embedded), + "link" => Some(Self::ObjectLink), + "option" => Some(Self::Optional), + "map" => Some(Self::Map), + "flag" => Some(Self::BitBool), + _ => None, + } + } + + fn to_rito_name(&self) -> &'static str { + match self { + Self::None => "none", + Self::Bool => "bool", + Self::I8 => "i8", + Self::U8 => "u8", + Self::I16 => "i16", + Self::U16 => "u16", + Self::I32 => "i32", + Self::U32 => "u32", + Self::I64 => "i64", + Self::U64 => "u64", + Self::F32 => "f32", + Self::Vector2 => "vec2", + Self::Vector3 => "vec3", + Self::Vector4 => "vec4", + Self::Matrix44 => "mtx44", + Self::Color => "rgba", + Self::String => "string", + Self::Hash => "hash", + Self::WadChunkLink => "file", + Self::Container => "list", + Self::UnorderedContainer => "list2", + Self::Struct => "pointer", + Self::Embedded => "embed", + Self::ObjectLink => "link", + Self::Optional => "option", + Self::Map => "map", + Self::BitBool => "flag", + } } } @@ -108,6 +120,8 @@ impl FromStr for RitobinType { type Err = (); fn from_str(s: &str) -> Result { - type_name_to_kind(s).map(RitobinType::simple).ok_or(()) + PropertyKind::from_rito_name(s) + .map(RitobinType::simple) + .ok_or(()) } } From a83adcbfc236a0192cc16a32013b62a96c944ee2 Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Mon, 23 Mar 2026 21:29:43 +0000 Subject: [PATCH 155/187] fix: reexport Cst to lib root --- crates/ltk_ritobin/src/lib.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/crates/ltk_ritobin/src/lib.rs b/crates/ltk_ritobin/src/lib.rs index 776c7ed7..d5535f7f 100644 --- a/crates/ltk_ritobin/src/lib.rs +++ b/crates/ltk_ritobin/src/lib.rs @@ -53,3 +53,5 @@ pub mod types; pub use hashes::*; pub use types::*; + +pub use cst::Cst; From 36f7f4d8872634dd80ce0e0348e1efa8d5741d75 Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Mon, 23 Mar 2026 21:36:55 +0000 Subject: [PATCH 156/187] chore: tweak example eprintln --- crates/ltk_ritobin/examples/bin_to_rito.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/ltk_ritobin/examples/bin_to_rito.rs b/crates/ltk_ritobin/examples/bin_to_rito.rs index 81bb1bf8..db0b73f7 100644 --- a/crates/ltk_ritobin/examples/bin_to_rito.rs +++ b/crates/ltk_ritobin/examples/bin_to_rito.rs @@ -11,7 +11,7 @@ fn main() { .and_then(|p| PathBuf::from_str(&p).ok()) .zip(args.next().and_then(|p| PathBuf::from_str(&p).ok())) else { - eprintln!("Usage: './from_bin [PATH_TO_BIN] [OUTPUT_PATH]'"); + eprintln!("Usage: './bin_to_rito [PATH_TO_BIN] [OUTPUT_PATH]'"); return; }; println!("Converting {input_path:?} to ritobin..."); From 350be2a75f05429fd49877f998817528c4af0e01 Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Mon, 23 Mar 2026 21:43:36 +0000 Subject: [PATCH 157/187] feat: rito_to_bin example --- crates/ltk_ritobin/examples/rito_to_bin.rs | 37 ++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 crates/ltk_ritobin/examples/rito_to_bin.rs diff --git a/crates/ltk_ritobin/examples/rito_to_bin.rs b/crates/ltk_ritobin/examples/rito_to_bin.rs new file mode 100644 index 00000000..61cc1379 --- /dev/null +++ b/crates/ltk_ritobin/examples/rito_to_bin.rs @@ -0,0 +1,37 @@ +use std::{fs::File, path::PathBuf, str::FromStr}; + +fn main() { + let mut args = std::env::args().skip(1); + let Some((input_path, output_path)) = args + .next() + .and_then(|p| PathBuf::from_str(&p).ok()) + .zip(args.next().and_then(|p| PathBuf::from_str(&p).ok())) + else { + eprintln!("Usage: './rito_to_bin [PATH_TO_RITOBIN] [OUTPUT_BIN_PATH]'"); + return; + }; + println!("Converting {input_path:?} to bin..."); + + let text = std::fs::read_to_string(input_path).unwrap(); + + let cst = ltk_ritobin::Cst::parse(&text); + if !cst.errors.is_empty() { + eprintln!("Errors while parsing:"); + for err in cst.errors { + eprintln!("- {err:#?}"); + } + return; + } + + let (bin, errors) = cst.build_bin(&text); + if !errors.is_empty() { + eprintln!("Errors while converting to bin:"); + for err in errors { + eprintln!("- {err:#?}"); + } + return; + } + + let mut file = File::create(output_path).unwrap(); + bin.to_writer(&mut file).unwrap(); +} From bf98d6c919e2e469f33dda4d7ce1585b136dd74e Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Mon, 23 Mar 2026 21:43:41 +0000 Subject: [PATCH 158/187] chore: doc --- crates/ltk_ritobin/src/cst/tree.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/crates/ltk_ritobin/src/cst/tree.rs b/crates/ltk_ritobin/src/cst/tree.rs index 288c31d1..feb90281 100644 --- a/crates/ltk_ritobin/src/cst/tree.rs +++ b/crates/ltk_ritobin/src/cst/tree.rs @@ -92,6 +92,10 @@ macro_rules! format_to { }; } impl Cst { + /// Parses a CST from ritobin source code. + /// + /// **NOTE:** Parsing errors will end up in [`Self::errors`] - make sure to check this if needed + /// (e.g before calling [`Self::build_bin`] later) pub fn parse(text: &str) -> Self { let tokens = tokenizer::lex(text); let mut p = Parser::new(text, tokens); From 2a6f45a6a53c3441870c8ba6cf04b79b2a39b5cb Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Mon, 23 Mar 2026 21:58:49 +0000 Subject: [PATCH 159/187] fix: cst builder hash literals --- crates/ltk_ritobin/src/cst/builder.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/ltk_ritobin/src/cst/builder.rs b/crates/ltk_ritobin/src/cst/builder.rs index b35d27a3..66e6e19a 100644 --- a/crates/ltk_ritobin/src/cst/builder.rs +++ b/crates/ltk_ritobin/src/cst/builder.rs @@ -93,14 +93,14 @@ impl Builder { } } fn hash_type_lit(&mut self, h: u32) -> Child { - match self.hashes.lookup_type(h).map(|h| format!("\"{h}\"")) { - Some(h) => self.spanned_token(Tok::String, h), + match self.hashes.lookup_type(h).map(|h| h.to_string()) { + Some(h) => self.spanned_token(Tok::Name, h), None => self.spanned_token(Tok::HexLit, hex_fmt(h)), } } fn hash_field_lit(&mut self, h: u32) -> Child { - match self.hashes.lookup_field(h).map(|h| format!("\"{h}\"")) { - Some(h) => self.spanned_token(Tok::String, h), + match self.hashes.lookup_field(h).map(|h| h.to_string()) { + Some(h) => self.spanned_token(Tok::Name, h), None => self.spanned_token(Tok::HexLit, hex_fmt(h)), } } From 9f0cddbc1a25ef3c1b03563cec10e0ae3fc42cf1 Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Mon, 23 Mar 2026 21:58:56 +0000 Subject: [PATCH 160/187] fix: cst builder map entry separation --- crates/ltk_ritobin/src/cst/builder.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/crates/ltk_ritobin/src/cst/builder.rs b/crates/ltk_ritobin/src/cst/builder.rs index 66e6e19a..c631fbbc 100644 --- a/crates/ltk_ritobin/src/cst/builder.rs +++ b/crates/ltk_ritobin/src/cst/builder.rs @@ -236,7 +236,12 @@ impl Builder { let children = map .entries() .iter() - .flat_map(|(k, v)| [self.value_to_cst(k), token(Tok::Eq), self.value_to_cst(v)]) + .map(|(k, v)| { + tree( + Kind::Entry, + vec![self.value_to_cst(k), token(Tok::Eq), self.value_to_cst(v)], + ) + }) .collect(); self.block(children) } From 9c426fee3792cb815648ffc29db60b0c0636620f Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Tue, 24 Mar 2026 11:59:06 +0000 Subject: [PATCH 161/187] feat: add Null token --- crates/ltk_ritobin/src/parse/tokenizer.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/crates/ltk_ritobin/src/parse/tokenizer.rs b/crates/ltk_ritobin/src/parse/tokenizer.rs index 36f2f63b..d8b3f42f 100644 --- a/crates/ltk_ritobin/src/parse/tokenizer.rs +++ b/crates/ltk_ritobin/src/parse/tokenizer.rs @@ -16,9 +16,10 @@ pub enum TokenKind { String, UnterminatedString, -Comment, + Comment, - True, False, + // keywords + True, False, Null, Name, Number, HexLit, } @@ -52,6 +53,7 @@ impl TokenKind { TokenKind::Comment => None, TokenKind::True => Some("true"), TokenKind::False => Some("false"), + TokenKind::Null => Some("null"), TokenKind::Name => None, TokenKind::Number => None, TokenKind::HexLit => None, @@ -82,6 +84,7 @@ impl Display for TokenKind { TokenKind::UnterminatedString => "unterminated string literal", TokenKind::True => "'true'", TokenKind::False => "'false'", + TokenKind::Null => "'null'", TokenKind::Name => "keyword", TokenKind::Number => "number", TokenKind::HexLit => "hexadecimal literal", @@ -106,7 +109,7 @@ pub fn lex(mut text: &str) -> Vec { ], ); - let keywords = ("true false", [True, False]); + let keywords = ("true false null", [True, False, Null]); let source = text; From 1e0c51c5f13814c2049bb592908a61c0cf20adbe Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Tue, 24 Mar 2026 17:02:48 +0000 Subject: [PATCH 162/187] fix: parse Null literals --- crates/ltk_ritobin/src/parse/impls.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/ltk_ritobin/src/parse/impls.rs b/crates/ltk_ritobin/src/parse/impls.rs index 55d84e09..affaef1d 100644 --- a/crates/ltk_ritobin/src/parse/impls.rs +++ b/crates/ltk_ritobin/src/parse/impls.rs @@ -117,7 +117,7 @@ pub fn entry_value(p: &mut Parser) -> bool { (UnterminatedString, _) => { p.advance_with_error(ErrorKind::UnterminatedString, None); } - (String | Number | HexLit | True | False, _) => { + (String | Number | HexLit | True | False | Null, _) => { p.scope(TreeKind::Literal, |p| p.advance()); } (LCurly, _) => { From 168c47a7cb9566ff9fda1c3b9191bd3727899d3f Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Tue, 24 Mar 2026 17:03:08 +0000 Subject: [PATCH 163/187] fix: correct null handling in cst builder + null rt test --- crates/ltk_ritobin/src/cst/builder.rs | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/crates/ltk_ritobin/src/cst/builder.rs b/crates/ltk_ritobin/src/cst/builder.rs index c631fbbc..ffb9c2b4 100644 --- a/crates/ltk_ritobin/src/cst/builder.rs +++ b/crates/ltk_ritobin/src/cst/builder.rs @@ -228,9 +228,7 @@ impl Builder { }; self.block(children) } - PropertyValueEnum::None(_) => { - tree(Kind::Literal, vec![token(Tok::LCurly), token(Tok::RCurly)]) - } + PropertyValueEnum::None(_) => tree(Kind::Literal, vec![token(Tok::Null)]), PropertyValueEnum::Map(map) => { let children = map @@ -393,6 +391,21 @@ mod test { .build(), ); } + + #[test] + fn null() { + roundtrip( + Bin::builder() + .object( + BinObject::builder(0xDEADBEEF, 0x12344321) + .property(0x1, values::None::default()) + .build(), + ) + .build(), + ); + panic!(); + } + #[test] fn numerics() { roundtrip( From 8b19fc267410bf76e6a9ba0b6e00d799a2503366 Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Tue, 24 Mar 2026 17:19:04 +0000 Subject: [PATCH 164/187] test: add rtt's for all property types --- crates/ltk_ritobin/src/cst/builder.rs | 158 +++++++++++++++++++++++--- 1 file changed, 141 insertions(+), 17 deletions(-) diff --git a/crates/ltk_ritobin/src/cst/builder.rs b/crates/ltk_ritobin/src/cst/builder.rs index ffb9c2b4..52dec319 100644 --- a/crates/ltk_ritobin/src/cst/builder.rs +++ b/crates/ltk_ritobin/src/cst/builder.rs @@ -338,6 +338,7 @@ impl Builder { #[cfg(test)] mod test { + use glam::Vec2; use ltk_meta::{property::values, Bin, BinObject}; use super::*; @@ -379,19 +380,6 @@ mod test { pretty_assertions::assert_eq!(bin2, bin); } - #[test] - fn string() { - roundtrip( - Bin::builder() - .object( - BinObject::builder(0xDEADBEEF, 0x12344321) - .property(0x44444444, values::String::from("hello")) - .build(), - ) - .build(), - ); - } - #[test] fn null() { roundtrip( @@ -403,7 +391,6 @@ mod test { ) .build(), ); - panic!(); } #[test] @@ -462,13 +449,118 @@ mod test { ); } #[test] - fn list() { + fn bool_bitbool() { + roundtrip( + Bin::builder() + .object( + BinObject::builder(0xDEADBEEF, 0x12344321) + .property(0x1, values::Bool::new(true)) + .property(0x2, values::Bool::new(false)) + .property(0x3, values::BitBool::new(true)) + .property(0x4, values::BitBool::new(false)) + .build(), + ) + .build(), + ); + } + #[test] + fn string() { + roundtrip( + Bin::builder() + .object( + BinObject::builder(0xDEADBEEF, 0x12344321) + .property(0x44444444, values::String::from("hello")) + .build(), + ) + .build(), + ); + } + #[test] + fn hashes() { + roundtrip( + Bin::builder() + .object( + BinObject::builder(0xDEADBEEF, 0x12344321) + .property(0x1, values::Hash::new(123123)) + .property(0x2, values::Hash::new(u32::MAX)) + .property(0x3, values::ObjectLink::new(123123)) + .property(0x4, values::ObjectLink::new(u32::MAX)) + .property(0x5, values::WadChunkLink::new(123123)) + .property(0x6, values::WadChunkLink::new(u64::MAX)) + .build(), + ) + .build(), + ); + } + + #[test] + fn struct_and_embedded() { + roundtrip( + Bin::builder() + .object( + BinObject::builder(0xDEADBEEF, 0x12344321) + .property( + 0x91, + values::Struct { + class_hash: 0x123, + meta: Default::default(), + properties: [ + ( + 0x1, + BinProperty { + name_hash: 0x1, + value: values::U64::new(5).into(), + }, + ), + ( + 0x2, + BinProperty { + name_hash: 0x2, + value: values::U64::new(10).into(), + }, + ), + ] + .into_iter() + .collect(), + }, + ) + .property( + 0x92, + values::Embedded(values::Struct { + class_hash: 0x234, + meta: Default::default(), + properties: [ + ( + 0x2, + BinProperty { + name_hash: 0x2, + value: values::U64::new(5).into(), + }, + ), + ( + 0x3, + BinProperty { + name_hash: 0x3, + value: values::U64::new(10).into(), + }, + ), + ] + .into_iter() + .collect(), + }), + ) + .build(), + ) + .build(), + ); + } + + #[test] + fn lists() { roundtrip( Bin::builder() .object( BinObject::builder(0xDEADBEEF, 0x12344321) - .property(0x1, values::String::from("hello")) - .property(0x2, values::U64::new(9)) .property( 0x9191919, values::Container::new(vec![ @@ -477,6 +569,14 @@ mod test { values::U64::new(7), ]), ) + .property( + 0x9191918, + values::UnorderedContainer(values::Container::new(vec![ + values::U32::new(5), + values::U32::new(6), + values::U32::new(7), + ])), + ) .build(), ) .build(), @@ -506,4 +606,28 @@ mod test { .build(), ); } + + #[test] + fn optional() { + roundtrip( + Bin::builder() + .object( + BinObject::builder(0xDEADBEEF, 0x12344321) + .property( + 0x1, + values::Optional::new(PropertyKind::Vector2, None).unwrap(), + ) + .property( + 0x2, + values::Optional::new( + PropertyKind::Vector2, + Some(values::Vector2::new(Vec2::new(0.1, -5.0)).into()), + ) + .unwrap(), + ) + .build(), + ) + .build(), + ); + } } From baeb637cdb635ef022d09adbd395246ba206552b Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Tue, 24 Mar 2026 19:00:32 +0000 Subject: [PATCH 165/187] fix: remove BinProperty references --- crates/ltk_ritobin/src/cst/builder.rs | 73 ++++++++------------- crates/ltk_ritobin/src/typecheck/visitor.rs | 8 +-- 2 files changed, 27 insertions(+), 54 deletions(-) diff --git a/crates/ltk_ritobin/src/cst/builder.rs b/crates/ltk_ritobin/src/cst/builder.rs index 52dec319..1f7830ba 100644 --- a/crates/ltk_ritobin/src/cst/builder.rs +++ b/crates/ltk_ritobin/src/cst/builder.rs @@ -1,6 +1,6 @@ use std::fmt::{LowerHex, Write}; -use ltk_meta::{property::values, Bin, BinObject, BinProperty, PropertyKind, PropertyValueEnum}; +use ltk_meta::{property::values, Bin, BinObject, PropertyKind, PropertyValueEnum}; use crate::{ cst::{Child, Cst, Kind}, @@ -216,7 +216,7 @@ impl Builder { let children = s .properties .iter() - .map(|(_k, v)| self.property_to_cst(v)) + .map(|(k, v)| self.property_to_cst(*k, v)) .collect(); tree(Kind::Class, vec![k, self.block(children)]) } @@ -279,10 +279,10 @@ impl Builder { tree(Kind::TypeExpr, children) } - fn property_to_cst(&mut self, prop: &BinProperty) -> Child { - let k = self.hash_field_lit(prop.name_hash); - let t = self.rito_type(prop.value.rito_type()); - let v = self.value_to_cst(&prop.value); + fn property_to_cst(&mut self, name_hash: u32, value: &PropertyValueEnum) -> Child { + let k = self.hash_field_lit(name_hash); + let t = self.rito_type(value.rito_type()); + let v = self.value_to_cst(value); self.entry(k, Some(t), v) } @@ -299,8 +299,8 @@ impl Builder { .iter() .map(|(k, v)| { let k = tree(Kind::EntryKey, vec![self.hash_field_lit(*k)]); - let t = self.rito_type(v.value.rito_type()); - let v = self.value_to_cst(&v.value); + let t = self.rito_type(v.rito_type()); + let v = self.value_to_cst(v); self.entry(k, Some(t), v) }) .collect(); @@ -339,7 +339,10 @@ impl Builder { #[cfg(test)] mod test { use glam::Vec2; - use ltk_meta::{property::values, Bin, BinObject}; + use ltk_meta::{ + property::{values, NoMeta}, + Bin, BinObject, + }; use super::*; use crate::print::CstPrinter; @@ -385,7 +388,7 @@ mod test { roundtrip( Bin::builder() .object( - BinObject::builder(0xDEADBEEF, 0x12344321) + BinObject::::builder(0xDEADBEEF, 0x12344321) .property(0x1, values::None::default()) .build(), ) @@ -398,7 +401,7 @@ mod test { roundtrip( Bin::builder() .object( - BinObject::builder(0xDEADBEEF, 0x12344321) + BinObject::::builder(0xDEADBEEF, 0x12344321) .property(0x1, values::U64::new(12)) .property(0x2, values::U32::new(23)) .property(0x3, values::U16::new(34)) @@ -420,7 +423,7 @@ mod test { roundtrip( Bin::builder() .object( - BinObject::builder(0xDEADBEEF, 0x12344321) + BinObject::::builder(0xDEADBEEF, 0x12344321) .property(0x1, values::Vector2::new(glam::Vec2::new(0.1, -65.0))) .property(0x2, values::Vector3::new(glam::Vec3::new(1000., -0.0, 2.))) .property( @@ -453,7 +456,7 @@ mod test { roundtrip( Bin::builder() .object( - BinObject::builder(0xDEADBEEF, 0x12344321) + BinObject::::builder(0xDEADBEEF, 0x12344321) .property(0x1, values::Bool::new(true)) .property(0x2, values::Bool::new(false)) .property(0x3, values::BitBool::new(true)) @@ -468,7 +471,7 @@ mod test { roundtrip( Bin::builder() .object( - BinObject::builder(0xDEADBEEF, 0x12344321) + BinObject::::builder(0xDEADBEEF, 0x12344321) .property(0x44444444, values::String::from("hello")) .build(), ) @@ -480,7 +483,7 @@ mod test { roundtrip( Bin::builder() .object( - BinObject::builder(0xDEADBEEF, 0x12344321) + BinObject::::builder(0xDEADBEEF, 0x12344321) .property(0x1, values::Hash::new(123123)) .property(0x2, values::Hash::new(u32::MAX)) .property(0x3, values::ObjectLink::new(123123)) @@ -498,27 +501,15 @@ mod test { roundtrip( Bin::builder() .object( - BinObject::builder(0xDEADBEEF, 0x12344321) + BinObject::::builder(0xDEADBEEF, 0x12344321) .property( 0x91, values::Struct { class_hash: 0x123, meta: Default::default(), properties: [ - ( - 0x1, - BinProperty { - name_hash: 0x1, - value: values::U64::new(5).into(), - }, - ), - ( - 0x2, - BinProperty { - name_hash: 0x2, - value: values::U64::new(10).into(), - }, - ), + (0x1, values::U64::new(5).into()), + (0x2, values::U64::new(10).into()), ] .into_iter() .collect(), @@ -530,20 +521,8 @@ mod test { class_hash: 0x234, meta: Default::default(), properties: [ - ( - 0x2, - BinProperty { - name_hash: 0x2, - value: values::U64::new(5).into(), - }, - ), - ( - 0x3, - BinProperty { - name_hash: 0x3, - value: values::U64::new(10).into(), - }, - ), + (0x2, values::U64::new(5).into()), + (0x3, values::U64::new(10).into()), ] .into_iter() .collect(), @@ -560,7 +539,7 @@ mod test { roundtrip( Bin::builder() .object( - BinObject::builder(0xDEADBEEF, 0x12344321) + BinObject::::builder(0xDEADBEEF, 0x12344321) .property( 0x9191919, values::Container::new(vec![ @@ -588,7 +567,7 @@ mod test { roundtrip( Bin::builder() .object( - BinObject::builder(0xfeeb1e, 0x111) + BinObject::::builder(0xfeeb1e, 0x111) .property( 0x1, values::Map::new( @@ -612,7 +591,7 @@ mod test { roundtrip( Bin::builder() .object( - BinObject::builder(0xDEADBEEF, 0x12344321) + BinObject::::builder(0xDEADBEEF, 0x12344321) .property( 0x1, values::Optional::new(PropertyKind::Vector2, None).unwrap(), diff --git a/crates/ltk_ritobin/src/typecheck/visitor.rs b/crates/ltk_ritobin/src/typecheck/visitor.rs index 4572c5ae..fe47192b 100644 --- a/crates/ltk_ritobin/src/typecheck/visitor.rs +++ b/crates/ltk_ritobin/src/typecheck/visitor.rs @@ -854,13 +854,7 @@ impl<'a> TypeChecker<'a> { return parent; }; - struct_val.properties.insert( - *key, - ltk_meta::BinProperty { - name_hash: *key, - value, - }, - ); + struct_val.properties.insert(*key, value); } PropertyValueEnum::ObjectLink(_object_link_value) => todo!(), PropertyValueEnum::Map(map_value) => { From 7ea748eb3b8069b7597706b7b27be3d323f3651d Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Tue, 24 Mar 2026 19:22:40 +0000 Subject: [PATCH 166/187] fix: handle WadChunkLink's properly --- crates/ltk_ritobin/src/typecheck/visitor.rs | 89 +++++++++------------ 1 file changed, 40 insertions(+), 49 deletions(-) diff --git a/crates/ltk_ritobin/src/typecheck/visitor.rs b/crates/ltk_ritobin/src/typecheck/visitor.rs index fe47192b..945c82e4 100644 --- a/crates/ltk_ritobin/src/typecheck/visitor.rs +++ b/crates/ltk_ritobin/src/typecheck/visitor.rs @@ -4,7 +4,9 @@ use glam::Vec4; use indexmap::IndexMap; use ltk_hash::fnv1a; use ltk_meta::{ - property::values, traits::PropertyExt, Bin, BinObject, PropertyKind, PropertyValueEnum, + property::{values, NoMeta}, + traits::PropertyExt, + Bin, BinObject, PropertyKind, PropertyValueEnum, }; use xxhash_rust::xxh64::xxh64; @@ -404,8 +406,10 @@ pub fn coerce_type( } }), PropertyKind::WadChunkLink => Some(match value { - // FIXME: does the lexer give Hash when u64? if so we are cooked PropertyValueEnum::WadChunkLink(_) => return Some(value), + PropertyValueEnum::Hash(hash) => { + values::WadChunkLink::new_with_meta((*hash).into(), hash.meta).into() + } PropertyValueEnum::String(str) => { values::WadChunkLink::new_with_meta(xxh64(str.as_bytes(), 0), str.meta).into() } @@ -487,6 +491,21 @@ pub fn resolve_rito_type(ctx: &mut Ctx<'_>, tree: &Cst) -> Result Result, Diagnostic> { + // TODO: better errs here? + let src = ctx.text[span].strip_prefix("0x").ok_or(InvalidHash(span))?; + + Ok(match u32::from_str_radix(src, 16) { + Ok(hash) => PropertyValueEnum::Hash(values::Hash::new_with_meta(hash, span)), + Err(_) => match u64::from_str_radix(src, 16) { + Ok(hash) => { + PropertyValueEnum::WadChunkLink(values::WadChunkLink::new_with_meta(hash, span)) + } + Err(_) => return Err(InvalidHash(span)), + }, + }) +} + pub fn resolve_value( ctx: &mut Ctx, tree: &Cst, @@ -522,16 +541,17 @@ pub fn resolve_value( Token { kind: TokenKind::HexLit, span, - } => { - // TODO: better err here? - u32::from_str_radix( - ctx.text[span] - .strip_prefix("0x") - .ok_or(InvalidHash(class.span))?, - 16, - ) - .map_err(|_| InvalidHash(class.span))? - } + } => match resolve_hash(ctx, *span)? { + PropertyValueEnum::Hash(hash) => *hash, + value => { + return Err(TypeMismatch { + span: *value.meta(), + expected: RitoType::simple(PropertyKind::Hash), + expected_span: None, + got: value.rito_type().into(), + }); + } + }, _ => { return Err(InvalidHash(class.span)); } @@ -578,16 +598,7 @@ pub fn resolve_value( cst::Child::Token(Token { kind: TokenKind::HexLit, span, - }) => { - let txt = &ctx.text[span] - .strip_prefix("0x") - .ok_or(Diagnostic::InvalidHash(*span))?; - values::Hash::new_with_meta( - u32::from_str_radix(txt, 16).map_err(|_| Diagnostic::InvalidHash(*span))?, - *span, - ) - .into() - } + }) => resolve_hash(ctx, *span)?, cst::Child::Token(Token { kind: TokenKind::Number, span, @@ -660,42 +671,22 @@ pub fn resolve_entry( let key = c.expect_tree(Kind::EntryKey)?; - let (key, key_span) = match key.children.first().ok_or(InvalidHash(key.span))? { + let key = match key.children.first().ok_or(InvalidHash(key.span))? { Child::Token(Token { kind: TokenKind::Name, span, - }) => ( - PropertyValueEnum::from(values::String::from(&ctx.text[span])), - *span, - ), + }) => PropertyValueEnum::from(values::String::new_with_meta(ctx.text[span].into(), *span)), Child::Token(Token { kind: TokenKind::String, span, - }) => ( - PropertyValueEnum::from(values::String::from( - &ctx.text[Span::new(span.start + 1, span.end - 1)], - )), + }) => PropertyValueEnum::from(values::String::new_with_meta( + ctx.text[Span::new(span.start + 1, span.end - 1)].into(), *span, - ), + )), Child::Token(Token { kind: TokenKind::HexLit, span, - }) => { - // TODO: better err here? - ( - PropertyValueEnum::Hash( - u32::from_str_radix( - ctx.text[span] - .strip_prefix("0x") - .ok_or(InvalidHash(*span))?, - 16, - ) - .map_err(|_| InvalidHash(*span))? - .into(), - ), - *span, - ) - } + }) => resolve_hash(ctx, *span)?, _ => { return Err(InvalidHash(key.span).into()); } @@ -747,7 +738,7 @@ pub fn resolve_entry( let value = match (kind, resolved_val) { (None, Some(value)) => value, - (None, None) => return Err(MissingType(key_span).into()), + (None, None) => return Err(MissingType(*key.meta()).into()), (Some(kind), Some(ivalue)) => match ivalue.kind() == kind.base { true => ivalue, false => { From 2431b9daef1cb3a62b584aecd05d9ee0c1e50405 Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Tue, 24 Mar 2026 19:25:48 +0000 Subject: [PATCH 167/187] feat: proper bool/bitbool typechecking --- crates/ltk_ritobin/src/typecheck/visitor.rs | 30 +++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/crates/ltk_ritobin/src/typecheck/visitor.rs b/crates/ltk_ritobin/src/typecheck/visitor.rs index 945c82e4..84ab39e8 100644 --- a/crates/ltk_ritobin/src/typecheck/visitor.rs +++ b/crates/ltk_ritobin/src/typecheck/visitor.rs @@ -418,6 +418,26 @@ pub fn coerce_type( return None; } }), + PropertyKind::BitBool => Some(match value { + PropertyValueEnum::BitBool(_) => return Some(value), + PropertyValueEnum::Bool(bool) => { + values::BitBool::new_with_meta(*bool, bool.meta).into() + } + other => { + eprintln!("\x1b[41mcannot coerce {other:?} to {to:?}\x1b[0m"); + return None; + } + }), + PropertyKind::Bool => Some(match value { + PropertyValueEnum::Bool(_) => return Some(value), + PropertyValueEnum::BitBool(bool) => { + values::Bool::new_with_meta(*bool, bool.meta).into() + } + other => { + eprintln!("\x1b[41mcannot coerce {other:?} to {to:?}\x1b[0m"); + return None; + } + }), to if to == value.kind() => Some(value), _ => None, } @@ -595,6 +615,16 @@ pub fn resolve_value( *span, ) .into(), + + cst::Child::Token(Token { + kind: TokenKind::True, + span, + }) => values::Bool::new_with_meta(true, *span).into(), + cst::Child::Token(Token { + kind: TokenKind::False, + span, + }) => values::Bool::new_with_meta(false, *span).into(), + cst::Child::Token(Token { kind: TokenKind::HexLit, span, From 58c643b56938998474baabd8b081378d3f431c1e Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Tue, 24 Mar 2026 19:26:57 +0000 Subject: [PATCH 168/187] chore: rm unused import --- crates/ltk_ritobin/src/typecheck/visitor.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/crates/ltk_ritobin/src/typecheck/visitor.rs b/crates/ltk_ritobin/src/typecheck/visitor.rs index 84ab39e8..132b2034 100644 --- a/crates/ltk_ritobin/src/typecheck/visitor.rs +++ b/crates/ltk_ritobin/src/typecheck/visitor.rs @@ -4,9 +4,7 @@ use glam::Vec4; use indexmap::IndexMap; use ltk_hash::fnv1a; use ltk_meta::{ - property::{values, NoMeta}, - traits::PropertyExt, - Bin, BinObject, PropertyKind, PropertyValueEnum, + property::values, traits::PropertyExt, Bin, BinObject, PropertyKind, PropertyValueEnum, }; use xxhash_rust::xxh64::xxh64; From 7dec10f0b44bfb5650e1a06dc3ef38493e663a22 Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Tue, 24 Mar 2026 19:56:32 +0000 Subject: [PATCH 169/187] fix: fmt issues --- crates/ltk_ritobin/src/print.rs | 23 +++++++++++++++++++++-- crates/ltk_ritobin/src/print/visitor.rs | 25 ++++++++++++++++--------- 2 files changed, 37 insertions(+), 11 deletions(-) diff --git a/crates/ltk_ritobin/src/print.rs b/crates/ltk_ritobin/src/print.rs index 4d98be2f..eaa61ab9 100644 --- a/crates/ltk_ritobin/src/print.rs +++ b/crates/ltk_ritobin/src/print.rs @@ -88,6 +88,10 @@ mod test { pretty_assertions::assert_eq!(str.trim(), is.trim()); } + fn assert_pretty_rt(input: &str, size: usize) { + assert_pretty(input, input, size); + } + #[test] fn simple_list() { assert_pretty( @@ -102,8 +106,8 @@ mod test { assert_pretty( r#" vec2List : list [ vec2, ] = { {3, 6} {1 10000} }"#, r#"vec2List: list[vec2] = { - { 3, 6 } - { 1, 10000 } + { 3, 6 } + { 1, 10000 } }"#, 80, ); @@ -171,4 +175,19 @@ linked: list[string] = { "DATA/Characters/Viego/Viego.bin" 80, ); } + + #[test] + fn zaahen_01() { + assert_pretty_rt( + r#"bankUnits: list2[embed] = { + BankUnit { + events: list[string] = { + "PPlay_sfx_Zaahen_Dance3D_buffactivatePlay_sfx_Zaahen_Dance3D_buffactivatelay_sfx_Zaahen_Dance3D_buffactivate" + } + } + BankUnit { } +}"#, + 120, + ); + } } diff --git a/crates/ltk_ritobin/src/print/visitor.rs b/crates/ltk_ritobin/src/print/visitor.rs index d015df66..0cba5477 100644 --- a/crates/ltk_ritobin/src/print/visitor.rs +++ b/crates/ltk_ritobin/src/print/visitor.rs @@ -269,15 +269,17 @@ impl<'a, W: Write> CstVisitor<'a, W> { } Cmd::Line => { - self.out.write_char('\n')?; - for _ in 0..self.indent { - self.out.write_char(' ')?; + if !self.block_line { + self.out.write_char('\n')?; + for _ in 0..self.indent { + self.out.write_char(' ')?; + } + self.printed_bytes += self.indent + 1; + self.col = self.indent; + self.propagate_break(); + self.block_space = true; + self.block_line = true; } - self.printed_bytes += self.indent + 1; - self.col = self.indent; - self.propagate_break(); - self.block_space = true; - self.block_line = true; } Cmd::SoftLine => match self.modes.last().unwrap() { @@ -348,9 +350,14 @@ impl<'a, W: Write> CstVisitor<'a, W> { .copied() .unwrap_or(self.queue.len() + self.printed_commands); + // if self.printed_commands < limit { + // println!("## SAFE FLUSH"); + // } + while self.printed_commands < limit { let cmd = self.queue.pop_front().unwrap(); self.printed_commands += 1; + // eprintln!("- {cmd:?}"); self.print(cmd)?; } Ok(()) @@ -453,7 +460,7 @@ impl<'a, W: Write> CstVisitor<'a, W> { if let Some(list) = self.list_stack.last() { if list.len > 1 { self.force_group(list.grp, Mode::Break); - self.softline(); + // self.softline(); } } self.end_group(); From 24453bd35910d4aa9e0055e12fbe978b89109b2a Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Tue, 24 Mar 2026 23:27:52 +0000 Subject: [PATCH 170/187] feat: UnexpectedContainerItem when can't inject type --- crates/ltk_ritobin/src/typecheck/visitor.rs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/crates/ltk_ritobin/src/typecheck/visitor.rs b/crates/ltk_ritobin/src/typecheck/visitor.rs index 132b2034..583a3c20 100644 --- a/crates/ltk_ritobin/src/typecheck/visitor.rs +++ b/crates/ltk_ritobin/src/typecheck/visitor.rs @@ -166,6 +166,12 @@ pub enum Diagnostic { got: RitoTypeOrVirtual, }, + UnexpectedContainerItem { + span: Span, + expected: RitoType, + expected_span: Option, + }, + ResolveLiteral, AmbiguousNumeric(Span), @@ -208,6 +214,7 @@ impl Diagnostic { UnknownType(span) | SubtypeCountMismatch { span, .. } | UnexpectedSubtypes { span, .. } + | UnexpectedContainerItem { span, .. } | MissingType(span) | TypeMismatch { span, .. } | ShadowedEntry { shadower: span, .. } @@ -930,6 +937,15 @@ impl<'a> TypeChecker<'a> { .unwrap(); } other => { + self.ctx.diagnostics.push( + UnexpectedContainerItem { + span: *other.meta(), + expected: other.rito_type(), + expected_span: None, + } + .unwrap(), + ); + eprintln!("cant inject into {:?}", other.kind()) } } From 9223f01bbff2751c5d2b3b130969555f351c0b30 Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Tue, 24 Mar 2026 23:30:09 +0000 Subject: [PATCH 171/187] test: add broken type arg test --- crates/ltk_ritobin/src/print.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/crates/ltk_ritobin/src/print.rs b/crates/ltk_ritobin/src/print.rs index eaa61ab9..b3975b71 100644 --- a/crates/ltk_ritobin/src/print.rs +++ b/crates/ltk_ritobin/src/print.rs @@ -190,4 +190,13 @@ linked: list[string] = { "DATA/Characters/Viego/Viego.bin" 120, ); } + + #[test] + fn broken_type_arg() { + assert_pretty( + r#"thing4: list[u3 2] = { 0, 0, 0, 0, 0, 0, 0 }"#, + r#"thing4: list[u32] = { 0, 0, 0, 0, 0, 0, 0 }"#, + 120, + ); + } } From 4dc620e216c1d9e620b252bdee5cc3ff52b1e742 Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Wed, 25 Mar 2026 15:28:45 +0000 Subject: [PATCH 172/187] fix: eat all unexpected tokens inside type arg expression --- crates/ltk_ritobin/src/parse/impls.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/crates/ltk_ritobin/src/parse/impls.rs b/crates/ltk_ritobin/src/parse/impls.rs index affaef1d..79517877 100644 --- a/crates/ltk_ritobin/src/parse/impls.rs +++ b/crates/ltk_ritobin/src/parse/impls.rs @@ -150,6 +150,9 @@ pub fn type_expr(p: &mut Parser) { } } }); + while !p.at(TokenKind::RBrack) { + p.advance(); + } p.expect(TokenKind::RBrack); } }); From f12b621c0f50da629b75377beadbac5177df2b29 Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Wed, 25 Mar 2026 16:10:41 +0000 Subject: [PATCH 173/187] feat(parser): allow entries to be terminated early by RCurly's --- crates/ltk_ritobin/src/parse/impls.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/crates/ltk_ritobin/src/parse/impls.rs b/crates/ltk_ritobin/src/parse/impls.rs index 79517877..4be3bba0 100644 --- a/crates/ltk_ritobin/src/parse/impls.rs +++ b/crates/ltk_ritobin/src/parse/impls.rs @@ -67,6 +67,12 @@ pub fn stmt(p: &mut Parser) -> MarkClosed { return p.close(m, TreeKind::Entry); } + if p.at(TokenKind::RCurly) { + p.scope(TreeKind::EntryTerminator, |_| {}); + let g = p.close(m, TreeKind::Entry); + return g; + } + p.scope(TreeKind::EntryTerminator, |p| { let mut one = false; if p.eof() { From 573381a12b298eb237a23f43bdfbdfc9a9820472 Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Wed, 25 Mar 2026 16:11:00 +0000 Subject: [PATCH 174/187] feat(print): support inlining structs/classes via config --- crates/ltk_ritobin/src/print.rs | 82 ++++++++++++++++++------- crates/ltk_ritobin/src/print/config.rs | 17 +++++ crates/ltk_ritobin/src/print/visitor.rs | 33 +++++++++- 3 files changed, 106 insertions(+), 26 deletions(-) diff --git a/crates/ltk_ritobin/src/print.rs b/crates/ltk_ritobin/src/print.rs index b3975b71..42e6d9e6 100644 --- a/crates/ltk_ritobin/src/print.rs +++ b/crates/ltk_ritobin/src/print.rs @@ -62,10 +62,10 @@ impl Print for Bin { mod test { use crate::{ cst::Cst, - print::{config::PrintConfig, CstPrinter}, + print::{config::PrintConfig, CstPrinter, WrapConfig}, }; - fn assert_pretty(input: &str, is: &str, size: usize) { + fn assert_pretty(input: &str, is: &str, config: PrintConfig<()>) { let cst = Cst::parse(input); let mut str = String::new(); @@ -73,23 +73,15 @@ mod test { eprintln!("#### CST:\n{str}"); let mut str = String::new(); - CstPrinter::new( - input, - &mut str, - PrintConfig { - indent_size: 4, - line_width: size, - hashes: (), - }, - ) - .print(&cst) - .unwrap(); + CstPrinter::new(input, &mut str, config) + .print(&cst) + .unwrap(); pretty_assertions::assert_eq!(str.trim(), is.trim()); } - fn assert_pretty_rt(input: &str, size: usize) { - assert_pretty(input, input, size); + fn assert_pretty_rt(input: &str, config: PrintConfig<()>) { + assert_pretty(input, input, config); } #[test] @@ -97,7 +89,7 @@ mod test { assert_pretty( r#" b : list [ i8, ] = { 3, 6 1 }"#, r#"b: list[i8] = { 3, 6, 1 }"#, - 80, + PrintConfig::default(), ); } @@ -109,7 +101,7 @@ mod test { { 3, 6 } { 1, 10000 } }"#, - 80, + PrintConfig::default(), ); } @@ -126,7 +118,7 @@ mod test { b: string = "foo" } }"#, - 80, + PrintConfig::default(), ); } @@ -139,7 +131,7 @@ mod test { r#"skinUpgradeData: embed = skinUpgradeData { mGearSkinUpgrades: list[link] = { 0x3b9c7079, 0x17566805 } }"#, - 80, + PrintConfig::default(), ); } @@ -155,7 +147,7 @@ linked: list[string] = { "DATA/Characters/Viego/Viego.bin" "DATA/Characters/Viego/Viego.bin" "DATA/Viego_Skins_Skin0_Skins_Skin1_Skins_Skin10_Skins_Skin11_Skins_Skin12_Skins_Skin13_Skins_Skin14_Skins_Skin15_Skins_Skin16_Skins_Skin17_Skins_Skin18_Skins_Skin2_Skins_Skin3_Skins_Skin4_Skins_Skin43_Skins_Skin5_Skins_Skin6_Skins_Skin7_Skins_Skin8.bin" }"#, - 80, + PrintConfig::default(), ); } @@ -172,7 +164,7 @@ linked: list[string] = { "DATA/Characters/Viego/Viego.bin" AugmentGroup: list2[link] = { 0x383e4602 } } }"#, - 80, + PrintConfig::default(), ); } @@ -187,7 +179,7 @@ linked: list[string] = { "DATA/Characters/Viego/Viego.bin" } BankUnit { } }"#, - 120, + PrintConfig::default(), ); } @@ -196,7 +188,51 @@ linked: list[string] = { "DATA/Characters/Viego/Viego.bin" assert_pretty( r#"thing4: list[u3 2] = { 0, 0, 0, 0, 0, 0, 0 }"#, r#"thing4: list[u32] = { 0, 0, 0, 0, 0, 0, 0 }"#, - 120, + PrintConfig::default(), + ); + } + + #[test] + fn inline_single_field_struct() { + assert_pretty_rt( + r#"loadscreen: embed = CensoredImage { image: string = "val" }"#, + PrintConfig { + wrapping: WrapConfig { + allow_inline_structs: true, + }, + ..Default::default() + }, + ); + } + #[test] + fn inline_nested_single_field_struct() { + assert_pretty_rt( + r#"loadscreen: embed = CensoredImage { + image: embed = Image { src: string = "val" } +}"#, + PrintConfig { + wrapping: WrapConfig { + allow_inline_structs: true, + }, + ..Default::default() + }, + ); + } + + #[test] + fn dont_inline_nested_single_field_struct() { + assert_pretty_rt( + r#"loadscreen: embed = CensoredImage { + image: embed = Image { + src: string = "val" + } +}"#, + PrintConfig { + wrapping: WrapConfig { + allow_inline_structs: false, + }, + ..Default::default() + }, ); } } diff --git a/crates/ltk_ritobin/src/print/config.rs b/crates/ltk_ritobin/src/print/config.rs index 610c454e..a8d6e88c 100644 --- a/crates/ltk_ritobin/src/print/config.rs +++ b/crates/ltk_ritobin/src/print/config.rs @@ -1,5 +1,18 @@ use crate::HashProvider; +#[derive(Debug, Clone, Copy)] +pub struct WrapConfig { + pub allow_inline_structs: bool, +} + +impl Default for WrapConfig { + fn default() -> Self { + Self { + allow_inline_structs: false, + } + } +} + /// Configuration for the ritobin printer. #[derive(Debug, Clone)] pub struct PrintConfig { @@ -8,6 +21,8 @@ pub struct PrintConfig { /// Maximum line width pub line_width: usize, + pub wrapping: WrapConfig, + pub hashes: Hashes, } @@ -16,6 +31,7 @@ impl Default for PrintConfig<()> { Self { indent_size: 4, line_width: 120, + wrapping: Default::default(), hashes: (), } } @@ -26,6 +42,7 @@ impl PrintConfig { PrintConfig { indent_size: self.indent_size, line_width: self.line_width, + wrapping: self.wrapping, hashes, } } diff --git a/crates/ltk_ritobin/src/print/visitor.rs b/crates/ltk_ritobin/src/print/visitor.rs index 0cba5477..da035f89 100644 --- a/crates/ltk_ritobin/src/print/visitor.rs +++ b/crates/ltk_ritobin/src/print/visitor.rs @@ -414,10 +414,22 @@ impl<'a, W: Write> CstVisitor<'a, W> { .children .iter() .filter(|n| { - n.tree() - .is_some_and(|t| matches!(t.kind, Kind::ListItem | Kind::ListItemBlock)) + n.tree().is_some_and(|t| { + matches!(t.kind, Kind::ListItem | Kind::ListItemBlock | Kind::Entry) + }) }) .count(); + + if self.config.wrapping.allow_inline_structs { + if let Some(last) = self.list_stack.last() { + if len > 1 { + self.force_group(grp, Mode::Break); + } else { + self.force_group(last.grp, Mode::Break); + } + } + } + if len > 0 { self.list_stack.push(ListContext { len: len.try_into().unwrap(), @@ -440,7 +452,10 @@ impl<'a, W: Write> CstVisitor<'a, W> { self.softline(); } Kind::Entry => { - self.line(); + match self.config.wrapping.allow_inline_structs { + true => self.softline(), + false => self.line(), + }; // self.flush().unwrap(); } _ => {} @@ -465,6 +480,18 @@ impl<'a, W: Write> CstVisitor<'a, W> { } self.end_group(); } + Kind::Entry if self.config.wrapping.allow_inline_structs => { + if let Some(list) = self.list_stack.last() { + if list.len > 1 { + self.force_group(list.grp, Mode::Break); + self.text_if(";", Mode::Flat); + // self.softline(); + } + } else { + // self.text_if(";", Mode::Flat); + // self.softline(); + } + } Kind::ListItem | Kind::TypeArg => { if let Some(ctx) = self.list_stack.last() { let last_item = ctx.idx + 1 == ctx.len; From 445bdae9c00ead354f9434f7a809f37208dff328 Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Wed, 25 Mar 2026 16:20:45 +0000 Subject: [PATCH 175/187] fix!: clean up PrintConfig --- crates/ltk_ritobin/examples/rito_fmt.rs | 7 ++--- crates/ltk_ritobin/src/print.rs | 21 ++----------- crates/ltk_ritobin/src/print/config.rs | 42 +++++++++++++++++++------ crates/ltk_ritobin/src/print/visitor.rs | 10 +++--- 4 files changed, 43 insertions(+), 37 deletions(-) diff --git a/crates/ltk_ritobin/examples/rito_fmt.rs b/crates/ltk_ritobin/examples/rito_fmt.rs index 1eb0a99e..db8ddd42 100644 --- a/crates/ltk_ritobin/examples/rito_fmt.rs +++ b/crates/ltk_ritobin/examples/rito_fmt.rs @@ -2,7 +2,7 @@ use std::{path::PathBuf, str::FromStr}; use ltk_ritobin::{ cst::Cst, - print::{CstPrinter, PrintConfig}, + print::{CstPrinter, PrintConfig, WrapConfig}, }; fn main() { @@ -30,10 +30,7 @@ fn main() { CstPrinter::new( &input, &mut str, - PrintConfig { - line_width: size, - ..Default::default() - }, + PrintConfig::default().wrap(WrapConfig::default().line_width(size)), ) .print(&cst) .unwrap(); diff --git a/crates/ltk_ritobin/src/print.rs b/crates/ltk_ritobin/src/print.rs index 42e6d9e6..1643f50f 100644 --- a/crates/ltk_ritobin/src/print.rs +++ b/crates/ltk_ritobin/src/print.rs @@ -196,12 +196,7 @@ linked: list[string] = { "DATA/Characters/Viego/Viego.bin" fn inline_single_field_struct() { assert_pretty_rt( r#"loadscreen: embed = CensoredImage { image: string = "val" }"#, - PrintConfig { - wrapping: WrapConfig { - allow_inline_structs: true, - }, - ..Default::default() - }, + PrintConfig::default().wrap(WrapConfig::default().inline_structs(true)), ); } #[test] @@ -210,12 +205,7 @@ linked: list[string] = { "DATA/Characters/Viego/Viego.bin" r#"loadscreen: embed = CensoredImage { image: embed = Image { src: string = "val" } }"#, - PrintConfig { - wrapping: WrapConfig { - allow_inline_structs: true, - }, - ..Default::default() - }, + PrintConfig::default().wrap(WrapConfig::default().inline_structs(false)), ); } @@ -227,12 +217,7 @@ linked: list[string] = { "DATA/Characters/Viego/Viego.bin" src: string = "val" } }"#, - PrintConfig { - wrapping: WrapConfig { - allow_inline_structs: false, - }, - ..Default::default() - }, + PrintConfig::default().wrap(WrapConfig::default().inline_structs(false)), ); } } diff --git a/crates/ltk_ritobin/src/print/config.rs b/crates/ltk_ritobin/src/print/config.rs index a8d6e88c..8b42b2ca 100644 --- a/crates/ltk_ritobin/src/print/config.rs +++ b/crates/ltk_ritobin/src/print/config.rs @@ -2,13 +2,31 @@ use crate::HashProvider; #[derive(Debug, Clone, Copy)] pub struct WrapConfig { - pub allow_inline_structs: bool, + /// Maximum line width - will try to break blocks if the line exceeds this number. + pub line_width: usize, + + /// Whether to allow the printing of structs/classes in one line + /// (still subject to line_width wrapping) + pub inline_structs: bool, +} + +impl WrapConfig { + pub fn line_width(mut self, line_width: usize) -> Self { + self.line_width = line_width; + self + } + + pub fn inline_structs(mut self, inline_structs: bool) -> Self { + self.inline_structs = inline_structs; + self + } } impl Default for WrapConfig { fn default() -> Self { Self { - allow_inline_structs: false, + line_width: 120, + inline_structs: false, } } } @@ -18,10 +36,9 @@ impl Default for WrapConfig { pub struct PrintConfig { /// Number of spaces per indent level. pub indent_size: usize, - /// Maximum line width - pub line_width: usize, - pub wrapping: WrapConfig, + /// Config relating to how/when to wrap + pub wrap: WrapConfig, pub hashes: Hashes, } @@ -30,19 +47,26 @@ impl Default for PrintConfig<()> { fn default() -> Self { Self { indent_size: 4, - line_width: 120, - wrapping: Default::default(), + wrap: Default::default(), hashes: (), } } } impl PrintConfig { + pub fn wrap(mut self, wrap: WrapConfig) -> Self { + self.wrap = wrap; + self + } + pub fn indent_size(mut self, indent_size: usize) -> Self { + self.indent_size = indent_size; + self + } + pub fn with_hashes(self, hashes: H2) -> PrintConfig

{ PrintConfig { indent_size: self.indent_size, - line_width: self.line_width, - wrapping: self.wrapping, + wrap: self.wrap, hashes, } } diff --git a/crates/ltk_ritobin/src/print/visitor.rs b/crates/ltk_ritobin/src/print/visitor.rs index da035f89..dfdab2b8 100644 --- a/crates/ltk_ritobin/src/print/visitor.rs +++ b/crates/ltk_ritobin/src/print/visitor.rs @@ -189,7 +189,7 @@ impl<'a, W: Write> CstVisitor<'a, W> { /// break the first/oldest group if running size is too big (bottom of the stack) pub fn check_running_size(&mut self) { if let Some(size) = self.size_stack.last() { - if self.col + size > self.config.line_width { + if self.col + size > self.config.wrap.line_width { self.break_first_group(); } } @@ -206,7 +206,7 @@ impl<'a, W: Write> CstVisitor<'a, W> { match cmd { Cmd::Text(s) | Cmd::TextIf(s, Mode::Flat) => { col += s.len(); - if col > self.config.line_width { + if col > self.config.wrap.line_width { return false; } } @@ -420,7 +420,7 @@ impl<'a, W: Write> CstVisitor<'a, W> { }) .count(); - if self.config.wrapping.allow_inline_structs { + if self.config.wrap.inline_structs { if let Some(last) = self.list_stack.last() { if len > 1 { self.force_group(grp, Mode::Break); @@ -452,7 +452,7 @@ impl<'a, W: Write> CstVisitor<'a, W> { self.softline(); } Kind::Entry => { - match self.config.wrapping.allow_inline_structs { + match self.config.wrap.inline_structs { true => self.softline(), false => self.line(), }; @@ -480,7 +480,7 @@ impl<'a, W: Write> CstVisitor<'a, W> { } self.end_group(); } - Kind::Entry if self.config.wrapping.allow_inline_structs => { + Kind::Entry if self.config.wrap.inline_structs => { if let Some(list) = self.list_stack.last() { if list.len > 1 { self.force_group(list.grp, Mode::Break); From ab6afd25d0f351df460e20e358e1ce81a1c15522 Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Wed, 25 Mar 2026 21:54:51 +0000 Subject: [PATCH 176/187] feat: add inline_lists config --- crates/ltk_ritobin/src/print.rs | 57 ++++++++++++++++++++++++- crates/ltk_ritobin/src/print/config.rs | 12 +++++- crates/ltk_ritobin/src/print/visitor.rs | 23 +++++++--- 3 files changed, 85 insertions(+), 7 deletions(-) diff --git a/crates/ltk_ritobin/src/print.rs b/crates/ltk_ritobin/src/print.rs index 1643f50f..09f3c9db 100644 --- a/crates/ltk_ritobin/src/print.rs +++ b/crates/ltk_ritobin/src/print.rs @@ -205,7 +205,7 @@ linked: list[string] = { "DATA/Characters/Viego/Viego.bin" r#"loadscreen: embed = CensoredImage { image: embed = Image { src: string = "val" } }"#, - PrintConfig::default().wrap(WrapConfig::default().inline_structs(false)), + PrintConfig::default().wrap(WrapConfig::default().inline_structs(true)), ); } @@ -220,4 +220,59 @@ linked: list[string] = { "DATA/Characters/Viego/Viego.bin" PrintConfig::default().wrap(WrapConfig::default().inline_structs(false)), ); } + + #[test] + fn dont_inline_simple_list_or_struct() { + assert_pretty_rt( + r#"loadscreen: embed = CensoredImage { + b: list[i8] = { + 3 + 6 + 1 + } + image: embed = Image { + src: string = "val" + } +}"#, + PrintConfig::default().wrap( + WrapConfig::default() + .inline_lists(false) + .inline_structs(false), + ), + ); + } + #[test] + fn dont_inline_simple_list_and_inline_struct() { + assert_pretty_rt( + r#"loadscreen: embed = CensoredImage { + b: list[i8] = { + 3 + 6 + 1 + } + image: embed = Image { src: string = "val" } +}"#, + PrintConfig::default().wrap( + WrapConfig::default() + .inline_lists(false) + .inline_structs(true), + ), + ); + } + #[test] + fn inline_simple_list_and_dont_inline_struct() { + assert_pretty_rt( + r#"loadscreen: embed = CensoredImage { + b: list[i8] = { 3, 6, 1 } + image: embed = Image { + src: string = "val" + } +}"#, + PrintConfig::default().wrap( + WrapConfig::default() + .inline_lists(true) + .inline_structs(false), + ), + ); + } } diff --git a/crates/ltk_ritobin/src/print/config.rs b/crates/ltk_ritobin/src/print/config.rs index 8b42b2ca..de32d246 100644 --- a/crates/ltk_ritobin/src/print/config.rs +++ b/crates/ltk_ritobin/src/print/config.rs @@ -6,8 +6,12 @@ pub struct WrapConfig { pub line_width: usize, /// Whether to allow the printing of structs/classes in one line - /// (still subject to line_width wrapping) + /// (subject to [`Self::line_width`] wrapping) pub inline_structs: bool, + + /// Whether to allow the printing of lists in one line + /// (subject to [`Self::line_width`] wrapping) + pub inline_lists: bool, } impl WrapConfig { @@ -20,6 +24,11 @@ impl WrapConfig { self.inline_structs = inline_structs; self } + + pub fn inline_lists(mut self, inline_lists: bool) -> Self { + self.inline_lists = inline_lists; + self + } } impl Default for WrapConfig { @@ -27,6 +36,7 @@ impl Default for WrapConfig { Self { line_width: 120, inline_structs: false, + inline_lists: true, } } } diff --git a/crates/ltk_ritobin/src/print/visitor.rs b/crates/ltk_ritobin/src/print/visitor.rs index dfdab2b8..4a6928b8 100644 --- a/crates/ltk_ritobin/src/print/visitor.rs +++ b/crates/ltk_ritobin/src/print/visitor.rs @@ -399,6 +399,11 @@ impl<'a, W: Write> CstVisitor<'a, W> { .iter() .filter(|n| n.tree().is_some_and(|t| t.kind == Kind::ListItem)) .count(); + + if !self.config.wrap.inline_lists { + self.force_group(grp, Mode::Break); + } + if len > 0 { self.list_stack.push(ListContext { len: len.try_into().unwrap(), @@ -410,25 +415,33 @@ impl<'a, W: Write> CstVisitor<'a, W> { Kind::Block => { // eprintln!("BLOCK: {:#?}", tree.children); let grp = self.begin_group(None); - let len = tree + let list_len = tree .children .iter() .filter(|n| { - n.tree().is_some_and(|t| { - matches!(t.kind, Kind::ListItem | Kind::ListItemBlock | Kind::Entry) - }) + n.tree() + .is_some_and(|t| matches!(t.kind, Kind::ListItem | Kind::ListItemBlock)) }) .count(); + let struct_len = tree + .children + .iter() + .filter(|n| n.tree().is_some_and(|t| matches!(t.kind, Kind::Entry))) + .count(); if self.config.wrap.inline_structs { if let Some(last) = self.list_stack.last() { - if len > 1 { + if struct_len > 1 { self.force_group(grp, Mode::Break); } else { self.force_group(last.grp, Mode::Break); } } } + if !self.config.wrap.inline_lists && list_len > 0 { + self.force_group(grp, Mode::Break); + } + let len = struct_len + list_len; if len > 0 { self.list_stack.push(ListContext { From 8ab4e6b423e11f8fb1a94c363817c9fb4d3c2f77 Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Wed, 25 Mar 2026 22:35:32 +0000 Subject: [PATCH 177/187] fix(parser): less leaky entries when unterminated string as value --- crates/ltk_ritobin/src/parse/impls.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/crates/ltk_ritobin/src/parse/impls.rs b/crates/ltk_ritobin/src/parse/impls.rs index 4be3bba0..71e73f62 100644 --- a/crates/ltk_ritobin/src/parse/impls.rs +++ b/crates/ltk_ritobin/src/parse/impls.rs @@ -121,7 +121,10 @@ pub fn entry_value(p: &mut Parser) -> bool { // }); } (UnterminatedString, _) => { - p.advance_with_error(ErrorKind::UnterminatedString, None); + p.scope(TreeKind::Literal, |p| { + p.advance_with_error(ErrorKind::UnterminatedString, None) + }); + return false; } (String | Number | HexLit | True | False | Null, _) => { p.scope(TreeKind::Literal, |p| p.advance()); From c866ca61436c32786cb8e1d033c7bcc2d123a6bf Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Wed, 25 Mar 2026 22:35:56 +0000 Subject: [PATCH 178/187] test: add unterminated string fmt test --- crates/ltk_ritobin/src/print.rs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/crates/ltk_ritobin/src/print.rs b/crates/ltk_ritobin/src/print.rs index 09f3c9db..d815f0c6 100644 --- a/crates/ltk_ritobin/src/print.rs +++ b/crates/ltk_ritobin/src/print.rs @@ -275,4 +275,20 @@ linked: list[string] = { "DATA/Characters/Viego/Viego.bin" ), ); } + + #[test] + fn unterminated_string() { + assert_pretty_rt( + r#"ConformToPathRigPoseModifierData { + mStartingJointName: hash = "L_Clavicle + mEndingJointName: hash = "l_hand" + mDefaultMaskName: hash = 0x7136e1bc + mMaxBoneAngle: f32 = 115 + mDampingValue: f32 = 8 + mVelMultiplier: f32 = 0 + mFrequency: f32 = 20 +}"#, + PrintConfig::default(), + ) + } } From 588cc86cfedbe3a751f665ed563fa0bb022da2bd Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Wed, 25 Mar 2026 22:56:26 +0000 Subject: [PATCH 179/187] fix(lex): tokenize numerics like ".5" --- crates/ltk_ritobin/src/parse/tokenizer.rs | 45 +++++++++++------------ 1 file changed, 21 insertions(+), 24 deletions(-) diff --git a/crates/ltk_ritobin/src/parse/tokenizer.rs b/crates/ltk_ritobin/src/parse/tokenizer.rs index d8b3f42f..8fd8afdc 100644 --- a/crates/ltk_ritobin/src/parse/tokenizer.rs +++ b/crates/ltk_ritobin/src/parse/tokenizer.rs @@ -251,39 +251,36 @@ pub fn lex(mut text: &str) -> Vec { } } - fn scan_number(mut s: &str) -> Option<&str> { - if let Some(rest) = s.strip_prefix('-') { - s = rest; - } - + fn take_num_segment(s: &str) -> Option<(&str, &str)> { let rest = trim(s, |c| matches!(c, '0'..='9' | '_'))?; - let int_part = &s[..s.len() - rest.len()]; + let seg = &s[..s.len() - rest.len()]; - if int_part.is_empty() - || int_part.starts_with('_') - || int_part.ends_with('_') - || int_part.contains("__") - { + if seg.is_empty() || seg.starts_with('_') || seg.ends_with('_') || seg.contains("__") { return None; } - s = rest; + Some((seg, rest)) + } + + fn scan_number(mut s: &str) -> Option<&str> { + if let Some(rest) = s.strip_prefix('-') { + s = rest; + } + // ".5" if let Some(after_dot) = s.strip_prefix('.') { - let rest = trim(after_dot, |c| matches!(c, '0'..='9' | '_'))?; - // let frac_part = &after_dot[..after_dot.len() - rest.len()]; - // - // if frac_part.is_empty() - // || frac_part.starts_with('_') - // || frac_part.ends_with('_') - // || frac_part.contains("__") - // { - // return None; - // } + let (_frac, rest) = take_num_segment(after_dot)?; + return Some(rest); + } - s = rest; + // "123" / "123.45" + let (_int, mut rest) = take_num_segment(s)?; + + if let Some(after_dot) = rest.strip_prefix('.') { + let (_frac, new_rest) = take_num_segment(after_dot)?; + rest = new_rest; } - Some(s) + Some(rest) } } From 2fa3d7738e720e9088a240753a791d90ab60d5a0 Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Wed, 25 Mar 2026 22:59:06 +0000 Subject: [PATCH 180/187] test: add nice to have case --- crates/ltk_ritobin/src/print.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/crates/ltk_ritobin/src/print.rs b/crates/ltk_ritobin/src/print.rs index d815f0c6..774d0e4d 100644 --- a/crates/ltk_ritobin/src/print.rs +++ b/crates/ltk_ritobin/src/print.rs @@ -287,6 +287,21 @@ linked: list[string] = { "DATA/Characters/Viego/Viego.bin" mDampingValue: f32 = 8 mVelMultiplier: f32 = 0 mFrequency: f32 = 20 +}"#, + PrintConfig::default(), + ) + } + + #[ignore = "nice to have"] + #[test] + fn class_body_on_new_line() { + assert_pretty( + r#"ConformToPathRigPoseModifierData + { + mFrequency: f32 = 20 +}"#, + r#"ConformToPathRigPoseModifierData { + mFrequency: f32 = 20 }"#, PrintConfig::default(), ) From 58ca3ef837e54a7a82282e155c1a74ec13b07b1c Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Wed, 25 Mar 2026 23:00:13 +0000 Subject: [PATCH 181/187] fix(typecheck): support parsing numerics with '_'s --- crates/ltk_ritobin/src/typecheck/visitor.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/crates/ltk_ritobin/src/typecheck/visitor.rs b/crates/ltk_ritobin/src/typecheck/visitor.rs index 583a3c20..1fa2df22 100644 --- a/crates/ltk_ritobin/src/typecheck/visitor.rs +++ b/crates/ltk_ritobin/src/typecheck/visitor.rs @@ -643,6 +643,8 @@ pub fn resolve_value( return Err(AmbiguousNumeric(*span)); }; + let txt = txt.replace('_', ""); + match kind_hint { K::U8 => P::U8(values::U8::new_with_meta( txt.parse::().map_err(|_| Diagnostic::ResolveLiteral)?, From 6ba23917b85e9bae7d7387423dbf2eb458aa644a Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Thu, 26 Mar 2026 20:46:53 +0000 Subject: [PATCH 182/187] fix(typecheck): remove expect() in collect_to_bin --- crates/ltk_ritobin/src/typecheck/visitor.rs | 43 ++++++++++++--------- 1 file changed, 25 insertions(+), 18 deletions(-) diff --git a/crates/ltk_ritobin/src/typecheck/visitor.rs b/crates/ltk_ritobin/src/typecheck/visitor.rs index 1fa2df22..a65cb6d7 100644 --- a/crates/ltk_ritobin/src/typecheck/visitor.rs +++ b/crates/ltk_ritobin/src/typecheck/visitor.rs @@ -810,26 +810,33 @@ impl<'a> TypeChecker<'a> { ); return None; }; - Some(map.into_entries().into_iter().filter_map(|(key, value)| { - let PropertyValueEnum::Hash(path_hash) = coerce_type(key, PropertyKind::Hash)? - else { - return None; - }; - - if let PropertyValueEnum::Embedded(values::Embedded(struct_val)) = value { - let struct_val = struct_val.no_meta(); - // eprintln!("struct_val: {struct_val:?}"); - Some(BinObject { - path_hash: *path_hash, - class_hash: struct_val.class_hash, - properties: struct_val.properties.clone(), + Some( + map.into_entries() + .into_iter() + .filter_map(|(key, value)| { + let PropertyValueEnum::Hash(path_hash) = + coerce_type(key, PropertyKind::Hash)? + else { + return None; + }; + + if let PropertyValueEnum::Embedded(values::Embedded(struct_val)) = value + { + let struct_val = struct_val.no_meta(); + // eprintln!("struct_val: {struct_val:?}"); + Some(BinObject { + path_hash: *path_hash, + class_hash: struct_val.class_hash, + properties: struct_val.properties.clone(), + }) + } else { + None + } }) - } else { - None - } - })) + .collect::>(), + ) }) - .expect("no 'entries' entry"); + .unwrap_or_default(); let tree = Bin::new(objects, Vec::::new()); From 42b3add9d52a12e784a2f86baa6a849d1feb9a59 Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Sat, 28 Mar 2026 23:13:59 +0000 Subject: [PATCH 183/187] feat: handle dependencies in typecheck/builder --- crates/ltk_ritobin/samples/aatrox.bak.rito | 1343 + crates/ltk_ritobin/samples/aatrox.rito | 1203 + .../samples/azirultsoldier.fmt.rito | 516 + .../ltk_ritobin/samples/azirultsoldier.rito | 516 + crates/ltk_ritobin/samples/cac479.rito | 645 + crates/ltk_ritobin/samples/skin0.py | 1202 + crates/ltk_ritobin/samples/skin0.rito | 1202 + crates/ltk_ritobin/samples/test.py | 14 + crates/ltk_ritobin/samples/test2.rito | 9 + crates/ltk_ritobin/samples/test3.rito | 6 + crates/ltk_ritobin/samples/test5.rito | 23 + crates/ltk_ritobin/samples/zaahen.rito | 47377 ++++++++++++++++ crates/ltk_ritobin/src/cst/builder.rs | 28 +- crates/ltk_ritobin/src/typecheck/visitor.rs | 42 +- 14 files changed, 54122 insertions(+), 4 deletions(-) create mode 100644 crates/ltk_ritobin/samples/aatrox.bak.rito create mode 100644 crates/ltk_ritobin/samples/aatrox.rito create mode 100644 crates/ltk_ritobin/samples/azirultsoldier.fmt.rito create mode 100644 crates/ltk_ritobin/samples/azirultsoldier.rito create mode 100644 crates/ltk_ritobin/samples/cac479.rito create mode 100644 crates/ltk_ritobin/samples/skin0.py create mode 100644 crates/ltk_ritobin/samples/skin0.rito create mode 100644 crates/ltk_ritobin/samples/test.py create mode 100644 crates/ltk_ritobin/samples/test2.rito create mode 100644 crates/ltk_ritobin/samples/test3.rito create mode 100644 crates/ltk_ritobin/samples/test5.rito create mode 100644 crates/ltk_ritobin/samples/zaahen.rito diff --git a/crates/ltk_ritobin/samples/aatrox.bak.rito b/crates/ltk_ritobin/samples/aatrox.bak.rito new file mode 100644 index 00000000..c98b1c32 --- /dev/null +++ b/crates/ltk_ritobin/samples/aatrox.bak.rito @@ -0,0 +1,1343 @@ +#PROP_text +type: string = "PROP" +version: u32 = 3 +linked: list[string] = { + "DATA/Aatrox_Skins_Root_Skins_Skin0_Skins_Skin1_Skins_Skin10_Skins_Skin11_Skins_Skin12_Skins_Skin13_Skins_Skin14_Skins_Skin15_Skins_Skin16_Skins_Skin17_Skins_Skin18_Skins_Skin19_Skins_Skin2_Skins_Skin20_Skins_Skin21_Skins_Skin22_Skins_Skin23_Skins_Skin24_Skins_Skin25_Skins_Skin26_Skins_Skin27_Skins_Skin28_Skins_Skin29_Skins_Skin3_Skins_Skin30_Skins_Skin31_Skins_Skin32_Skins_Skin4_Skins_Skin5_Skins_Skin6_Skins_Skin7_Skins_Skin8_Skins_Skin9.bin" + "DATA/Characters/Aatrox/Aatrox.bin" + "DATA/Aatrox_Skins_Skin0_Skins_Skin2_Skins_Skin20_Skins_Skin3_Skins_Skin30_Skins_Skin31_Skins_Skin32_Skins_Skin4_Skins_Skin5_Skins_Skin6_Skins_Skin7_Skins_Skin8.bin" + "DATA/Characters/Aatrox/Animations/Skin0.bin" + "DATA/Aatrox_Skins_Skin0_Skins_Skin1_Skins_Skin10_Skins_Skin2_Skins_Skin20_Skins_Skin3_Skins_Skin4_Skins_Skin5_Skins_Skin6_Skins_Skin7_Skins_Skin8_Skins_Skin9.bin" + "DATA/Aatrox_Skins_Skin0_Skins_Skin1_Skins_Skin2_Skins_Skin3_Skins_Skin4_Skins_Skin5_Skins_Skin6_Skins_Skin7.bin" + "DATA/Aatrox_Skins_Skin0_Skins_Skin1_Skins_Skin2_Skins_Skin20_Skins_Skin3_Skins_Skin4_Skins_Skin5_Skins_Skin6_Skins_Skin7_Skins_Skin8.bin" + "DATA/Aatrox_Skins_Skin0_Skins_Skin2_Skins_Skin20_Skins_Skin3_Skins_Skin4_Skins_Skin5_Skins_Skin6_Skins_Skin7_Skins_Skin8.bin" + "DATA/Aatrox_Skins_Skin0_Skins_Skin2_Skins_Skin3_Skins_Skin4_Skins_Skin5_Skins_Skin6.bin" + "DATA/Aatrox_Skins_Skin0_Skins_Skin1_Skins_Skin3.bin" + "DATA/Aatrox_Skins_Skin0_Skins_Skin3_Skins_Skin7.bin" + "DATA/Aatrox_Skins_Skin0_Skins_Skin3.bin" +} +entries: map[hash,embed] = { + "Characters/Aatrox/Skins/Skin0" = SkinCharacterDataProperties { + skinClassification: u32 = 1 + championSkinName: string = "Aatrox" + metaDataTags: string = "gender:male,race:darkin,element:dark" + loadscreen: embed = CensoredImage { + image: string = "ASSETS/Characters/Aatrox/Skins/Base/AatroxLoadscreen.dds" + } + skinAudioProperties: embed = skinAudioProperties { + tagEventList: list[string] = { + "Aatrox" + } + bankUnits: list2[embed] = { + BankUnit { + name: string = "Aatrox_Base_SFX" + bankPath: list[string] = { + "ASSETS/Sounds/Wwise2016/SFX/Characters/Aatrox/Skins/Base/Aatrox_Base_SFX_audio.bnk" + "ASSETS/Sounds/Wwise2016/SFX/Characters/Aatrox/Skins/Base/Aatrox_Base_SFX_events.bnk" + } + events: list[string] = { + "Play_sfx_Aatrox_AatroxBasicAttack2_OnCast" + "Play_sfx_Aatrox_AatroxBasicAttack2_OnHit" + "Play_sfx_Aatrox_AatroxBasicAttack3_OnCast" + "Play_sfx_Aatrox_AatroxBasicAttack3_OnHit" + "Play_sfx_Aatrox_AatroxBasicAttack_OnCast" + "Play_sfx_Aatrox_AatroxBasicAttack_OnHit" + "Play_sfx_Aatrox_AatroxCritAttack_OnCast" + "Play_sfx_Aatrox_AatroxCritAttack_OnHit" + "Play_sfx_Aatrox_AatroxE_OnCast" + "Play_sfx_Aatrox_AatroxPassiveAttack_OnCast" + "Play_sfx_Aatrox_AatroxPassiveAttack_OnHit" + "Play_sfx_Aatrox_AatroxPassiveDebuff_OnBuffActivate" + "Play_sfx_Aatrox_AatroxPassiveDebuff_OnBuffDeactivate" + "Play_sfx_Aatrox_AatroxPassiveReady_OnBuffActivate" + "Play_sfx_Aatrox_AatroxQ1_OnCast_all" + "Play_sfx_Aatrox_AatroxQ1_OnHit_miss" + "Play_sfx_Aatrox_AatroxQ1_OnHit_normal_all" + "Play_sfx_Aatrox_AatroxQ1_OnHit_normal_player" + "Play_sfx_Aatrox_AatroxQ1_OnHit_sweetspot_all" + "Play_sfx_Aatrox_AatroxQ1_OnHit_sweetspot_player" + "Play_sfx_Aatrox_AatroxQ2_OnCast_all" + "Play_sfx_Aatrox_AatroxQ2_OnHit_miss" + "Play_sfx_Aatrox_AatroxQ2_OnHit_normal_all" + "Play_sfx_Aatrox_AatroxQ2_OnHit_normal_player" + "Play_sfx_Aatrox_AatroxQ2_OnHit_sweetspot_all" + "Play_sfx_Aatrox_AatroxQ2_OnHit_sweetspot_player" + "Play_sfx_Aatrox_AatroxQ3_OnCast_all" + "Play_sfx_Aatrox_AatroxQ3_OnHit_miss" + "Play_sfx_Aatrox_AatroxQ3_OnHit_normal_all" + "Play_sfx_Aatrox_AatroxQ3_OnHit_normal_player" + "Play_sfx_Aatrox_AatroxQ3_OnHit_sweetspot_all" + "Play_sfx_Aatrox_AatroxQ3_OnHit_sweetspot_player" + "Play_sfx_Aatrox_AatroxR_6seconds" + "Play_sfx_Aatrox_AatroxR_buffdeactivate" + "Play_sfx_Aatrox_AatroxR_end" + "Play_sfx_Aatrox_AatroxR_OnBuffActivate_all" + "Play_sfx_Aatrox_AatroxR_OnBuffActivate_player" + "Play_sfx_Aatrox_AatroxRAttack1_OnCast" + "Play_sfx_Aatrox_AatroxRAttack1_OnHit" + "Play_sfx_Aatrox_AatroxRAttack2_OnCast" + "Play_sfx_Aatrox_AatroxRAttack2_OnHit" + "Play_sfx_Aatrox_AatroxRRevive_all" + "Play_sfx_Aatrox_AatroxRRevive_player" + "Play_sfx_Aatrox_AatroxW_OnCast" + "Play_sfx_Aatrox_AatroxW_OnHit" + "Play_sfx_Aatrox_AatroxW_OnMissileCast" + "Play_sfx_Aatrox_AatroxW_OnMissileLaunch" + "Play_sfx_Aatrox_AatroxWBump_OnBuffActivate" + "Play_sfx_Aatrox_AatroxWChains_OnBuffActivate" + "Play_sfx_Aatrox_AatroxWChains_OnBuffDeactivate" + "Play_sfx_Aatrox_Dance3D_In_buffactivate" + "Play_sfx_Aatrox_Dance3D_loop_buffactivate" + "Play_sfx_Aatrox_Death3D_cast" + "Play_sfx_Aatrox_Joke3D_buffactivate" + "Play_sfx_Aatrox_Recall3D_buffactivate" + "Play_sfx_Aatrox_Taunt3D_buffactivate" + "Set_Switch_Aatrox_R_Active" + "Set_Switch_Aatrox_R_Inactive" + "Stop_sfx_Aatrox_AatroxW_OnMissileLaunch" + "Stop_sfx_Aatrox_AatroxWBump_OnBuffActivate" + "Stop_sfx_Aatrox_AatroxWChains_OnBuffActivate" + "Stop_sfx_Aatrox_Dance3D_In_buffactivate" + "Stop_sfx_Aatrox_Joke3D_buffactivate" + "Stop_sfx_Aatrox_Recall3D_buffactivate" + "Stop_sfx_Aatrox_Taunt3D_buffactivate" + "Switch_Aatrox_Footsteps_Brush" + "Switch_Aatrox_Footsteps_Dirt" + "Switch_Aatrox_Footsteps_Stone" + "Switch_Aatrox_Footsteps_Water" + } + } + BankUnit { + name: string = "Aatrox_Base_VO" + bankPath: list[string] = { + "ASSETS/Sounds/Wwise2016/VO/en_US/Characters/Aatrox/Skins/Base/Aatrox_Base_VO_audio.bnk" + "ASSETS/Sounds/Wwise2016/VO/en_US/Characters/Aatrox/Skins/Base/Aatrox_Base_VO_events.bnk" + "ASSETS/Sounds/Wwise2016/VO/en_US/Characters/Aatrox/Skins/Base/Aatrox_Base_VO_audio.wpk" + } + events: list[string] = { + "Play_vo_Aatrox_AatroxE_cast3D" + "Play_vo_Aatrox_AatroxQ_OnCast" + "Play_vo_Aatrox_AatroxR_cast3D" + "Play_vo_Aatrox_AatroxRRevive_OnBuffCast" + "Play_vo_Aatrox_AatroxW_cast3D" + "Play_vo_Aatrox_Attack2DGeneral" + "Play_vo_Aatrox_Attack2DPantheon" + "Play_vo_Aatrox_Attack2DTryndamere" + "Play_vo_Aatrox_Attack2DZoe" + "Play_vo_Aatrox_Death3D" + "Play_vo_Aatrox_FirstEncounter3DAkali" + "Play_vo_Aatrox_FirstEncounter3DAnivia" + "Play_vo_Aatrox_FirstEncounter3DCamille" + "Play_vo_Aatrox_FirstEncounter3DDarius" + "Play_vo_Aatrox_FirstEncounter3DFiora" + "Play_vo_Aatrox_FirstEncounter3DGalio" + "Play_vo_Aatrox_FirstEncounter3DGangplank" + "Play_vo_Aatrox_FirstEncounter3DGaren" + "Play_vo_Aatrox_FirstEncounter3DGeneral" + "Play_vo_Aatrox_FirstEncounter3DIllaoi" + "Play_vo_Aatrox_FirstEncounter3DJax" + "Play_vo_Aatrox_FirstEncounter3DKaisa" + "Play_vo_Aatrox_FirstEncounter3DKayle" + "Play_vo_Aatrox_FirstEncounter3DKayn" + "Play_vo_Aatrox_FirstEncounter3DKennen" + "Play_vo_Aatrox_FirstEncounter3DKled" + "Play_vo_Aatrox_FirstEncounter3DMalphite" + "Play_vo_Aatrox_FirstEncounter3DMaokai" + "Play_vo_Aatrox_FirstEncounter3DMorgana" + "Play_vo_Aatrox_FirstEncounter3DMundo" + "Play_vo_Aatrox_FirstEncounter3DNasus" + "Play_vo_Aatrox_FirstEncounter3DNautilus" + "Play_vo_Aatrox_FirstEncounter3DOrnn" + "Play_vo_Aatrox_FirstEncounter3DPantheon" + "Play_vo_Aatrox_FirstEncounter3DQuinn" + "Play_vo_Aatrox_FirstEncounter3DRenekton" + "Play_vo_Aatrox_FirstEncounter3DRiven" + "Play_vo_Aatrox_FirstEncounter3DRumble" + "Play_vo_Aatrox_FirstEncounter3DShen" + "Play_vo_Aatrox_FirstEncounter3DSion" + "Play_vo_Aatrox_FirstEncounter3DTargon" + "Play_vo_Aatrox_FirstEncounter3DTaric" + "Play_vo_Aatrox_FirstEncounter3DTeemo" + "Play_vo_Aatrox_FirstEncounter3DTrundle" + "Play_vo_Aatrox_FirstEncounter3DTryndamere" + "Play_vo_Aatrox_FirstEncounter3DVarus" + "Play_vo_Aatrox_FirstEncounter3DVoid" + "Play_vo_Aatrox_FirstEncounter3DYorick" + "Play_vo_Aatrox_FirstEncounter3DZoe" + "Play_vo_Aatrox_Joke3DGeneral" + "Play_vo_Aatrox_Kill3DAatrox" + "Play_vo_Aatrox_Kill3DAnivia" + "Play_vo_Aatrox_Kill3DCamille" + "Play_vo_Aatrox_Kill3DDarius" + "Play_vo_Aatrox_Kill3DFiora" + "Play_vo_Aatrox_Kill3DGangplank" + "Play_vo_Aatrox_Kill3DGaren" + "Play_vo_Aatrox_Kill3DGeneral" + "Play_vo_Aatrox_Kill3DIllaoi" + "Play_vo_Aatrox_Kill3DKaisa" + "Play_vo_Aatrox_Kill3DKayle" + "Play_vo_Aatrox_Kill3DKayn" + "Play_vo_Aatrox_Kill3DKled" + "Play_vo_Aatrox_Kill3DMalphite" + "Play_vo_Aatrox_Kill3DMaokai" + "Play_vo_Aatrox_Kill3DMorgana" + "Play_vo_Aatrox_Kill3DNasus" + "Play_vo_Aatrox_Kill3DNautilus" + "Play_vo_Aatrox_Kill3DOrnn" + "Play_vo_Aatrox_Kill3DPantheon" + "Play_vo_Aatrox_Kill3DRiven" + "Play_vo_Aatrox_Kill3DShen" + "Play_vo_Aatrox_Kill3DSion" + "Play_vo_Aatrox_Kill3DTaric" + "Play_vo_Aatrox_Kill3DTeemo" + "Play_vo_Aatrox_Kill3DTryndamere" + "Play_vo_Aatrox_Kill3DVarus" + "Play_vo_Aatrox_Kill3DZoe" + "Play_vo_Aatrox_Laugh3DGeneral" + "Play_vo_Aatrox_MasteryResponse3DGeneral" + "Play_vo_Aatrox_Move2DFirstPantheon" + "Play_vo_Aatrox_Move2DLong" + "Play_vo_Aatrox_Move2DRReady" + "Play_vo_Aatrox_Move2DStandard" + "Play_vo_Aatrox_Taunt3DGeneral" + } + voiceOver: bool = true + } + } + } + skinAnimationProperties: embed = skinAnimationProperties { + animationGraphData: link = "Characters/Aatrox/Animations/Skin0" + } + skinMeshProperties: embed = SkinMeshDataProperties { + skeleton: string = "ASSETS/Characters/Aatrox/Skins/Base/Aatrox.skl" + simpleSkin: string = "ASSETS/Characters/Aatrox/Skins/Base/Aatrox.skn" + texture: string = "ASSETS/Characters/Aatrox/Skins/Base/Aatrox_Base_TX_CM.dds" + skinScale: f32 = 1.09000003 + selfIllumination: f32 = 0.699999988 + brushAlphaOverride: f32 = 0.550000012 + overrideBoundingBox: option[vec3] = { + { 130, 250, 130 } + } + material: link = "Characters/Aatrox/Skins/Skin0/Materials/Aatrox_VFXBase_inst" + reflectionFresnelColor: rgba = { 0, 0, 0, 255 } + initialSubmeshToHide: string = "Wings" + initialSubmeshShadowsToHide: string = "Banner" + materialOverride: list[embed] = { + SkinMeshDataProperties_MaterialOverride { + material: link = "Characters/Aatrox/Skins/Skin0/Materials/Sword_inst" + submesh: string = "Sword" + } + SkinMeshDataProperties_MaterialOverride { + material: link = "Characters/Aatrox/Skins/Skin0/Materials/Wing_inst" + submesh: string = "Wings" + } + SkinMeshDataProperties_MaterialOverride { + material: link = "Characters/Aatrox/Skins/Skin0/Materials/Banner_inst" + submesh: string = "Banner" + } + } + rigPoseModifierData: list[pointer] = { + ConformToPathRigPoseModifierData { + mStartingJointName: hash = "L_Wing_Banner_Ground1" + mEndingJointName: hash = "L_Wing_Banner_Ground4" + mDefaultMaskName: hash = "empty" + mMaxBoneAngle: f32 = 150 + mVelMultiplier: f32 = 0 + mFrequency: f32 = 5 + } + ConformToPathRigPoseModifierData { + mStartingJointName: hash = "R_Wing_Banner_Ground1" + mEndingJointName: hash = "R_Wing_Banner_Ground4" + mDefaultMaskName: hash = "empty" + mMaxBoneAngle: f32 = 150 + mVelMultiplier: f32 = 0 + mFrequency: f32 = 5 + } + } + } + armorMaterial: string = "Flesh" + defaultAnimations: list[string] = { + "BaseBuffPose" + } + mContextualActionData: link = "Characters/Aatrox/CAC/Aatrox_Base" + iconCircle: option[string] = { + "ASSETS/Characters/Aatrox/HUD/Aatrox_Circle.dds" + } + iconSquare: option[string] = { + "ASSETS/Characters/Aatrox/HUD/Aatrox_Square.dds" + } + healthBarData: embed = CharacterHealthBarDataRecord { + attachToBone: string = "Buffbone_Cstm_Healthbar" + unitHealthBarStyle: u8 = 10 + } + mResourceResolver: link = "Characters/Aatrox/Skins/Skin0/Resources" + PersistentEffectConditions: list2[pointer] = { + PersistentEffectConditionData { + OwnerCondition: pointer = HasBuffDynamicMaterialBoolDriver { + Spell: hash = "Characters/Aatrox/Spells/AatroxPassiveAbility/AatroxPassiveReady" + } + PersistentVfxs: list2[embed] = { + PersistentVfxData { + boneName: string = "Weapon_Heart" + effectKey: hash = "Aatrox_P_Ready" + } + } + } + } + } + "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_E_Active_buff" = VfxSystemDefinitionData { + complexEmitterDefinitionData: list[pointer] = { + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 1.5 + } + particleLinger: option[f32] = { + 1 + } + lifetime: option[f32] = { + 1 + } + isSingleParticle: flag = true + emitterName: string = "Avatar" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + primitive: pointer = VfxPrimitiveAttachedMesh { + mMesh: embed = VfxMeshDefinitionData { + mSubmeshesToDraw: list[hash] = { + "BODY" + "Shoulder" + } + } + } + blendMode: u8 = 1 + color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { + 0 + 0.100000001 + 0.899999976 + 1 + } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + depthBiasFactors: vec2 = { -1, -1 } + disableBackfaceCull: bool = true + particleIsLocalOrientation: flag = true + isUniformScale: flag = true + isRandomStartFrame: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 1.00100005, 1.00100005, 1.00100005 } + } + texture: string = "ASSETS/Characters/Aatrox/Skins/Base/Particles/Aatrox_Base_E_buff_avatar.dds" + uvMode: u8 = 2 + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.25 + } + particleLinger: option[f32] = { + 1 + } + lifetime: option[f32] = { + 1 + } + isSingleParticle: flag = true + emitterName: string = "Avatar_activate" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + primitive: pointer = VfxPrimitiveAttachedMesh { + mMesh: embed = VfxMeshDefinitionData { + mSubmeshesToDraw: list[hash] = { + "BODY" + "Shoulder" + } + } + } + blendMode: u8 = 4 + color: embed = ValueColor { + constantValue: vec4 = { 1, 1, 1, 0.650003791 } + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { + 0 + 0.100000001 + 0.800000012 + 1 + } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 0.650003791 } + { 1, 1, 1, 0.650003791 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = 1 + disableBackfaceCull: bool = true + particleIsLocalOrientation: flag = true + isUniformScale: flag = true + isRandomStartFrame: flag = true + uvScrollClamp: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 1.00999999, 1.00999999, 1.00999999 } + } + texture: string = "ASSETS/Characters/Aatrox/Skins/Base/Particles/Aatrox_Base_E_buff_avatar_sheen.dds" + uvMode: u8 = 2 + birthUvScrollRate: embed = ValueVector2 { + constantValue: vec2 = { 0, 2 } + } + texAddressModeBase: u8 = 2 + } + } + particleName: string = "Aatrox_Base_E_Active_buff" + particlePath: string = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_E_Active_buff" + } + "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_E_Dash" = VfxSystemDefinitionData { + complexEmitterDefinitionData: list[pointer] = { + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.300000012 + } + particleLinger: option[f32] = { + 0.200000003 + } + lifetime: option[f32] = { + 1.10000002 + } + isSingleParticle: flag = true + emitterName: string = "Avatar" + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, 50 } + } + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + primitive: pointer = VfxPrimitiveAttachedMesh { + mMesh: embed = VfxMeshDefinitionData { + mSubmeshesToDraw: list[hash] = { + "BODY" + } + } + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 1, 1, 0.500007629 } + } + color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { + 0 + 0.100000001 + 0.5 + 1 + } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0.300007641 } + { 1, 1, 1, 0 } + } + } + } + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { + 0 + 0.200000003 + 1 + } + values: list[f32] = { + 0 + 0 + 0.5 + } + } + } + erosionFeatherOut: f32 = 0.300000012 + erosionMapName: string = "ASSETS/Characters/Aatrox/Skins/Base/Particles/Aatrox_Base_Q_SmokeErode.dds" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + disableBackfaceCull: bool = true + particleIsLocalOrientation: flag = true + isUniformScale: flag = true + isRandomStartFrame: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 1.00999999, 1, 1 } + } + texture: string = "ASSETS/Characters/Aatrox/Skins/Base/Aatrox_Base_TX_CM.dds" + numFrames: u16 = 4 + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.300000012 + } + particleLinger: option[f32] = { + 0.200000003 + } + lifetime: option[f32] = { + 1.10000002 + } + isSingleParticle: flag = true + emitterName: string = "Avatar1" + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, 50 } + } + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + primitive: pointer = VfxPrimitiveAttachedMesh { + mMesh: embed = VfxMeshDefinitionData { + mSubmeshesToDraw: list[hash] = { + "Sword" + } + } + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 1, 1, 0.500007629 } + } + color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { + 0 + 0.100000001 + 0.5 + 1 + } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0.300007641 } + { 1, 1, 1, 0 } + } + } + } + disableBackfaceCull: bool = true + particleIsLocalOrientation: flag = true + isUniformScale: flag = true + isRandomStartFrame: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 1.00999999, 1, 1 } + } + texture: string = "ASSETS/Characters/Aatrox/Skins/Base/Aatrox_Base_Sword_TX_CM.dds" + numFrames: u16 = 4 + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.300000012 + } + particleLinger: option[f32] = { + 0.200000003 + } + lifetime: option[f32] = { + 1.10000002 + } + isSingleParticle: flag = true + emitterName: string = "Avatar2" + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, 50 } + } + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + primitive: pointer = VfxPrimitiveAttachedMesh { + mMesh: embed = VfxMeshDefinitionData { + mSubmeshesToDraw: list[hash] = { + "Wings" + } + } + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 1, 1, 0.500007629 } + } + color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { + 0 + 0.100000001 + 0.5 + 1 + } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0.300007641 } + { 1, 1, 1, 0 } + } + } + } + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { + 0 + 0.200000003 + 1 + } + values: list[f32] = { + 0 + 0 + 0.5 + } + } + } + erosionFeatherOut: f32 = 0.300000012 + erosionMapName: string = "ASSETS/Characters/Aatrox/Skins/Base/Particles/Aatrox_Base_Q_SmokeErode.dds" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + disableBackfaceCull: bool = true + particleIsLocalOrientation: flag = true + isUniformScale: flag = true + isRandomStartFrame: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 1.00999999, 1, 1 } + } + texture: string = "ASSETS/Characters/Aatrox/Skins/Base/Aatrox_Wings_TX_CM.dds" + numFrames: u16 = 4 + } + } + particleName: string = "Aatrox_Base_E_Dash" + particlePath: string = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_E_Dash" + mIsPoseAfterimage: bool = true + } + "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_P_Ready" = VfxSystemDefinitionData { + complexEmitterDefinitionData: list[pointer] = { + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.699999988 + } + particleLinger: option[f32] = { + 1 + } + emitterName: string = "Basic" + importance: u8 = 2 + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + blendMode: u8 = 4 + color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { + 0 + 0.400000006 + 1 + } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 0.330006868, 0, 0, 1 } + } + } + } + depthBiasFactors: vec2 = { -1, -2 } + isUniformScale: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 1, 0, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { + 0 + 1 + } + keyValues: list[f32] = { + 0 + 360 + } + } + VfxProbabilityTableData {} + VfxProbabilityTableData {} + } + times: list[f32] = { + 0 + } + values: list[vec3] = { + { 1, 0, 0 } + } + } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 150, 100, 100 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { + 0 + 1 + } + keyValues: list[f32] = { + 0.5 + 1 + } + } + VfxProbabilityTableData {} + VfxProbabilityTableData {} + } + times: list[f32] = { + 0 + } + values: list[vec3] = { + { 150, 100, 100 } + } + } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { + 0 + 0.200000003 + 1 + } + values: list[vec3] = { + { 0.25, 0.25, 2.5 } + { 1, 1, 1 } + { 0.25, 0.25, 0.25 } + } + } + } + texture: string = "ASSETS/Characters/Aatrox/Skins/Base/Particles/Aatrox_Base_TEMP_Diana_Skin11_W_FaintGlow.dds" + paletteDefinition: pointer = VfxPaletteDefinitionData { + paletteTexture: string = "ASSETS/Characters/Aatrox/Skins/Base/Particles/Aatrox_Base_AA_Gradient_RGB.dds" + palleteSrcMixColor: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + paletteSelector: embed = ValueVector3 { + constantValue: vec3 = { 2, 0, 0 } + } + paletteCount: i32 = 8 + } + } + } + particleName: string = "Aatrox_Base_P_Ready" + particlePath: string = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_P_Ready" + } + "Characters/Aatrox/Skins/Skin0/Materials/Sword_inst" = StaticMaterialDef { + name: string = "Characters/Aatrox/Skins/Skin0/Materials/Sword_inst" + samplerValues: list2[embed] = { + StaticMaterialShaderSamplerDef { + samplerName: string = "Diffuse_Texture" + textureName: string = "ASSETS/Characters/Aatrox/Skins/Base/Aatrox_Base_Sword_TX_CM.dds" + addressU: u32 = 1 + addressV: u32 = 1 + addressW: u32 = 1 + } + StaticMaterialShaderSamplerDef { + samplerName: string = "Mask_Texture" + textureName: string = "ASSETS/Characters/Aatrox/Skins/Base/Particles/Aatrox_Base_P_Sword_Mask.dds" + addressW: u32 = 1 + } + StaticMaterialShaderSamplerDef { + samplerName: string = "Gradient_Texture" + textureName: string = "ASSETS/Shared/Materials/Gradient_test_01.dds" + addressU: u32 = 1 + addressV: u32 = 1 + } + } + paramValues: list2[embed] = { + StaticMaterialShaderParamDef { + name: string = "Mask_Intensity" + value: vec4 = { 0.792500019, 0, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Bloom_Intensity" + value: vec4 = { 4, 0, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Scrolling_Scale" + value: vec4 = { 1, 1, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Scrolling_Rate" + value: vec4 = { 0, -1, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Color" + value: vec4 = { 1, 0.301960796, 0.0274509806, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Dissolve_Bias" + value: vec4 = { -1, 0, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Dissolve_SmoothStep" + value: vec4 = { 0, 0.200000003, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Gradient_Sharpness" + value: vec4 = { 0.400000006, 0, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Alpha_Sharpness" + value: vec4 = { 0.00100000005, 0, 0, 0 } + } + } + switches: list2[embed] = { + StaticMaterialSwitchDef { + name: string = "USE_COLORDODGE" + on: bool = false + } + StaticMaterialSwitchDef { + name: string = "USE_ADDATIVE" + } + StaticMaterialSwitchDef { + name: string = "USE_LERP" + on: bool = false + } + StaticMaterialSwitchDef { + name: string = "USE_DISSOLVE" + on: bool = false + } + } + shaderMacros: map[string,string] = { + "NUM_BLEND_WEIGHTS" = "4" + } + techniques: list[embed] = { + StaticMaterialTechniqueDef { + name: string = "normal" + passes: list[embed] = { + StaticMaterialPassDef { + shader: link = "Shaders/SkinnedMesh/Scrolling_ColorDodge_Masked" + blendEnable: bool = true + srcColorBlendFactor: u32 = 6 + srcAlphaBlendFactor: u32 = 6 + dstColorBlendFactor: u32 = 7 + dstAlphaBlendFactor: u32 = 7 + } + } + } + } + childTechniques: list[embed] = { + StaticMaterialChildTechniqueDef { + name: string = "transition" + parentName: string = "normal" + shaderMacros: map[string,string] = { + "TRANSITION" = "1" + } + } + } + dynamicMaterial: pointer = DynamicMaterialDef { + parameters: list[embed] = { + DynamicMaterialParameterDef { + name: string = "Mask_Intensity" + driver: pointer = LerpMaterialDriver { + mBoolDriver: pointer = HasBuffDynamicMaterialBoolDriver { + mScriptName: string = "AatroxPassiveReady" + } + mOnValue: f32 = 0.75 + mTurnOffTimeSec: f32 = 0.200000003 + } + } + } + } + } + "Characters/Aatrox/Skins/Skin0/Materials/Banner_inst" = StaticMaterialDef { + name: string = "Characters/Aatrox/Skins/Skin0/Materials/Banner_inst" + samplerValues: list2[embed] = { + StaticMaterialShaderSamplerDef { + samplerName: string = "Diffuse_Texture" + textureName: string = "ASSETS/Characters/Aatrox/Skins/Base/Particles/Aatrox_Base_I_Banner_color.dds" + addressU: u32 = 1 + addressV: u32 = 1 + addressW: u32 = 1 + } + StaticMaterialShaderSamplerDef { + samplerName: string = "Mask_Texture" + textureName: string = "ASSETS/Characters/Aatrox/Skins/Base/Particles/Aatrox_Base_I_Banner.dds" + addressW: u32 = 1 + } + } + paramValues: list2[embed] = { + StaticMaterialShaderParamDef { + name: string = "UV_Scale" + value: vec4 = { 1, 1, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Scroll_Speed" + value: vec4 = { 0, -0.300000012, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Alpha_Bias" + value: vec4 = { 0.300000012, 0, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "UV_Scale_BLUE" + value: vec4 = { 1, 1, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Scroll_Speed_BLUE" + value: vec4 = { 0, -0.200000003, 0, 0 } + } + } + switches: list2[embed] = { + StaticMaterialSwitchDef { + name: string = "MULTIPLY_ADD" + on: bool = false + } + StaticMaterialSwitchDef { + name: string = "USE_RED_TO_ALPHA" + } + StaticMaterialSwitchDef { + name: string = "USE_BLUE_CHANNEL" + } + } + shaderMacros: map[string,string] = { + "NUM_BLEND_WEIGHTS" = "4" + } + techniques: list[embed] = { + StaticMaterialTechniqueDef { + name: string = "normal" + passes: list[embed] = { + StaticMaterialPassDef { + shader: link = "Shaders/SkinnedMesh/ScrollingCustomAlpha" + blendEnable: bool = true + srcColorBlendFactor: u32 = 6 + srcAlphaBlendFactor: u32 = 6 + dstColorBlendFactor: u32 = 7 + dstAlphaBlendFactor: u32 = 7 + } + } + } + } + childTechniques: list[embed] = { + StaticMaterialChildTechniqueDef { + name: string = "transition" + parentName: string = "normal" + shaderMacros: map[string,string] = { + "TRANSITION" = "1" + } + } + } + } + "Characters/Aatrox/Skins/Skin0/Materials/Aatrox_VFXBase_inst" = StaticMaterialDef { + name: string = "Characters/Aatrox/Skins/Skin0/Materials/Aatrox_VFXBase_inst" + samplerValues: list2[embed] = { + StaticMaterialShaderSamplerDef { + samplerName: string = "Diffuse_Texture" + textureName: string = "ASSETS/Characters/Aatrox/Skins/Base/Aatrox_Base_TX_CM.dds" + addressU: u32 = 1 + addressV: u32 = 1 + addressW: u32 = 1 + } + StaticMaterialShaderSamplerDef { + samplerName: string = "Mask_Texture" + textureName: string = "ASSETS/Characters/Aatrox/Skins/Base/Particles/Aatrox_Base_R_body_mask.dds" + addressU: u32 = 1 + addressV: u32 = 1 + addressW: u32 = 1 + } + StaticMaterialShaderSamplerDef { + samplerName: string = "Gradient_Texture" + textureName: string = "ASSETS/Shared/Materials/Gradient_test_01.dds" + addressU: u32 = 1 + addressV: u32 = 1 + addressW: u32 = 1 + } + } + paramValues: list2[embed] = { + StaticMaterialShaderParamDef { + name: string = "Dissolve_SmoothStep" + value: vec4 = { 0, 0.150000006, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Dissolve_Bias" + value: vec4 = { -0.200000003, 0, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Pulse_Rate" + value: vec4 = { 3, 0, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Pulse_Max" + value: vec4 = { 0.400000006, 0, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Gradient_Sharpness" + value: vec4 = { 0.5, 0, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Alpha_Sharpness" + value: vec4 = { 0.00100000005, 0, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Bloom_Intensity" + value: vec4 = { 10, 0, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Pulse_Offset" + value: vec4 = { 0.300000012, 0, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Alpha" + value: vec4 = { 1, 0, 0, 0 } + } + } + shaderMacros: map[string,string] = { + "NUM_BLEND_WEIGHTS" = "4" + } + techniques: list[embed] = { + StaticMaterialTechniqueDef { + name: string = "normal" + passes: list[embed] = { + StaticMaterialPassDef { + shader: link = "Shaders/SkinnedMesh/Aatrox_VFXBase" + blendEnable: bool = true + srcColorBlendFactor: u32 = 6 + srcAlphaBlendFactor: u32 = 6 + dstColorBlendFactor: u32 = 7 + dstAlphaBlendFactor: u32 = 7 + } + } + } + } + childTechniques: list[embed] = { + StaticMaterialChildTechniqueDef { + name: string = "transition" + parentName: string = "normal" + shaderMacros: map[string,string] = { + "TRANSITION" = "1" + } + } + } + dynamicMaterial: pointer = DynamicMaterialDef { + parameters: list[embed] = { + DynamicMaterialParameterDef { + name: string = "Dissolve_Bias" + driver: pointer = MaxMaterialDriver { + mDrivers: list[pointer] = { + FloatGraphMaterialDriver { + driver: pointer = LerpMaterialDriver { + mBoolDriver: pointer = IsDeadDynamicMaterialBoolDriver {} + mTurnOnTimeSec: f32 = 4 + mTurnOffTimeSec: f32 = 0 + } + graph: embed = VfxAnimatedFloatVariableData { + times: list[f32] = { + 0.00171930937 + 0.216738746 + 0.766768217 + 1.00488436 + } + values: list[f32] = { + -0.22144419 + 0.260138661 + 0.752247512 + 0.86541003 + } + } + } + FloatGraphMaterialDriver { + driver: pointer = LerpMaterialDriver { + mBoolDriver: pointer = IsAnimationPlayingDynamicMaterialBoolDriver { + mAnimationNames: list[hash] = { + "Passive_Death" + } + } + mTurnOnTimeSec: f32 = 3 + } + graph: embed = VfxAnimatedFloatVariableData { + times: list[f32] = { + 0.00321787666 + 0.381477386 + 0.997775316 + } + values: list[f32] = { + -0.225780264 + 0.583815038 + 0.994219661 + } + } + } + } + } + } + DynamicMaterialParameterDef { + name: string = "Pulse_Rate" + driver: pointer = LerpMaterialDriver { + mBoolDriver: pointer = HasBuffDynamicMaterialBoolDriver { + mScriptName: string = "AatroxR" + } + mOnValue: f32 = 5 + mTurnOnTimeSec: f32 = 0 + mTurnOffTimeSec: f32 = 0 + } + } + } + } + } + "Characters/Aatrox/Skins/Skin0/Materials/Wing_inst" = StaticMaterialDef { + name: string = "Characters/Aatrox/Skins/Skin0/Materials/Wing_inst" + samplerValues: list2[embed] = { + StaticMaterialShaderSamplerDef { + samplerName: string = "Diffuse_Texture" + textureName: string = "ASSETS/Characters/Aatrox/Skins/Base/Aatrox_Wings_TX_CM.dds" + addressU: u32 = 1 + addressV: u32 = 1 + addressW: u32 = 1 + } + StaticMaterialShaderSamplerDef { + samplerName: string = "Mask_Texture" + textureName: string = "ASSETS/Characters/Aatrox/Skins/Base/Particles/Aatrox_Base_R_wing_mask.dds" + addressW: u32 = 1 + } + StaticMaterialShaderSamplerDef { + samplerName: string = "Gradient_Texture" + textureName: string = "ASSETS/Characters/Aatrox/Skins/Base/Particles/Aatrox_Base_R_mat_gradient.dds" + addressU: u32 = 1 + addressV: u32 = 1 + } + } + paramValues: list2[embed] = { + StaticMaterialShaderParamDef { + name: string = "Mask_Intensity" + value: vec4 = { 0.939999998, 0, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Bloom_Intensity" + value: vec4 = { 5, 0, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Scrolling_Scale" + value: vec4 = { 1, 1, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Scrolling_Rate" + value: vec4 = { -0.5, -0.5, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Color" + value: vec4 = { 1, 0.250980407, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Dissolve_Bias" + value: vec4 = { 0.785000026, 0, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Dissolve_SmoothStep" + value: vec4 = { 0, 0.5, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Gradient_Sharpness" + value: vec4 = { 2, 0, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Alpha_Sharpness" + value: vec4 = { 0.00100000005, 0, 0, 0 } + } + } + switches: list2[embed] = { + StaticMaterialSwitchDef { + name: string = "USE_COLORDODGE" + on: bool = false + } + StaticMaterialSwitchDef { + name: string = "USE_ADDATIVE" + } + StaticMaterialSwitchDef { + name: string = "USE_LERP" + on: bool = false + } + StaticMaterialSwitchDef { + name: string = "USE_DISSOLVE" + } + } + shaderMacros: map[string,string] = { + "NUM_BLEND_WEIGHTS" = "4" + } + techniques: list[embed] = { + StaticMaterialTechniqueDef { + name: string = "normal" + passes: list[embed] = { + StaticMaterialPassDef { + shader: link = "Shaders/SkinnedMesh/Scrolling_ColorDodge_Masked" + blendEnable: bool = true + srcColorBlendFactor: u32 = 6 + srcAlphaBlendFactor: u32 = 6 + dstColorBlendFactor: u32 = 7 + dstAlphaBlendFactor: u32 = 7 + } + } + } + } + childTechniques: list[embed] = { + StaticMaterialChildTechniqueDef { + name: string = "transition" + parentName: string = "normal" + shaderMacros: map[string,string] = { + "TRANSITION" = "1" + } + } + } + dynamicMaterial: pointer = DynamicMaterialDef { + parameters: list[embed] = { + DynamicMaterialParameterDef { + name: string = "Dissolve_Bias" + driver: pointer = SwitchMaterialDriver { + mElements: list[embed] = { + SwitchMaterialDriverElement { + mCondition: pointer = HasBuffDynamicMaterialBoolDriver { + mScriptName: string = "AatroxRFX" + } + mValue: pointer = LerpMaterialDriver { + mBoolDriver: pointer = HasBuffDynamicMaterialBoolDriver { + mScriptName: string = "AatroxRFX" + mDeactivateEarlySeconds: f32 = 1 + } + mOnValue: f32 = -1 + mOffValue: f32 = 1 + mTurnOnTimeSec: f32 = 2 + } + } + SwitchMaterialDriverElement { + mCondition: pointer = HasBuffDynamicMaterialBoolDriver { + mScriptName: string = "AatroxRReviveMaterialOverride" + } + mValue: pointer = LerpMaterialDriver { + mBoolDriver: pointer = HasBuffDynamicMaterialBoolDriver { + mScriptName: string = "AatroxRReviveMaterialOverride" + } + mOffValue: f32 = -0.180000007 + mTurnOnTimeSec: f32 = 6 + mTurnOffTimeSec: f32 = 0 + } + } + SwitchMaterialDriverElement { + mCondition: pointer = IsAnimationPlayingDynamicMaterialBoolDriver { + mAnimationNames: list[hash] = { + 0x909068b6 + } + } + mValue: pointer = LerpMaterialDriver { + mBoolDriver: pointer = IsAnimationPlayingDynamicMaterialBoolDriver { + mAnimationNames: list[hash] = { + 0x909068b6 + } + } + mOnValue: f32 = -1 + mOffValue: f32 = 1 + mTurnOnTimeSec: f32 = 0.200000003 + mTurnOffTimeSec: f32 = 0.200000003 + } + } + SwitchMaterialDriverElement { + mCondition: pointer = IsAnimationPlayingDynamicMaterialBoolDriver { + mAnimationNames: list[hash] = { + "taunt" + } + } + mValue: pointer = LerpMaterialDriver { + mBoolDriver: pointer = IsAnimationPlayingDynamicMaterialBoolDriver { + mAnimationNames: list[hash] = { + "taunt" + } + } + mOnValue: f32 = -1 + mOffValue: f32 = 1 + mTurnOnTimeSec: f32 = 0.200000003 + mTurnOffTimeSec: f32 = 0.200000003 + } + } + } + mDefaultValue: pointer = FloatLiteralMaterialDriver { + mValue: f32 = 1 + } + } + } + } + } + } + "Characters/Aatrox/Skins/Skin0/Resources" = ResourceResolver { + resourceMap: map[hash,link] = { + "Aatrox_Q_Indicator_01" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_Q_Indicator_01" + 0x4c250437 = "Characters/Kayn/Skins/Skin0/Particles/Kayn_Base_Primary_R_tar_child" + "Aatrox_Q_cas1" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_Q_cas1" + "Aatrox_Q_cas3" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_Q_cas3" + "Aatrox_Q_cas2" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_Q_cas2" + "Aatrox_AA_Trail_01" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_AA_Trail_01" + "Aatrox_AA_Trail_03" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_AA_Trail_03" + "Aatrox_AA_Trail_02" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_AA_Trail_02" + 0x57532b4b = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_AA_Hit_Tar01" + 0x58532cde = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_AA_Hit_Tar02" + "Aatrox_W_mis" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_W_mis" + "Aatrox_W_Beam_Tar" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_W_Beam_Tar" + "Aatrox_W_Core" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_W_Core" + "Aatrox_Q_Indicator_02" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_Q_Indicator_02" + "Aatrox_Q_Indicator_03" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_Q_Indicator_03" + "Aatrox_E_Dash" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_E_Dash" + "Aatrox_E_Active_buff" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_E_Active_buff" + "Aatrox_Q_Trail_01" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_Q_Trail_01" + "Aatrox_Q_Trail_02" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_Q_Trail_02" + "Aatrox_Q_Trail_03" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_Q_Trail_03" + "Aatrox_Q_Indicator_01_Ally" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_Q_Indicator_01_Ally" + "Aatrox_Q_Indicator_02_Ally" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_Q_Indicator_02_Ally" + "Aatrox_Q_Indicator_03_Ally" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_Q_Indicator_03_Ally" + "Aatrox_P_Ready" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_P_Ready" + "Aatrox_R_Fear" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_R_Fear" + "Aatrox_P_Activate" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_P_Activate" + "Aatrox_E_Heal" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_E_Heal" + "Aatrox_Death_ambers" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_Death_ambers" + "Aatrox_R_Attack_01" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_R_Attack_01" + "Aatrox_P_Hit_Tar" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_P_Hit_Tar" + "Aatrox_R_Attack_02" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_R_Attack_02" + "Aatrox_W_Cas" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_W_Cas" + "Aatrox_E_Dash_trail" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_E_Dash_trail" + "Aatrox_E_Dash2" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_E_Dash2" + "Aatrox_W_Hand_glow_cas" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_W_Hand_glow_cas" + "Aatrox_Q_Hit_Tar" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_Q_Hit_Tar" + "Aatrox_Q_Sweet_hit_tar" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_Q_Sweet_hit_tar" + "Aatrox_W_Core_Area" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_W_Core_Area" + "Aatrox_P_Attack_trail" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_P_Attack_trail" + "Aatrox_R_Revive_end" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_R_Revive_end" + "Aatrox_E_Buf_Sword" = 0x00000000 + "Aatrox_Passive_Sheathe_Sword" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_Passive_Sheathe_Sword" + "Aatrox_R_Revive_Duration" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_R_Revive_Duration" + "Aatrox_R_Revive_Diration_Sword" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_R_Revive_Diration_Sword" + "Aatrox_R_SpeedBuff" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_R_SpeedBuff" + "Aatrox_P_Debuff" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_P_Debuff" + "Aatrox_Recall_Ground" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_Recall_Ground" + "Aatrox_Recall_Beam" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_Recall_Beam" + "Aatrox_Recall_Weapon_glow" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_Recall_Weapon_glow" + "Aatrox_Recall_Hand_glow" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_Recall_Hand_glow" + "Aatrox_W_Core_End" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_W_Core_End" + "Aatrox_W_Beam_Tar_Break" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_W_Beam_Tar_Break" + "Aatrox_W_Hit_Tar" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_W_Hit_Tar" + "Aatrox_W_Beam_Tar_Pull" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_W_Beam_Tar_Pull" + "Aatrox_AA_Crit_Hit_Tar" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_AA_Crit_Hit_Tar" + "Aatrox_AA_Crit_Trail" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_AA_Crit_Trail" + "Aatrox_Dance_Ground" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_Dance_Ground" + "Aatrox_Taunt_Ground" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_Taunt_Ground" + 0x5b2b3b83 = "Maps/Particles/SRX/Base/SRX_Audio_Hextech_Storm_loop" + 0x2c43403d = "Maps/Particles/SR/SRU_Braziers_Chemtech_Child_02" + 0x20bae730 = "Maps/Shipping/Map22/Particles/Set9/TFT9_Trait_Demacia_Celebration_Child7" + } + } +} diff --git a/crates/ltk_ritobin/samples/aatrox.rito b/crates/ltk_ritobin/samples/aatrox.rito new file mode 100644 index 00000000..aa2600eb --- /dev/null +++ b/crates/ltk_ritobin/samples/aatrox.rito @@ -0,0 +1,1203 @@ +#PROP_text +type: string = "PROP" +version: u32 = 3 +linked: list[string] = { + "DATA/Aatrox_Skins_Root_Skins_Skin0_Skins_Skin1_Skins_Skin10_Skins_Skin11_Skins_Skin12_Skins_Skin13_Skins_Skin14_Skins_Skin15_Skins_Skin16_Skins_Skin17_Skins_Skin18_Skins_Skin19_Skins_Skin2_Skins_Skin20_Skins_Skin21_Skins_Skin22_Skins_Skin23_Skins_Skin24_Skins_Skin25_Skins_Skin26_Skins_Skin27_Skins_Skin28_Skins_Skin29_Skins_Skin3_Skins_Skin30_Skins_Skin31_Skins_Skin32_Skins_Skin4_Skins_Skin5_Skins_Skin6_Skins_Skin7_Skins_Skin8_Skins_Skin9.bin" + "DATA/Characters/Aatrox/Aatrox.bin" + "DATA/Aatrox_Skins_Skin0_Skins_Skin2_Skins_Skin20_Skins_Skin3_Skins_Skin30_Skins_Skin31_Skins_Skin32_Skins_Skin4_Skins_Skin5_Skins_Skin6_Skins_Skin7_Skins_Skin8.bin" + "DATA/Characters/Aatrox/Animations/Skin0.bin" + "DATA/Aatrox_Skins_Skin0_Skins_Skin1_Skins_Skin10_Skins_Skin2_Skins_Skin20_Skins_Skin3_Skins_Skin4_Skins_Skin5_Skins_Skin6_Skins_Skin7_Skins_Skin8_Skins_Skin9.bin" + "DATA/Aatrox_Skins_Skin0_Skins_Skin1_Skins_Skin2_Skins_Skin3_Skins_Skin4_Skins_Skin5_Skins_Skin6_Skins_Skin7.bin" + "DATA/Aatrox_Skins_Skin0_Skins_Skin1_Skins_Skin2_Skins_Skin20_Skins_Skin3_Skins_Skin4_Skins_Skin5_Skins_Skin6_Skins_Skin7_Skins_Skin8.bin" + "DATA/Aatrox_Skins_Skin0_Skins_Skin2_Skins_Skin20_Skins_Skin3_Skins_Skin4_Skins_Skin5_Skins_Skin6_Skins_Skin7_Skins_Skin8.bin" + "DATA/Aatrox_Skins_Skin0_Skins_Skin2_Skins_Skin3_Skins_Skin4_Skins_Skin5_Skins_Skin6.bin" + "DATA/Aatrox_Skins_Skin0_Skins_Skin1_Skins_Skin3.bin" + "DATA/Aatrox_Skins_Skin0_Skins_Skin3_Skins_Skin7.bin" + "DATA/Aatrox_Skins_Skin0_Skins_Skin3.bin" +} +entries: map[hash, embed] = { + "Characters/Aatrox/Skins/Skin0" = SkinCharacterDataProperties { + skinClassification: u32 = 1 + championSkinName: string = "Aatrox" + metaDataTags: string = "gender:male,race:darkin,element:dark" + loadscreen: embed = CensoredImage { + image: string = "ASSETS/Characters/Aatrox/Skins/Base/AatroxLoadscreen.dds" + } + skinAudioProperties: embed = skinAudioProperties { + tagEventList: list[string] = { "Aatrox" } + bankUnits: list2[embed] = { + BankUnit { + name: string = "Aatrox_Base_SFX" + bankPath: list[string] = { + "ASSETS/Sounds/Wwise2016/SFX/Characters/Aatrox/Skins/Base/Aatrox_Base_SFX_audio.bnk" + "ASSETS/Sounds/Wwise2016/SFX/Characters/Aatrox/Skins/Base/Aatrox_Base_SFX_events.bnk" + } + + events: list[string] = { + "Play_sfx_Aatrox_AatroxBasicAttack2_OnCast" + "Play_sfx_Aatrox_AatroxBasicAttack2_OnHit" + "Play_sfx_Aatrox_AatroxBasicAttack3_OnCast" + "Play_sfx_Aatrox_AatroxBasicAttack3_OnHit" + "Play_sfx_Aatrox_AatroxBasicAttack_OnCast" + "Play_sfx_Aatrox_AatroxBasicAttack_OnHit" + "Play_sfx_Aatrox_AatroxCritAttack_OnCast" + "Play_sfx_Aatrox_AatroxCritAttack_OnHit" + "Play_sfx_Aatrox_AatroxE_OnCast" + "Play_sfx_Aatrox_AatroxPassiveAttack_OnCast" + "Play_sfx_Aatrox_AatroxPassiveAttack_OnHit" + "Play_sfx_Aatrox_AatroxPassiveDebuff_OnBuffActivate" + "Play_sfx_Aatrox_AatroxPassiveDebuff_OnBuffDeactivate" + "Play_sfx_Aatrox_AatroxPassiveReady_OnBuffActivate" + "Play_sfx_Aatrox_AatroxQ1_OnCast_all" + "Play_sfx_Aatrox_AatroxQ1_OnHit_miss" + "Play_sfx_Aatrox_AatroxQ1_OnHit_normal_all" + "Play_sfx_Aatrox_AatroxQ1_OnHit_normal_player" + "Play_sfx_Aatrox_AatroxQ1_OnHit_sweetspot_all" + "Play_sfx_Aatrox_AatroxQ1_OnHit_sweetspot_player" + "Play_sfx_Aatrox_AatroxQ2_OnCast_all" + "Play_sfx_Aatrox_AatroxQ2_OnHit_miss" + "Play_sfx_Aatrox_AatroxQ2_OnHit_normal_all" + "Play_sfx_Aatrox_AatroxQ2_OnHit_normal_player" + "Play_sfx_Aatrox_AatroxQ2_OnHit_sweetspot_all" + "Play_sfx_Aatrox_AatroxQ2_OnHit_sweetspot_player" + "Play_sfx_Aatrox_AatroxQ3_OnCast_all" + "Play_sfx_Aatrox_AatroxQ3_OnHit_miss" + "Play_sfx_Aatrox_AatroxQ3_OnHit_normal_all" + "Play_sfx_Aatrox_AatroxQ3_OnHit_normal_player" + "Play_sfx_Aatrox_AatroxQ3_OnHit_sweetspot_all" + "Play_sfx_Aatrox_AatroxQ3_OnHit_sweetspot_player" + "Play_sfx_Aatrox_AatroxR_6seconds" + "Play_sfx_Aatrox_AatroxR_buffdeactivate" + "Play_sfx_Aatrox_AatroxR_end" + "Play_sfx_Aatrox_AatroxR_OnBuffActivate_all" + "Play_sfx_Aatrox_AatroxR_OnBuffActivate_player" + "Play_sfx_Aatrox_AatroxRAttack1_OnCast" + "Play_sfx_Aatrox_AatroxRAttack1_OnHit" + "Play_sfx_Aatrox_AatroxRAttack2_OnCast" + "Play_sfx_Aatrox_AatroxRAttack2_OnHit" + "Play_sfx_Aatrox_AatroxRRevive_all" + "Play_sfx_Aatrox_AatroxRRevive_player" + "Play_sfx_Aatrox_AatroxW_OnCast" + "Play_sfx_Aatrox_AatroxW_OnHit" + "Play_sfx_Aatrox_AatroxW_OnMissileCast" + "Play_sfx_Aatrox_AatroxW_OnMissileLaunch" + "Play_sfx_Aatrox_AatroxWBump_OnBuffActivate" + "Play_sfx_Aatrox_AatroxWChains_OnBuffActivate" + "Play_sfx_Aatrox_AatroxWChains_OnBuffDeactivate" + "Play_sfx_Aatrox_Dance3D_In_buffactivate" + "Play_sfx_Aatrox_Dance3D_loop_buffactivate" + "Play_sfx_Aatrox_Death3D_cast" + "Play_sfx_Aatrox_Joke3D_buffactivate" + "Play_sfx_Aatrox_Recall3D_buffactivate" + "Play_sfx_Aatrox_Taunt3D_buffactivate" + "Set_Switch_Aatrox_R_Active" + "Set_Switch_Aatrox_R_Inactive" + "Stop_sfx_Aatrox_AatroxW_OnMissileLaunch" + "Stop_sfx_Aatrox_AatroxWBump_OnBuffActivate" + "Stop_sfx_Aatrox_AatroxWChains_OnBuffActivate" + "Stop_sfx_Aatrox_Dance3D_In_buffactivate" + "Stop_sfx_Aatrox_Joke3D_buffactivate" + "Stop_sfx_Aatrox_Recall3D_buffactivate" + "Stop_sfx_Aatrox_Taunt3D_buffactivate" + "Switch_Aatrox_Footsteps_Brush" + "Switch_Aatrox_Footsteps_Dirt" + "Switch_Aatrox_Footsteps_Stone" + "Switch_Aatrox_Footsteps_Water" + } + } + BankUnit { + name: string = "Aatrox_Base_VO" + bankPath: list[string] = { + "ASSETS/Sounds/Wwise2016/VO/en_US/Characters/Aatrox/Skins/Base/Aatrox_Base_VO_audio.bnk" + "ASSETS/Sounds/Wwise2016/VO/en_US/Characters/Aatrox/Skins/Base/Aatrox_Base_VO_events.bnk" + "ASSETS/Sounds/Wwise2016/VO/en_US/Characters/Aatrox/Skins/Base/Aatrox_Base_VO_audio.wpk" + } + events: list[string] = { + "Play_vo_Aatrox_AatroxE_cast3D" + "Play_vo_Aatrox_AatroxQ_OnCast" + "Play_vo_Aatrox_AatroxR_cast3D" + "Play_vo_Aatrox_AatroxRRevive_OnBuffCast" + "Play_vo_Aatrox_AatroxW_cast3D" + "Play_vo_Aatrox_Attack2DGeneral" + "Play_vo_Aatrox_Attack2DPantheon" + "Play_vo_Aatrox_Attack2DTryndamere" + "Play_vo_Aatrox_Attack2DZoe" + "Play_vo_Aatrox_Death3D" + "Play_vo_Aatrox_FirstEncounter3DAkali" + "Play_vo_Aatrox_FirstEncounter3DAnivia" + "Play_vo_Aatrox_FirstEncounter3DCamille" + "Play_vo_Aatrox_FirstEncounter3DDarius" + "Play_vo_Aatrox_FirstEncounter3DFiora" + "Play_vo_Aatrox_FirstEncounter3DGalio" + "Play_vo_Aatrox_FirstEncounter3DGangplank" + "Play_vo_Aatrox_FirstEncounter3DGaren" + "Play_vo_Aatrox_FirstEncounter3DGeneral" + "Play_vo_Aatrox_FirstEncounter3DIllaoi" + "Play_vo_Aatrox_FirstEncounter3DJax" + "Play_vo_Aatrox_FirstEncounter3DKaisa" + "Play_vo_Aatrox_FirstEncounter3DKayle" + "Play_vo_Aatrox_FirstEncounter3DKayn" + "Play_vo_Aatrox_FirstEncounter3DKennen" + "Play_vo_Aatrox_FirstEncounter3DKled" + "Play_vo_Aatrox_FirstEncounter3DMalphite" + "Play_vo_Aatrox_FirstEncounter3DMaokai" + "Play_vo_Aatrox_FirstEncounter3DMorgana" + "Play_vo_Aatrox_FirstEncounter3DMundo" + "Play_vo_Aatrox_FirstEncounter3DNasus" + "Play_vo_Aatrox_FirstEncounter3DNautilus" + "Play_vo_Aatrox_FirstEncounter3DOrnn" + "Play_vo_Aatrox_FirstEncounter3DPantheon" + "Play_vo_Aatrox_FirstEncounter3DQuinn" + "Play_vo_Aatrox_FirstEncounter3DRenekton" + "Play_vo_Aatrox_FirstEncounter3DRiven" + "Play_vo_Aatrox_FirstEncounter3DRumble" + "Play_vo_Aatrox_FirstEncounter3DShen" + "Play_vo_Aatrox_FirstEncounter3DSion" + "Play_vo_Aatrox_FirstEncounter3DTargon" + "Play_vo_Aatrox_FirstEncounter3DTaric" + "Play_vo_Aatrox_FirstEncounter3DTeemo" + "Play_vo_Aatrox_FirstEncounter3DTrundle" + "Play_vo_Aatrox_FirstEncounter3DTryndamere" + "Play_vo_Aatrox_FirstEncounter3DVarus" + "Play_vo_Aatrox_FirstEncounter3DVoid" + "Play_vo_Aatrox_FirstEncounter3DYorick" + "Play_vo_Aatrox_FirstEncounter3DZoe" + "Play_vo_Aatrox_Joke3DGeneral" + "Play_vo_Aatrox_Kill3DAatrox" + "Play_vo_Aatrox_Kill3DAnivia" + "Play_vo_Aatrox_Kill3DCamille" + "Play_vo_Aatrox_Kill3DDarius" + "Play_vo_Aatrox_Kill3DFiora" + "Play_vo_Aatrox_Kill3DGangplank" + "Play_vo_Aatrox_Kill3DGaren" + "Play_vo_Aatrox_Kill3DGeneral" + "Play_vo_Aatrox_Kill3DIllaoi" + "Play_vo_Aatrox_Kill3DKaisa" + "Play_vo_Aatrox_Kill3DKayle" + "Play_vo_Aatrox_Kill3DKayn" + "Play_vo_Aatrox_Kill3DKled" + "Play_vo_Aatrox_Kill3DMalphite" + "Play_vo_Aatrox_Kill3DMaokai" + "Play_vo_Aatrox_Kill3DMorgana" + "Play_vo_Aatrox_Kill3DNasus" + "Play_vo_Aatrox_Kill3DNautilus" + "Play_vo_Aatrox_Kill3DOrnn" + "Play_vo_Aatrox_Kill3DPantheon" + "Play_vo_Aatrox_Kill3DRiven" + "Play_vo_Aatrox_Kill3DShen" + "Play_vo_Aatrox_Kill3DSion" + "Play_vo_Aatrox_Kill3DTaric" + "Play_vo_Aatrox_Kill3DTeemo" + "Play_vo_Aatrox_Kill3DTryndamere" + "Play_vo_Aatrox_Kill3DVarus" + "Play_vo_Aatrox_Kill3DZoe" + "Play_vo_Aatrox_Laugh3DGeneral" + "Play_vo_Aatrox_MasteryResponse3DGeneral" + "Play_vo_Aatrox_Move2DFirstPantheon" + "Play_vo_Aatrox_Move2DLong" + "Play_vo_Aatrox_Move2DRReady" + "Play_vo_Aatrox_Move2DStandard" + "Play_vo_Aatrox_Taunt3DGeneral" + } + voiceOver: bool = true + } + } + } + skinAnimationProperties: embed = skinAnimationProperties { + animationGraphData: link = "Characters/Aatrox/Animations/Skin0" + } + skinMeshProperties: embed = SkinMeshDataProperties { + skeleton: string = "ASSETS/Characters/Aatrox/Skins/Base/Aatrox.skl" + simpleSkin: string = "ASSETS/Characters/Aatrox/Skins/Base/Aatrox.skn" + texture: string = "ASSETS/Characters/Aatrox/Skins/Base/Aatrox_Base_TX_CM.dds" + skinScale: f32 = 1.09000003 + selfIllumination: f32 = 0.699999988 + brushAlphaOverride: f32 = 0.550000012 + overrideBoundingBox: option[vec3] = { { 130, 250, 130 } } + material: link = "Characters/Aatrox/Skins/Skin0/Materials/Aatrox_VFXBase_inst" + reflectionFresnelColor: rgba = { 0, 0, 0, 255 } + initialSubmeshToHide: string = "Wings" + initialSubmeshShadowsToHide: string = "Banner" + materialOverride: list[embed] = { + SkinMeshDataProperties_MaterialOverride { + material: link = "Characters/Aatrox/Skins/Skin0/Materials/Sword_inst" + submesh: string = "Sword" + } + SkinMeshDataProperties_MaterialOverride { + material: link = "Characters/Aatrox/Skins/Skin0/Materials/Wing_inst" + submesh: string = "Wings" + } + SkinMeshDataProperties_MaterialOverride { + material: link = "Characters/Aatrox/Skins/Skin0/Materials/Banner_inst" + submesh: string = "Banner" + } + } + rigPoseModifierData: list[pointer] = { + ConformToPathRigPoseModifierData { + mStartingJointName: hash = "L_Wing_Banner_Ground1" + mEndingJointName: hash = "L_Wing_Banner_Ground4" + mDefaultMaskName: hash = "empty" + mMaxBoneAngle: f32 = 150 + mVelMultiplier: f32 = 0 + mFrequency: f32 = 5 + } + ConformToPathRigPoseModifierData { + mStartingJointName: hash = "R_Wing_Banner_Ground1" + mEndingJointName: hash = "R_Wing_Banner_Ground4" + mDefaultMaskName: hash = "empty" + mMaxBoneAngle: f32 = 150 + mVelMultiplier: f32 = 0 + mFrequency: f32 = 5 + } + } + } + armorMaterial: string = "Flesh" + defaultAnimations: list[string] = { "BaseBuffPose" } + mContextualActionData: link = "Characters/Aatrox/CAC/Aatrox_Base" + iconCircle: option[string] = { "ASSETS/Characters/Aatrox/HUD/Aatrox_Circle.dds" } + iconSquare: option[string] = { "ASSETS/Characters/Aatrox/HUD/Aatrox_Square.dds" } + healthBarData: embed = CharacterHealthBarDataRecord { + attachToBone: string = "Buffbone_Cstm_Healthbar" + unitHealthBarStyle: u8 = 10 + } + mResourceResolver: link = "Characters/Aatrox/Skins/Skin0/Resources" + PersistentEffectConditions: list2[pointer] = { + PersistentEffectConditionData { + OwnerCondition: pointer = HasBuffDynamicMaterialBoolDriver { + Spell: hash = "Characters/Aatrox/Spells/AatroxPassiveAbility/AatroxPassiveReady" + } + PersistentVfxs: list2[embed] = { + PersistentVfxData { + boneName: string = "Weapon_Heart" + effectKey: hash = "Aatrox_P_Ready" + } + } + } + } + } + "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_E_Active_buff" = VfxSystemDefinitionData { + complexEmitterDefinitionData: list[pointer] = { + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 1.5 + } + particleLinger: option[f32] = { 1 } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "Avatar" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + primitive: pointer = VfxPrimitiveAttachedMesh { + mMesh: embed = VfxMeshDefinitionData { + mSubmeshesToDraw: list[hash] = { "BODY", "Shoulder" } + } + } + blendMode: u8 = 1 + color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.100000001, 0.899999976, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + depthBiasFactors: vec2 = { -1, -1 } + disableBackfaceCull: bool = true + particleIsLocalOrientation: flag = true + isUniformScale: flag = true + isRandomStartFrame: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 1.00100005, 1.00100005, 1.00100005 } + } + texture: string = "ASSETS/Characters/Aatrox/Skins/Base/Particles/Aatrox_Base_E_buff_avatar.dds" + uvMode: u8 = 2 + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.25 + } + particleLinger: option[f32] = { 1 } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "Avatar_activate" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + primitive: pointer = VfxPrimitiveAttachedMesh { + mMesh: embed = VfxMeshDefinitionData { + mSubmeshesToDraw: list[hash] = { "BODY", "Shoulder" } + } + } + blendMode: u8 = 4 + color: embed = ValueColor { + constantValue: vec4 = { 1, 1, 1, 0.650003791 } + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.100000001, 0.800000012, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 0.650003791 } + { 1, 1, 1, 0.650003791 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = 1 + disableBackfaceCull: bool = true + particleIsLocalOrientation: flag = true + isUniformScale: flag = true + isRandomStartFrame: flag = true + uvScrollClamp: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 1.00999999, 1.00999999, 1.00999999 } + } + texture: string = "ASSETS/Characters/Aatrox/Skins/Base/Particles/Aatrox_Base_E_buff_avatar_sheen.dds" + uvMode: u8 = 2 + birthUvScrollRate: embed = ValueVector2 { + constantValue: vec2 = { 0, 2 } + } + texAddressModeBase: u8 = 2 + } + } + particleName: string = "Aatrox_Base_E_Active_buff" + particlePath: string = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_E_Active_buff" + } + "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_E_Dash" = VfxSystemDefinitionData { + complexEmitterDefinitionData: list[pointer] = { + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.300000012 + } + particleLinger: option[f32] = { 0.200000003 } + lifetime: option[f32] = { 1.10000002 } + isSingleParticle: flag = true + emitterName: string = "Avatar" + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, 50 } + } + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + primitive: pointer = VfxPrimitiveAttachedMesh { + mMesh: embed = VfxMeshDefinitionData { + mSubmeshesToDraw: list[hash] = { "BODY" } + } + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 1, 1, 0.500007629 } + } + color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.100000001, 0.5, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0.300007641 } + { 1, 1, 1, 0 } + } + } + } + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.200000003, 1 } + values: list[f32] = { 0, 0, 0.5 } + } + } + erosionFeatherOut: f32 = 0.300000012 + erosionMapName: string = "ASSETS/Characters/Aatrox/Skins/Base/Particles/Aatrox_Base_Q_SmokeErode.dds" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + disableBackfaceCull: bool = true + particleIsLocalOrientation: flag = true + isUniformScale: flag = true + isRandomStartFrame: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 1.00999999, 1, 1 } + } + texture: string = "ASSETS/Characters/Aatrox/Skins/Base/Aatrox_Base_TX_CM.dds" + numFrames: u16 = 4 + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.300000012 + } + particleLinger: option[f32] = { 0.200000003 } + lifetime: option[f32] = { 1.10000002 } + isSingleParticle: flag = true + emitterName: string = "Avatar1" + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, 50 } + } + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + primitive: pointer = VfxPrimitiveAttachedMesh { + mMesh: embed = VfxMeshDefinitionData { + mSubmeshesToDraw: list[hash] = { "Sword" } + } + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 1, 1, 0.500007629 } + } + color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.100000001, 0.5, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0.300007641 } + { 1, 1, 1, 0 } + } + } + } + disableBackfaceCull: bool = true + particleIsLocalOrientation: flag = true + isUniformScale: flag = true + isRandomStartFrame: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 1.00999999, 1, 1 } + } + texture: string = "ASSETS/Characters/Aatrox/Skins/Base/Aatrox_Base_Sword_TX_CM.dds" + numFrames: u16 = 4 + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.300000012 + } + particleLinger: option[f32] = { 0.200000003 } + lifetime: option[f32] = { 1.10000002 } + isSingleParticle: flag = true + emitterName: string = "Avatar2" + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, 50 } + } + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + primitive: pointer = VfxPrimitiveAttachedMesh { + mMesh: embed = VfxMeshDefinitionData { + mSubmeshesToDraw: list[hash] = { "Wings" } + } + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 1, 1, 0.500007629 } + } + color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.100000001, 0.5, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0.300007641 } + { 1, 1, 1, 0 } + } + } + } + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.200000003, 1 } + values: list[f32] = { 0, 0, 0.5 } + } + } + erosionFeatherOut: f32 = 0.300000012 + erosionMapName: string = "ASSETS/Characters/Aatrox/Skins/Base/Particles/Aatrox_Base_Q_SmokeErode.dds" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + disableBackfaceCull: bool = true + particleIsLocalOrientation: flag = true + isUniformScale: flag = true + isRandomStartFrame: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 1.00999999, 1, 1 } + } + texture: string = "ASSETS/Characters/Aatrox/Skins/Base/Aatrox_Wings_TX_CM.dds" + numFrames: u16 = 4 + } + } + particleName: string = "Aatrox_Base_E_Dash" + particlePath: string = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_E_Dash" + mIsPoseAfterimage: bool = true + } + "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_P_Ready" = VfxSystemDefinitionData { + complexEmitterDefinitionData: list[pointer] = { + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.699999988 + } + particleLinger: option[f32] = { 1 } + emitterName: string = "Basic" + importance: u8 = 2 + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + blendMode: u8 = 4 + color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.400000006, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 0.330006868, 0, 0, 1 } + } + } + } + depthBiasFactors: vec2 = { -1, -2 } + isUniformScale: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 1, 0, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 1, 0, 0 } } + } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 150, 100, 100 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 150, 100, 100 } } + } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.200000003, 1 } + values: list[vec3] = { + { 0.25, 0.25, 2.5 } + { 1, 1, 1 } + { 0.25, 0.25, 0.25 } + } + } + } + texture: string = "ASSETS/Characters/Aatrox/Skins/Base/Particles/Aatrox_Base_TEMP_Diana_Skin11_W_FaintGlow.dds" + paletteDefinition: pointer = VfxPaletteDefinitionData { + paletteTexture: string = "ASSETS/Characters/Aatrox/Skins/Base/Particles/Aatrox_Base_AA_Gradient_RGB.dds" + palleteSrcMixColor: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + paletteSelector: embed = ValueVector3 { + constantValue: vec3 = { 2, 0, 0 } + } + paletteCount: i32 = 8 + } + } + } + particleName: string = "Aatrox_Base_P_Ready" + particlePath: string = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_P_Ready" + } + "Characters/Aatrox/Skins/Skin0/Materials/Sword_inst" = StaticMaterialDef { + name: string = "Characters/Aatrox/Skins/Skin0/Materials/Sword_inst" + samplerValues: list2[embed] = { + StaticMaterialShaderSamplerDef { + samplerName: string = "Diffuse_Texture" + textureName: string = "ASSETS/Characters/Aatrox/Skins/Base/Aatrox_Base_Sword_TX_CM.dds" + addressU: u32 = 1 + addressV: u32 = 1 + addressW: u32 = 1 + } + StaticMaterialShaderSamplerDef { + samplerName: string = "Mask_Texture" + textureName: string = "ASSETS/Characters/Aatrox/Skins/Base/Particles/Aatrox_Base_P_Sword_Mask.dds" + addressW: u32 = 1 + } + StaticMaterialShaderSamplerDef { + samplerName: string = "Gradient_Texture" + textureName: string = "ASSETS/Shared/Materials/Gradient_test_01.dds" + addressU: u32 = 1 + addressV: u32 = 1 + } + } + paramValues: list2[embed] = { + StaticMaterialShaderParamDef { + name: string = "Mask_Intensity" + value: vec4 = { 0.792500019, 0, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Bloom_Intensity" + value: vec4 = { 4, 0, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Scrolling_Scale" + value: vec4 = { 1, 1, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Scrolling_Rate" + value: vec4 = { 0, -1, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Color" + value: vec4 = { 1, 0.301960796, 0.0274509806, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Dissolve_Bias" + value: vec4 = { -1, 0, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Dissolve_SmoothStep" + value: vec4 = { 0, 0.200000003, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Gradient_Sharpness" + value: vec4 = { 0.400000006, 0, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Alpha_Sharpness" + value: vec4 = { 0.00100000005, 0, 0, 0 } + } + } + switches: list2[embed] = { + StaticMaterialSwitchDef { + name: string = "USE_COLORDODGE" + on: bool = false + } + StaticMaterialSwitchDef { + name: string = "USE_ADDATIVE" + } + StaticMaterialSwitchDef { + name: string = "USE_LERP" + on: bool = false + } + StaticMaterialSwitchDef { + name: string = "USE_DISSOLVE" + on: bool = false + } + } + shaderMacros: map[string, string] = { + "NUM_BLEND_WEIGHTS" = "4" + } + techniques: list[embed] = { + StaticMaterialTechniqueDef { + name: string = "normal" + passes: list[embed] = { + StaticMaterialPassDef { + shader: link = "Shaders/SkinnedMesh/Scrolling_ColorDodge_Masked" + blendEnable: bool = true + srcColorBlendFactor: u32 = 6 + srcAlphaBlendFactor: u32 = 6 + dstColorBlendFactor: u32 = 7 + dstAlphaBlendFactor: u32 = 7 + } + } + } + } + childTechniques: list[embed] = { + StaticMaterialChildTechniqueDef { + name: string = "transition" + parentName: string = "normal" + shaderMacros: map[string, string] = { + "TRANSITION" = "1" + } + } + } + dynamicMaterial: pointer = DynamicMaterialDef { + parameters: list[embed] = { + DynamicMaterialParameterDef { + name: string = "Mask_Intensity" + driver: pointer = LerpMaterialDriver { + mBoolDriver: pointer = HasBuffDynamicMaterialBoolDriver { + mScriptName: string = "AatroxPassiveReady" + } + mOnValue: f32 = 0.75 + mTurnOffTimeSec: f32 = 0.200000003 + } + } + } + } + } + "Characters/Aatrox/Skins/Skin0/Materials/Banner_inst" = StaticMaterialDef { + name: string = "Characters/Aatrox/Skins/Skin0/Materials/Banner_inst" + samplerValues: list2[embed] = { + StaticMaterialShaderSamplerDef { + samplerName: string = "Diffuse_Texture" + textureName: string = "ASSETS/Characters/Aatrox/Skins/Base/Particles/Aatrox_Base_I_Banner_color.dds" + addressU: u32 = 1 + addressV: u32 = 1 + addressW: u32 = 1 + } + StaticMaterialShaderSamplerDef { + samplerName: string = "Mask_Texture" + textureName: string = "ASSETS/Characters/Aatrox/Skins/Base/Particles/Aatrox_Base_I_Banner.dds" + addressW: u32 = 1 + } + } + paramValues: list2[embed] = { + StaticMaterialShaderParamDef { + name: string = "UV_Scale" + value: vec4 = { 1, 1, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Scroll_Speed" + value: vec4 = { 0, -0.300000012, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Alpha_Bias" + value: vec4 = { 0.300000012, 0, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "UV_Scale_BLUE" + value: vec4 = { 1, 1, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Scroll_Speed_BLUE" + value: vec4 = { 0, -0.200000003, 0, 0 } + } + } + switches: list2[embed] = { + StaticMaterialSwitchDef { + name: string = "MULTIPLY_ADD" + on: bool = false + } + StaticMaterialSwitchDef { + name: string = "USE_RED_TO_ALPHA" + } + StaticMaterialSwitchDef { + name: string = "USE_BLUE_CHANNEL" + } + } + shaderMacros: map[string, string] = { + "NUM_BLEND_WEIGHTS" = "4" + } + techniques: list[embed] = { + StaticMaterialTechniqueDef { + name: string = "normal" + passes: list[embed] = { + StaticMaterialPassDef { + shader: link = "Shaders/SkinnedMesh/ScrollingCustomAlpha" + blendEnable: bool = true + srcColorBlendFactor: u32 = 6 + srcAlphaBlendFactor: u32 = 6 + dstColorBlendFactor: u32 = 7 + dstAlphaBlendFactor: u32 = 7 + } + } + } + } + childTechniques: list[embed] = { + StaticMaterialChildTechniqueDef { + name: string = "transition" + parentName: string = "normal" + shaderMacros: map[string, string] = { + "TRANSITION" = "1" + } + } + } + } + "Characters/Aatrox/Skins/Skin0/Materials/Aatrox_VFXBase_inst" = StaticMaterialDef { + name: string = "Characters/Aatrox/Skins/Skin0/Materials/Aatrox_VFXBase_inst" + samplerValues: list2[embed] = { + StaticMaterialShaderSamplerDef { + samplerName: string = "Diffuse_Texture" + textureName: string = "ASSETS/Characters/Aatrox/Skins/Base/Aatrox_Base_TX_CM.dds" + addressU: u32 = 1 + addressV: u32 = 1 + addressW: u32 = 1 + } + StaticMaterialShaderSamplerDef { + samplerName: string = "Mask_Texture" + textureName: string = "ASSETS/Characters/Aatrox/Skins/Base/Particles/Aatrox_Base_R_body_mask.dds" + addressU: u32 = 1 + addressV: u32 = 1 + addressW: u32 = 1 + } + StaticMaterialShaderSamplerDef { + samplerName: string = "Gradient_Texture" + textureName: string = "ASSETS/Shared/Materials/Gradient_test_01.dds" + addressU: u32 = 1 + addressV: u32 = 1 + addressW: u32 = 1 + } + } + paramValues: list2[embed] = { + StaticMaterialShaderParamDef { + name: string = "Dissolve_SmoothStep" + value: vec4 = { 0, 0.150000006, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Dissolve_Bias" + value: vec4 = { -0.200000003, 0, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Pulse_Rate" + value: vec4 = { 3, 0, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Pulse_Max" + value: vec4 = { 0.400000006, 0, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Gradient_Sharpness" + value: vec4 = { 0.5, 0, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Alpha_Sharpness" + value: vec4 = { 0.00100000005, 0, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Bloom_Intensity" + value: vec4 = { 10, 0, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Pulse_Offset" + value: vec4 = { 0.300000012, 0, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Alpha" + value: vec4 = { 1, 0, 0, 0 } + } + } + shaderMacros: map[string, string] = { + "NUM_BLEND_WEIGHTS" = "4" + } + techniques: list[embed] = { + StaticMaterialTechniqueDef { + name: string = "normal" + passes: list[embed] = { + StaticMaterialPassDef { + shader: link = "Shaders/SkinnedMesh/Aatrox_VFXBase" + blendEnable: bool = true + srcColorBlendFactor: u32 = 6 + srcAlphaBlendFactor: u32 = 6 + dstColorBlendFactor: u32 = 7 + dstAlphaBlendFactor: u32 = 7 + } + } + } + } + childTechniques: list[embed] = { + StaticMaterialChildTechniqueDef { + name: string = "transition" + parentName: string = "normal" + shaderMacros: map[string, string] = { + "TRANSITION" = "1" + } + } + } + dynamicMaterial: pointer = DynamicMaterialDef { + parameters: list[embed] = { + DynamicMaterialParameterDef { + name: string = "Dissolve_Bias" + driver: pointer = MaxMaterialDriver { + mDrivers: list[pointer] = { + FloatGraphMaterialDriver { + driver: pointer = LerpMaterialDriver { + mBoolDriver: pointer = IsDeadDynamicMaterialBoolDriver { } + mTurnOnTimeSec: f32 = 4 + mTurnOffTimeSec: f32 = 0 + } + graph: embed = VfxAnimatedFloatVariableData { + times: list[f32] = { 0.00171930937, 0.216738746, 0.766768217, 1.00488436 } + values: list[f32] = { -0.22144419, 0.260138661, 0.752247512, 0.86541003 } + } + } + FloatGraphMaterialDriver { + driver: pointer = LerpMaterialDriver { + mBoolDriver: pointer = IsAnimationPlayingDynamicMaterialBoolDriver { + mAnimationNames: list[hash] = { "Passive_Death" } + } + mTurnOnTimeSec: f32 = 3 + } + graph: embed = VfxAnimatedFloatVariableData { + times: list[f32] = { 0.00321787666, 0.381477386, 0.997775316 } + values: list[f32] = { -0.225780264, 0.583815038, 0.994219661 } + } + } + } + } + } + DynamicMaterialParameterDef { + name: string = "Pulse_Rate" + driver: pointer = LerpMaterialDriver { + mBoolDriver: pointer = HasBuffDynamicMaterialBoolDriver { + mScriptName: string = "AatroxR" + } + mOnValue: f32 = 5 + mTurnOnTimeSec: f32 = 0 + mTurnOffTimeSec: f32 = 0 + } + } + } + } + } + "Characters/Aatrox/Skins/Skin0/Materials/Wing_inst" = StaticMaterialDef { + name: string = "Characters/Aatrox/Skins/Skin0/Materials/Wing_inst" + samplerValues: list2[embed] = { + StaticMaterialShaderSamplerDef { + samplerName: string = "Diffuse_Texture" + textureName: string = "ASSETS/Characters/Aatrox/Skins/Base/Aatrox_Wings_TX_CM.dds" + addressU: u32 = 1 + addressV: u32 = 1 + addressW: u32 = 1 + } + StaticMaterialShaderSamplerDef { + samplerName: string = "Mask_Texture" + textureName: string = "ASSETS/Characters/Aatrox/Skins/Base/Particles/Aatrox_Base_R_wing_mask.dds" + addressW: u32 = 1 + } + StaticMaterialShaderSamplerDef { + samplerName: string = "Gradient_Texture" + textureName: string = "ASSETS/Characters/Aatrox/Skins/Base/Particles/Aatrox_Base_R_mat_gradient.dds" + addressU: u32 = 1 + addressV: u32 = 1 + } + } + paramValues: list2[embed] = { + StaticMaterialShaderParamDef { + name: string = "Mask_Intensity" + value: vec4 = { 0.939999998, 0, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Bloom_Intensity" + value: vec4 = { 5, 0, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Scrolling_Scale" + value: vec4 = { 1, 1, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Scrolling_Rate" + value: vec4 = { -0.5, -0.5, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Color" + value: vec4 = { 1, 0.250980407, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Dissolve_Bias" + value: vec4 = { 0.785000026, 0, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Dissolve_SmoothStep" + value: vec4 = { 0, 0.5, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Gradient_Sharpness" + value: vec4 = { 2, 0, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Alpha_Sharpness" + value: vec4 = { 0.00100000005, 0, 0, 0 } + } + } + switches: list2[embed] = { + StaticMaterialSwitchDef { + name: string = "USE_COLORDODGE" + on: bool = false + } + StaticMaterialSwitchDef { + name: string = "USE_ADDATIVE" + } + StaticMaterialSwitchDef { + name: string = "USE_LERP" + on: bool = false + } + StaticMaterialSwitchDef { + name: string = "USE_DISSOLVE" + } + } + shaderMacros: map[string, string] = { + "NUM_BLEND_WEIGHTS" = "4" + } + techniques: list[embed] = { + StaticMaterialTechniqueDef { + name: string = "normal" + passes: list[embed] = { + StaticMaterialPassDef { + shader: link = "Shaders/SkinnedMesh/Scrolling_ColorDodge_Masked" + blendEnable: bool = true + srcColorBlendFactor: u32 = 6 + srcAlphaBlendFactor: u32 = 6 + dstColorBlendFactor: u32 = 7 + dstAlphaBlendFactor: u32 = 7 + } + } + } + } + childTechniques: list[embed] = { + StaticMaterialChildTechniqueDef { + name: string = "transition" + parentName: string = "normal" + shaderMacros: map[string, string] = { + "TRANSITION" = "1" + } + } + } + dynamicMaterial: pointer = DynamicMaterialDef { + parameters: list[embed] = { + DynamicMaterialParameterDef { + name: string = "Dissolve_Bias" + driver: pointer = SwitchMaterialDriver { + mElements: list[embed] = { + SwitchMaterialDriverElement { + mCondition: pointer = HasBuffDynamicMaterialBoolDriver { + mScriptName: string = "AatroxRFX" + } + mValue: pointer = LerpMaterialDriver { + mBoolDriver: pointer = HasBuffDynamicMaterialBoolDriver { + mScriptName: string = "AatroxRFX" + mDeactivateEarlySeconds: f32 = 1 + } + mOnValue: f32 = -1 + mOffValue: f32 = 1 + mTurnOnTimeSec: f32 = 2 + } + } + SwitchMaterialDriverElement { + mCondition: pointer = HasBuffDynamicMaterialBoolDriver { + mScriptName: string = "AatroxRReviveMaterialOverride" + } + mValue: pointer = LerpMaterialDriver { + mBoolDriver: pointer = HasBuffDynamicMaterialBoolDriver { + mScriptName: string = "AatroxRReviveMaterialOverride" + } + mOffValue: f32 = -0.180000007 + mTurnOnTimeSec: f32 = 6 + mTurnOffTimeSec: f32 = 0 + } + } + SwitchMaterialDriverElement { + mCondition: pointer = IsAnimationPlayingDynamicMaterialBoolDriver { + mAnimationNames: list[hash] = { 0x909068b6 } + } + mValue: pointer = LerpMaterialDriver { + mBoolDriver: pointer = IsAnimationPlayingDynamicMaterialBoolDriver { + mAnimationNames: list[hash] = { 0x909068b6 } + } + mOnValue: f32 = -1 + mOffValue: f32 = 1 + mTurnOnTimeSec: f32 = 0.200000003 + mTurnOffTimeSec: f32 = 0.200000003 + } + } + SwitchMaterialDriverElement { + mCondition: pointer = IsAnimationPlayingDynamicMaterialBoolDriver { + mAnimationNames: list[hash] = { "taunt" } + } + mValue: pointer = LerpMaterialDriver { + mBoolDriver: pointer = IsAnimationPlayingDynamicMaterialBoolDriver { + mAnimationNames: list[hash] = { "taunt" } + } + mOnValue: f32 = -1 + mOffValue: f32 = 1 + mTurnOnTimeSec: f32 = 0.200000003 + mTurnOffTimeSec: f32 = 0.200000003 + } + } + } + mDefaultValue: pointer = FloatLiteralMaterialDriver { + mValue: f32 = 1 + } + } + } + } + } + } + "Characters/Aatrox/Skins/Skin0/Resources" = ResourceResolver { + resourceMap: map[hash, link] = { + "Aatrox_Q_Indicator_01" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_Q_Indicator_01" + 0x4c250437 = "Characters/Kayn/Skins/Skin0/Particles/Kayn_Base_Primary_R_tar_child" + "Aatrox_Q_cas1" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_Q_cas1" + "Aatrox_Q_cas3" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_Q_cas3" + "Aatrox_Q_cas2" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_Q_cas2" + "Aatrox_AA_Trail_01" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_AA_Trail_01" + "Aatrox_AA_Trail_03" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_AA_Trail_03" + "Aatrox_AA_Trail_02" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_AA_Trail_02" + 0x57532b4b = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_AA_Hit_Tar01" + 0x58532cde = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_AA_Hit_Tar02" + "Aatrox_W_mis" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_W_mis" + "Aatrox_W_Beam_Tar" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_W_Beam_Tar" + "Aatrox_W_Core" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_W_Core" + "Aatrox_Q_Indicator_02" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_Q_Indicator_02" + "Aatrox_Q_Indicator_03" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_Q_Indicator_03" + "Aatrox_E_Dash" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_E_Dash" + "Aatrox_E_Active_buff" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_E_Active_buff" + "Aatrox_Q_Trail_01" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_Q_Trail_01" + "Aatrox_Q_Trail_02" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_Q_Trail_02" + "Aatrox_Q_Trail_03" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_Q_Trail_03" + "Aatrox_Q_Indicator_01_Ally" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_Q_Indicator_01_Ally" + "Aatrox_Q_Indicator_02_Ally" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_Q_Indicator_02_Ally" + "Aatrox_Q_Indicator_03_Ally" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_Q_Indicator_03_Ally" + "Aatrox_P_Ready" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_P_Ready" + "Aatrox_R_Fear" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_R_Fear" + "Aatrox_P_Activate" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_P_Activate" + "Aatrox_E_Heal" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_E_Heal" + "Aatrox_Death_ambers" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_Death_ambers" + "Aatrox_R_Attack_01" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_R_Attack_01" + "Aatrox_P_Hit_Tar" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_P_Hit_Tar" + "Aatrox_R_Attack_02" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_R_Attack_02" + "Aatrox_W_Cas" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_W_Cas" + "Aatrox_E_Dash_trail" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_E_Dash_trail" + "Aatrox_E_Dash2" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_E_Dash2" + "Aatrox_W_Hand_glow_cas" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_W_Hand_glow_cas" + "Aatrox_Q_Hit_Tar" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_Q_Hit_Tar" + "Aatrox_Q_Sweet_hit_tar" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_Q_Sweet_hit_tar" + "Aatrox_W_Core_Area" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_W_Core_Area" + "Aatrox_P_Attack_trail" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_P_Attack_trail" + "Aatrox_R_Revive_end" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_R_Revive_end" + "Aatrox_E_Buf_Sword" = 0x00000000 + "Aatrox_Passive_Sheathe_Sword" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_Passive_Sheathe_Sword" + "Aatrox_R_Revive_Duration" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_R_Revive_Duration" + "Aatrox_R_Revive_Diration_Sword" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_R_Revive_Diration_Sword" + "Aatrox_R_SpeedBuff" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_R_SpeedBuff" + "Aatrox_P_Debuff" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_P_Debuff" + "Aatrox_Recall_Ground" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_Recall_Ground" + "Aatrox_Recall_Beam" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_Recall_Beam" + "Aatrox_Recall_Weapon_glow" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_Recall_Weapon_glow" + "Aatrox_Recall_Hand_glow" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_Recall_Hand_glow" + "Aatrox_W_Core_End" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_W_Core_End" + "Aatrox_W_Beam_Tar_Break" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_W_Beam_Tar_Break" + "Aatrox_W_Hit_Tar" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_W_Hit_Tar" + "Aatrox_W_Beam_Tar_Pull" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_W_Beam_Tar_Pull" + "Aatrox_AA_Crit_Hit_Tar" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_AA_Crit_Hit_Tar" + "Aatrox_AA_Crit_Trail" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_AA_Crit_Trail" + "Aatrox_Dance_Ground" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_Dance_Ground" + "Aatrox_Taunt_Ground" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_Taunt_Ground" + 0x5b2b3b83 = "Maps/Particles/SRX/Base/SRX_Audio_Hextech_Storm_loop" + 0x2c43403d = "Maps/Particles/SR/SRU_Braziers_Chemtech_Child_02" + 0x20bae730 = "Maps/Shipping/Map22/Particles/Set9/TFT9_Trait_Demacia_Celebration_Child7" + } + } +} \ No newline at end of file diff --git a/crates/ltk_ritobin/samples/azirultsoldier.fmt.rito b/crates/ltk_ritobin/samples/azirultsoldier.fmt.rito new file mode 100644 index 00000000..bae87ffa --- /dev/null +++ b/crates/ltk_ritobin/samples/azirultsoldier.fmt.rito @@ -0,0 +1,516 @@ +#PROP_text +type: string = "PROP" +version: u32 = 3 +linked: list[string] = { } +entries: map[hash, embed] = { + "Characters/AzirUltSoldier/Skins/Skin14/Particles/AzirUltSoldier_Skin14_Idle_Effect_VFX" = VfxSystemDefinitionData { + complexEmitterDefinitionData: list[pointer] = { + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = -1 + } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "Temp_Mesh" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, 20 } + } + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Azir/Skins/Skin14/Particles/Polygon_Idle_Soldier_FX.scb" + } + } + blendMode: u8 = 1 + Color: embed = ValueColor { + constantValue: vec4 = { 0.11, 0.08, 0.87, 0.4 } + } + alphaRef: u8 = 0 + disableBackfaceCull: bool = true + isUniformScale: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 0, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 1, 5, 5 } + } + texture: string = "ASSETS/Characters/Azir/Skins/Skin14/Particles/Polygon_texture_Idle_Soldior_Ult_02.tex" + birthUvRotateRate: embed = ValueFloat { + constantValue: f32 = 50 + } + particleUVRotateRate: embed = IntegratedValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0 } + values: list[f32] = { 0 } + } + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = -1 + } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "Temp_Mesh2" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, -5, 40 } + } + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Azir/Skins/Skin14/Particles/Polygon_Idle_Soldior_Ult.scb" + } + } + blendMode: u8 = 4 + Color: embed = ValueColor { + constantValue: vec4 = { 0.35, 0.64, 1, 0.8 } + } + pass: i16 = 2 + alphaRef: u8 = 0 + disableBackfaceCull: bool = true + isUniformScale: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 0, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 0.6, 5, 5 } + } + texture: string = "ASSETS/Characters/Azir/Skins/Skin14/Particles/Decal_Banners_FlipBooks.tex" + frameRate: f32 = 1.5 + numFrames: u16 = 4 + texDiv: vec2 = { 2, 2 } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = -1 + } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "Temp_Mesh3" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, 20 } + } + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Azir/Skins/Skin14/Particles/Polygon_Idle_Soldier_FX.scb" + } + } + blendMode: u8 = 1 + Color: embed = ValueColor { + constantValue: vec4 = { 0.18, 0.23, 0.84, 0.5 } + } + pass: i16 = -1 + alphaRef: u8 = 0 + disableBackfaceCull: bool = true + isUniformScale: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 0, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 1, 5, 5 } + } + texture: string = "ASSETS/Characters/Azir/Skins/Skin14/Particles/Polygon_texture_Idle_Soldior_Ult.tex" + birthUvRotateRate: embed = ValueFloat { + constantValue: f32 = 90 + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = -1 + } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "Temp_Mesh4" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, 20 } + } + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Azir/Skins/Skin14/Particles/Polygon_Idle_Soldier_FX.scb" + } + } + blendMode: u8 = 4 + Color: embed = ValueColor { + constantValue: vec4 = { 0.17, 1, 0.97, 0.8 } + } + pass: i16 = 1 + alphaRef: u8 = 0 + disableBackfaceCull: bool = true + isUniformScale: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 0, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 1, 5, 5 } + } + texture: string = "ASSETS/Characters/Azir/Skins/Skin14/Particles/Polygon_texture_Idle_Soldior_Ult_02.tex" + birthUvRotateRate: embed = ValueFloat { + constantValue: f32 = 50 + } + particleUVRotateRate: embed = IntegratedValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0 } + values: list[f32] = { 0 } + } + } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Azir/Skins/Skin14/Particles/Azir_Skin14_EBeam2.tex" + uvScaleMult: embed = ValueVector2 { + constantValue: vec2 = { 0.3, 1 } + } + birthUvRotateRateMult: embed = ValueFloat { + constantValue: f32 = 100 + } + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = -1 + } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "Temp_Mesh5" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, 30 } + } + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Azir/Skins/Skin14/Particles/Polygon_Idle_Soldier_FX.scb" + } + } + blendMode: u8 = 1 + Color: embed = ValueColor { + constantValue: vec4 = { 0.33, 0.43, 1, 0.6 } + } + pass: i16 = 1 + alphaRef: u8 = 0 + disableBackfaceCull: bool = true + isUniformScale: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 0, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 1.2, 5, 5 } + } + texture: string = "ASSETS/Characters/Azir/Skins/Skin14/Particles/Aura_Self.tex" + frameRate: f32 = 1.5 + numFrames: u16 = 4 + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 15 + } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "body" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 15, -30 } + } + primitive: pointer = VfxPrimitiveArbitraryQuad { } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.38, 0.62, 1, 0.6 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.2, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = 210 + meshRenderFlags: u8 = 0 + depthBiasFactors: vec2 = { 0, -50 } + particleIsLocalOrientation: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 20, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 120, 30, 60 } + } + texture: string = "ASSETS/Shared/Particles/Base_Flare_Cas.tex" + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Azir/Skins/Skin14/Particles/Azir_Skin14_Code.tex" + uvScaleMult: embed = ValueVector2 { + constantValue: vec2 = { 2, 2 } + } + birthUvScrollRateMult: embed = ValueVector2 { + constantValue: vec2 = { -0.1, 0 } + } + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 15 + } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "body1" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 15, -30 } + } + primitive: pointer = VfxPrimitiveArbitraryQuad { } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.7569, 0.6039, 0.4275, 1 } + } + Color: embed = ValueColor { + constantValue: vec4 = { 1, 1, 1, 0.4 } + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.2, 1 } + values: list[vec4] = { + { 1, 1, 1, 0.4 } + { 1, 1, 1, 0.4 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = 215 + meshRenderFlags: u8 = 0 + depthBiasFactors: vec2 = { 0, -30 } + particleIsLocalOrientation: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 20, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 130, 30, 60 } + } + texture: string = "ASSETS/Shared/Particles/Akshan_Skin10_Sparker01.tex" + textureMult: pointer = VfxTextureMultDefinitionData { + uvScaleMult: embed = ValueVector2 { + constantValue: vec2 = { 2, 2 } + } + birthUvScrollRateMult: embed = ValueVector2 { + constantValue: vec2 = { 0, 0.05 } + } + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 15 + } + lifetime: option[f32] = { 15 } + isSingleParticle: flag = true + emitterName: string = "Basic" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + SpawnShape: pointer = 0xee39916f { + emitOffset: vec3 = { 0, 15, -30 } + } + EmitterPosition: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 0, 0 } } + } + } + primitive: pointer = VfxPrimitiveArbitraryQuad { } + blendMode: u8 = 4 + Color: embed = ValueColor { + constantValue: vec4 = { 0.15, 0.23, 1, 0.6 } + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { + 0 + 0.0893 + 0.1209 + 0.1363 + 0.262 + 0.2706 + 0.3148 + 0.3604 + 0.3608 + 0.405 + 0.5 + 0.6622 + 0.7687 + 0.8109 + 0.8608 + 0.9021 + 1 + } + values: list[vec4] = { + { 0.15, 0.23, 1, 0 } + { 0.15, 0.23, 1, 0.1071 } + { 0.15, 0.23, 1, 0.6 } + { 0.15, 0.23, 1, 0.15 } + { 0.15, 0.23, 1, 0.6 } + { 0.15, 0.23, 1, 0.0353 } + { 0.15, 0.23, 1, 0.0882 } + { 0.15, 0.23, 1, 0.3176 } + { 0.15, 0.23, 1, 0.6 } + { 0.15, 0.23, 1, 0.2029 } + { 0.15, 0.23, 1, 0.6 } + { 0.15, 0.23, 1, 0.4054 } + { 0.15, 0.23, 1, 0.5054 } + { 0.15, 0.23, 1, 0.1043 } + { 0.15, 0.23, 1, 0.3587 } + { 0.15, 0.23, 1, 0.0457 } + { 0.15, 0.23, 1, 0 } + } + } + } + pass: i16 = 5 + alphaRef: u8 = 0 + depthBiasFactors: vec2 = { -1, -30 } + particleIsLocalOrientation: flag = true + isUniformScale: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 0, 90 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 50, 70, 0 } + } + texture: string = "ASSETS/Characters/Azir/Skins/Skin14/Particles/Aura_Self.tex" + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Azir/Skins/Skin14/Particles/Azir_Skin14_Sacn_Lines.tex" + uvScaleMult: embed = ValueVector2 { + constantValue: vec2 = { 1, 0.7 } + } + birthUvScrollRateMult: embed = ValueVector2 { + constantValue: vec2 = { 0, -0.2 } + } + birthUVOffsetMult: embed = ValueVector2 { + constantValue: vec2 = { 1, 1 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec2] = { { 1, 1 } } + } + } + } + } + } + visibilityRadius: f32 = 5000 + particleName: string = "AzirUltSoldier_Skin14_Idle_Effect_VFX" + particlePath: string = "Characters/AzirUltSoldier/Skins/Skin14/Particles/AzirUltSoldier_Skin14_Idle_Effect_VFX" + flags: u16 = 198 + } + "Characters/AzirUltSoldier/Skins/Skin14/Particles/AzirUltSoldier_Skin14_P_Idle" = VfxSystemDefinitionData { + complexEmitterDefinitionData: list[pointer] = { + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.1 + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = -1 + } + particleLinger: option[f32] = { 0.4 } + isSingleParticle: flag = true + emitterName: string = "Temp_Avatar" + disabled: bool = true + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + primitive: pointer = VfxPrimitiveAttachedMesh { + mMesh: embed = VfxMeshDefinitionData { + mSubmeshesToDraw: list[hash] = { 0xbe6dcac2 } + mSubmeshesToDrawAlways: list[hash] = { 0xbe6dcac2 } + mLockMeshToAttachment: bool = true + } + } + particleColorTexture: string = "ASSETS/Shared/Particles/color-rampdown_2.TFT_Set15.tex" + Color: embed = ValueColor { + constantValue: vec4 = { 0.07, 0.35, 1, 0.5 } + } + meshRenderFlags: u8 = 0 + alphaRef: u8 = 0 + depthBiasFactors: vec2 = { -1, -1 } + disableBackfaceCull: bool = true + particleIsLocalOrientation: flag = true + isUniformScale: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 0, 180, 90 } + } + texture: string = "ASSETS/Characters/Azir/Skins/Skin14/Particles/Mask_Idle_Soldier.tex" + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Azir/Skins/Skin14/Particles/FN_Universal_Praxis_Red_001.tex" + UvRotationMult: embed = ValueFloat { + constantValue: f32 = 180 + } + uvScaleMult: embed = ValueVector2 { + constantValue: vec2 = { 1, 5 } + } + birthUvScrollRateMult: embed = ValueVector2 { + constantValue: vec2 = { 0, -1 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec2] = { { 0, -1 } } + } + } + } + } + } + visibilityRadius: f32 = 5000 + particleName: string = "AzirUltSoldier_Skin14_P_Idle" + particlePath: string = "Characters/AzirUltSoldier/Skins/Skin14/Particles/AzirUltSoldier_Skin14_P_Idle" + flags: u16 = 198 + } +} diff --git a/crates/ltk_ritobin/samples/azirultsoldier.rito b/crates/ltk_ritobin/samples/azirultsoldier.rito new file mode 100644 index 00000000..fb5bb855 --- /dev/null +++ b/crates/ltk_ritobin/samples/azirultsoldier.rito @@ -0,0 +1,516 @@ +#PROP_text +type: string = "PROP" +version: u32 = 3 +linked: list[string] = { } +entries: map[hash, embed] = { + "Characters/AzirUltSoldier/Skins/Skin14/Particles/AzirUltSoldier_Skin14_Idle_Effect_VFX" = VfxSystemDefinitionData { + complexEmitterDefinitionData: list[pointer] = { + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = -1 + } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "Temp_Mesh" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, 20 } + } + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Azir/Skins/Skin14/Particles/Polygon_Idle_Soldier_FX.scb" + } + } + blendMode: u8 = 1 + Color: embed = ValueColor { + constantValue: vec4 = { 0.11, 0.08, 0.87, 0.4 } + } + alphaRef: u8 = 0 + disableBackfaceCull: bool = true + isUniformScale: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 0, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 1, 5, 5 } + } + texture: string = "ASSETS/Characters/Azir/Skins/Skin14/Particles/Polygon_texture_Idle_Soldior_Ult_02.tex" + birthUvRotateRate: embed = ValueFloat { + constantValue: f32 = 50 + } + particleUVRotateRate: embed = IntegratedValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0 } + values: list[f32] = { 0 } + } + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = -1 + } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "Temp_Mesh2" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, -5, 40 } + } + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Azir/Skins/Skin14/Particles/Polygon_Idle_Soldior_Ult.scb" + } + } + blendMode: u8 = 4 + Color: embed = ValueColor { + constantValue: vec4 = { 0.35, 0.64, 1, 0.8 } + } + pass: i16 = 2 + alphaRef: u8 = 0 + disableBackfaceCull: bool = true + isUniformScale: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 0, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 0.6, 5, 5 } + } + texture: string = "ASSETS/Characters/Azir/Skins/Skin14/Particles/Decal_Banners_FlipBooks.tex" + frameRate: f32 = 1.5 + numFrames: u16 = 4 + texDiv: vec2 = { 2, 2 } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = -1 + } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "Temp_Mesh3" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, 20 } + } + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Azir/Skins/Skin14/Particles/Polygon_Idle_Soldier_FX.scb" + } + } + blendMode: u8 = 1 + Color: embed = ValueColor { + constantValue: vec4 = { 0.18, 0.23, 0.84, 0.5 } + } + pass: i16 = -1 + alphaRef: u8 = 0 + disableBackfaceCull: bool = true + isUniformScale: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 0, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 1, 5, 5 } + } + texture: string = "ASSETS/Characters/Azir/Skins/Skin14/Particles/Polygon_texture_Idle_Soldior_Ult.tex" + birthUvRotateRate: embed = ValueFloat { + constantValue: f32 = 90 + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = -1 + } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "Temp_Mesh4" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, 20 } + } + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Azir/Skins/Skin14/Particles/Polygon_Idle_Soldier_FX.scb" + } + } + blendMode: u8 = 4 + Color: embed = ValueColor { + constantValue: vec4 = { 0.17, 1, 0.97, 0.8 } + } + pass: i16 = 1 + alphaRef: u8 = 0 + disableBackfaceCull: bool = true + isUniformScale: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 0, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 1, 5, 5 } + } + texture: string = "ASSETS/Characters/Azir/Skins/Skin14/Particles/Polygon_texture_Idle_Soldior_Ult_02.tex" + birthUvRotateRate: embed = ValueFloat { + constantValue: f32 = 50 + } + particleUVRotateRate: embed = IntegratedValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0 } + values: list[f32] = { 0 } + } + } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Azir/Skins/Skin14/Particles/Azir_Skin14_EBeam2.tex" + uvScaleMult: embed = ValueVector2 { + constantValue: vec2 = { 0.3, 1 } + } + birthUvRotateRateMult: embed = ValueFloat { + constantValue: f32 = 100 + } + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = -1 + } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "Temp_Mesh5" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, 30 } + } + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Azir/Skins/Skin14/Particles/Polygon_Idle_Soldier_FX.scb" + } + } + blendMode: u8 = 1 + Color: embed = ValueColor { + constantValue: vec4 = { 0.33, 0.43, 1, 0.6 } + } + pass: i16 = 1 + alphaRef: u8 = 0 + disableBackfaceCull: bool = true + isUniformScale: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 0, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 1.2, 5, 5 } + } + texture: string = "ASSETS/Characters/Azir/Skins/Skin14/Particles/Aura_Self.tex" + frameRate: f32 = 1.5 + numFrames: u16 = 4 + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 15 + } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "body" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 15, -30 } + } + primitive: pointer = VfxPrimitiveArbitraryQuad { } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.38, 0.62, 1, 0.6 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.2, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = 210 + meshRenderFlags: u8 = 0 + depthBiasFactors: vec2 = { 0, -50 } + particleIsLocalOrientation: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 20, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 120, 30, 60 } + } + texture: string = "ASSETS/Shared/Particles/Base_Flare_Cas.tex" + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Azir/Skins/Skin14/Particles/Azir_Skin14_Code.tex" + uvScaleMult: embed = ValueVector2 { + constantValue: vec2 = { 2, 2 } + } + birthUvScrollRateMult: embed = ValueVector2 { + constantValue: vec2 = { -0.1, 0 } + } + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 15 + } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "body1" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 15, -30 } + } + primitive: pointer = VfxPrimitiveArbitraryQuad { } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.7569, 0.6039, 0.4275, 1 } + } + Color: embed = ValueColor { + constantValue: vec4 = { 1, 1, 1, 0.4 } + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.2, 1 } + values: list[vec4] = { + { 1, 1, 1, 0.4 } + { 1, 1, 1, 0.4 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = 215 + meshRenderFlags: u8 = 0 + depthBiasFactors: vec2 = { 0, -30 } + particleIsLocalOrientation: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 20, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 130, 30, 60 } + } + texture: string = "ASSETS/Shared/Particles/Akshan_Skin10_Sparker01.tex" + textureMult: pointer = VfxTextureMultDefinitionData { + uvScaleMult: embed = ValueVector2 { + constantValue: vec2 = { 2, 2 } + } + birthUvScrollRateMult: embed = ValueVector2 { + constantValue: vec2 = { 0, 0.05 } + } + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 15 + } + lifetime: option[f32] = { 15 } + isSingleParticle: flag = true + emitterName: string = "Basic" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + SpawnShape: pointer = 0xee39916f { + emitOffset: vec3 = { 0, 15, -30 } + } + EmitterPosition: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 0, 0 } } + } + } + primitive: pointer = VfxPrimitiveArbitraryQuad { } + blendMode: u8 = 4 + Color: embed = ValueColor { + constantValue: vec4 = { 0.15, 0.23, 1, 0.6 } + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { + 0 + 0.0893 + 0.1209 + 0.1363 + 0.262 + 0.2706 + 0.3148 + 0.3604 + 0.3608 + 0.405 + 0.5 + 0.6622 + 0.7687 + 0.8109 + 0.8608 + 0.9021 + 1 + } + values: list[vec4] = { + { 0.15, 0.23, 1, 0 } + { 0.15, 0.23, 1, 0.1071 } + { 0.15, 0.23, 1, 0.6 } + { 0.15, 0.23, 1, 0.15 } + { 0.15, 0.23, 1, 0.6 } + { 0.15, 0.23, 1, 0.0353 } + { 0.15, 0.23, 1, 0.0882 } + { 0.15, 0.23, 1, 0.3176 } + { 0.15, 0.23, 1, 0.6 } + { 0.15, 0.23, 1, 0.2029 } + { 0.15, 0.23, 1, 0.6 } + { 0.15, 0.23, 1, 0.4054 } + { 0.15, 0.23, 1, 0.5054 } + { 0.15, 0.23, 1, 0.1043 } + { 0.15, 0.23, 1, 0.3587 } + { 0.15, 0.23, 1, 0.0457 } + { 0.15, 0.23, 1, 0 } + } + } + } + pass: i16 = 5 + alphaRef: u8 = 0 + depthBiasFactors: vec2 = { -1, -30 } + particleIsLocalOrientation: flag = true + isUniformScale: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 0, 90 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 50, 70, 0 } + } + texture: string = "ASSETS/Characters/Azir/Skins/Skin14/Particles/Aura_Self.tex" + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Azir/Skins/Skin14/Particles/Azir_Skin14_Sacn_Lines.tex" + uvScaleMult: embed = ValueVector2 { + constantValue: vec2 = { 1, 0.7 } + } + birthUvScrollRateMult: embed = ValueVector2 { + constantValue: vec2 = { 0, -0.2 } + } + birthUVOffsetMult: embed = ValueVector2 { + constantValue: vec2 = { 1, 1 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec2] = { { 1, 1 } } + } + } + } + } + } + visibilityRadius: f32 = 5000 + particleName: string = "AzirUltSoldier_Skin14_Idle_Effect_VFX" + particlePath: string = "Characters/AzirUltSoldier/Skins/Skin14/Particles/AzirUltSoldier_Skin14_Idle_Effect_VFX" + flags: u16 = 198 + } + "Characters/AzirUltSoldier/Skins/Skin14/Particles/AzirUltSoldier_Skin14_P_Idle" = VfxSystemDefinitionData { + complexEmitterDefinitionData: list[pointer] = { + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.1 + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = -1 + } + particleLinger: option[f32] = { 0.4 } + isSingleParticle: flag = true + emitterName: string = "Temp_Avatar" + disabled: bool = true + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + primitive: pointer = VfxPrimitiveAttachedMesh { + mMesh: embed = VfxMeshDefinitionData { + mSubmeshesToDraw: list[hash] = { 0xbe6dcac2 } + mSubmeshesToDrawAlways: list[hash] = { 0xbe6dcac2 } + mLockMeshToAttachment: bool = true + } + } + particleColorTexture: string = "ASSETS/Shared/Particles/color-rampdown_2.TFT_Set15.tex" + Color: embed = ValueColor { + constantValue: vec4 = { 0.07, 0.35, 1, 0.5 } + } + meshRenderFlags: u8 = 0 + alphaRef: u8 = 0 + depthBiasFactors: vec2 = { -1, -1 } + disableBackfaceCull: bool = true + particleIsLocalOrientation: flag = true + isUniformScale: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 0, 180, 90 } + } + texture: string = "ASSETS/Characters/Azir/Skins/Skin14/Particles/Mask_Idle_Soldier.tex" + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Azir/Skins/Skin14/Particles/FN_Universal_Praxis_Red_001.tex" + UvRotationMult: embed = ValueFloat { + constantValue: f32 = 180 + } + uvScaleMult: embed = ValueVector2 { + constantValue: vec2 = { 1, 5 } + } + birthUvScrollRateMult: embed = ValueVector2 { + constantValue: vec2 = { 0, -1 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec2] = { { 0, -1 } } + } + } + } + } + } + visibilityRadius: f32 = 5000 + particleName: string = "AzirUltSoldier_Skin14_P_Idle" + particlePath: string = "Characters/AzirUltSoldier/Skins/Skin14/Particles/AzirUltSoldier_Skin14_P_Idle" + flags: u16 = 198 + } +} diff --git a/crates/ltk_ritobin/samples/cac479.rito b/crates/ltk_ritobin/samples/cac479.rito new file mode 100644 index 00000000..36c2380d --- /dev/null +++ b/crates/ltk_ritobin/samples/cac479.rito @@ -0,0 +1,645 @@ +#PROP_text +type: string = "PROP" +version: u32 = 3 +entries: map[hash, embed] = { + 0x4065c771 = 0x45cd899f { + 0x868eb76a: list[pointer] = { + 0x9cde442 { + 0xae839c67: embed = 0x4300058 { + 0xb4b427aa: f32 = 2 + } + 0x2a552694: embed = 0x4300058 { + 0xb4b427aa: f32 = 0.15 + } + 0x2431d42c: option[f32] = { 10.25 } + 0x5212abee: option[f32] = { 1 } + 0x42bd7f6b: flag = true + 0x3d25b8ce: string = "flash2" + 0xca406316: embed = 0x4300058 { + 0xb4b427aa: f32 = 1 + } + 0x4ffce322: pointer = 0xb13097f0 { + 0x95111b29: f32 = 0.005 + } + 0xfa784eab: u8 = 1 + 0x83cdeaa1: embed = 0x74f91dd { + 0xb4b427aa: vec4 = { + 0.46666667 + 0.7176471 + 0.9529412 + 0.9100023 + } + } + 0x3d7e6258: embed = 0x74f91dd { + 0xbc037de7: pointer = 0x4349c5f5 { + 0x5d68eeb5: list[f32] = { 0, 0.2, 0.5, 1 } + 0x34474c3b: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + 0x7b7a7318: i16 = -10 + 0xbfb0efdd: pointer = 0x1daa3fb0 { + 0x1f661402: f32 = 30 + } + 0x3559e15b: flag = true + 0x5932ff9c: embed = 0x68dc32b6 { + 0xb4b427aa: vec3 = { 1, 0, 0 } + 0xbc037de7: pointer = 0xacd81180 { + 0xa7084719: list[pointer] = { + 0x53a6c97e { + 0x40c351da: list[f32] = { 0, 1 } + 0xe44b7382: list[f32] = { 0, 360 } + } + 0x53a6c97e { } + 0x53a6c97e { } + } + 0x5d68eeb5: list[f32] = { 0 } + 0x34474c3b: list[vec3] = { + { 1, 0, 0 } + } + } + } + 0xf0eb7084: embed = 0x68dc32b6 { + 0xb4b427aa: vec3 = { 150, 1, 1 } + } + 0x3c6468f4: string = "ASSETS/Characters/Sett/Skins/Skin56/Particles/Aura_Self.DDS" + } + 0x9cde442 { + 0xae839c67: embed = 0x4300058 { + 0xb4b427aa: f32 = 1 + } + 0x2a552694: embed = 0x4300058 { + 0xb4b427aa: f32 = 0.2 + } + 0x2431d42c: option[f32] = { 10.25 } + 0x5212abee: option[f32] = { 1 } + 0x42bd7f6b: flag = true + 0x3d25b8ce: string = "flash3" + 0xca406316: embed = 0x4300058 { + 0xb4b427aa: f32 = 1 + } + 0x4ffce322: pointer = 0xb13097f0 { + 0x95111b29: f32 = 0.005 + } + 0xfa784eab: u8 = 4 + 0x83cdeaa1: embed = 0x74f91dd { + 0xb4b427aa: vec4 = { 0.14509805, 0.40784314, 0.9372549, 0.2 } + } + 0x3d7e6258: embed = 0x74f91dd { + 0xbc037de7: pointer = 0x4349c5f5 { + 0x5d68eeb5: list[f32] = { 0, 0.2, 0.5, 1 } + 0x34474c3b: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + 0x7b7a7318: i16 = 6 + 0x6563bee8: u8 = 1 + 0x3559e15b: flag = true + 0x5932ff9c: embed = 0x68dc32b6 { + 0xb4b427aa: vec3 = { 1, 0, 0 } + 0xbc037de7: pointer = 0xacd81180 { + 0xa7084719: list[pointer] = { + 0x53a6c97e { + 0x40c351da: list[f32] = { 0, 1 } + 0xe44b7382: list[f32] = { 0, 360 } + } + 0x53a6c97e { } + 0x53a6c97e { } + } + 0x5d68eeb5: list[f32] = { 0 } + 0x34474c3b: list[vec3] = { + { 1, 0, 0 } + } + } + } + 0xf0eb7084: embed = 0x68dc32b6 { + 0xb4b427aa: vec3 = { 350, 1, 1 } + } + 0xd4e17a53: embed = 0x68dc32b6 { + 0xbc037de7: pointer = 0xacd81180 { + 0x5d68eeb5: list[f32] = { 0, 0.34120736, 1 } + 0x34474c3b: list[vec3] = { + { 1, 1, 1 } + { 0.8634538, 0.77465767, 0.6587926 } + { 0, 0, 0 } + } + } + } + 0x3c6468f4: string = "ASSETS/Characters/Sett/Skins/Skin56/Particles/Aura_Self.DDS" + } + 0x9cde442 { + 0x22e763bc: f32 = 0.03 + 0xae839c67: embed = 0x4300058 { + 0xb4b427aa: f32 = 1 + } + 0x2a552694: embed = 0x4300058 { + 0xb4b427aa: f32 = 0.14 + } + 0x2431d42c: option[f32] = { 0.5 } + 0x5212abee: option[f32] = { 0.5 } + 0x42bd7f6b: flag = true + 0x3d25b8ce: string = "Beamdown" + 0x563d4a22: embed = 0x68dc32b6 { + 0xbc037de7: pointer = 0xacd81180 { + 0xa7084719: list[pointer] = { + 0x53a6c97e { } + 0x53a6c97e { } + 0x53a6c97e { } + } + 0x5d68eeb5: list[f32] = { 0 } + 0x34474c3b: list[vec3] = { + { 0, 0, 0 } + } + } + } + 0xfa784eab: u8 = 1 + 0x83cdeaa1: embed = 0x74f91dd { + 0xbc037de7: pointer = 0x4349c5f5 { + 0x5d68eeb5: list[f32] = { 0 } + 0x34474c3b: list[vec4] = { + { 1, 1, 1, 1 } + } + } + } + 0x3d7e6258: embed = 0x74f91dd { + 0xbc037de7: pointer = 0x4349c5f5 { + 0x5d68eeb5: list[f32] = { 0.4, 0.5, 1 } + 0x34474c3b: list[vec4] = { + { 0.9254902, 0.93333334, 0.3647059, 1 } + { 0.9254902, 0.93333334, 0.3647059, 1 } + { 0.0627451, 0.17254902, 0.99607843, 1 } + } + } + } + 0x7b7a7318: i16 = 4 + 0x67b5d729: vec2 = { -3, -3 } + 0x3559e15b: flag = true + 0x5932ff9c: embed = 0x68dc32b6 { + 0xb4b427aa: vec3 = { 1, 0, 0 } + 0xbc037de7: pointer = 0xacd81180 { + 0xa7084719: list[pointer] = { + 0x53a6c97e { + 0x40c351da: list[f32] = { 0, 1 } + 0xe44b7382: list[f32] = { 0, 360 } + } + 0x53a6c97e { } + 0x53a6c97e { } + } + 0x5d68eeb5: list[f32] = { 0 } + 0x34474c3b: list[vec3] = { + { 1, 0, 0 } + } + } + } + 0xf0eb7084: embed = 0x68dc32b6 { + 0xb4b427aa: vec3 = { 110, 300, 0 } + 0xbc037de7: pointer = 0xacd81180 { + 0xa7084719: list[pointer] = { + 0x53a6c97e { + 0x40c351da: list[f32] = { 0, 1 } + 0xe44b7382: list[f32] = { 0.7, 1 } + } + 0x53a6c97e { } + 0x53a6c97e { } + } + 0x5d68eeb5: list[f32] = { 0 } + 0x34474c3b: list[vec3] = { + { 110, 300, 0 } + { 110, 300, 0 } + } + } + } + 0xd4e17a53: embed = 0x68dc32b6 { + 0xbc037de7: pointer = 0xacd81180 { + 0x5d68eeb5: list[f32] = { 0, 0.15, 1 } + 0x34474c3b: list[vec3] = { + { 0, 0, 0 } + { 0.7, 0, 0 } + { 1, 0, 0 } + } + } + } + 0x3c6468f4: string = "ASSETS/Characters/Sett/Skins/Skin56/Particles/Sett_Skin56_Pop02.dds" + 0x9b111ae4: f32 = 6 + 0x1e67b0f1: u16 = 2 + 0x86a84509: vec2 = { 2, 1 } + 0x2f2e99f2: pointer = 0xb097c1bd { + 0x2f2e99f2: string = "ASSETS/Characters/Sett/Skins/Skin56/Particles/Sett_Skin56_line1.dds" + 0xcd124686: embed = 0x69dc3449 { + 0xb4b427aa: vec2 = { 2, 1 } + } + } + } + 0x9cde442 { + 0x22e763bc: f32 = 0.05 + 0xae839c67: embed = 0x4300058 { + 0xb4b427aa: f32 = 2 + } + 0x2a552694: embed = 0x4300058 { + 0xb4b427aa: f32 = 0.1 + } + 0x2431d42c: option[f32] = { 0.5 } + 0x5212abee: option[f32] = { 0.5 } + 0x42bd7f6b: flag = true + 0x3d25b8ce: string = "bright_spikes" + 0xb6fe52f: vec3 = { 0, -130, 0 } + 0xfa41ab8d: embed = 0x68dc32b6 { + 0xb4b427aa: vec3 = { 0, 400, 200 } + 0xbc037de7: pointer = 0xacd81180 { + 0xa7084719: list[pointer] = { + 0x53a6c97e { } + 0x53a6c97e { + 0x40c351da: list[f32] = { 0, 1 } + 0xe44b7382: list[f32] = { -1, 1 } + } + 0x53a6c97e { } + } + 0x5d68eeb5: list[f32] = { 0 } + 0x34474c3b: list[vec3] = { + { 0, 400, 200 } + } + } + } + 0x3bf0b4ed: pointer = 0xba945ee1 { + 0x9c677a2c: u8 = 1 + 0x23a0d95c: vec3 = { 12, 0, 0 } + } + 0x4ffce322: pointer = 0xb13097f0 { + 0x95111b29: f32 = 0.005 + } + 0x7b14f6: pointer = 0x4beb81fd { } + 0xfa784eab: u8 = 1 + 0x83cdeaa1: embed = 0x74f91dd { + 0xbc037de7: pointer = 0x4349c5f5 { + 0x5d68eeb5: list[f32] = { 0 } + 0x34474c3b: list[vec4] = { + { 1, 1, 1, 1 } + } + } + } + 0x3d7e6258: embed = 0x74f91dd { + 0xb4b427aa: vec4 = { 1, 0.28627452, 0.19607843, 1 } + 0xbc037de7: pointer = 0x4349c5f5 { + 0x5d68eeb5: list[f32] = { 0, 0.2, 0.8, 1 } + 0x34474c3b: list[vec4] = { + { 0.9254902, 0.93333334, 0.3647059, 0 } + { 0.9254902, 0.93333334, 0.3647059, 1 } + { 0.0627451, 0.17254902, 0.99607843, 1 } + { 0.9254902, 0.93333334, 0.3647059, 0 } + } + } + } + 0xddfca826: flag = true + 0x5932ff9c: embed = 0x68dc32b6 { + 0xb4b427aa: vec3 = { 90, -90, 0 } + } + 0xf0eb7084: embed = 0x68dc32b6 { + 0xb4b427aa: vec3 = { 140, 100, 0 } + 0xbc037de7: pointer = 0xacd81180 { + 0xa7084719: list[pointer] = { + 0x53a6c97e { } + 0x53a6c97e { + 0x40c351da: list[f32] = { 0, 0.5, 0.51, 1 } + 0xe44b7382: list[f32] = { 1, 1, -1, -1 } + } + 0x53a6c97e { } + } + 0x5d68eeb5: list[f32] = { 0 } + 0x34474c3b: list[vec3] = { + { 140, 100, 0 } + } + } + } + 0x3c6468f4: string = "ASSETS/Characters/Sett/Skins/Skin56/Particles/Sett_Skin25_Q_Pop03.dds" + 0x9b111ae4: f32 = 5 + 0x1e67b0f1: u16 = 2 + 0x86a84509: vec2 = { 2, 1 } + } + 0x9cde442 { + 0xae839c67: embed = 0x4300058 { + 0xb4b427aa: f32 = 3 + } + 0x2a552694: embed = 0x4300058 { + 0xb4b427aa: f32 = 0.5 + 0xbc037de7: pointer = 0xfe064c88 { + 0xa7084719: list[pointer] = { + 0x53a6c97e { + 0x40c351da: list[f32] = { 0, 1 } + 0xe44b7382: list[f32] = { 0.4, 0.75 } + } + } + 0x5d68eeb5: list[f32] = { 0 } + 0x34474c3b: list[f32] = { 0.5 } + } + } + 0x2431d42c: option[f32] = { 1 } + 0x5212abee: option[f32] = { 0.4 } + 0x42bd7f6b: flag = true + 0x3d25b8ce: string = "BlueBeams" + 0xca406316: embed = 0x4300058 { + 0xb4b427aa: f32 = 1 + } + 0x563d4a22: embed = 0x68dc32b6 { + 0xb4b427aa: vec3 = { 0, 10, 0 } + } + 0x7b14f6: pointer = 0xa14bd4d0 { } + 0xfa784eab: u8 = 1 + 0x3d7e6258: embed = 0x74f91dd { + 0xb4b427aa: vec4 = { 1, 0.66569006, 0.19215687, 1 } + 0xbc037de7: pointer = 0x4349c5f5 { + 0x5d68eeb5: list[f32] = { 0, 1 } + 0x34474c3b: list[vec4] = { + { 0.654902, 0.09411765, 0.9254902, 1 } + { 0.0627451, 0.17254902, 0.99607843, 1 } + } + } + } + 0x7b7a7318: i16 = 6 + 0x2674b1b5: u8 = 3 + 0x5932ff9c: embed = 0x68dc32b6 { + 0xb4b427aa: vec3 = { 1, 1, 0 } + 0xbc037de7: pointer = 0xacd81180 { + 0xa7084719: list[pointer] = { + 0x53a6c97e { + 0x40c351da: list[f32] = { 0, 0.5, 0.5001, 1 } + 0xe44b7382: list[f32] = { 0, -45, -135, -180 } + } + 0x53a6c97e { + 0x40c351da: list[f32] = { 0, 1 } + 0xe44b7382: list[f32] = { 0, -180 } + } + 0x53a6c97e { } + } + 0x5d68eeb5: list[f32] = { 0 } + 0x34474c3b: list[vec3] = { + { 1, 1, 0 } + } + } + } + 0x2ae335b2: flag = false + 0xf0eb7084: embed = 0x68dc32b6 { + 0xb4b427aa: vec3 = { 15, 100, 60 } + 0xbc037de7: pointer = 0xacd81180 { + 0xa7084719: list[pointer] = { + 0x53a6c97e { + 0x40c351da: list[f32] = { 0, 1 } + 0xe44b7382: list[f32] = { 1, 0.4 } + } + 0x53a6c97e { + 0x40c351da: list[f32] = { 0, 1 } + 0xe44b7382: list[f32] = { 0.5, 0.3 } + } + 0x53a6c97e { } + } + 0x5d68eeb5: list[f32] = { 0 } + 0x34474c3b: list[vec3] = { + { 15, 100, 60 } + } + } + } + 0xd4e17a53: embed = 0x68dc32b6 { + 0xbc037de7: pointer = 0xacd81180 { + 0x5d68eeb5: list[f32] = { 0, 0.2, 1 } + 0x34474c3b: list[vec3] = { + { 1, 1, 1 } + { 1, 1.5, 1 } + { 0, 1.7, 1 } + } + } + } + 0x3c6468f4: string = "ASSETS/Characters/Sett/Skins/Skin56/Particles/Sett_Skin18_Q_LongDot.dds" + 0x2f2e99f2: pointer = 0xb097c1bd { + 0x2f2e99f2: string = "ASSETS/Characters/Sett/Skins/Skin56/Particles/Sett_Skin56_Dot.dds" + 0x32356474: embed = 0x69dc3449 { + 0xb4b427aa: vec2 = { 0, 3 } + } + } + } + 0x9cde442 { + 0xae839c67: embed = 0x4300058 { + 0xb4b427aa: f32 = 1 + } + 0x2a552694: embed = 0x4300058 { + 0xb4b427aa: f32 = 0.05 + } + 0x5212abee: option[f32] = { 0.2 } + 0x42bd7f6b: flag = true + 0x3d25b8ce: string = "RedSun" + 0x3bf0b4ed: pointer = 0xee39916f { + 0xe5f268dd: vec3 = { 0, 10, 0 } + } + 0x563d4a22: embed = 0x68dc32b6 { + 0xbc037de7: pointer = 0xacd81180 { + 0xa7084719: list[pointer] = { + 0x53a6c97e { } + 0x53a6c97e { } + 0x53a6c97e { } + } + 0x5d68eeb5: list[f32] = { 0 } + 0x34474c3b: list[vec3] = { + { 0, 0, 0 } + } + } + } + 0xfa784eab: u8 = 4 + 0x3d7e6258: embed = 0x74f91dd { + 0xb4b427aa: vec4 = { 1, 0.7378805, 0.05882353, 1 } + 0xbc037de7: pointer = 0x4349c5f5 { + 0x5d68eeb5: list[f32] = { 0, 1 } + 0x34474c3b: list[vec4] = { + { 0.9254902, 0.93333334, 0.3647059, 1 } + { 0.654902, 0.09411765, 0.9254902, 1 } + } + } + } + 0x7b7a7318: i16 = 9 + 0x6563bee8: u8 = 1 + 0x3559e15b: flag = true + 0x5932ff9c: embed = 0x68dc32b6 { + 0xb4b427aa: vec3 = { 90, 0, 0 } + } + 0xf0eb7084: embed = 0x68dc32b6 { + 0xb4b427aa: vec3 = { 200, 5, 7.3 } + } + 0x3c6468f4: string = "ASSETS/Characters/Sett/Skins/Skin56/Particles/Sett_Skin56_Q_Glow.dds" + } + 0x9cde442 { + 0x22e763bc: f32 = 0.07 + 0xae839c67: embed = 0x4300058 { + 0xb4b427aa: f32 = 1 + } + 0x2a552694: embed = 0x4300058 { + 0xb4b427aa: f32 = 0.25 + } + 0x2431d42c: option[f32] = { 0.5 } + 0x5212abee: option[f32] = { 0.5 } + 0x42bd7f6b: flag = true + 0x3d25b8ce: string = "dark_spikes" + 0xb6fe52f: vec3 = { 0, -110, 0 } + 0xfa41ab8d: embed = 0x68dc32b6 { + 0xb4b427aa: vec3 = { 0, 0, 100 } + } + 0x3bf0b4ed: pointer = 0xee39916f { + 0xe5f268dd: vec3 = { 0, 10, 0 } + } + 0x563d4a22: embed = 0x68dc32b6 { + 0xbc037de7: pointer = 0xacd81180 { + 0xa7084719: list[pointer] = { + 0x53a6c97e { } + 0x53a6c97e { } + 0x53a6c97e { } + } + 0x5d68eeb5: list[f32] = { 0 } + 0x34474c3b: list[vec3] = { + { 0, 0, 0 } + } + } + } + 0x4ffce322: pointer = 0xb13097f0 { + 0x95111b29: f32 = 0.005 + } + 0x7b14f6: pointer = 0x4beb81fd { } + 0xfa784eab: u8 = 1 + 0x3d7e6258: embed = 0x74f91dd { + 0xb4b427aa: vec4 = { 1, 0, 0.49803922, 1 } + 0xbc037de7: pointer = 0x4349c5f5 { + 0x5d68eeb5: list[f32] = { 0, 0.2, 0.6, 1 } + 0x34474c3b: list[vec4] = { + { 0.14509805, 0.40784314, 0.9372549, 0 } + { 0.0627451, 0.17254902, 0.99607843, 1 } + { 0.14509805, 0.40784314, 0.9372549, 1 } + { 0.14509805, 0.40784314, 0.9372549, 0 } + } + } + } + 0xddfca826: flag = true + 0x5932ff9c: embed = 0x68dc32b6 { + 0xb4b427aa: vec3 = { 90, -90, 0 } + } + 0xf0eb7084: embed = 0x68dc32b6 { + 0xb4b427aa: vec3 = { 110, 90, 0 } + 0xbc037de7: pointer = 0xacd81180 { + 0xa7084719: list[pointer] = { + 0x53a6c97e { } + 0x53a6c97e { + 0x40c351da: list[f32] = { 0, 0.5, 0.51, 1 } + 0xe44b7382: list[f32] = { 1, 1, -1, -1 } + } + 0x53a6c97e { } + } + 0x5d68eeb5: list[f32] = { 0 } + 0x34474c3b: list[vec3] = { + { 110, 90, 0 } + } + } + } + 0x3c6468f4: string = "ASSETS/Characters/Sett/Skins/Skin56/Particles/Sett_Skin25_Q_Pop03.dds" + 0x9b111ae4: f32 = 15 + 0x1e67b0f1: u16 = 2 + 0x86a84509: vec2 = { 2, 1 } + } + 0x9cde442 { + 0xae839c67: embed = 0x4300058 { + 0xb4b427aa: f32 = 1 + } + 0x2a552694: embed = 0x4300058 { + 0xb4b427aa: f32 = 0.11 + } + 0x5212abee: option[f32] = { 0.5 } + 0x42bd7f6b: flag = true + 0x3d25b8ce: string = "Beamdown2" + 0x563d4a22: embed = 0x68dc32b6 { + 0xbc037de7: pointer = 0xacd81180 { + 0xa7084719: list[pointer] = { + 0x53a6c97e { } + 0x53a6c97e { } + 0x53a6c97e { } + } + 0x5d68eeb5: list[f32] = { 0 } + 0x34474c3b: list[vec3] = { + { 0, 0, 0 } + } + } + } + 0xfa784eab: u8 = 4 + 0x3d7e6258: embed = 0x74f91dd { + 0xbc037de7: pointer = 0x4349c5f5 { + 0x5d68eeb5: list[f32] = { 0.4, 0.5, 1 } + 0x34474c3b: list[vec4] = { + { 0.9254902, 0.93333334, 0.3647059, 1 } + { 0.46666667, 0.7176471, 0.9529412, 1 } + { 0.0627451, 0.17254902, 0.99607843, 1 } + } + } + } + 0x7b7a7318: i16 = 10 + 0x67b5d729: vec2 = { -3, -30 } + 0x6563bee8: u8 = 1 + 0x3559e15b: flag = true + 0x5932ff9c: embed = 0x68dc32b6 { + 0xb4b427aa: vec3 = { 1, 0, 0 } + 0xbc037de7: pointer = 0xacd81180 { + 0xa7084719: list[pointer] = { + 0x53a6c97e { + 0x40c351da: list[f32] = { 0, 1 } + 0xe44b7382: list[f32] = { 0, 360 } + } + 0x53a6c97e { } + 0x53a6c97e { } + } + 0x5d68eeb5: list[f32] = { 0 } + 0x34474c3b: list[vec3] = { + { 1, 0, 0 } + } + } + } + 0xf0eb7084: embed = 0x68dc32b6 { + 0xb4b427aa: vec3 = { 130, 300, 0 } + 0xbc037de7: pointer = 0xacd81180 { + 0xa7084719: list[pointer] = { + 0x53a6c97e { + 0x40c351da: list[f32] = { 0, 1 } + 0xe44b7382: list[f32] = { 0.7, 1 } + } + 0x53a6c97e { } + 0x53a6c97e { } + } + 0x5d68eeb5: list[f32] = { 0 } + 0x34474c3b: list[vec3] = { + { 130, 300, 0 } + } + } + } + 0xd4e17a53: embed = 0x68dc32b6 { + 0xb4b427aa: vec3 = { 1, 1.5, 2 } + 0xbc037de7: pointer = 0xacd81180 { + 0x5d68eeb5: list[f32] = { 0, 0.3, 0.6, 1 } + 0x34474c3b: list[vec3] = { + { 0, 0, 0 } + { 1, 1.5, 2 } + { 0.4, 0.3, 0.4 } + { 0.3, 0, 0 } + } + } + } + 0x3c6468f4: string = "ASSETS/Characters/Sett/Skins/Skin56/Particles/Sett_Skin25_Q_XGlitchFlip.dds" + 0x9b111ae4: f32 = 10 + 0x1e67b0f1: u16 = 4 + 0x86a84509: vec2 = { 2, 2 } + 0x968279e0: embed = 0x4300058 { + 0xb4b427aa: f32 = 180 + } + } + } + 0xecf1c6bc: string = "Caitlyn_Base_W_E_Tar_Headshot_Beam" + 0xe7638138: string = "Characters/Caitlyn/Skins/Skin0/Particles/Caitlyn_Base_W_E_Tar_Headshot_Beam" + } +} \ No newline at end of file diff --git a/crates/ltk_ritobin/samples/skin0.py b/crates/ltk_ritobin/samples/skin0.py new file mode 100644 index 00000000..243b7777 --- /dev/null +++ b/crates/ltk_ritobin/samples/skin0.py @@ -0,0 +1,1202 @@ +#PROP_text +type: string = "PROP" +version: u32 = 3 +linked: list[string] = { + "DATA/Aatrox_Skins_Root_Skins_Skin0_Skins_Skin1_Skins_Skin10_Skins_Skin11_Skins_Skin12_Skins_Skin13_Skins_Skin14_Skins_Skin15_Skins_Skin16_Skins_Skin17_Skins_Skin18_Skins_Skin19_Skins_Skin2_Skins_Skin20_Skins_Skin21_Skins_Skin22_Skins_Skin23_Skins_Skin24_Skins_Skin25_Skins_Skin26_Skins_Skin27_Skins_Skin28_Skins_Skin29_Skins_Skin3_Skins_Skin30_Skins_Skin31_Skins_Skin32_Skins_Skin4_Skins_Skin5_Skins_Skin6_Skins_Skin7_Skins_Skin8_Skins_Skin9.bin" + "DATA/Characters/Aatrox/Aatrox.bin" + "DATA/Aatrox_Skins_Skin0_Skins_Skin2_Skins_Skin20_Skins_Skin3_Skins_Skin30_Skins_Skin31_Skins_Skin32_Skins_Skin4_Skins_Skin5_Skins_Skin6_Skins_Skin7_Skins_Skin8.bin" + "DATA/Characters/Aatrox/Animations/Skin0.bin" + "DATA/Aatrox_Skins_Skin0_Skins_Skin1_Skins_Skin10_Skins_Skin2_Skins_Skin20_Skins_Skin3_Skins_Skin4_Skins_Skin5_Skins_Skin6_Skins_Skin7_Skins_Skin8_Skins_Skin9.bin" + "DATA/Aatrox_Skins_Skin0_Skins_Skin1_Skins_Skin2_Skins_Skin3_Skins_Skin4_Skins_Skin5_Skins_Skin6_Skins_Skin7.bin" + "DATA/Aatrox_Skins_Skin0_Skins_Skin1_Skins_Skin2_Skins_Skin20_Skins_Skin3_Skins_Skin4_Skins_Skin5_Skins_Skin6_Skins_Skin7_Skins_Skin8.bin" + "DATA/Aatrox_Skins_Skin0_Skins_Skin2_Skins_Skin20_Skins_Skin3_Skins_Skin4_Skins_Skin5_Skins_Skin6_Skins_Skin7_Skins_Skin8.bin" + "DATA/Aatrox_Skins_Skin0_Skins_Skin2_Skins_Skin3_Skins_Skin4_Skins_Skin5_Skins_Skin6.bin" + "DATA/Aatrox_Skins_Skin0_Skins_Skin1_Skins_Skin3.bin" + "DATA/Aatrox_Skins_Skin0_Skins_Skin3_Skins_Skin7.bin" + "DATA/Aatrox_Skins_Skin0_Skins_Skin3.bin" +} +entries: map[hash, embed] = { + "Characters/Aatrox/Skins/Skin0" = SkinCharacterDataProperties { + skinClassification: u32 = 1 + championSkinName: string = "Aatrox" + metaDataTags: string = "gender:male,race:darkin,element:dark" + loadscreen: embed = CensoredImage { + image: string = "ASSETS/Characters/Aatrox/Skins/Base/AatroxLoadscreen.dds" + } + skinAudioProperties: embed = skinAudioProperties { + tagEventList: list[string] = { "Aatrox" } + bankUnits: list2[embed] = { + BankUnit { + name: string = "Aatrox_Base_SFX" + bankPath: list[string] = { + "ASSETS/Sounds/Wwise2016/SFX/Characters/Aatrox/Skins/Base/Aatrox_Base_SFX_audio.bnk" + "ASSETS/Sounds/Wwise2016/SFX/Characters/Aatrox/Skins/Base/Aatrox_Base_SFX_events.bnk" + } + events: list[string] = { + "Play_sfx_Aatrox_AatroxBasicAttack2_OnCast" + "Play_sfx_Aatrox_AatroxBasicAttack2_OnHit" + "Play_sfx_Aatrox_AatroxBasicAttack3_OnCast" + "Play_sfx_Aatrox_AatroxBasicAttack3_OnHit" + "Play_sfx_Aatrox_AatroxBasicAttack_OnCast" + "Play_sfx_Aatrox_AatroxBasicAttack_OnHit" + "Play_sfx_Aatrox_AatroxCritAttack_OnCast" + "Play_sfx_Aatrox_AatroxCritAttack_OnHit" + "Play_sfx_Aatrox_AatroxE_OnCast" + "Play_sfx_Aatrox_AatroxPassiveAttack_OnCast" + "Play_sfx_Aatrox_AatroxPassiveAttack_OnHit" + "Play_sfx_Aatrox_AatroxPassiveDebuff_OnBuffActivate" + "Play_sfx_Aatrox_AatroxPassiveDebuff_OnBuffDeactivate" + "Play_sfx_Aatrox_AatroxPassiveReady_OnBuffActivate" + "Play_sfx_Aatrox_AatroxQ1_OnCast_all" + "Play_sfx_Aatrox_AatroxQ1_OnHit_miss" + "Play_sfx_Aatrox_AatroxQ1_OnHit_normal_all" + "Play_sfx_Aatrox_AatroxQ1_OnHit_normal_player" + "Play_sfx_Aatrox_AatroxQ1_OnHit_sweetspot_all" + "Play_sfx_Aatrox_AatroxQ1_OnHit_sweetspot_player" + "Play_sfx_Aatrox_AatroxQ2_OnCast_all" + "Play_sfx_Aatrox_AatroxQ2_OnHit_miss" + "Play_sfx_Aatrox_AatroxQ2_OnHit_normal_all" + "Play_sfx_Aatrox_AatroxQ2_OnHit_normal_player" + "Play_sfx_Aatrox_AatroxQ2_OnHit_sweetspot_all" + "Play_sfx_Aatrox_AatroxQ2_OnHit_sweetspot_player" + "Play_sfx_Aatrox_AatroxQ3_OnCast_all" + "Play_sfx_Aatrox_AatroxQ3_OnHit_miss" + "Play_sfx_Aatrox_AatroxQ3_OnHit_normal_all" + "Play_sfx_Aatrox_AatroxQ3_OnHit_normal_player" + "Play_sfx_Aatrox_AatroxQ3_OnHit_sweetspot_all" + "Play_sfx_Aatrox_AatroxQ3_OnHit_sweetspot_player" + "Play_sfx_Aatrox_AatroxR_6seconds" + "Play_sfx_Aatrox_AatroxR_buffdeactivate" + "Play_sfx_Aatrox_AatroxR_end" + "Play_sfx_Aatrox_AatroxR_OnBuffActivate_all" + "Play_sfx_Aatrox_AatroxR_OnBuffActivate_player" + "Play_sfx_Aatrox_AatroxRAttack1_OnCast" + "Play_sfx_Aatrox_AatroxRAttack1_OnHit" + "Play_sfx_Aatrox_AatroxRAttack2_OnCast" + "Play_sfx_Aatrox_AatroxRAttack2_OnHit" + "Play_sfx_Aatrox_AatroxRRevive_all" + "Play_sfx_Aatrox_AatroxRRevive_player" + "Play_sfx_Aatrox_AatroxW_OnCast" + "Play_sfx_Aatrox_AatroxW_OnHit" + "Play_sfx_Aatrox_AatroxW_OnMissileCast" + "Play_sfx_Aatrox_AatroxW_OnMissileLaunch" + "Play_sfx_Aatrox_AatroxWBump_OnBuffActivate" + "Play_sfx_Aatrox_AatroxWChains_OnBuffActivate" + "Play_sfx_Aatrox_AatroxWChains_OnBuffDeactivate" + "Play_sfx_Aatrox_Dance3D_In_buffactivate" + "Play_sfx_Aatrox_Dance3D_loop_buffactivate" + "Play_sfx_Aatrox_Death3D_cast" + "Play_sfx_Aatrox_Joke3D_buffactivate" + "Play_sfx_Aatrox_Recall3D_buffactivate" + "Play_sfx_Aatrox_Taunt3D_buffactivate" + "Set_Switch_Aatrox_R_Active" + "Set_Switch_Aatrox_R_Inactive" + "Stop_sfx_Aatrox_AatroxW_OnMissileLaunch" + "Stop_sfx_Aatrox_AatroxWBump_OnBuffActivate" + "Stop_sfx_Aatrox_AatroxWChains_OnBuffActivate" + "Stop_sfx_Aatrox_Dance3D_In_buffactivate" + "Stop_sfx_Aatrox_Joke3D_buffactivate" + "Stop_sfx_Aatrox_Recall3D_buffactivate" + "Stop_sfx_Aatrox_Taunt3D_buffactivate" + "Switch_Aatrox_Footsteps_Brush" + "Switch_Aatrox_Footsteps_Dirt" + "Switch_Aatrox_Footsteps_Stone" + "Switch_Aatrox_Footsteps_Water" + } + } + BankUnit { + name: string = "Aatrox_Base_VO" + bankPath: list[string] = { + "ASSETS/Sounds/Wwise2016/VO/en_US/Characters/Aatrox/Skins/Base/Aatrox_Base_VO_audio.bnk" + "ASSETS/Sounds/Wwise2016/VO/en_US/Characters/Aatrox/Skins/Base/Aatrox_Base_VO_events.bnk" + "ASSETS/Sounds/Wwise2016/VO/en_US/Characters/Aatrox/Skins/Base/Aatrox_Base_VO_audio.wpk" + } + events: list[string] = { + "Play_vo_Aatrox_AatroxE_cast3D" + "Play_vo_Aatrox_AatroxQ_OnCast" + "Play_vo_Aatrox_AatroxR_cast3D" + "Play_vo_Aatrox_AatroxRRevive_OnBuffCast" + "Play_vo_Aatrox_AatroxW_cast3D" + "Play_vo_Aatrox_Attack2DGeneral" + "Play_vo_Aatrox_Attack2DPantheon" + "Play_vo_Aatrox_Attack2DTryndamere" + "Play_vo_Aatrox_Attack2DZoe" + "Play_vo_Aatrox_Death3D" + "Play_vo_Aatrox_FirstEncounter3DAkali" + "Play_vo_Aatrox_FirstEncounter3DAnivia" + "Play_vo_Aatrox_FirstEncounter3DCamille" + "Play_vo_Aatrox_FirstEncounter3DDarius" + "Play_vo_Aatrox_FirstEncounter3DFiora" + "Play_vo_Aatrox_FirstEncounter3DGalio" + "Play_vo_Aatrox_FirstEncounter3DGangplank" + "Play_vo_Aatrox_FirstEncounter3DGaren" + "Play_vo_Aatrox_FirstEncounter3DGeneral" + "Play_vo_Aatrox_FirstEncounter3DIllaoi" + "Play_vo_Aatrox_FirstEncounter3DJax" + "Play_vo_Aatrox_FirstEncounter3DKaisa" + "Play_vo_Aatrox_FirstEncounter3DKayle" + "Play_vo_Aatrox_FirstEncounter3DKayn" + "Play_vo_Aatrox_FirstEncounter3DKennen" + "Play_vo_Aatrox_FirstEncounter3DKled" + "Play_vo_Aatrox_FirstEncounter3DMalphite" + "Play_vo_Aatrox_FirstEncounter3DMaokai" + "Play_vo_Aatrox_FirstEncounter3DMorgana" + "Play_vo_Aatrox_FirstEncounter3DMundo" + "Play_vo_Aatrox_FirstEncounter3DNasus" + "Play_vo_Aatrox_FirstEncounter3DNautilus" + "Play_vo_Aatrox_FirstEncounter3DOrnn" + "Play_vo_Aatrox_FirstEncounter3DPantheon" + "Play_vo_Aatrox_FirstEncounter3DQuinn" + "Play_vo_Aatrox_FirstEncounter3DRenekton" + "Play_vo_Aatrox_FirstEncounter3DRiven" + "Play_vo_Aatrox_FirstEncounter3DRumble" + "Play_vo_Aatrox_FirstEncounter3DShen" + "Play_vo_Aatrox_FirstEncounter3DSion" + "Play_vo_Aatrox_FirstEncounter3DTargon" + "Play_vo_Aatrox_FirstEncounter3DTaric" + "Play_vo_Aatrox_FirstEncounter3DTeemo" + "Play_vo_Aatrox_FirstEncounter3DTrundle" + "Play_vo_Aatrox_FirstEncounter3DTryndamere" + "Play_vo_Aatrox_FirstEncounter3DVarus" + "Play_vo_Aatrox_FirstEncounter3DVoid" + "Play_vo_Aatrox_FirstEncounter3DYorick" + "Play_vo_Aatrox_FirstEncounter3DZoe" + "Play_vo_Aatrox_Joke3DGeneral" + "Play_vo_Aatrox_Kill3DAatrox" + "Play_vo_Aatrox_Kill3DAnivia" + "Play_vo_Aatrox_Kill3DCamille" + "Play_vo_Aatrox_Kill3DDarius" + "Play_vo_Aatrox_Kill3DFiora" + "Play_vo_Aatrox_Kill3DGangplank" + "Play_vo_Aatrox_Kill3DGaren" + "Play_vo_Aatrox_Kill3DGeneral" + "Play_vo_Aatrox_Kill3DIllaoi" + "Play_vo_Aatrox_Kill3DKaisa" + "Play_vo_Aatrox_Kill3DKayle" + "Play_vo_Aatrox_Kill3DKayn" + "Play_vo_Aatrox_Kill3DKled" + "Play_vo_Aatrox_Kill3DMalphite" + "Play_vo_Aatrox_Kill3DMaokai" + "Play_vo_Aatrox_Kill3DMorgana" + "Play_vo_Aatrox_Kill3DNasus" + "Play_vo_Aatrox_Kill3DNautilus" + "Play_vo_Aatrox_Kill3DOrnn" + "Play_vo_Aatrox_Kill3DPantheon" + "Play_vo_Aatrox_Kill3DRiven" + "Play_vo_Aatrox_Kill3DShen" + "Play_vo_Aatrox_Kill3DSion" + "Play_vo_Aatrox_Kill3DTaric" + "Play_vo_Aatrox_Kill3DTeemo" + "Play_vo_Aatrox_Kill3DTryndamere" + "Play_vo_Aatrox_Kill3DVarus" + "Play_vo_Aatrox_Kill3DZoe" + "Play_vo_Aatrox_Laugh3DGeneral" + "Play_vo_Aatrox_MasteryResponse3DGeneral" + "Play_vo_Aatrox_Move2DFirstPantheon" + "Play_vo_Aatrox_Move2DLong" + "Play_vo_Aatrox_Move2DRReady" + "Play_vo_Aatrox_Move2DStandard" + "Play_vo_Aatrox_Taunt3DGeneral" + } + voiceOver: bool = true + } + } + } + skinAnimationProperties: embed = skinAnimationProperties { + animationGraphData: link = "Characters/Aatrox/Animations/Skin0" + } + skinMeshProperties: embed = SkinMeshDataProperties { + skeleton: string = "ASSETS/Characters/Aatrox/Skins/Base/Aatrox.skl" + simpleSkin: string = "ASSETS/Characters/Aatrox/Skins/Base/Aatrox.skn" + texture: string = "ASSETS/Characters/Aatrox/Skins/Base/Aatrox_Base_TX_CM.dds" + skinScale: f32 = 1.09000003 + selfIllumination: f32 = 0.699999988 + brushAlphaOverride: f32 = 0.550000012 + overrideBoundingBox: option[vec3] = { { 130, 250, 130 } } + material: link = "Characters/Aatrox/Skins/Skin0/Materials/Aatrox_VFXBase_inst" + reflectionFresnelColor: rgba = { 0, 0, 0, 255 } + initialSubmeshToHide: string = "Wings" + initialSubmeshShadowsToHide: string = "Banner" + materialOverride: list[embed] = { + SkinMeshDataProperties_MaterialOverride { + material: link = "Characters/Aatrox/Skins/Skin0/Materials/Sword_inst" + submesh: string = "Sword" + } + SkinMeshDataProperties_MaterialOverride { + material: link = "Characters/Aatrox/Skins/Skin0/Materials/Wing_inst" + submesh: string = "Wings" + } + SkinMeshDataProperties_MaterialOverride { + material: link = "Characters/Aatrox/Skins/Skin0/Materials/Banner_inst" + submesh: string = "Banner" + } + } + rigPoseModifierData: list[pointer] = { + ConformToPathRigPoseModifierData { + mStartingJointName: hash = "L_Wing_Banner_Ground1" + mEndingJointName: hash = "L_Wing_Banner_Ground4" + mDefaultMaskName: hash = "empty" + mMaxBoneAngle: f32 = 150 + mVelMultiplier: f32 = 0 + mFrequency: f32 = 5 + } + ConformToPathRigPoseModifierData { + mStartingJointName: hash = "R_Wing_Banner_Ground1" + mEndingJointName: hash = "R_Wing_Banner_Ground4" + mDefaultMaskName: hash = "empty" + mMaxBoneAngle: f32 = 150 + mVelMultiplier: f32 = 0 + mFrequency: f32 = 5 + } + } + } + armorMaterial: string = "Flesh" + defaultAnimations: list[string] = { "BaseBuffPose" } + mContextualActionData: link = "Characters/Aatrox/CAC/Aatrox_Base" + iconCircle: option[string] = { "ASSETS/Characters/Aatrox/HUD/Aatrox_Circle.dds" } + iconSquare: option[string] = { "ASSETS/Characters/Aatrox/HUD/Aatrox_Square.dds" } + healthBarData: embed = CharacterHealthBarDataRecord { + attachToBone: string = "Buffbone_Cstm_Healthbar" + unitHealthBarStyle: u8 = 10 + } + mResourceResolver: link = "Characters/Aatrox/Skins/Skin0/Resources" + PersistentEffectConditions: list2[pointer] = { + PersistentEffectConditionData { + OwnerCondition: pointer = HasBuffDynamicMaterialBoolDriver { + Spell: hash = "Characters/Aatrox/Spells/AatroxPassiveAbility/AatroxPassiveReady" + } + PersistentVfxs: list2[embed] = { + PersistentVfxData { + boneName: string = "Weapon_Heart" + effectKey: hash = "Aatrox_P_Ready" + } + } + } + } + } + "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_E_Active_buff" = VfxSystemDefinitionData { + complexEmitterDefinitionData: list[pointer] = { + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 1.5 + } + particleLinger: option[f32] = { 1 } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "Avatar" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + primitive: pointer = VfxPrimitiveAttachedMesh { + mMesh: embed = VfxMeshDefinitionData { + mSubmeshesToDraw: list[hash] = { "BODY", "Shoulder" } + } + } + blendMode: u8 = 1 + color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.100000001, 0.899999976, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + depthBiasFactors: vec2 = { -1, -1 } + disableBackfaceCull: bool = true + particleIsLocalOrientation: flag = true + isUniformScale: flag = true + isRandomStartFrame: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 1.00100005, 1.00100005, 1.00100005 } + } + texture: string = "ASSETS/Characters/Aatrox/Skins/Base/Particles/Aatrox_Base_E_buff_avatar.dds" + uvMode: u8 = 2 + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.25 + } + particleLinger: option[f32] = { 1 } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "Avatar_activate" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + primitive: pointer = VfxPrimitiveAttachedMesh { + mMesh: embed = VfxMeshDefinitionData { + mSubmeshesToDraw: list[hash] = { "BODY", "Shoulder" } + } + } + blendMode: u8 = 4 + color: embed = ValueColor { + constantValue: vec4 = { 1, 1, 1, 0.650003791 } + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.100000001, 0.800000012, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 0.650003791 } + { 1, 1, 1, 0.650003791 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = 1 + disableBackfaceCull: bool = true + particleIsLocalOrientation: flag = true + isUniformScale: flag = true + isRandomStartFrame: flag = true + uvScrollClamp: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 1.00999999, 1.00999999, 1.00999999 } + } + texture: string = "ASSETS/Characters/Aatrox/Skins/Base/Particles/Aatrox_Base_E_buff_avatar_sheen.dds" + uvMode: u8 = 2 + birthUvScrollRate: embed = ValueVector2 { + constantValue: vec2 = { 0, 2 } + } + texAddressModeBase: u8 = 2 + } + } + particleName: string = "Aatrox_Base_E_Active_buff" + particlePath: string = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_E_Active_buff" + } + "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_E_Dash" = VfxSystemDefinitionData { + complexEmitterDefinitionData: list[pointer] = { + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.300000012 + } + particleLinger: option[f32] = { 0.200000003 } + lifetime: option[f32] = { 1.10000002 } + isSingleParticle: flag = true + emitterName: string = "Avatar" + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, 50 } + } + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + primitive: pointer = VfxPrimitiveAttachedMesh { + mMesh: embed = VfxMeshDefinitionData { + mSubmeshesToDraw: list[hash] = { "BODY" } + } + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 1, 1, 0.500007629 } + } + color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.100000001, 0.5, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0.300007641 } + { 1, 1, 1, 0 } + } + } + } + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.200000003, 1 } + values: list[f32] = { 0, 0, 0.5 } + } + } + erosionFeatherOut: f32 = 0.300000012 + erosionMapName: string = "ASSETS/Characters/Aatrox/Skins/Base/Particles/Aatrox_Base_Q_SmokeErode.dds" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + disableBackfaceCull: bool = true + particleIsLocalOrientation: flag = true + isUniformScale: flag = true + isRandomStartFrame: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 1.00999999, 1, 1 } + } + texture: string = "ASSETS/Characters/Aatrox/Skins/Base/Aatrox_Base_TX_CM.dds" + numFrames: u16 = 4 + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.300000012 + } + particleLinger: option[f32] = { 0.200000003 } + lifetime: option[f32] = { 1.10000002 } + isSingleParticle: flag = true + emitterName: string = "Avatar1" + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, 50 } + } + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + primitive: pointer = VfxPrimitiveAttachedMesh { + mMesh: embed = VfxMeshDefinitionData { + mSubmeshesToDraw: list[hash] = { "Sword" } + } + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 1, 1, 0.500007629 } + } + color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.100000001, 0.5, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0.300007641 } + { 1, 1, 1, 0 } + } + } + } + disableBackfaceCull: bool = true + particleIsLocalOrientation: flag = true + isUniformScale: flag = true + isRandomStartFrame: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 1.00999999, 1, 1 } + } + texture: string = "ASSETS/Characters/Aatrox/Skins/Base/Aatrox_Base_Sword_TX_CM.dds" + numFrames: u16 = 4 + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.300000012 + } + particleLinger: option[f32] = { 0.200000003 } + lifetime: option[f32] = { 1.10000002 } + isSingleParticle: flag = true + emitterName: string = "Avatar2" + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, 50 } + } + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + primitive: pointer = VfxPrimitiveAttachedMesh { + mMesh: embed = VfxMeshDefinitionData { + mSubmeshesToDraw: list[hash] = { "Wings" } + } + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 1, 1, 0.500007629 } + } + color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.100000001, 0.5, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0.300007641 } + { 1, 1, 1, 0 } + } + } + } + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.200000003, 1 } + values: list[f32] = { 0, 0, 0.5 } + } + } + erosionFeatherOut: f32 = 0.300000012 + erosionMapName: string = "ASSETS/Characters/Aatrox/Skins/Base/Particles/Aatrox_Base_Q_SmokeErode.dds" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + disableBackfaceCull: bool = true + particleIsLocalOrientation: flag = true + isUniformScale: flag = true + isRandomStartFrame: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 1.00999999, 1, 1 } + } + texture: string = "ASSETS/Characters/Aatrox/Skins/Base/Aatrox_Wings_TX_CM.dds" + numFrames: u16 = 4 + } + } + particleName: string = "Aatrox_Base_E_Dash" + particlePath: string = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_E_Dash" + mIsPoseAfterimage: bool = true + } + "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_P_Ready" = VfxSystemDefinitionData { + complexEmitterDefinitionData: list[pointer] = { + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.699999988 + } + particleLinger: option[f32] = { 1 } + emitterName: string = "Basic" + importance: u8 = 2 + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + blendMode: u8 = 4 + color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.400000006, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 0.330006868, 0, 0, 1 } + } + } + } + depthBiasFactors: vec2 = { -1, -2 } + isUniformScale: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 1, 0, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 1, 0, 0 } } + } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 150, 100, 100 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 150, 100, 100 } } + } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.200000003, 1 } + values: list[vec3] = { + { 0.25, 0.25, 2.5 } + { 1, 1, 1 } + { 0.25, 0.25, 0.25 } + } + } + } + texture: string = "ASSETS/Characters/Aatrox/Skins/Base/Particles/Aatrox_Base_TEMP_Diana_Skin11_W_FaintGlow.dds" + paletteDefinition: pointer = VfxPaletteDefinitionData { + paletteTexture: string = "ASSETS/Characters/Aatrox/Skins/Base/Particles/Aatrox_Base_AA_Gradient_RGB.dds" + palleteSrcMixColor: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + paletteSelector: embed = ValueVector3 { + constantValue: vec3 = { 2, 0, 0 } + } + paletteCount: i32 = 8 + } + } + } + particleName: string = "Aatrox_Base_P_Ready" + particlePath: string = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_P_Ready" + } + "Characters/Aatrox/Skins/Skin0/Materials/Sword_inst" = StaticMaterialDef { + name: string = "Characters/Aatrox/Skins/Skin0/Materials/Sword_inst" + samplerValues: list2[embed] = { + StaticMaterialShaderSamplerDef { + samplerName: string = "Diffuse_Texture" + textureName: string = "ASSETS/Characters/Aatrox/Skins/Base/Aatrox_Base_Sword_TX_CM.dds" + addressU: u32 = 1 + addressV: u32 = 1 + addressW: u32 = 1 + } + StaticMaterialShaderSamplerDef { + samplerName: string = "Mask_Texture" + textureName: string = "ASSETS/Characters/Aatrox/Skins/Base/Particles/Aatrox_Base_P_Sword_Mask.dds" + addressW: u32 = 1 + } + StaticMaterialShaderSamplerDef { + samplerName: string = "Gradient_Texture" + textureName: string = "ASSETS/Shared/Materials/Gradient_test_01.dds" + addressU: u32 = 1 + addressV: u32 = 1 + } + } + paramValues: list2[embed] = { + StaticMaterialShaderParamDef { + name: string = "Mask_Intensity" + value: vec4 = { 0.792500019, 0, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Bloom_Intensity" + value: vec4 = { 4, 0, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Scrolling_Scale" + value: vec4 = { 1, 1, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Scrolling_Rate" + value: vec4 = { 0, -1, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Color" + value: vec4 = { 1, 0.301960796, 0.0274509806, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Dissolve_Bias" + value: vec4 = { -1, 0, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Dissolve_SmoothStep" + value: vec4 = { 0, 0.200000003, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Gradient_Sharpness" + value: vec4 = { 0.400000006, 0, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Alpha_Sharpness" + value: vec4 = { 0.00100000005, 0, 0, 0 } + } + } + switches: list2[embed] = { + StaticMaterialSwitchDef { + name: string = "USE_COLORDODGE" + on: bool = false + } + StaticMaterialSwitchDef { + name: string = "USE_ADDATIVE" + } + StaticMaterialSwitchDef { + name: string = "USE_LERP" + on: bool = false + } + StaticMaterialSwitchDef { + name: string = "USE_DISSOLVE" + on: bool = false + } + } + shaderMacros: map[string, string] = { + "NUM_BLEND_WEIGHTS" = "4" + } + techniques: list[embed] = { + StaticMaterialTechniqueDef { + name: string = "normal" + passes: list[embed] = { + StaticMaterialPassDef { + shader: link = "Shaders/SkinnedMesh/Scrolling_ColorDodge_Masked" + blendEnable: bool = true + srcColorBlendFactor: u32 = 6 + srcAlphaBlendFactor: u32 = 6 + dstColorBlendFactor: u32 = 7 + dstAlphaBlendFactor: u32 = 7 + } + } + } + } + childTechniques: list[embed] = { + StaticMaterialChildTechniqueDef { + name: string = "transition" + parentName: string = "normal" + shaderMacros: map[string, string] = { + "TRANSITION" = "1" + } + } + } + dynamicMaterial: pointer = DynamicMaterialDef { + parameters: list[embed] = { + DynamicMaterialParameterDef { + name: string = "Mask_Intensity" + driver: pointer = LerpMaterialDriver { + mBoolDriver: pointer = HasBuffDynamicMaterialBoolDriver { + mScriptName: string = "AatroxPassiveReady" + } + mOnValue: f32 = 0.75 + mTurnOffTimeSec: f32 = 0.200000003 + } + } + } + } + } + "Characters/Aatrox/Skins/Skin0/Materials/Banner_inst" = StaticMaterialDef { + name: string = "Characters/Aatrox/Skins/Skin0/Materials/Banner_inst" + samplerValues: list2[embed] = { + StaticMaterialShaderSamplerDef { + samplerName: string = "Diffuse_Texture" + textureName: string = "ASSETS/Characters/Aatrox/Skins/Base/Particles/Aatrox_Base_I_Banner_color.dds" + addressU: u32 = 1 + addressV: u32 = 1 + addressW: u32 = 1 + } + StaticMaterialShaderSamplerDef { + samplerName: string = "Mask_Texture" + textureName: string = "ASSETS/Characters/Aatrox/Skins/Base/Particles/Aatrox_Base_I_Banner.dds" + addressW: u32 = 1 + } + } + paramValues: list2[embed] = { + StaticMaterialShaderParamDef { + name: string = "UV_Scale" + value: vec4 = { 1, 1, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Scroll_Speed" + value: vec4 = { 0, -0.300000012, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Alpha_Bias" + value: vec4 = { 0.300000012, 0, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "UV_Scale_BLUE" + value: vec4 = { 1, 1, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Scroll_Speed_BLUE" + value: vec4 = { 0, -0.200000003, 0, 0 } + } + } + switches: list2[embed] = { + StaticMaterialSwitchDef { + name: string = "MULTIPLY_ADD" + on: bool = false + } + StaticMaterialSwitchDef { + name: string = "USE_RED_TO_ALPHA" + } + StaticMaterialSwitchDef { + name: string = "USE_BLUE_CHANNEL" + } + } + shaderMacros: map[string, string] = { + "NUM_BLEND_WEIGHTS" = "4" + } + techniques: list[embed] = { + StaticMaterialTechniqueDef { + name: string = "normal" + passes: list[embed] = { + StaticMaterialPassDef { + shader: link = "Shaders/SkinnedMesh/ScrollingCustomAlpha" + blendEnable: bool = true + srcColorBlendFactor: u32 = 6 + srcAlphaBlendFactor: u32 = 6 + dstColorBlendFactor: u32 = 7 + dstAlphaBlendFactor: u32 = 7 + } + } + } + } + childTechniques: list[embed] = { + StaticMaterialChildTechniqueDef { + name: string = "transition" + parentName: string = "normal" + shaderMacros: map[string, string] = { + "TRANSITION" = "1" + } + } + } + } + "Characters/Aatrox/Skins/Skin0/Materials/Aatrox_VFXBase_inst" = StaticMaterialDef { + name: string = "Characters/Aatrox/Skins/Skin0/Materials/Aatrox_VFXBase_inst" + samplerValues: list2[embed] = { + StaticMaterialShaderSamplerDef { + samplerName: string = "Diffuse_Texture" + textureName: string = "ASSETS/Characters/Aatrox/Skins/Base/Aatrox_Base_TX_CM.dds" + addressU: u32 = 1 + addressV: u32 = 1 + addressW: u32 = 1 + } + StaticMaterialShaderSamplerDef { + samplerName: string = "Mask_Texture" + textureName: string = "ASSETS/Characters/Aatrox/Skins/Base/Particles/Aatrox_Base_R_body_mask.dds" + addressU: u32 = 1 + addressV: u32 = 1 + addressW: u32 = 1 + } + StaticMaterialShaderSamplerDef { + samplerName: string = "Gradient_Texture" + textureName: string = "ASSETS/Shared/Materials/Gradient_test_01.dds" + addressU: u32 = 1 + addressV: u32 = 1 + addressW: u32 = 1 + } + } + paramValues: list2[embed] = { + StaticMaterialShaderParamDef { + name: string = "Dissolve_SmoothStep" + value: vec4 = { 0, 0.150000006, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Dissolve_Bias" + value: vec4 = { -0.200000003, 0, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Pulse_Rate" + value: vec4 = { 3, 0, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Pulse_Max" + value: vec4 = { 0.400000006, 0, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Gradient_Sharpness" + value: vec4 = { 0.5, 0, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Alpha_Sharpness" + value: vec4 = { 0.00100000005, 0, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Bloom_Intensity" + value: vec4 = { 10, 0, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Pulse_Offset" + value: vec4 = { 0.300000012, 0, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Alpha" + value: vec4 = { 1, 0, 0, 0 } + } + } + shaderMacros: map[string, string] = { + "NUM_BLEND_WEIGHTS" = "4" + } + techniques: list[embed] = { + StaticMaterialTechniqueDef { + name: string = "normal" + passes: list[embed] = { + StaticMaterialPassDef { + shader: link = "Shaders/SkinnedMesh/Aatrox_VFXBase" + blendEnable: bool = true + srcColorBlendFactor: u32 = 6 + srcAlphaBlendFactor: u32 = 6 + dstColorBlendFactor: u32 = 7 + dstAlphaBlendFactor: u32 = 7 + } + } + } + } + childTechniques: list[embed] = { + StaticMaterialChildTechniqueDef { + name: string = "transition" + parentName: string = "normal" + shaderMacros: map[string, string] = { + "TRANSITION" = "1" + } + } + } + dynamicMaterial: pointer = DynamicMaterialDef { + parameters: list[embed] = { + DynamicMaterialParameterDef { + name: string = "Dissolve_Bias" + driver: pointer = MaxMaterialDriver { + mDrivers: list[pointer] = { + FloatGraphMaterialDriver { + driver: pointer = LerpMaterialDriver { + mBoolDriver: pointer = IsDeadDynamicMaterialBoolDriver { } + mTurnOnTimeSec: f32 = 4 + mTurnOffTimeSec: f32 = 0 + } + graph: embed = VfxAnimatedFloatVariableData { + times: list[f32] = { 0.00171930937, 0.216738746, 0.766768217, 1.00488436 } + values: list[f32] = { -0.22144419, 0.260138661, 0.752247512, 0.86541003 } + } + } + FloatGraphMaterialDriver { + driver: pointer = LerpMaterialDriver { + mBoolDriver: pointer = IsAnimationPlayingDynamicMaterialBoolDriver { + mAnimationNames: list[hash] = { "Passive_Death" } + } + mTurnOnTimeSec: f32 = 3 + } + graph: embed = VfxAnimatedFloatVariableData { + times: list[f32] = { 0.00321787666, 0.381477386, 0.997775316 } + values: list[f32] = { -0.225780264, 0.583815038, 0.994219661 } + } + } + } + } + } + DynamicMaterialParameterDef { + name: string = "Pulse_Rate" + driver: pointer = LerpMaterialDriver { + mBoolDriver: pointer = HasBuffDynamicMaterialBoolDriver { + mScriptName: string = "AatroxR" + } + mOnValue: f32 = 5 + mTurnOnTimeSec: f32 = 0 + mTurnOffTimeSec: f32 = 0 + } + } + } + } + } + "Characters/Aatrox/Skins/Skin0/Materials/Wing_inst" = StaticMaterialDef { + name: string = "Characters/Aatrox/Skins/Skin0/Materials/Wing_inst" + samplerValues: list2[embed] = { + StaticMaterialShaderSamplerDef { + samplerName: string = "Diffuse_Texture" + textureName: string = "ASSETS/Characters/Aatrox/Skins/Base/Aatrox_Wings_TX_CM.dds" + addressU: u32 = 1 + addressV: u32 = 1 + addressW: u32 = 1 + } + StaticMaterialShaderSamplerDef { + samplerName: string = "Mask_Texture" + textureName: string = "ASSETS/Characters/Aatrox/Skins/Base/Particles/Aatrox_Base_R_wing_mask.dds" + addressW: u32 = 1 + } + StaticMaterialShaderSamplerDef { + samplerName: string = "Gradient_Texture" + textureName: string = "ASSETS/Characters/Aatrox/Skins/Base/Particles/Aatrox_Base_R_mat_gradient.dds" + addressU: u32 = 1 + addressV: u32 = 1 + } + } + paramValues: list2[embed] = { + StaticMaterialShaderParamDef { + name: string = "Mask_Intensity" + value: vec4 = { 0.939999998, 0, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Bloom_Intensity" + value: vec4 = { 5, 0, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Scrolling_Scale" + value: vec4 = { 1, 1, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Scrolling_Rate" + value: vec4 = { -0.5, -0.5, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Color" + value: vec4 = { 1, 0.250980407, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Dissolve_Bias" + value: vec4 = { 0.785000026, 0, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Dissolve_SmoothStep" + value: vec4 = { 0, 0.5, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Gradient_Sharpness" + value: vec4 = { 2, 0, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Alpha_Sharpness" + value: vec4 = { 0.00100000005, 0, 0, 0 } + } + } + switches: list2[embed] = { + StaticMaterialSwitchDef { + name: string = "USE_COLORDODGE" + on: bool = false + } + StaticMaterialSwitchDef { + name: string = "USE_ADDATIVE" + } + StaticMaterialSwitchDef { + name: string = "USE_LERP" + on: bool = false + } + StaticMaterialSwitchDef { + name: string = "USE_DISSOLVE" + } + } + shaderMacros: map[string, string] = { + "NUM_BLEND_WEIGHTS" = "4" + } + techniques: list[embed] = { + StaticMaterialTechniqueDef { + name: string = "normal" + passes: list[embed] = { + StaticMaterialPassDef { + shader: link = "Shaders/SkinnedMesh/Scrolling_ColorDodge_Masked" + blendEnable: bool = true + srcColorBlendFactor: u32 = 6 + srcAlphaBlendFactor: u32 = 6 + dstColorBlendFactor: u32 = 7 + dstAlphaBlendFactor: u32 = 7 + } + } + } + } + childTechniques: list[embed] = { + StaticMaterialChildTechniqueDef { + name: string = "transition" + parentName: string = "normal" + shaderMacros: map[string, string] = { + "TRANSITION" = "1" + } + } + } + dynamicMaterial: pointer = DynamicMaterialDef { + parameters: list[embed] = { + DynamicMaterialParameterDef { + name: string = "Dissolve_Bias" + driver: pointer = SwitchMaterialDriver { + mElements: list[embed] = { + SwitchMaterialDriverElement { + mCondition: pointer = HasBuffDynamicMaterialBoolDriver { + mScriptName: string = "AatroxRFX" + } + mValue: pointer = LerpMaterialDriver { + mBoolDriver: pointer = HasBuffDynamicMaterialBoolDriver { + mScriptName: string = "AatroxRFX" + mDeactivateEarlySeconds: f32 = 1 + } + mOnValue: f32 = -1 + mOffValue: f32 = 1 + mTurnOnTimeSec: f32 = 2 + } + } + SwitchMaterialDriverElement { + mCondition: pointer = HasBuffDynamicMaterialBoolDriver { + mScriptName: string = "AatroxRReviveMaterialOverride" + } + mValue: pointer = LerpMaterialDriver { + mBoolDriver: pointer = HasBuffDynamicMaterialBoolDriver { + mScriptName: string = "AatroxRReviveMaterialOverride" + } + mOffValue: f32 = -0.180000007 + mTurnOnTimeSec: f32 = 6 + mTurnOffTimeSec: f32 = 0 + } + } + SwitchMaterialDriverElement { + mCondition: pointer = IsAnimationPlayingDynamicMaterialBoolDriver { + mAnimationNames: list[hash] = { 0x909068b6 } + } + mValue: pointer = LerpMaterialDriver { + mBoolDriver: pointer = IsAnimationPlayingDynamicMaterialBoolDriver { + mAnimationNames: list[hash] = { 0x909068b6 } + } + mOnValue: f32 = -1 + mOffValue: f32 = 1 + mTurnOnTimeSec: f32 = 0.200000003 + mTurnOffTimeSec: f32 = 0.200000003 + } + } + SwitchMaterialDriverElement { + mCondition: pointer = IsAnimationPlayingDynamicMaterialBoolDriver { + mAnimationNames: list[hash] = { "taunt" } + } + mValue: pointer = LerpMaterialDriver { + mBoolDriver: pointer = IsAnimationPlayingDynamicMaterialBoolDriver { + mAnimationNames: list[hash] = { "taunt" } + } + mOnValue: f32 = -1 + mOffValue: f32 = 1 + mTurnOnTimeSec: f32 = 0.200000003 + mTurnOffTimeSec: f32 = 0.200000003 + } + } + } + mDefaultValue: pointer = FloatLiteralMaterialDriver { + mValue: f32 = 1 + } + } + } + } + } + } + "Characters/Aatrox/Skins/Skin0/Resources" = ResourceResolver { + resourceMap: map[hash, link] = { + "Aatrox_Q_Indicator_01" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_Q_Indicator_01" + 0x4c250437 = "Characters/Kayn/Skins/Skin0/Particles/Kayn_Base_Primary_R_tar_child" + "Aatrox_Q_cas1" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_Q_cas1" + "Aatrox_Q_cas3" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_Q_cas3" + "Aatrox_Q_cas2" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_Q_cas2" + "Aatrox_AA_Trail_01" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_AA_Trail_01" + "Aatrox_AA_Trail_03" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_AA_Trail_03" + "Aatrox_AA_Trail_02" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_AA_Trail_02" + 0x57532b4b = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_AA_Hit_Tar01" + 0x58532cde = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_AA_Hit_Tar02" + "Aatrox_W_mis" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_W_mis" + "Aatrox_W_Beam_Tar" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_W_Beam_Tar" + "Aatrox_W_Core" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_W_Core" + "Aatrox_Q_Indicator_02" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_Q_Indicator_02" + "Aatrox_Q_Indicator_03" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_Q_Indicator_03" + "Aatrox_E_Dash" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_E_Dash" + "Aatrox_E_Active_buff" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_E_Active_buff" + "Aatrox_Q_Trail_01" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_Q_Trail_01" + "Aatrox_Q_Trail_02" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_Q_Trail_02" + "Aatrox_Q_Trail_03" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_Q_Trail_03" + "Aatrox_Q_Indicator_01_Ally" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_Q_Indicator_01_Ally" + "Aatrox_Q_Indicator_02_Ally" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_Q_Indicator_02_Ally" + "Aatrox_Q_Indicator_03_Ally" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_Q_Indicator_03_Ally" + "Aatrox_P_Ready" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_P_Ready" + "Aatrox_R_Fear" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_R_Fear" + "Aatrox_P_Activate" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_P_Activate" + "Aatrox_E_Heal" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_E_Heal" + "Aatrox_Death_ambers" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_Death_ambers" + "Aatrox_R_Attack_01" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_R_Attack_01" + "Aatrox_P_Hit_Tar" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_P_Hit_Tar" + "Aatrox_R_Attack_02" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_R_Attack_02" + "Aatrox_W_Cas" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_W_Cas" + "Aatrox_E_Dash_trail" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_E_Dash_trail" + "Aatrox_E_Dash2" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_E_Dash2" + "Aatrox_W_Hand_glow_cas" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_W_Hand_glow_cas" + "Aatrox_Q_Hit_Tar" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_Q_Hit_Tar" + "Aatrox_Q_Sweet_hit_tar" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_Q_Sweet_hit_tar" + "Aatrox_W_Core_Area" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_W_Core_Area" + "Aatrox_P_Attack_trail" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_P_Attack_trail" + "Aatrox_R_Revive_end" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_R_Revive_end" + "Aatrox_E_Buf_Sword" = 0x00000000 + "Aatrox_Passive_Sheathe_Sword" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_Passive_Sheathe_Sword" + "Aatrox_R_Revive_Duration" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_R_Revive_Duration" + "Aatrox_R_Revive_Diration_Sword" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_R_Revive_Diration_Sword" + "Aatrox_R_SpeedBuff" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_R_SpeedBuff" + "Aatrox_P_Debuff" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_P_Debuff" + "Aatrox_Recall_Ground" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_Recall_Ground" + "Aatrox_Recall_Beam" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_Recall_Beam" + "Aatrox_Recall_Weapon_glow" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_Recall_Weapon_glow" + "Aatrox_Recall_Hand_glow" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_Recall_Hand_glow" + "Aatrox_W_Core_End" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_W_Core_End" + "Aatrox_W_Beam_Tar_Break" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_W_Beam_Tar_Break" + "Aatrox_W_Hit_Tar" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_W_Hit_Tar" + "Aatrox_W_Beam_Tar_Pull" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_W_Beam_Tar_Pull" + "Aatrox_AA_Crit_Hit_Tar" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_AA_Crit_Hit_Tar" + "Aatrox_AA_Crit_Trail" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_AA_Crit_Trail" + "Aatrox_Dance_Ground" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_Dance_Ground" + "Aatrox_Taunt_Ground" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_Taunt_Ground" + 0x5b2b3b83 = "Maps/Particles/SRX/Base/SRX_Audio_Hextech_Storm_loop" + 0x2c43403d = "Maps/Particles/SR/SRU_Braziers_Chemtech_Child_02" + 0x20bae730 = "Maps/Shipping/Map22/Particles/Set9/TFT9_Trait_Demacia_Celebration_Child7" + } + } +} \ No newline at end of file diff --git a/crates/ltk_ritobin/samples/skin0.rito b/crates/ltk_ritobin/samples/skin0.rito new file mode 100644 index 00000000..e237f203 --- /dev/null +++ b/crates/ltk_ritobin/samples/skin0.rito @@ -0,0 +1,1202 @@ +#PROP_text +type: string = "PROP" +version: u32 = 3 +linked: list[string] = { + "DATA/Aatrox_Skins_Root_Skins_Skin0_Skins_Skin1_Skins_Skin10_Skins_Skin11_Skins_Skin12_Skins_Skin13_Skins_Skin14_Skins_Skin15_Skins_Skin16_Skins_Skin17_Skins_Skin18_Skins_Skin19_Skins_Skin2_Skins_Skin20_Skins_Skin21_Skins_Skin22_Skins_Skin23_Skins_Skin24_Skins_Skin25_Skins_Skin26_Skins_Skin27_Skins_Skin28_Skins_Skin29_Skins_Skin3_Skins_Skin30_Skins_Skin31_Skins_Skin32_Skins_Skin4_Skins_Skin5_Skins_Skin6_Skins_Skin7_Skins_Skin8_Skins_Skin9.bin" + "DATA/Characters/Aatrox/Aatrox.bin" + "DATA/Aatrox_Skins_Skin0_Skins_Skin2_Skins_Skin20_Skins_Skin3_Skins_Skin30_Skins_Skin31_Skins_Skin32_Skins_Skin4_Skins_Skin5_Skins_Skin6_Skins_Skin7_Skins_Skin8.bin" + "DATA/Characters/Aatrox/Animations/Skin0.bin" + "DATA/Aatrox_Skins_Skin0_Skins_Skin1_Skins_Skin10_Skins_Skin2_Skins_Skin20_Skins_Skin3_Skins_Skin4_Skins_Skin5_Skins_Skin6_Skins_Skin7_Skins_Skin8_Skins_Skin9.bin" + "DATA/Aatrox_Skins_Skin0_Skins_Skin1_Skins_Skin2_Skins_Skin3_Skins_Skin4_Skins_Skin5_Skins_Skin6_Skins_Skin7.bin" + "DATA/Aatrox_Skins_Skin0_Skins_Skin1_Skins_Skin2_Skins_Skin20_Skins_Skin3_Skins_Skin4_Skins_Skin5_Skins_Skin6_Skins_Skin7_Skins_Skin8.bin" + "DATA/Aatrox_Skins_Skin0_Skins_Skin2_Skins_Skin20_Skins_Skin3_Skins_Skin4_Skins_Skin5_Skins_Skin6_Skins_Skin7_Skins_Skin8.bin" + "DATA/Aatrox_Skins_Skin0_Skins_Skin2_Skins_Skin3_Skins_Skin4_Skins_Skin5_Skins_Skin6.bin" + "DATA/Aatrox_Skins_Skin0_Skins_Skin1_Skins_Skin3.bin" + "DATA/Aatrox_Skins_Skin0_Skins_Skin3_Skins_Skin7.bin" + "DATA/Aatrox_Skins_Skin0_Skins_Skin3.bin" +} +entries: map[hash, embed] = { + "Characters/Aatrox/Skins/Skin0" = SkinCharacterDataProperties { + skinClassification: u32 = 1 + championSkinName: string = "Aatrox" + metaDataTags: string = "gender:male,race:darkin,element:dark" + loadscreen: embed = CensoredImage { + image: string = "ASSETS/Characters/Aatrox/Skins/Base/AatroxLoadscreen.dds" + } + skinAudioProperties: embed = skinAudioProperties { + tagEventList: list[string] = { "Aatrox" } + bankUnits: list2[embed] = { + BankUnit { + name: string = "Aatrox_Base_SFX" + bankPath: list[string] = { + "ASSETS/Sounds/Wwise2016/SFX/Characters/Aatrox/Skins/Base/Aatrox_Base_SFX_audio.bnk" + "ASSETS/Sounds/Wwise2016/SFX/Characters/Aatrox/Skins/Base/Aatrox_Base_SFX_events.bnk" + } + events: list[string] = { + "Play_sfx_Aatrox_AatroxBasicAttack2_OnCast" + "Play_sfx_Aatrox_AatroxBasicAttack2_OnHit" + "Play_sfx_Aatrox_AatroxBasicAttack3_OnCast" + "Play_sfx_Aatrox_AatroxBasicAttack3_OnHit" + "Play_sfx_Aatrox_AatroxBasicAttack_OnCast" + "Play_sfx_Aatrox_AatroxBasicAttack_OnHit" + "Play_sfx_Aatrox_AatroxCritAttack_OnCast" + "Play_sfx_Aatrox_AatroxCritAttack_OnHit" + "Play_sfx_Aatrox_AatroxE_OnCast" + "Play_sfx_Aatrox_AatroxPassiveAttack_OnCast" + "Play_sfx_Aatrox_AatroxPassiveAttack_OnHit" + "Play_sfx_Aatrox_AatroxPassiveDebuff_OnBuffActivate" + "Play_sfx_Aatrox_AatroxPassiveDebuff_OnBuffDeactivate" + "Play_sfx_Aatrox_AatroxPassiveReady_OnBuffActivate" + "Play_sfx_Aatrox_AatroxQ1_OnCast_all" + "Play_sfx_Aatrox_AatroxQ1_OnHit_miss" + "Play_sfx_Aatrox_AatroxQ1_OnHit_normal_all" + "Play_sfx_Aatrox_AatroxQ1_OnHit_normal_player" + "Play_sfx_Aatrox_AatroxQ1_OnHit_sweetspot_all" + "Play_sfx_Aatrox_AatroxQ1_OnHit_sweetspot_player" + "Play_sfx_Aatrox_AatroxQ2_OnCast_all" + "Play_sfx_Aatrox_AatroxQ2_OnHit_miss" + "Play_sfx_Aatrox_AatroxQ2_OnHit_normal_all" + "Play_sfx_Aatrox_AatroxQ2_OnHit_normal_player" + "Play_sfx_Aatrox_AatroxQ2_OnHit_sweetspot_all" + "Play_sfx_Aatrox_AatroxQ2_OnHit_sweetspot_player" + "Play_sfx_Aatrox_AatroxQ3_OnCast_all" + "Play_sfx_Aatrox_AatroxQ3_OnHit_miss" + "Play_sfx_Aatrox_AatroxQ3_OnHit_normal_all" + "Play_sfx_Aatrox_AatroxQ3_OnHit_normal_player" + "Play_sfx_Aatrox_AatroxQ3_OnHit_sweetspot_all" + "Play_sfx_Aatrox_AatroxQ3_OnHit_sweetspot_player" + "Play_sfx_Aatrox_AatroxR_6seconds" + "Play_sfx_Aatrox_AatroxR_buffdeactivate" + "Play_sfx_Aatrox_AatroxR_end" + "Play_sfx_Aatrox_AatroxR_OnBuffActivate_all" + "Play_sfx_Aatrox_AatroxR_OnBuffActivate_player" + "Play_sfx_Aatrox_AatroxRAttack1_OnCast" + "Play_sfx_Aatrox_AatroxRAttack1_OnHit" + "Play_sfx_Aatrox_AatroxRAttack2_OnCast" + "Play_sfx_Aatrox_AatroxRAttack2_OnHit" + "Play_sfx_Aatrox_AatroxRRevive_all" + "Play_sfx_Aatrox_AatroxRRevive_player" + "Play_sfx_Aatrox_AatroxW_OnCast" + "Play_sfx_Aatrox_AatroxW_OnHit" + "Play_sfx_Aatrox_AatroxW_OnMissileCast" + "Play_sfx_Aatrox_AatroxW_OnMissileLaunch" + "Play_sfx_Aatrox_AatroxWBump_OnBuffActivate" + "Play_sfx_Aatrox_AatroxWChains_OnBuffActivate" + "Play_sfx_Aatrox_AatroxWChains_OnBuffDeactivate" + "Play_sfx_Aatrox_Dance3D_In_buffactivate" + "Play_sfx_Aatrox_Dance3D_loop_buffactivate" + "Play_sfx_Aatrox_Death3D_cast" + "Play_sfx_Aatrox_Joke3D_buffactivate" + "Play_sfx_Aatrox_Recall3D_buffactivate" + "Play_sfx_Aatrox_Taunt3D_buffactivate" + "Set_Switch_Aatrox_R_Active" + "Set_Switch_Aatrox_R_Inactive" + "Stop_sfx_Aatrox_AatroxW_OnMissileLaunch" + "Stop_sfx_Aatrox_AatroxWBump_OnBuffActivate" + "Stop_sfx_Aatrox_AatroxWChains_OnBuffActivate" + "Stop_sfx_Aatrox_Dance3D_In_buffactivate" + "Stop_sfx_Aatrox_Joke3D_buffactivate" + "Stop_sfx_Aatrox_Recall3D_buffactivate" + "Stop_sfx_Aatrox_Taunt3D_buffactivate" + "Switch_Aatrox_Footsteps_Brush" + "Switch_Aatrox_Footsteps_Dirt" + "Switch_Aatrox_Footsteps_Stone" + "Switch_Aatrox_Footsteps_Water" + } + } + BankUnit { + name: string = "Aatrox_Base_VO" + bankPath: list[string] = { + "ASSETS/Sounds/Wwise2016/VO/en_US/Characters/Aatrox/Skins/Base/Aatrox_Base_VO_audio.bnk" + "ASSETS/Sounds/Wwise2016/VO/en_US/Characters/Aatrox/Skins/Base/Aatrox_Base_VO_events.bnk" + "ASSETS/Sounds/Wwise2016/VO/en_US/Characters/Aatrox/Skins/Base/Aatrox_Base_VO_audio.wpk" + } + events: list[string] = { + "Play_vo_Aatrox_AatroxE_cast3D" + "Play_vo_Aatrox_AatroxQ_OnCast" + "Play_vo_Aatrox_AatroxR_cast3D" + "Play_vo_Aatrox_AatroxRRevive_OnBuffCast" + "Play_vo_Aatrox_AatroxW_cast3D" + "Play_vo_Aatrox_Attack2DGeneral" + "Play_vo_Aatrox_Attack2DPantheon" + "Play_vo_Aatrox_Attack2DTryndamere" + "Play_vo_Aatrox_Attack2DZoe" + "Play_vo_Aatrox_Death3D" + "Play_vo_Aatrox_FirstEncounter3DAkali" + "Play_vo_Aatrox_FirstEncounter3DAnivia" + "Play_vo_Aatrox_FirstEncounter3DCamille" + "Play_vo_Aatrox_FirstEncounter3DDarius" + "Play_vo_Aatrox_FirstEncounter3DFiora" + "Play_vo_Aatrox_FirstEncounter3DGalio" + "Play_vo_Aatrox_FirstEncounter3DGangplank" + "Play_vo_Aatrox_FirstEncounter3DGaren" + "Play_vo_Aatrox_FirstEncounter3DGeneral" + "Play_vo_Aatrox_FirstEncounter3DIllaoi" + "Play_vo_Aatrox_FirstEncounter3DJax" + "Play_vo_Aatrox_FirstEncounter3DKaisa" + "Play_vo_Aatrox_FirstEncounter3DKayle" + "Play_vo_Aatrox_FirstEncounter3DKayn" + "Play_vo_Aatrox_FirstEncounter3DKennen" + "Play_vo_Aatrox_FirstEncounter3DKled" + "Play_vo_Aatrox_FirstEncounter3DMalphite" + "Play_vo_Aatrox_FirstEncounter3DMaokai" + "Play_vo_Aatrox_FirstEncounter3DMorgana" + "Play_vo_Aatrox_FirstEncounter3DMundo" + "Play_vo_Aatrox_FirstEncounter3DNasus" + "Play_vo_Aatrox_FirstEncounter3DNautilus" + "Play_vo_Aatrox_FirstEncounter3DOrnn" + "Play_vo_Aatrox_FirstEncounter3DPantheon" + "Play_vo_Aatrox_FirstEncounter3DQuinn" + "Play_vo_Aatrox_FirstEncounter3DRenekton" + "Play_vo_Aatrox_FirstEncounter3DRiven" + "Play_vo_Aatrox_FirstEncounter3DRumble" + "Play_vo_Aatrox_FirstEncounter3DShen" + "Play_vo_Aatrox_FirstEncounter3DSion" + "Play_vo_Aatrox_FirstEncounter3DTargon" + "Play_vo_Aatrox_FirstEncounter3DTaric" + "Play_vo_Aatrox_FirstEncounter3DTeemo" + "Play_vo_Aatrox_FirstEncounter3DTrundle" + "Play_vo_Aatrox_FirstEncounter3DTryndamere" + "Play_vo_Aatrox_FirstEncounter3DVarus" + "Play_vo_Aatrox_FirstEncounter3DVoid" + "Play_vo_Aatrox_FirstEncounter3DYorick" + "Play_vo_Aatrox_FirstEncounter3DZoe" + "Play_vo_Aatrox_Joke3DGeneral" + "Play_vo_Aatrox_Kill3DAatrox" + "Play_vo_Aatrox_Kill3DAnivia" + "Play_vo_Aatrox_Kill3DCamille" + "Play_vo_Aatrox_Kill3DDarius" + "Play_vo_Aatrox_Kill3DFiora" + "Play_vo_Aatrox_Kill3DGangplank" + "Play_vo_Aatrox_Kill3DGaren" + "Play_vo_Aatrox_Kill3DGeneral" + "Play_vo_Aatrox_Kill3DIllaoi" + "Play_vo_Aatrox_Kill3DKaisa" + "Play_vo_Aatrox_Kill3DKayle" + "Play_vo_Aatrox_Kill3DKayn" + "Play_vo_Aatrox_Kill3DKled" + "Play_vo_Aatrox_Kill3DMalphite" + "Play_vo_Aatrox_Kill3DMaokai" + "Play_vo_Aatrox_Kill3DMorgana" + "Play_vo_Aatrox_Kill3DNasus" + "Play_vo_Aatrox_Kill3DNautilus" + "Play_vo_Aatrox_Kill3DOrnn" + "Play_vo_Aatrox_Kill3DPantheon" + "Play_vo_Aatrox_Kill3DRiven" + "Play_vo_Aatrox_Kill3DShen" + "Play_vo_Aatrox_Kill3DSion" + "Play_vo_Aatrox_Kill3DTaric" + "Play_vo_Aatrox_Kill3DTeemo" + "Play_vo_Aatrox_Kill3DTryndamere" + "Play_vo_Aatrox_Kill3DVarus" + "Play_vo_Aatrox_Kill3DZoe" + "Play_vo_Aatrox_Laugh3DGeneral" + "Play_vo_Aatrox_MasteryResponse3DGeneral" + "Play_vo_Aatrox_Move2DFirstPantheon" + "Play_vo_Aatrox_Move2DLong" + "Play_vo_Aatrox_Move2DRReady" + "Play_vo_Aatrox_Move2DStandard" + "Play_vo_Aatrox_Taunt3DGeneral" + } + voiceOver: bool = true + } + } + } + skinAnimationProperties: embed = skinAnimationProperties { + animationGraphData: link = "Characters/Aatrox/Animations/Skin0" + } + skinMeshProperties: embed = SkinMeshDataProperties { + skeleton: string = "ASSETS/Characters/Aatrox/Skins/Base/Aatrox.skl" + simpleSkin: string = "ASSETS/Characters/Aatrox/Skins/Base/Aatrox.skn" + texture: string = "ASSETS/Characters/Aatrox/Skins/Base/Aatrox_Base_TX_CM.dds" + skinScale: f32 = 1.09000003 + selfIllumination: f32 = 0.699999988 + brushAlphaOverride: f32 = 0.550000012 + overrideBoundingBox: option[vec3] = { { 130, 250, 130 } } + material: link = "Characters/Aatrox/Skins/Skin0/Materials/Aatrox_VFXBase_inst" + reflectionFresnelColor: rgba = { 0, 0, 0, 255 } + initialSubmeshToHide: string = "Wings" + initialSubmeshShadowsToHide: string = "Banner" + materialOverride: list[embed] = { + SkinMeshDataProperties_MaterialOverride { + material: link = "Characters/Aatrox/Skins/Skin0/Materials/Sword_inst" + submesh: string = "Sword" + } + SkinMeshDataProperties_MaterialOverride { + material: link = "Characters/Aatrox/Skins/Skin0/Materials/Wing_inst" + submesh: string = "Wings" + } + SkinMeshDataProperties_MaterialOverride { + material: link = "Characters/Aatrox/Skins/Skin0/Materials/Banner_inst" + submesh: string = "Banner" + } + } + rigPoseModifierData: list[pointer] = { + ConformToPathRigPoseModifierData { + mStartingJointName: hash = "L_Wing_Banner_Ground1" + mEndingJointName: hash = "L_Wing_Banner_Ground4" + mDefaultMaskName: hash = "empty" + mMaxBoneAngle: f32 = 150 + mVelMultiplier: f32 = 0 + mFrequency: f32 = 5 + } + ConformToPathRigPoseModifierData { + mStartingJointName: hash = "R_Wing_Banner_Ground1" + mEndingJointName: hash = "R_Wing_Banner_Ground4" + mDefaultMaskName: hash = "empty" + mMaxBoneAngle: f32 = 150 + mVelMultiplier: f32 = 0 + mFrequency: f32 = 5 + } + } + } + armorMaterial: string = "Flesh" + defaultAnimations: list[string] = { "BaseBuffPose" } + mContextualActionData: link = "Characters/Aatrox/CAC/Aatrox_Base" + iconCircle: option[string] = { "ASSETS/Characters/Aatrox/HUD/Aatrox_Circle.dds" } + iconSquare: option[string] = { "ASSETS/Characters/Aatrox/HUD/Aatrox_Square.dds" } + healthBarData: embed = CharacterHealthBarDataRecord { + attachToBone: string = "Buffbone_Cstm_Healthbar" + unitHealthBarStyle: u8 = 10 + } + mResourceResolver: link = "Characters/Aatrox/Skins/Skin0/Resources" + PersistentEffectConditions: list2[pointer] = { + PersistentEffectConditionData { + OwnerCondition: pointer = HasBuffDynamicMaterialBoolDriver { + Spell: hash = "Characters/Aatrox/Spells/AatroxPassiveAbility/AatroxPassiveReady" + } + PersistentVfxs: list2[embed] = { + PersistentVfxData { + boneName: string = "Weapon_Heart" + effectKey: hash = "Aatrox_P_Ready" + } + } + } + } + } + "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_E_Active_buff" = VfxSystemDefinitionData { + complexEmitterDefinitionData: list[pointer] = { + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 1.5 + } + particleLinger: option[f32] = { 1 } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "Avatar" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + primitive: pointer = VfxPrimitiveAttachedMesh { + mMesh: embed = VfxMeshDefinitionData { + mSubmeshesToDraw: list[hash] = { "BODY", "Shoulder" } + } + } + blendMode: u8 = 1 + color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.100000001, 0.899999976, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + depthBiasFactors: vec2 = { -1, -1 } + disableBackfaceCull: bool = true + particleIsLocalOrientation: flag = true + isUniformScale: flag = true + isRandomStartFrame: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 1.00100005, 1.00100005, 1.00100005 } + } + texture: string = "ASSETS/Characters/Aatrox/Skins/Base/Particles/Aatrox_Base_E_buff_avatar.dds" + uvMode: u8 = 2 + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.25 + } + particleLinger: option[f32] = { 1 } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "Avatar_activate" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + primitive: pointer = VfxPrimitiveAttachedMesh { + mMesh: embed = VfxMeshDefinitionData { + mSubmeshesToDraw: list[hash] = { "BODY", "Shoulder" } + } + } + blendMode: u8 = 4 + color: embed = ValueColor { + constantValue: vec4 = { 1, 1, 1, 0.650003791 } + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.100000001, 0.800000012, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 0.650003791 } + { 1, 1, 1, 0.650003791 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = 1 + disableBackfaceCull: bool = true + particleIsLocalOrientation: flag = true + isUniformScale: flag = true + isRandomStartFrame: flag = true + uvScrollClamp: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 1.00999999, 1.00999999, 1.00999999 } + } + texture: string = "ASSETS/Characters/Aatrox/Skins/Base/Particles/Aatrox_Base_E_buff_avatar_sheen.dds" + uvMode: u8 = 2 + birthUvScrollRate: embed = ValueVector2 { + constantValue: vec2 = { 0, 2 } + } + texAddressModeBase: u8 = 2 + } + } + particleName: string = "Aatrox_Base_E_Active_buff" + particlePath: string = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_E_Active_buff" + } + "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_E_Dash" = VfxSystemDefinitionData { + complexEmitterDefinitionData: list[pointer] = { + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.300000012 + } + particleLinger: option[f32] = { 0.200000003 } + lifetime: option[f32] = { 1.10000002 } + isSingleParticle: flag = true + emitterName: string = "Avatar" + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, 50 } + } + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + primitive: pointer = VfxPrimitiveAttachedMesh { + mMesh: embed = VfxMeshDefinitionData { + mSubmeshesToDraw: list[hash] = { "BODY" } + } + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 1, 1, 0.500007629 } + } + color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.100000001, 0.5, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0.300007641 } + { 1, 1, 1, 0 } + } + } + } + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.200000003, 1 } + values: list[f32] = { 0, 0, 0.5 } + } + } + erosionFeatherOut: f32 = 0.300000012 + erosionMapName: string = "ASSETS/Characters/Aatrox/Skins/Base/Particles/Aatrox_Base_Q_SmokeErode.dds" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + disableBackfaceCull: bool = true + particleIsLocalOrientation: flag = true + isUniformScale: flag = true + isRandomStartFrame: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 1.00999999, 1, 1 } + } + texture: string = "ASSETS/Characters/Aatrox/Skins/Base/Aatrox_Base_TX_CM.dds" + numFrames: u16 = 4 + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.300000012 + } + particleLinger: option[f32] = { 0.200000003 } + lifetime: option[f32] = { 1.10000002 } + isSingleParticle: flag = true + emitterName: string = "Avatar1" + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, 50 } + } + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + primitive: pointer = VfxPrimitiveAttachedMesh { + mMesh: embed = VfxMeshDefinitionData { + mSubmeshesToDraw: list[hash] = { "Sword" } + } + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 1, 1, 0.500007629 } + } + color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.100000001, 0.5, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0.300007641 } + { 1, 1, 1, 0 } + } + } + } + disableBackfaceCull: bool = true + particleIsLocalOrientation: flag = true + isUniformScale: flag = true + isRandomStartFrame: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 1.00999999, 1, 1 } + } + texture: string = "ASSETS/Characters/Aatrox/Skins/Base/Aatrox_Base_Sword_TX_CM.dds" + numFrames: u16 = 4 + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.300000012 + } + particleLinger: option[f32] = { 0.200000003 } + lifetime: option[f32] = { 1.10000002 } + isSingleParticle: flag = true + emitterName: string = "Avatar2" + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, 50 } + } + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + primitive: pointer = VfxPrimitiveAttachedMesh { + mMesh: embed = VfxMeshDefinitionData { + mSubmeshesToDraw: list[hash] = { "Wings" } + } + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 1, 1, 0.500007629 } + } + color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.100000001, 0.5, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0.300007641 } + { 1, 1, 1, 0 } + } + } + } + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.200000003, 1 } + values: list[f32] = { 0, 0, 0.5 } + } + } + erosionFeatherOut: f32 = 0.300000012 + erosionMapName: string = "ASSETS/Characters/Aatrox/Skins/Base/Particles/Aatrox_Base_Q_SmokeErode.dds" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + disableBackfaceCull: bool = true + particleIsLocalOrientation: flag = true + isUniformScale: flag = true + isRandomStartFrame: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 1.00999999, 1, 1 } + } + texture: string = "ASSETS/Characters/Aatrox/Skins/Base/Aatrox_Wings_TX_CM.dds" + numFrames: u16 = 4 + } + } + particleName: string = "Aatrox_Base_E_Dash" + particlePath: string = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_E_Dash" + mIsPoseAfterimage: bool = true + } + "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_P_Ready" = VfxSystemDefinitionData { + complexEmitterDefinitionData: list[pointer] = { + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.699999988 + } + particleLinger: option[f32] = { 1 } + emitterName: string = "Basic" + importance: u8 = 2 + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + blendMode: u8 = 4 + color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.400000006, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 0.330006868, 0, 0, 1 } + } + } + } + depthBiasFactors: vec2 = { -1, -2 } + isUniformScale: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 1, 0, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 1, 0, 0 } } + } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 150, 100, 100 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 150, 100, 100 } } + } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.200000003, 1 } + values: list[vec3] = { + { 0.25, 0.25, 2.5 } + { 1, 1, 1 } + { 0.25, 0.25, 0.25 } + } + } + } + texture: string = "ASSETS/Characters/Aatrox/Skins/Base/Particles/Aatrox_Base_TEMP_Diana_Skin11_W_FaintGlow.dds" + paletteDefinition: pointer = VfxPaletteDefinitionData { + paletteTexture: string = "ASSETS/Characters/Aatrox/Skins/Base/Particles/Aatrox_Base_AA_Gradient_RGB.dds" + palleteSrcMixColor: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + paletteSelector: embed = ValueVector3 { + constantValue: vec3 = { 2, 0, 0 } + } + paletteCount: i32 = 8 + } + } + } + particleName: string = "Aatrox_Base_P_Ready" + particlePath: string = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_P_Ready" + } + "Characters/Aatrox/Skins/Skin0/Materials/Sword_inst" = StaticMaterialDef { + name: string = "Characters/Aatrox/Skins/Skin0/Materials/Sword_inst" + samplerValues: list2[embed] = { + StaticMaterialShaderSamplerDef { + samplerName: string = "Diffuse_Texture" + textureName: string = "ASSETS/Characters/Aatrox/Skins/Base/Aatrox_Base_Sword_TX_CM.dds" + addressU: u32 = 1 + addressV: u32 = 1 + addressW: u32 = 1 + } + StaticMaterialShaderSamplerDef { + samplerName: string = "Mask_Texture" + textureName: string = "ASSETS/Characters/Aatrox/Skins/Base/Particles/Aatrox_Base_P_Sword_Mask.dds" + addressW: u32 = 1 + } + StaticMaterialShaderSamplerDef { + samplerName: string = "Gradient_Texture" + textureName: string = "ASSETS/Shared/Materials/Gradient_test_01.dds" + addressU: u32 = 1 + addressV: u32 = 1 + } + } + paramValues: list2[embed] = { + StaticMaterialShaderParamDef { + name: string = "Mask_Intensity" + value: vec4 = { 0.792500019, 0, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Bloom_Intensity" + value: vec4 = { 4, 0, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Scrolling_Scale" + value: vec4 = { 1, 1, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Scrolling_Rate" + value: vec4 = { 0, -1, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Color" + value: vec4 = { 1, 0.301960796, 0.0274509806, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Dissolve_Bias" + value: vec4 = { -1, 0, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Dissolve_SmoothStep" + value: vec4 = { 0, 0.200000003, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Gradient_Sharpness" + value: vec4 = { 0.400000006, 0, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Alpha_Sharpness" + value: vec4 = { 0.00100000005, 0, 0, 0 } + } + } + switches: list2[embed] = { + StaticMaterialSwitchDef { + name: string = "USE_COLORDODGE" + on: bool = false + } + StaticMaterialSwitchDef { + name: string = "USE_ADDATIVE" + } + StaticMaterialSwitchDef { + name: string = "USE_LERP" + on: bool = false + } + StaticMaterialSwitchDef { + name: string = "USE_DISSOLVE" + on: bool = false + } + } + shaderMacros: map[string, string] = { + "NUM_BLEND_WEIGHTS" = "4" + } + techniques: list[embed] = { + StaticMaterialTechniqueDef { + name: string = "normal" + passes: list[embed] = { + StaticMaterialPassDef { + shader: link = "Shaders/SkinnedMesh/Scrolling_ColorDodge_Masked" + blendEnable: bool = true + srcColorBlendFactor: u32 = 6 + srcAlphaBlendFactor: u32 = 6 + dstColorBlendFactor: u32 = 7 + dstAlphaBlendFactor: u32 = 7 + } + } + } + } + childTechniques: list[embed] = { + StaticMaterialChildTechniqueDef { + name: string = "transition" + parentName: string = "normal" + shaderMacros: map[string, string] = { + "TRANSITION" = "1" + } + } + } + dynamicMaterial: pointer = DynamicMaterialDef { + parameters: list[embed] = { + DynamicMaterialParameterDef { + name: string = "Mask_Intensity" + driver: pointer = LerpMaterialDriver { + mBoolDriver: pointer = HasBuffDynamicMaterialBoolDriver { + mScriptName: string = "AatroxPassiveReady" + } + mOnValue: f32 = 0.75 + mTurnOffTimeSec: f32 = 0.200000003 + } + } + } + } + } + "Characters/Aatrox/Skins/Skin0/Materials/Banner_inst" = StaticMaterialDef { + name: string = "Characters/Aatrox/Skins/Skin0/Materials/Banner_inst" + samplerValues: list2[embed] = { + StaticMaterialShaderSamplerDef { + samplerName: string = "Diffuse_Texture" + textureName: string = "ASSETS/Characters/Aatrox/Skins/Base/Particles/Aatrox_Base_I_Banner_color.dds" + addressU: u32 = 1 + addressV: u32 = 1 + addressW: u32 = 1 + } + StaticMaterialShaderSamplerDef { + samplerName: string = "Mask_Texture" + textureName: string = "ASSETS/Characters/Aatrox/Skins/Base/Particles/Aatrox_Base_I_Banner.dds" + addressW: u32 = 1 + } + } + paramValues: list2[embed] = { + StaticMaterialShaderParamDef { + name: string = "UV_Scale" + value: vec4 = { 1, 1, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Scroll_Speed" + value: vec4 = { 0, -0.300000012, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Alpha_Bias" + value: vec4 = { 0.300000012, 0, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "UV_Scale_BLUE" + value: vec4 = { 1, 1, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Scroll_Speed_BLUE" + value: vec4 = { 0, -0.200000003, 0, 0 } + } + } + switches: list2[embed] = { + StaticMaterialSwitchDef { + name: string = "MULTIPLY_ADD" + on: bool = false + } + StaticMaterialSwitchDef { + name: string = "USE_RED_TO_ALPHA" + } + StaticMaterialSwitchDef { + name: string = "USE_BLUE_CHANNEL" + } + } + shaderMacros: map[string, string] = { + "NUM_BLEND_WEIGHTS" = "4" + } + techniques: list[embed] = { + StaticMaterialTechniqueDef { + name: string = "normal" + passes: list[embed] = { + StaticMaterialPassDef { + shader: link = "Shaders/SkinnedMesh/ScrollingCustomAlpha" + blendEnable: bool = true + srcColorBlendFactor: u32 = 6 + srcAlphaBlendFactor: u32 = 6 + dstColorBlendFactor: u32 = 7 + dstAlphaBlendFactor: u32 = 7 + } + } + } + } + childTechniques: list[embed] = { + StaticMaterialChildTechniqueDef { + name: string = "transition" + parentName: string = "normal" + shaderMacros: map[string, string] = { + "TRANSITION" = "1" + } + } + } + } + "Characters/Aatrox/Skins/Skin0/Materials/Aatrox_VFXBase_inst" = StaticMaterialDef { + name: string = "Characters/Aatrox/Skins/Skin0/Materials/Aatrox_VFXBase_inst" + samplerValues: list2[embed] = { + StaticMaterialShaderSamplerDef { + samplerName: string = "Diffuse_Texture" + textureName: string = "ASSETS/Characters/Aatrox/Skins/Base/Aatrox_Base_TX_CM.dds" + addressU: u32 = 1 + addressV: u32 = 1 + addressW: u32 = 1 + } + StaticMaterialShaderSamplerDef { + samplerName: string = "Mask_Texture" + textureName: string = "ASSETS/Characters/Aatrox/Skins/Base/Particles/Aatrox_Base_R_body_mask.dds" + addressU: u32 = 1 + addressV: u32 = 1 + addressW: u32 = 1 + } + StaticMaterialShaderSamplerDef { + samplerName: string = "Gradient_Texture" + textureName: string = "ASSETS/Shared/Materials/Gradient_test_01.dds" + addressU: u32 = 1 + addressV: u32 = 1 + addressW: u32 = 1 + } + } + paramValues: list2[embed] = { + StaticMaterialShaderParamDef { + name: string = "Dissolve_SmoothStep" + value: vec4 = { 0, 0.150000006, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Dissolve_Bias" + value: vec4 = { -0.200000003, 0, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Pulse_Rate" + value: vec4 = { 3, 0, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Pulse_Max" + value: vec4 = { 0.400000006, 0, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Gradient_Sharpness" + value: vec4 = { 0.5, 0, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Alpha_Sharpness" + value: vec4 = { 0.00100000005, 0, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Bloom_Intensity" + value: vec4 = { 10, 0, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Pulse_Offset" + value: vec4 = { 0.300000012, 0, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Alpha" + value: vec4 = { 1, 0, 0, 0 } + } + } + shaderMacros: map[string, string] = { + "NUM_BLEND_WEIGHTS" = "4" + } + techniques: list[embed] = { + StaticMaterialTechniqueDef { + name: string = "normal" + passes: list[embed] = { + StaticMaterialPassDef { + shader: link = "Shaders/SkinnedMesh/Aatrox_VFXBase" + blendEnable: bool = true + srcColorBlendFactor: u32 = 6 + srcAlphaBlendFactor: u32 = 6 + dstColorBlendFactor: u32 = 7 + dstAlphaBlendFactor: u32 = 7 + } + } + } + } + childTechniques: list[embed] = { + StaticMaterialChildTechniqueDef { + name: string = "transition" + parentName: string = "normal" + shaderMacros: map[string, string] = { + "TRANSITION" = "1" + } + } + } + dynamicMaterial: pointer = DynamicMaterialDef { + parameters: list[embed] = { + DynamicMaterialParameterDef { + name: string = "Dissolve_Bias" + driver: pointer = MaxMaterialDriver { + mDrivers: list[pointer] = { + FloatGraphMaterialDriver { + driver: pointer = LerpMaterialDriver { + mBoolDriver: pointer = IsDeadDynamicMaterialBoolDriver { } + mTurnOnTimeSec: f32 = 4 + mTurnOffTimeSec: f32 = 0 + } + graph: embed = VfxAnimatedFloatVariableData { + times: list[f32] = { 0.00171930937, 0.216738746, 0.766768217, 1.00488436 } + values: list[f32] = { -0.22144419, 0.260138661, 0.752247512, 0.86541003 } + } + } + FloatGraphMaterialDriver { + driver: pointer = LerpMaterialDriver { + mBoolDriver: pointer = IsAnimationPlayingDynamicMaterialBoolDriver { + mAnimationNames: list[hash] = { "Passive_Death" } + } + mTurnOnTimeSec: f32 = 3 + } + graph: embed = VfxAnimatedFloatVariableData { + times: list[f32] = { 0.00321787666, 0.381477386, 0.997775316 } + values: list[f32] = { -0.225780264, 0.583815038, 0.994219661 } + } + } + } + } + } + DynamicMaterialParameterDef { + name: string = "Pulse_Rate" + driver: pointer = LerpMaterialDriver { + mBoolDriver: pointer = HasBuffDynamicMaterialBoolDriver { + mScriptName: string = "AatroxR" + } + mOnValue: f32 = 5 + mTurnOnTimeSec: f32 = 0 + mTurnOffTimeSec: f32 = 0 + } + } + } + } + } + "Characters/Aatrox/Skins/Skin0/Materials/Wing_inst" = StaticMaterialDef { + name: string = "Characters/Aatrox/Skins/Skin0/Materials/Wing_inst" + samplerValues: list2[embed] = { + StaticMaterialShaderSamplerDef { + samplerName: string = "Diffuse_Texture" + textureName: string = "ASSETS/Characters/Aatrox/Skins/Base/Aatrox_Wings_TX_CM.dds" + addressU: u32 = 1 + addressV: u32 = 1 + addressW: u32 = 1 + } + StaticMaterialShaderSamplerDef { + samplerName: string = "Mask_Texture" + textureName: string = "ASSETS/Characters/Aatrox/Skins/Base/Particles/Aatrox_Base_R_wing_mask.dds" + addressW: u32 = 1 + } + StaticMaterialShaderSamplerDef { + samplerName: string = "Gradient_Texture" + textureName: string = "ASSETS/Characters/Aatrox/Skins/Base/Particles/Aatrox_Base_R_mat_gradient.dds" + addressU: u32 = 1 + addressV: u32 = 1 + } + } + paramValues: list2[embed] = { + StaticMaterialShaderParamDef { + name: string = "Mask_Intensity" + value: vec4 = { 0.939999998, 0, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Bloom_Intensity" + value: vec4 = { 5, 0, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Scrolling_Scale" + value: vec4 = { 1, 1, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Scrolling_Rate" + value: vec4 = { -0.5, -0.5, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Color" + value: vec4 = { 1, 0.250980407, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Dissolve_Bias" + value: vec4 = { 0.785000026, 0, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Dissolve_SmoothStep" + value: vec4 = { 0, 0.5, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Gradient_Sharpness" + value: vec4 = { 2, 0, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Alpha_Sharpness" + value: vec4 = { 0.00100000005, 0, 0, 0 } + } + } + switches: list2[embed] = { + StaticMaterialSwitchDef { + name: string = "USE_COLORDODGE" + on: bool = false + } + StaticMaterialSwitchDef { + name: string = "USE_ADDATIVE" + } + StaticMaterialSwitchDef { + name: string = "USE_LERP" + on: bool = false + } + StaticMaterialSwitchDef { + name: string = "USE_DISSOLVE" + } + } + shaderMacros: map[string, string] = { + "NUM_BLEND_WEIGHTS" = "4" + } + techniques: list[embed] = { + StaticMaterialTechniqueDef { + name: string = "normal" + passes: list[embed] = { + StaticMaterialPassDef { + shader: link = "Shaders/SkinnedMesh/Scrolling_ColorDodge_Masked" + blendEnable: bool = true + srcColorBlendFactor: u32 = 6 + srcAlphaBlendFactor: u32 = 6 + dstColorBlendFactor: u32 = 7 + dstAlphaBlendFactor: u32 = 7 + } + } + } + } + childTechniques: list[embed] = { + StaticMaterialChildTechniqueDef { + name: string = "transition" + parentName: string = "normal" + shaderMacros: map[string, string] = { + "TRANSITION" = "1" + } + } + } + dynamicMaterial: pointer = DynamicMaterialDef { + parameters: list[embed] = { + DynamicMaterialParameterDef { + name: string = "Dissolve_Bias" + driver: pointer = SwitchMaterialDriver { + mElements: list[embed] = { + SwitchMaterialDriverElement { + mCondition: pointer = HasBuffDynamicMaterialBoolDriver { + mScriptName: string = "AatroxRFX" + } + mValue: pointer = LerpMaterialDriver { + mBoolDriver: pointer = HasBuffDynamicMaterialBoolDriver { + mScriptName: string = "AatroxRFX" + mDeactivateEarlySeconds: f32 = 1 + } + mOnValue: f32 = -1 + mOffValue: f32 = 1 + mTurnOnTimeSec: f32 = 2 + } + } + SwitchMaterialDriverElement { + mCondition: pointer = HasBuffDynamicMaterialBoolDriver { + mScriptName: string = "AatroxRReviveMaterialOverride" + } + mValue: pointer = LerpMaterialDriver { + mBoolDriver: pointer = HasBuffDynamicMaterialBoolDriver { + mScriptName: string = "AatroxRReviveMaterialOverride" + } + mOffValue: f32 = -0.180000007 + mTurnOnTimeSec: f32 = 6 + mTurnOffTimeSec: f32 = 0 + } + } + SwitchMaterialDriverElement { + mCondition: pointer = IsAnimationPlayingDynamicMaterialBoolDriver { + mAnimationNames: list[hash] = { 0x909068b6 } + } + mValue: pointer = LerpMaterialDriver { + mBoolDriver: pointer = IsAnimationPlayingDynamicMaterialBoolDriver { + mAnimationNames: list[hash] = { 0x909068b6 } + } + mOnValue: f32 = -1 + mOffValue: f32 = 1 + mTurnOnTimeSec: f32 = 0.200000003 + mTurnOffTimeSec: f32 = 0.200000003 + } + } + SwitchMaterialDriverElement { + mCondition: pointer = IsAnimationPlayingDynamicMaterialBoolDriver { + mAnimationNames: list[hash] = { "taunt" } + } + mValue: pointer = LerpMaterialDriver { + mBoolDriver: pointer = IsAnimationPlayingDynamicMaterialBoolDriver { + mAnimationNames: list[hash] = { "taunt" } + } + mOnValue: f32 = -1 + mOffValue: f32 = 1 + mTurnOnTimeSec: f32 = 0.200000003 + mTurnOffTimeSec: f32 = 0.200000003 + } + } + } + mDefaultValue: pointer = FloatLiteralMaterialDriver { + mValue: f32 = 1 + } + } + } + } + } + } + "Characters/Aatrox/Skins/Skin0/Resources" = ResourceResolver { + resourceMap: map[hash, link] = { + "Aatrox_Q_Indicator_01" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_Q_Indicator_01" + 0x4c250437 = "Characters/Kayn/Skins/Skin0/Particles/Kayn_Base_Primary_R_tar_child" + "Aatrox_Q_cas1" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_Q_cas1" + "Aatrox_Q_cas3" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_Q_cas3" + "Aatrox_Q_cas2" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_Q_cas2" + "Aatrox_AA_Trail_01" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_AA_Trail_01" + "Aatrox_AA_Trail_03" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_AA_Trail_03" + "Aatrox_AA_Trail_02" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_AA_Trail_02" + 0x57532b4b = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_AA_Hit_Tar01" + 0x58532cde = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_AA_Hit_Tar02" + "Aatrox_W_mis" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_W_mis" + "Aatrox_W_Beam_Tar" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_W_Beam_Tar" + "Aatrox_W_Core" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_W_Core" + "Aatrox_Q_Indicator_02" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_Q_Indicator_02" + "Aatrox_Q_Indicator_03" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_Q_Indicator_03" + "Aatrox_E_Dash" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_E_Dash" + "Aatrox_E_Active_buff" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_E_Active_buff" + "Aatrox_Q_Trail_01" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_Q_Trail_01" + "Aatrox_Q_Trail_02" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_Q_Trail_02" + "Aatrox_Q_Trail_03" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_Q_Trail_03" + "Aatrox_Q_Indicator_01_Ally" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_Q_Indicator_01_Ally" + "Aatrox_Q_Indicator_02_Ally" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_Q_Indicator_02_Ally" + "Aatrox_Q_Indicator_03_Ally" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_Q_Indicator_03_Ally" + "Aatrox_P_Ready" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_P_Ready" + "Aatrox_R_Fear" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_R_Fear" + "Aatrox_P_Activate" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_P_Activate" + "Aatrox_E_Heal" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_E_Heal" + "Aatrox_Death_ambers" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_Death_ambers" + "Aatrox_R_Attack_01" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_R_Attack_01" + "Aatrox_P_Hit_Tar" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_P_Hit_Tar" + "Aatrox_R_Attack_02" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_R_Attack_02" + "Aatrox_W_Cas" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_W_Cas" + "Aatrox_E_Dash_trail" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_E_Dash_trail" + "Aatrox_E_Dash2" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_E_Dash2" + "Aatrox_W_Hand_glow_cas" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_W_Hand_glow_cas" + "Aatrox_Q_Hit_Tar" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_Q_Hit_Tar" + "Aatrox_Q_Sweet_hit_tar" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_Q_Sweet_hit_tar" + "Aatrox_W_Core_Area" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_W_Core_Area" + "Aatrox_P_Attack_trail" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_P_Attack_trail" + "Aatrox_R_Revive_end" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_R_Revive_end" + "Aatrox_E_Buf_Sword" = 0x00000000 + "Aatrox_Passive_Sheathe_Sword" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_Passive_Sheathe_Sword" + "Aatrox_R_Revive_Duration" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_R_Revive_Duration" + "Aatrox_R_Revive_Diration_Sword" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_R_Revive_Diration_Sword" + "Aatrox_R_SpeedBuff" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_R_SpeedBuff" + "Aatrox_P_Debuff" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_P_Debuff" + "Aatrox_Recall_Ground" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_Recall_Ground" + "Aatrox_Recall_Beam" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_Recall_Beam" + "Aatrox_Recall_Weapon_glow" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_Recall_Weapon_glow" + "Aatrox_Recall_Hand_glow" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_Recall_Hand_glow" + "Aatrox_W_Core_End" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_W_Core_End" + "Aatrox_W_Beam_Tar_Break" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_W_Beam_Tar_Break" + "Aatrox_W_Hit_Tar" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_W_Hit_Tar" + "Aatrox_W_Beam_Tar_Pull" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_W_Beam_Tar_Pull" + "Aatrox_AA_Crit_Hit_Tar" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_AA_Crit_Hit_Tar" + "Aatrox_AA_Crit_Trail" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_AA_Crit_Trail" + "Aatrox_Dance_Ground" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_Dance_Ground" + "Aatrox_Taunt_Ground" = "Characters/Aatrox/Skins/Skin0/Particles/Aatrox_Base_Taunt_Ground" + 0x5b2b3b83 = "Maps/Particles/SRX/Base/SRX_Audio_Hextech_Storm_loop" + 0x2c43403d = "Maps/Particles/SR/SRU_Braziers_Chemtech_Child_02" + 0x20bae730 = "Maps/Shipping/Map22/Particles/Set9/TFT9_Trait_Demacia_Celebration_Child7" + } + } +} diff --git a/crates/ltk_ritobin/samples/test.py b/crates/ltk_ritobin/samples/test.py new file mode 100644 index 00000000..28ea21f8 --- /dev/null +++ b/crates/ltk_ritobin/samples/test.py @@ -0,0 +1,14 @@ +#PROP_text +type: string = "PROP" +version: u32 = 3 +entries: map[hash, embed] = { + "foo" = Foo { + thing: option[vec3] = { { 0, 0, 0 } } + thing2: list[vec3] = { { 0, 0, 0 } } + thing3: list[vec3] = { + { 0, 0, 0 } + { 0, 0, 0 } + } + thing4: list[u32] = { 0000000 } + } +} diff --git a/crates/ltk_ritobin/samples/test2.rito b/crates/ltk_ritobin/samples/test2.rito new file mode 100644 index 00000000..c46bef68 --- /dev/null +++ b/crates/ltk_ritobin/samples/test2.rito @@ -0,0 +1,9 @@ +ConformToPathRigPoseModifierData { + mStartingJointName: hash = "L_Clavicle" + mEndingJointName: hash = "l_hand" + mDefaultMaskName: hash = "0x7136e1bc" + mMaxBoneAngle: f32 = 115 + mDampingValue: f32 = 123123 + mVelMultiplier: f32 = 0 + mFrequency: f32 = .5 +} diff --git a/crates/ltk_ritobin/samples/test3.rito b/crates/ltk_ritobin/samples/test3.rito new file mode 100644 index 00000000..e9e8b3a0 --- /dev/null +++ b/crates/ltk_ritobin/samples/test3.rito @@ -0,0 +1,6 @@ +SkinAugmentCategories: embed = SkinAugmentCategories { } +BorderAugments: list2[embed] = { + 0x4a70b12c { + AugmentGroup: list2[link] = { 0x383e4602 } + } +} \ No newline at end of file diff --git a/crates/ltk_ritobin/samples/test5.rito b/crates/ltk_ritobin/samples/test5.rito new file mode 100644 index 00000000..ce12bb41 --- /dev/null +++ b/crates/ltk_ritobin/samples/test5.rito @@ -0,0 +1,23 @@ +entries: map[hash, embed] = { + "Characters/Zaahen/Skins/Skin0" = SkinCharacterDataProperties { + bankUnits: list2[embed] = { + BankUnit { + name: string = "Zaahen_Base_SFX" + bankPath: list[string] = { + "ASSETS/Sounds/Wwise2016/SFX/Characters/Zaahen/Skins/Base/Zaahen_Base_SFX_audio.bnk" + "ASSETS/Sounds/Wwise2016/SFX/Characters/Zaahen/Skins/Base/Zaahen_Base_SFX_events.bnk" + } + events: list[string] = { + "Play_sfx_Zaahen_Dance3D_buffactivate" + "Play_sfx_Zaahen_Dance3D_loop" + "Stop_sfx_Zaahen_ZaahenW_OnMissileLaunch" + } + } + BankUnit { + name: string = "Zaahen_Base_SFX" + bankPath: list[string] = { } + events: list[string] = { } + } + } + } +} \ No newline at end of file diff --git a/crates/ltk_ritobin/samples/zaahen.rito b/crates/ltk_ritobin/samples/zaahen.rito new file mode 100644 index 00000000..a5039917 --- /dev/null +++ b/crates/ltk_ritobin/samples/zaahen.rito @@ -0,0 +1,47377 @@ +entries: map[hash, embed] = { + "Characters/Zaahen/Skins/Skin0" = SkinCharacterDataProperties { + skinClassification: u32 = 1 + championSkinName: string = "ZaahenBase" + metaDataTags: string = "gender:male,race:darkin" + loadscreen: embed = CensoredImage { + image: string = "ASSETS/Characters/Zaahen/Skins/Base/ZaahenLoadScreen_0.Zaahen.tex" + } + skinAudioProperties: embed = SkinAudioProperties { + tagEventList: list[string] = { "Zaahen" } + bankUnits: list2[embed] = { + BankUnit { + name: string = "Zaahen_Base_SFX" + bankPath: list[string] = { + "ASSETS/Sounds/Wwise2016/SFX/Characters/Zaahen/Skins/Base/Zaahen_Base_SFX_audio.bnk" + "ASSETS/Sounds/Wwise2016/SFX/Characters/Zaahen/Skins/Base/Zaahen_Base_SFX_events.bnk" + } + events: list[string] = { + "Play_sfx_Zaahen_Dance3D_buffactivate" + "Play_sfx_Zaahen_Dance3D_loop" + "Play_sfx_Zaahen_Death3D_cast" + "Play_sfx_Zaahen_Homeguard3D_leadin" + "Play_sfx_Zaahen_Homeguard3D_loop" + "Play_sfx_Zaahen_Idle3D_buffactivate" + "Play_sfx_Zaahen_Joke3D_buffactivate" + "Play_sfx_Zaahen_Laugh3D_buffactivate" + "Play_sfx_Zaahen_Recall3D_buffactivate" + "Play_sfx_Zaahen_Recall3D_winddown" + "Play_sfx_Zaahen_Respawn3D_buffactivate" + "Play_sfx_Zaahen_Taunt3D_buffactivate" + "Play_sfx_Zaahen_ZaahenBasicAttack2_OnCast" + "Play_sfx_Zaahen_ZaahenBasicAttack2_OnHit" + "Play_sfx_Zaahen_ZaahenBasicAttack3_OnCast" + "Play_sfx_Zaahen_ZaahenBasicAttack3_OnHit" + "Play_sfx_Zaahen_ZaahenBasicAttack_OnCast" + "Play_sfx_Zaahen_ZaahenBasicAttack_OnHit" + "Play_sfx_Zaahen_ZaahenCritAttack2_OnCast" + "Play_sfx_Zaahen_ZaahenCritAttack2_OnHit" + "Play_sfx_Zaahen_ZaahenCritAttack3_OnCast" + "Play_sfx_Zaahen_ZaahenCritAttack3_OnHit" + "Play_sfx_Zaahen_ZaahenCritAttack_OnCast" + "Play_sfx_Zaahen_ZaahenCritAttack_OnHit" + "Play_sfx_Zaahen_ZaahenE_OnCast" + "Play_sfx_Zaahen_ZaahenEAttack_AoE_buffactivate" + "Play_sfx_Zaahen_ZaahenEAttack_hit_inner" + "Play_sfx_Zaahen_ZaahenEAttack_hit_outer" + "Play_sfx_Zaahen_ZaahenP_loop_revive_ready" + "Play_sfx_Zaahen_ZaahenP_loop_stacks_max" + "Play_sfx_Zaahen_ZaahenP_revive_buffactivate" + "Play_sfx_Zaahen_ZaahenP_revive_ready" + "Play_sfx_Zaahen_ZaahenQ1_buffactivate" + "Play_sfx_Zaahen_ZaahenQ2_buffactivate" + "Play_sfx_Zaahen_ZaahenQ2_OnCast" + "Play_sfx_Zaahen_ZaahenQ2_warning" + "Play_sfx_Zaahen_ZaahenQ2Attack_OnCast" + "Play_sfx_Zaahen_ZaahenQ2Attack_OnHit" + "Play_sfx_Zaahen_ZaahenQ_OnCast" + "Play_sfx_Zaahen_ZaahenQAttack_OnCast" + "Play_sfx_Zaahen_ZaahenQAttack_OnHit" + "Play_sfx_Zaahen_ZaahenR_AoE_buffactivate" + "Play_sfx_Zaahen_ZaahenR_AoE_hit_champion" + "Play_sfx_Zaahen_ZaahenR_AoE_hit_minion" + "Play_sfx_Zaahen_ZaahenR_AoE_warning" + "Play_sfx_Zaahen_ZaahenR_dash" + "Play_sfx_Zaahen_ZaahenR_OnCast" + "Play_sfx_Zaahen_ZaahenW_hit_champion" + "Play_sfx_Zaahen_ZaahenW_hit_minion" + "Play_sfx_Zaahen_ZaahenW_OnCast" + "Play_sfx_Zaahen_ZaahenW_OnMissileLaunch" + "Play_sfx_Zaahen_ZaahenW_pull_cast" + "Play_sfx_Zaahen_ZaahenW_pull_champion" + "Play_sfx_Zaahen_ZaahenW_pull_minion" + "Stop_sfx_Zaahen_Homeguard3D_loop" + "Stop_sfx_Zaahen_Recall3D_winddown" + "Stop_sfx_Zaahen_Respawn3D_buffactivate" + "Stop_sfx_Zaahen_ZaahenEAttack_hit_inner" + "Stop_sfx_Zaahen_ZaahenEAttack_hit_outer" + "Stop_sfx_Zaahen_ZaahenP_loop_revive_ready" + "Stop_sfx_Zaahen_ZaahenP_loop_stacks_max" + "Stop_sfx_Zaahen_ZaahenQ1_buffactivate" + "Stop_sfx_Zaahen_ZaahenQ2_buffactivate" + "Stop_sfx_Zaahen_ZaahenQ2_warning" + "Stop_sfx_Zaahen_ZaahenW_OnMissileLaunch" + } + } + BankUnit { + name: string = "Zaahen_Base_SFX" + bankPath: list[string] = { + "ASSETS/Sounds/Wwise2016/SFX/Characters/Zaahen/Skins/Base/Zaahen_Base_SFX_audio.bnk" + "ASSETS/Sounds/Wwise2016/SFX/Characters/Zaahen/Skins/Base/Zaahen_Base_SFX_events.bnk" + } + events: list[string] = { + "Play_sfx_Zaahen_Dance3D_buffactivate" + "Play_sfx_Zaahen_Dance3D_loop" + "Play_sfx_Zaahen_Death3D_cast" + "Play_sfx_Zaahen_Homeguard3D_leadin" + "Play_sfx_Zaahen_Homeguard3D_loop" + "Play_sfx_Zaahen_Idle3D_buffactivate" + "Play_sfx_Zaahen_Joke3D_buffactivate" + "Play_sfx_Zaahen_Laugh3D_buffactivate" + "Play_sfx_Zaahen_Recall3D_buffactivate" + "Play_sfx_Zaahen_Recall3D_winddown" + "Play_sfx_Zaahen_Respawn3D_buffactivate" + "Play_sfx_Zaahen_Taunt3D_buffactivate" + "Play_sfx_Zaahen_ZaahenBasicAttack2_OnCast" + "Play_sfx_Zaahen_ZaahenBasicAttack2_OnHit" + "Play_sfx_Zaahen_ZaahenBasicAttack3_OnCast" + "Play_sfx_Zaahen_ZaahenBasicAttack3_OnHit" + "Play_sfx_Zaahen_ZaahenBasicAttack_OnCast" + "Play_sfx_Zaahen_ZaahenBasicAttack_OnHit" + "Play_sfx_Zaahen_ZaahenCritAttack2_OnCast" + "Play_sfx_Zaahen_ZaahenCritAttack2_OnHit" + "Play_sfx_Zaahen_ZaahenCritAttack3_OnCast" + "Play_sfx_Zaahen_ZaahenCritAttack3_OnHit" + "Play_sfx_Zaahen_ZaahenCritAttack_OnCast" + "Play_sfx_Zaahen_ZaahenCritAttack_OnHit" + "Play_sfx_Zaahen_ZaahenE_OnCast" + "Play_sfx_Zaahen_ZaahenEAttack_AoE_buffactivate" + "Play_sfx_Zaahen_ZaahenEAttack_hit_inner" + "Play_sfx_Zaahen_ZaahenEAttack_hit_outer" + "Play_sfx_Zaahen_ZaahenP_loop_revive_ready" + "Play_sfx_Zaahen_ZaahenP_loop_stacks_max" + "Play_sfx_Zaahen_ZaahenP_revive_buffactivate" + "Play_sfx_Zaahen_ZaahenP_revive_ready" + "Play_sfx_Zaahen_ZaahenQ1_buffactivate" + "Play_sfx_Zaahen_ZaahenQ2_buffactivate" + "Play_sfx_Zaahen_ZaahenQ2_OnCast" + "Play_sfx_Zaahen_ZaahenQ2_warning" + "Play_sfx_Zaahen_ZaahenQ2Attack_OnCast" + "Play_sfx_Zaahen_ZaahenQ2Attack_OnHit" + "Play_sfx_Zaahen_ZaahenQ_OnCast" + "Play_sfx_Zaahen_ZaahenQAttack_OnCast" + "Play_sfx_Zaahen_ZaahenQAttack_OnHit" + "Play_sfx_Zaahen_ZaahenR_AoE_buffactivate" + "Play_sfx_Zaahen_ZaahenR_AoE_hit_champion" + "Play_sfx_Zaahen_ZaahenR_AoE_hit_minion" + "Play_sfx_Zaahen_ZaahenR_AoE_warning" + "Play_sfx_Zaahen_ZaahenR_dash" + "Play_sfx_Zaahen_ZaahenR_OnCast" + "Play_sfx_Zaahen_ZaahenW_hit_champion" + "Play_sfx_Zaahen_ZaahenW_hit_minion" + "Play_sfx_Zaahen_ZaahenW_OnCast" + "Play_sfx_Zaahen_ZaahenW_OnMissileLaunch" + "Play_sfx_Zaahen_ZaahenW_pull_cast" + "Play_sfx_Zaahen_ZaahenW_pull_champion" + "Play_sfx_Zaahen_ZaahenW_pull_minion" + "Stop_sfx_Zaahen_Homeguard3D_loop" + "Stop_sfx_Zaahen_Recall3D_winddown" + "Stop_sfx_Zaahen_Respawn3D_buffactivate" + "Stop_sfx_Zaahen_ZaahenEAttack_hit_inner" + "Stop_sfx_Zaahen_ZaahenEAttack_hit_outer" + "Stop_sfx_Zaahen_ZaahenP_loop_revive_ready" + "Stop_sfx_Zaahen_ZaahenP_loop_stacks_max" + "Stop_sfx_Zaahen_ZaahenQ1_buffactivate" + "Stop_sfx_Zaahen_ZaahenQ2_buffactivate" + "Stop_sfx_Zaahen_ZaahenQ2_warning" + "Stop_sfx_Zaahen_ZaahenW_OnMissileLaunch" + } + } + BankUnit { + name: string = "Zaahen_Base_VO" + bankPath: list[string] = { + "ASSETS/Sounds/Wwise2016/VO/en_US/Characters/Zaahen/Skins/Base/Zaahen_Base_VO_audio.bnk" + "ASSETS/Sounds/Wwise2016/VO/en_US/Characters/Zaahen/Skins/Base/Zaahen_Base_VO_events.bnk" + "ASSETS/Sounds/Wwise2016/VO/en_US/Characters/Zaahen/Skins/Base/Zaahen_Base_VO_audio.wpk" + } + events: list[string] = { + "Play_vo_Zaahen_Assist3DYunara" + "Play_vo_Zaahen_Attack2DGeneral" + "Play_vo_Zaahen_Death3D" + "Play_vo_Zaahen_FirstEncounter3DAatrox" + "Play_vo_Zaahen_FirstEncounter3DAscended" + "Play_vo_Zaahen_FirstEncounter3DAzir" + "Play_vo_Zaahen_FirstEncounter3DDarkin" + "Play_vo_Zaahen_FirstEncounter3DDemacia" + "Play_vo_Zaahen_FirstEncounter3DDemon" + "Play_vo_Zaahen_FirstEncounter3DGeneral" + "Play_vo_Zaahen_FirstEncounter3DKayn" + "Play_vo_Zaahen_FirstEncounter3DKinkou" + "Play_vo_Zaahen_FirstEncounter3DLeBlanc" + "Play_vo_Zaahen_FirstEncounter3DNaafiri" + "Play_vo_Zaahen_FirstEncounter3DNasus" + "Play_vo_Zaahen_FirstEncounter3DRenekton" + "Play_vo_Zaahen_FirstEncounter3DShurima" + "Play_vo_Zaahen_FirstEncounter3DSivir" + "Play_vo_Zaahen_FirstEncounter3DVarus" + "Play_vo_Zaahen_FirstEncounter3DVoid" + "Play_vo_Zaahen_FirstEncounter3DXinZhao" + "Play_vo_Zaahen_FirstEncounter3DYunara" + "Play_vo_Zaahen_FirstEncounter3DZoe" + "Play_vo_Zaahen_Joke3DGeneral" + "Play_vo_Zaahen_JokeResponse3DGeneral" + "Play_vo_Zaahen_Kill3DAatrox" + "Play_vo_Zaahen_Kill3DAheadAllyTeam" + "Play_vo_Zaahen_Kill3DAscended" + "Play_vo_Zaahen_Kill3DBehindAllyTeam" + "Play_vo_Zaahen_Kill3DDarkin" + "Play_vo_Zaahen_Kill3DFirst" + "Play_vo_Zaahen_Kill3DGeneral" + "Play_vo_Zaahen_Kill3DKayn" + "Play_vo_Zaahen_Kill3DNaafiri" + "Play_vo_Zaahen_Kill3DPenta" + "Play_vo_Zaahen_Kill3DVarus" + "Play_vo_Zaahen_Kill3DXinZhao" + "Play_vo_Zaahen_Kill3DYunara" + "Play_vo_Zaahen_Laugh3DGeneral" + "Play_vo_Zaahen_Move2DFirst" + "Play_vo_Zaahen_Move2DFirstAllyAatrox" + "Play_vo_Zaahen_Move2DFirstAllyDarkin" + "Play_vo_Zaahen_Move2DFirstAllyKayn" + "Play_vo_Zaahen_Move2DFirstAllyNaafiri" + "Play_vo_Zaahen_Move2DFirstAllyVarus" + "Play_vo_Zaahen_Move2DFirstAllyXinZhao" + "Play_vo_Zaahen_Move2DFirstAllyYunara" + "Play_vo_Zaahen_Move2DLong" + "Play_vo_Zaahen_Move2DStandard" + "Play_vo_Zaahen_Recall3DGeneral" + "Play_vo_Zaahen_Respawn2DGeneral" + "Play_vo_Zaahen_Spell3DPMax" + "Play_vo_Zaahen_Spell3DPRevive" + "Play_vo_Zaahen_Spell3DPReviveDarkin" + "Play_vo_Zaahen_Spell3DPReviveXinZhao" + "Play_vo_Zaahen_Spell3DPReviveYunara" + "Play_vo_Zaahen_Taunt3DGeneral" + "Play_vo_Zaahen_ZaahenBasicAttack2_cast3D" + "Play_vo_Zaahen_ZaahenBasicAttack3_cast3D" + "Play_vo_Zaahen_ZaahenBasicAttack_cast3D" + "Play_vo_Zaahen_ZaahenCritAttack_cast3D" + "Play_vo_Zaahen_ZaahenE_cast3D" + "Play_vo_Zaahen_ZaahenQ2Attack_cast3D" + "Play_vo_Zaahen_ZaahenQAttack_cast3D" + "Play_vo_Zaahen_ZaahenR_cast3D" + "Play_vo_Zaahen_ZaahenW_cast3D" + } + voiceOver: bool = true + } + } + } + skinAnimationProperties: embed = SkinAnimationProperties { + animationGraphData: link = 0x33b9bbd + } + skinMeshProperties: embed = SkinMeshDataProperties { + skeleton: string = "ASSETS/Characters/Zaahen/Skins/Base/Zaahen_Base.Zaahen.skl" + simpleSkin: string = "ASSETS/Characters/Zaahen/Skins/Base/Zaahen_Base.Zaahen.skn" + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Zaahen_Base_TX_CM.Zaahen.tex" + skinScale: f32 = 0.95 + selfIllumination: f32 = 0.7 + overrideBoundingBox: option[vec3] = { { 100, 280, 100 } } + Material: link = 0x8dbfd9ac + reflectionFresnelColor: rgba = { 0, 0, 0, 255 } + initialSubmeshToHide: string = "Weapon_Smear" + materialOverride: list[embed] = { + SkinMeshDataProperties_MaterialOverride { + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Zaahen_Base_Smear_TX_CM.Zaahen.tex" + submesh: string = "Weapon_Smear" + } + SkinMeshDataProperties_MaterialOverride { + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Zaahen_Base_Weapon_TX_CM.Zaahen.tex" + submesh: string = "Weapon" + } + SkinMeshDataProperties_MaterialOverride { + Material: link = 0x8dbfd9ac + submesh: string = "Body" + } + SkinMeshDataProperties_MaterialOverride { + Material: link = 0xb9aca8b5 + submesh: string = "Wings" + } + } + rigPoseModifierData: list[pointer] = { + SpringPhysicsRigPoseModifierData { + name: hash = "l_armor" + Joint: hash = "L_Sleeve_Root" + DefaultOn: bool = false + DoRotation: bool = true + maxAngle: f32 = 50 + maxDistance: f32 = 50 + } + SpringPhysicsRigPoseModifierData { + name: hash = "R_Armor" + Joint: hash = "R_Sleeve_Root" + DefaultOn: bool = false + DoRotation: bool = true + maxAngle: f32 = 50 + maxDistance: f32 = 50 + } + ConformToPathRigPoseModifierData { + mStartingJointName: hash = "L_Shoulder" + mEndingJointName: hash = "L_Elbow" + mDefaultMaskName: hash = 0x4fc1e099 + mMaxBoneAngle: f32 = 100 + OnlyActivateInTurns: bool = true + } + ConformToPathRigPoseModifierData { + mStartingJointName: hash = "L_Wing3_1_SKN" + mEndingJointName: hash = "L_Wing3_4_SKN" + mDefaultMaskName: hash = 0x4fc1e099 + } + ConformToPathRigPoseModifierData { + mStartingJointName: hash = "R_Wing3_1_SKN" + mEndingJointName: hash = "R_Wing3_4_SKN" + mDefaultMaskName: hash = 0x4fc1e099 + } + } + } + armorMaterial: string = "Flesh" + defaultAnimations: list[string] = { "Weapon" } + mContextualActionData: link = 0x3186dd5 + iconCircle: option[string] = { "ASSETS/Characters/Zaahen/HUD/Zaahen_Circle_0.Zaahen.tex" } + iconSquare: option[string] = { "ASSETS/Characters/Zaahen/HUD/Zaahen_Square_0.Zaahen.tex" } + healthBarData: embed = CharacterHealthBarDataRecord { + attachToBone: string = "Buffbone_Cstm_Healthbar" + unitHealthBarStyle: u8 = 12 + } + mResourceResolver: link = 0x523bb166 + PersistentEffectConditions: list2[pointer] = { + 0x0 { } + } + } + "Characters/Zaahen/Skins/Skin0/Particles/Zaahen_Base_Q_1_Buff" = VfxSystemDefinitionData { + complexEmitterDefinitionData: list[pointer] = { + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 10 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 1.2 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.4, 1 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 1.2 } + } + } + particleLinger: option[f32] = { 0.5 } + fieldCollectionDefinition: pointer = VfxFieldCollectionDefinitionData { + fieldNoiseDefinitions: list[embed] = { + VfxFieldNoiseDefinitionData { + Position: embed = ValueVector3 { + constantValue: vec3 = { 0, 100, 0 } + } + radius: embed = ValueFloat { + constantValue: f32 = 300 + } + frequency: embed = ValueFloat { + constantValue: f32 = 50 + } + velocityDelta: embed = ValueFloat { + constantValue: f32 = 10 + } + axisFraction: vec3 = { 2, 2, 2 } + } + } + } + emitterName: string = "Sparks1" + birthVelocity: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.2, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 0, 0 } } + } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 2, 2, 2 } + } + worldAcceleration: embed = IntegratedValueVector3 { + constantValue: vec3 = { 0, 500, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 500, 0 } } + } + } + SpawnShape: pointer = VfxShapeBox { + flags: u8 = 1 + Size: vec3 = { 15, 10, 15 } + } + blendMode: u8 = 1 + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.2, 0.5 } + values: list[vec4] = { + { 0.8901961, 0.09803922, 0.09803922, 0 } + { 0.2, 0.2, 0.3019608, 1 } + { 0.8901961, 0.09803922, 0.09803922, 1 } + } + } + } + pass: i16 = 80 + depthBiasFactors: vec2 = { -1, -1 } + isDirectionOriented: flag = true + isUniformScale: flag = true + directionVelocityScale: f32 = 0.003 + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 6, 0, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.4, 1 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 6, 0, 0 } } + } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.12598425, 0.47637796, 1 } + values: list[vec3] = { + { 0, 0, 0 } + { 1, 1, 1 } + { 0.8360656, 0.5990991, 0.5990991 } + { 0, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Udyr_Base_VGU_GlowMask_Thicc.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 200 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.2 + } + emitterName: string = "LightTrail1" + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, 125 } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, 0.5 } + } + primitive: pointer = VfxPrimitiveCameraTrail { + mTrail: embed = VfxTrailDefinitionData { + mMode: u8 = 1 + mBirthTilingSize: embed = ValueVector3 { + constantValue: vec3 = { 800, 0, 0 } + } + mSmoothingMode: u8 = 1 + } + } + blendMode: u8 = 1 + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.079535216, 0.18529771, 0.37157086, 0.651592, 1 } + values: list[vec4] = { + { 0.8509804, 0.03137255, 0, 0 } + { 0.8509804, 0.03137255, 0, 0.9411765 } + { 0.8901961, 0.09803922, 0.09803922, 1 } + { 0.27450982, 0.06666667, 0.08235294, 0.6627451 } + { 0.27450982, 0.06666667, 0.08235294, 0.34901962 } + { 0.27450982, 0.06666667, 0.08235294, 0 } + } + } + } + pass: i16 = -10 + alphaRef: u8 = 0 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.2864675, 0.64652014, 1 } + values: list[f32] = { 0.190625, 0.571875, 0.8675568, 1 } + } + } + erosionFeatherIn: f32 = 0.15 + erosionFeatherOut: f32 = 0.15 + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Mordekaiser_Skin54_Noise_keka.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 0, 1, 0, 0 } + } + } + useNavmeshMask: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 20, 2, 2 } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 0.8, 0.8, 0.8 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.07960199, 0.14004976, 0.39004976, 0.75, 1 } + values: list[vec3] = { + { 0.32, 0.32, 0.32 } + { 0.72, 0.72, 0.72 } + { 0.7961644, 0.7961644, 0.7961644 } + { 0.7961644, 0.7961644, 0.7961644 } + { 0.4, 0.4, 0.4 } + { 0.24, 0.24, 0.24 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Mordekaiser_R_Smoke_Trail.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 150 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.2 + } + emitterName: string = "LightGlow1" + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, 125 } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, 0.5 } + } + primitive: pointer = VfxPrimitiveCameraTrail { + mTrail: embed = VfxTrailDefinitionData { + mMode: u8 = 1 + mBirthTilingSize: embed = ValueVector3 { + constantValue: vec3 = { 800, 0, 0 } + } + mSmoothingMode: u8 = 1 + } + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 1, 1, 0.34901962 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 0.8, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 0.8901961, 0.09803922, 0.09803922, 1 } + { 0.2, 0.2, 0.3019608, 1 } + { 0.13278401, 0.10722515, 0.16159303, 0 } + } + } + } + pass: i16 = -15 + alphaRef: u8 = 0 + useNavmeshMask: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 55, 2, 2 } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 0.8, 0.8, 0.8 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.07960199, 0.14004976, 0.39546493, 0.77527076, 1 } + values: list[vec3] = { + { 0.32000002, 0.32000002, 0.32000002 } + { 0.71999997, 0.71999997, 0.71999997 } + { 0.7961644, 0.7961644, 0.7961644 } + { 0.72706515, 0.7961644, 0.7961644 } + { 0.3814612, 0.4, 0.4 } + { 0.24000001, 0.24000001, 0.24000001 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/common_color-bellcurve32.Zaahen.tex" + uvRotation: embed = ValueFloat { + constantValue: f32 = 90 + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 6 + } + isSingleParticle: flag = true + emitterLinger: option[f32] = { 1 } + emitterName: string = "ADD_EdgeGlow" + importance: u8 = 3 + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 0, 0 } } + } + } + primitive: pointer = VfxPrimitiveAttachedMesh { + mMesh: embed = VfxMeshDefinitionData { + mSubmeshesToDraw: list[hash] = { "weapon" } + mSubmeshesToDrawAlways: list[hash] = { "weapon" } + mLockMeshToAttachment: bool = true + } + UseAvatarSpecificSubmeshMask: bool = true + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.27450982, 0.06666667, 0.08235294, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.15, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + } + } + } + pass: i16 = 10 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + constantValue: f32 = 0 + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.5, 1 } + values: list[f32] = { 0, 0, 0 } + } + } + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Emote_Einstein_01_mult.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + depthBiasFactors: vec2 = { -1, -15 } + particleIsLocalOrientation: flag = true + isRotationEnabled: flag = true + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Q_Glaive_Mask2.Zaahen.tex" + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Foundation_Tile01.Zaahen.tex" + UvRotationMult: embed = ValueFloat { + constantValue: f32 = 180 + } + birthUvScrollRateMult: embed = ValueVector2 { + constantValue: vec2 = { 0.5, 0 } + } + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0.8, 1 } + keyValues: list[f32] = { 0, 4 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 1 } + } + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 2 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.6, 1 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 2 } + } + } + emitterName: string = "groundfroth" + SpawnShape: pointer = VfxShapeCylinder { + flags: u8 = 1 + radius: f32 = 10 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, -50, 0 } + } + primitive: pointer = VfxPrimitiveArbitraryQuad { } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.27450982, 0.06666667, 0.08235294, 1 } + dynamics: pointer = VfxAnimatedColorVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.4, 0.8 } + } + } + times: list[f32] = { 0 } + values: list[vec4] = { { 0.27450982, 0.06666667, 0.08235294, 1 } } + } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 0.55, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0.85 } + { 1, 0.662745, 0.078431, 0 } + } + } + } + pass: i16 = 50 + colorLookUpTypeY: u8 = 3 + colorLookUpScales: vec2 = { 1, 0.5 } + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0.25, 1 } + values: list[f32] = { 0, 1 } + } + } + erosionSliceWidth: f32 = 1 + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Heimerdinger_Skin24_R_R_Splats_01_Erosion.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + erosionMapAddressMode: u8 = 0 + } + depthBiasFactors: vec2 = { -1, -100 } + isUniformScale: flag = true + isRandomStartFrame: flag = true + isGroundLayer: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 0, 360 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 90, 0, 360 } } + } + } + isLocalOrientation: flag = false + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 10, 0.9, 0.9 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 0.7, 1 } + keyValues: list[f32] = { 1, 1.5, 2 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 10, 0.9, 0.9 } } + } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.1, 0.25, 1 } + values: list[vec3] = { + { 0, 0, 0 } + { 0.95, 0.95, 0.95 } + { 1, 1, 1 } + { 1.1, 1.1, 1.1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Heimerdinger_Skin24_R_R_beam_02.Zaahen.tex" + numFrames: u16 = 4 + texDiv: vec2 = { 2, 2 } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.6 + } + particleLinger: option[f32] = { 10.6 } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "shovelBurstGlow" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + blendMode: u8 = 4 + Color: embed = ValueColor { + constantValue: vec4 = { 0.8901961, 0.09803922, 0.09803922, 0.29411766 } + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.3, 1 } + values: list[vec4] = { + { 0.8901961, 0.09803922, 0.09803922, 0 } + { 0.8901961, 0.09803922, 0.09803922, 0.29411766 } + { 0.8901961, 0.09803922, 0.09803922, 0 } + } + } + } + 0xcb13aff1: f32 = -40 + particleIsLocalOrientation: flag = true + isUniformScale: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 150, 105, 35 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 1, 1, 1 } + { 0.5, 0.5, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Aura_Self.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.3 + } + particleLinger: option[f32] = { 10.3 } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "handBurst" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.8901961, 0.09803922, 0.09803922, 1 } + } + Color: embed = ValueColor { + constantValue: vec4 = { 1, 1, 1, 0.498039 } + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.3, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 0.498039 } + { 1, 1, 1, 0 } + } + } + } + 0xcb13aff1: f32 = -40 + particleIsLocalOrientation: flag = true + isUniformScale: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 150, 105, 35 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 1, 1, 1 } + { 0.5, 0.5, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Aura_Self.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 5 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.5 + } + particleLinger: option[f32] = { 0.25 } + emitterName: string = "START5" + importance: u8 = 3 + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + SpawnShape: pointer = VfxShapeBox { + flags: u8 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, 100 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 0, 100 } } + } + } + primitive: pointer = VfxPrimitiveRay { } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.27450982, 0.06666667, 0.08235294, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.5, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = -5 + colorLookUpScales: vec2 = { 1, 0 } + alphaRef: u8 = 0 + 0xcb13aff1: f32 = -20 + disableBackfaceCull: bool = true + isUniformScale: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 0, 180, 0 } + } + isLocalOrientation: flag = false + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 100, 75, 1 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.5 } + values: list[vec3] = { + { 1, 1, 0 } + { 0.75, 2, 1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Foundation_Tile01.Zaahen.tex" + birthUvScrollRate: embed = ValueVector2 { + constantValue: vec2 = { 2, 0 } + } + birthUVOffset: embed = ValueVector2 { + constantValue: vec2 = { 1, 1 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec2] = { { 1, 1 } } + } + } + uvRotation: embed = ValueFloat { + constantValue: f32 = 270 + } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Aura_Self.Zaahen.tex" + texAddressModeMult: u8 = 2 + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.3 + } + particleLinger: option[f32] = { 10.3 } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "handBurst1" + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, 500, 0 } + } + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, -100, 0 } + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 1 } + } + Color: embed = ValueColor { + constantValue: vec4 = { 1, 1, 1, 0.498039 } + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.3, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 0.498039 } + { 1, 1, 1, 0 } + } + } + } + softParticleParams: pointer = VfxSoftParticleDefinitionData { + deltaIn: f32 = 10 + } + 0xcb13aff1: f32 = -40 + particleIsLocalOrientation: flag = true + isUniformScale: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 150, 105, 35 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 1, 1, 1 } + { 0.5, 0.5, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Naafiri_Base_R_Flash_sharp.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.3 + } + particleLinger: option[f32] = { 1 } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterLinger: option[f32] = { 1 } + emitterName: string = "ADD_EdgeGlow1" + importance: u8 = 3 + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + SpawnShape: pointer = VfxShapeLegacy { + emitOffset: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 0, 0 } } + } + } + emitRotationAngles: list[embed] = { + ValueFloat { } + ValueFloat { } + } + emitRotationAxes: list[vec3] = { + { 0, 0, 0 } + { 0, 0, 0 } + } + } + EmitterPosition: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 0, 0 } } + } + } + primitive: pointer = VfxPrimitiveAttachedMesh { + mMesh: embed = VfxMeshDefinitionData { + mSubmeshesToDraw: list[hash] = { "weapon" } + mSubmeshesToDrawAlways: list[hash] = { "weapon" } + mLockMeshToAttachment: bool = true + } + UseAvatarSpecificSubmeshMask: bool = true + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.27450982, 0.06666667, 0.08235294, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.15, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + } + } + } + pass: i16 = 8 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.5, 1 } + values: list[f32] = { 1, 0.5, 1 } + } + } + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Emote_Einstein_01_mult.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + depthBiasFactors: vec2 = { -1, -15 } + particleIsLocalOrientation: flag = true + isRotationEnabled: flag = true + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Q_Glaive_Mask2.Zaahen.tex" + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/common_color-bellcurve.Zaahen.tex" + birthUvScrollRateMult: embed = ValueVector2 { + constantValue: vec2 = { -0.5, 0 } + } + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 5 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.5 + } + emitterName: string = "START6" + importance: u8 = 3 + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, 100 } + } + primitive: pointer = VfxPrimitiveRay { } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.27450982, 0.06666667, 0.08235294, 0.25882354 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.5, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = -20 + colorLookUpScales: vec2 = { 1, 0 } + alphaRef: u8 = 0 + disableBackfaceCull: bool = true + isUniformScale: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 0, 180, 0 } + } + isLocalOrientation: flag = false + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 100, 75, 1 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.5 } + values: list[vec3] = { + { 1, 1, 0 } + { 0.75, 2, 1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/color-hold.Zaahen.tex" + birthUvScrollRate: embed = ValueVector2 { + constantValue: vec2 = { 0, 2 } + } + birthUVOffset: embed = ValueVector2 { + constantValue: vec2 = { 1, 1 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec2] = { { 1, 1 } } + } + } + uvRotation: embed = ValueFloat { + constantValue: f32 = 180 + } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Aura_Self.Zaahen.tex" + texAddressModeMult: u8 = 2 + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 6 + } + particleLinger: option[f32] = { 0.2 } + lifetime: option[f32] = { 5 } + isSingleParticle: flag = true + emitterLinger: option[f32] = { 0.5 } + emitterName: string = "Trail" + IsEmitterSpace: flag = true + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, -20, 15 } + } + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Q1_Buff_BladeMesh.Zaahen.scb" + } + } + blendMode: u8 = 1 + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.05, 0.9, 1 } + values: list[vec4] = { + { 0.54901963, 0.043137256, 0.08235294, 0 } + { 0.54901963, 0.043137256, 0.08235294, 1 } + { 0.4905165, 0.08004883, 0.08004883, 1 } + { 0.2509804, 0.03137255, 0.03137255, 0 } + } + } + } + pass: i16 = 17 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + constantValue: f32 = 0 + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0.1, 0.5, 0.8 } + values: list[f32] = { 0, 0, 0 } + } + } + erosionSliceWidth: f32 = 2 + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_BA_Trail_Darkin_1.Zaahen.tex" + erosionMapAddressMode: u8 = 0 + } + disableBackfaceCull: bool = true + particleIsLocalOrientation: flag = true + isUniformScale: flag = true + isRotationEnabled: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 270, 0, 180 } + } + rotation0: embed = IntegratedValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 0, 0 } } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/common_color-bellcurve32.Zaahen.tex" + particleUVScrollRate: embed = IntegratedValueVector2 { + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0 } + values: list[vec2] = { { 0, 0 } } + } + } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/common_color-bellcurve32.Zaahen.tex" + texAddressModeMult: u8 = 2 + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 6 + } + isSingleParticle: flag = true + emitterLinger: option[f32] = { 1 } + emitterName: string = "ADD_EdgeGlow2" + importance: u8 = 3 + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 0, 0 } } + } + } + primitive: pointer = VfxPrimitiveAttachedMesh { + mMesh: embed = VfxMeshDefinitionData { + mSubmeshesToDraw: list[hash] = { "weapon" } + mSubmeshesToDrawAlways: list[hash] = { "weapon" } + mLockMeshToAttachment: bool = true + } + UseAvatarSpecificSubmeshMask: bool = true + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.27450982, 0.06666667, 0.08235294, 0.5019608 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.15, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + } + } + } + pass: i16 = 8 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + constantValue: f32 = 0 + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.5, 1 } + values: list[f32] = { 0, 0, 0 } + } + } + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Emote_Einstein_01_mult.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + 0xcb13aff1: f32 = -1 + particleIsLocalOrientation: flag = true + isRotationEnabled: flag = true + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Q_Glaive_Mask3.Zaahen.tex" + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/color-hold.Zaahen.tex" + birthUvScrollRateMult: embed = ValueVector2 { + constantValue: vec2 = { 0.5, 0 } + } + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.15 + } + particleLinger: option[f32] = { 10.3 } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "handBurst2" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.8901961, 0.09803922, 0.09803922, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.3, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + softParticleParams: pointer = VfxSoftParticleDefinitionData { + beginIn: f32 = 10 + deltaIn: f32 = 100 + } + 0xcb13aff1: f32 = -40 + particleIsLocalOrientation: flag = true + isUniformScale: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 360, 0, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 360, 0, 0 } } + } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 400, 105, 35 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 1, 1, 1 } + { 0.5, 0.5, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Naafiri_Base_R_Flash_sharp.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 6 + } + isSingleParticle: flag = true + emitterLinger: option[f32] = { 1 } + emitterName: string = "ADD_EdgeGlow3" + importance: u8 = 3 + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 0, 0 } } + } + } + primitive: pointer = VfxPrimitiveAttachedMesh { + mMesh: embed = VfxMeshDefinitionData { + mSubmeshesToDraw: list[hash] = { "weapon" } + mSubmeshesToDrawAlways: list[hash] = { "weapon" } + mLockMeshToAttachment: bool = true + } + UseAvatarSpecificSubmeshMask: bool = true + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.27450982, 0.06666667, 0.08235294, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.15, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + } + } + } + pass: i16 = 9 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + constantValue: f32 = 0 + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.5, 1 } + values: list[f32] = { 0, 0, 0 } + } + } + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Emote_Einstein_01_mult.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + 0xcb13aff1: f32 = -2 + particleIsLocalOrientation: flag = true + isRotationEnabled: flag = true + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Q_Glaive_Mask2.Zaahen.tex" + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/color-hold.Zaahen.tex" + birthUvScrollRateMult: embed = ValueVector2 { + constantValue: vec2 = { 0.5, 0 } + } + } + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.3 + rate: embed = ValueFloat { + constantValue: f32 = 2 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 6 + } + particleLinger: option[f32] = { 0.2 } + lifetime: option[f32] = { 5 } + isSingleParticle: flag = true + emitterLinger: option[f32] = { 0.5 } + emitterName: string = "Trail2" + IsEmitterSpace: flag = true + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, -20, 15 } + } + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Q1_Buff_BladeMesh.Zaahen.scb" + } + } + blendMode: u8 = 1 + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.05, 0.9, 1 } + values: list[vec4] = { + { 0.8901961, 0.09803922, 0.09803922, 0 } + { 0.8901961, 0.09803922, 0.09803922, 1 } + { 0.8901961, 0.09803922, 0.09803922, 1 } + { 0.2509804, 0.03137255, 0.03137255, 0 } + } + } + } + pass: i16 = 20 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + constantValue: f32 = 0 + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0.1, 0.5, 0.8 } + values: list[f32] = { 0, 0, 0 } + } + } + erosionSliceWidth: f32 = 2 + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_BA_Trail_Darkin_1.Zaahen.tex" + erosionMapAddressMode: u8 = 0 + } + disableBackfaceCull: bool = true + particleIsLocalOrientation: flag = true + isUniformScale: flag = true + isRotationEnabled: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 270, 0, 180 } + } + rotation0: embed = IntegratedValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 0, 0 } } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/common_color-bellcurve32.Zaahen.tex" + particleUVScrollRate: embed = IntegratedValueVector2 { + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0 } + values: list[vec2] = { { 0, 0 } } + } + } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Aura_Self.Zaahen.tex" + birthUvScrollRateMult: embed = ValueVector2 { + constantValue: vec2 = { 0, -2 } + } + birthUVOffsetMult: embed = ValueVector2 { + constantValue: vec2 = { 0, 1 } + } + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 2 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 1 + } + isSingleParticle: flag = true + emitterLinger: option[f32] = { 1 } + emitterName: string = "ADD_EdgeGlow4" + importance: u8 = 3 + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 0, 0 } } + } + } + primitive: pointer = VfxPrimitiveAttachedMesh { + mMesh: embed = VfxMeshDefinitionData { + mSubmeshesToDraw: list[hash] = { "weapon" } + mSubmeshesToDrawAlways: list[hash] = { "weapon" } + mLockMeshToAttachment: bool = true + } + UseAvatarSpecificSubmeshMask: bool = true + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.27450982, 0.06666667, 0.08235294, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = 8 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + constantValue: f32 = 0 + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.5, 1 } + values: list[f32] = { 0, 0, 0 } + } + } + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Emote_Einstein_01_mult.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + 0xcb13aff1: f32 = -1 + particleIsLocalOrientation: flag = true + isRotationEnabled: flag = true + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Q_Glaive_Mask3.Zaahen.tex" + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Yasuo_Skin57_3026_Items_Noise_02.Zaahen.tex" + UvRotationMult: embed = ValueFloat { + constantValue: f32 = 180 + } + birthUvScrollRateMult: embed = ValueVector2 { + constantValue: vec2 = { 0.5, 0 } + } + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 5 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.4 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 0.4 } + } + } + particleLinger: option[f32] = { 2 } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "Cast_Towards1" + importance: u8 = 3 + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 100, 1200, 100 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.25, 1.2 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 100, 1200, 100 } } + } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 4, 4, 4 } + } + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + SpawnShape: pointer = VfxShapeBox { + flags: u8 = 1 + Size: vec3 = { 5, 5, 5 } + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 10, -150, 0 } + } + primitive: pointer = VfxPrimitiveArbitraryQuad { } + blendMode: u8 = 1 + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.2, 0.7, 1 } + values: list[vec4] = { + { 0.10980392, 0, 0.007919433, 0 } + { 0.8901961, 0.09803922, 0.09803922, 1 } + { 0.8901961, 0.09803922, 0.09803922, 1 } + { 0.10980392, 0, 0.03137255, 0 } + } + } + } + pass: i16 = 81 + depthBiasFactors: vec2 = { -1, -1 } + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, 90 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 100, 50, 0 } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Aura_Self.Zaahen.tex" + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Foundation_Tile01.Zaahen.tex" + UvRotationMult: embed = ValueFloat { + constantValue: f32 = 90 + } + uvScaleMult: embed = ValueVector2 { + constantValue: vec2 = { 0.5, 1 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 0.5 } + values: list[vec2] = { + { 2, 1 } + { 0.5, 1 } + } + } + } + birthUvScrollRateMult: embed = ValueVector2 { + constantValue: vec2 = { 0.5, 0.2 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec2] = { { 0.5, 0.2 } } + } + } + birthUVOffsetMult: embed = ValueVector2 { + constantValue: vec2 = { 1, 1 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec2] = { { 1, 1 } } + } + } + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 2 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.1 + } + isSingleParticle: flag = true + emitterLinger: option[f32] = { 1 } + emitterName: string = "ADD_EdgeGlow5" + importance: u8 = 3 + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 0, 0 } } + } + } + primitive: pointer = VfxPrimitiveAttachedMesh { + mMesh: embed = VfxMeshDefinitionData { + mSubmeshesToDraw: list[hash] = { "weapon" } + mSubmeshesToDrawAlways: list[hash] = { "weapon" } + mLockMeshToAttachment: bool = true + } + UseAvatarSpecificSubmeshMask: bool = true + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.8901961, 0.09803922, 0.09803922, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = 10 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + constantValue: f32 = 0 + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.5, 1 } + values: list[f32] = { 0, 0, 0 } + } + } + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Emote_Einstein_01_mult.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + depthBiasFactors: vec2 = { -1, -15 } + particleIsLocalOrientation: flag = true + isRotationEnabled: flag = true + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Q_Glaive_Mask3.Zaahen.tex" + textureMult: pointer = VfxTextureMultDefinitionData { + UvRotationMult: embed = ValueFloat { + constantValue: f32 = 180 + } + birthUvScrollRateMult: embed = ValueVector2 { + constantValue: vec2 = { 0.5, 0 } + } + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.1 + } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "glowFast2" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.92156863, 0.7607843, 0.49019608, 1 } + } + Color: embed = ValueColor { + constantValue: vec4 = { 1, 1, 1, 0.5000076 } + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0.003937008, 0.023544546, 0.8, 1 } + values: list[vec4] = { + { 1, 1, 1, 0.5000076 } + { 1, 1, 1, 0.5000076 } + { 1, 1, 1, 0.5000076 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = 10 + colorLookUpScales: vec2 = { 1, 0.8 } + colorLookUpOffsets: vec2 = { 0, 0.3 } + 0xcb13aff1: f32 = -40 + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 0, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 120, 220, 1 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 1, 0, 0 } + { 0, 1, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Star_Flare.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.3 + } + particleLinger: option[f32] = { 0.2 } + lifetime: option[f32] = { 5 } + isSingleParticle: flag = true + emitterLinger: option[f32] = { 0.5 } + emitterName: string = "Trail3" + IsEmitterSpace: flag = true + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, -20, 15 } + } + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Q1_Buff_BladeMesh.Zaahen.scb" + } + } + blendMode: u8 = 1 + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.05, 0.9, 1 } + values: list[vec4] = { + { 0.6500038, 0.17999542, 0.17999542, 0 } + { 0.27450982, 0.06666667, 0.08235294, 1 } + { 0.27450982, 0.06666667, 0.08235294, 1 } + { 0.2509804, 0.03137255, 0.03137255, 0 } + } + } + } + pass: i16 = 170 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + constantValue: f32 = 0 + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0.1, 0.5, 0.8 } + values: list[f32] = { 0, 0, 0 } + } + } + erosionSliceWidth: f32 = 2 + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_BA_Trail_Darkin_1.Zaahen.tex" + erosionMapAddressMode: u8 = 0 + } + disableBackfaceCull: bool = true + particleIsLocalOrientation: flag = true + isUniformScale: flag = true + isRotationEnabled: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 270, 0, 180 } + } + rotation0: embed = IntegratedValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 0, 0 } } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/common_color-bellcurve32.Zaahen.tex" + particleUVScrollRate: embed = IntegratedValueVector2 { + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0 } + values: list[vec2] = { { 0, 0 } } + } + } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Aura_Self.Zaahen.tex" + texAddressModeMult: u8 = 2 + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 10 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.3 + } + particleLinger: option[f32] = { 0.2 } + lifetime: option[f32] = { 5 } + isSingleParticle: flag = true + emitterLinger: option[f32] = { 0.5 } + emitterName: string = "Trail4" + IsEmitterSpace: flag = true + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, -20, 15 } + } + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Q1_Buff_BladeMesh.Zaahen.scb" + } + } + blendMode: u8 = 1 + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.05, 0.9, 1 } + values: list[vec4] = { + { 0.8901961, 0.09803922, 0.09803922, 0 } + { 0.8901961, 0.09803922, 0.09803922, 1 } + { 0.8901961, 0.09803922, 0.09803922, 1 } + { 0.2509804, 0.03137255, 0.03137255, 0 } + } + } + } + pass: i16 = 200 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + constantValue: f32 = 0 + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0.1, 0.5, 0.8 } + values: list[f32] = { 0, 0, 0 } + } + } + erosionSliceWidth: f32 = 2 + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_BA_Trail_Darkin_1.Zaahen.tex" + erosionMapAddressMode: u8 = 0 + } + disableBackfaceCull: bool = true + particleIsLocalOrientation: flag = true + isUniformScale: flag = true + isRotationEnabled: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 270, 0, 180 } + } + rotation0: embed = IntegratedValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 0, 0 } } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/common_color-bellcurve32.Zaahen.tex" + particleUVScrollRate: embed = IntegratedValueVector2 { + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0 } + values: list[vec2] = { { 0, 0 } } + } + } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Aura_Self.Zaahen.tex" + texAddressModeMult: u8 = 2 + birthUvScrollRateMult: embed = ValueVector2 { + constantValue: vec2 = { 0, -6 } + } + birthUVOffsetMult: embed = ValueVector2 { + constantValue: vec2 = { 0, 1 } + } + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.15 + } + particleLinger: option[f32] = { 10.3 } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "handBurst3" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.8901961, 0.09803922, 0.09803922, 1 } + } + Color: embed = ValueColor { + constantValue: vec4 = { 1, 1, 1, 0.8899977 } + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.3, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 0.8899977 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = 1 + 0xcb13aff1: f32 = -40 + particleIsLocalOrientation: flag = true + isUniformScale: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 360, 0, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 360, 0, 0 } } + } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 100, 105, 35 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 1, 1, 1 } + { 0.5, 0.5, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Naafiri_Base_R_Flash_sharp.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = -1 + } + particleLingerType: u8 = 1 + particleLinger: option[f32] = { 0.2 } + isSingleParticle: flag = true + emitterName: string = "blackOrb_main1" + importance: u8 = 3 + IsEmitterSpace: flag = true + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { -6, 0, 3 } + } + primitive: pointer = VfxPrimitiveArbitraryQuad { } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.27450982, 0.06666667, 0.08235294, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.44, 0.50064516 } + values: list[vec4] = { + { 0.59607846, 0.59607846, 0.59607846, 1 } + { 0.8509804, 0.8509804, 0.8509804, 1 } + { 1, 1, 1, 1 } + } + } + } + pass: i16 = 100 + alphaRef: u8 = 0 + 0xcb13aff1: f32 = -4 + particleIsLocalOrientation: flag = true + isUniformScale: flag = true + isRotationEnabled: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 0, 90, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 11, 1, 1 } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Udyr_Base_VGU_GlowMask_Thicc.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = -1 + } + particleLingerType: u8 = 1 + particleLinger: option[f32] = { 0.2 } + isSingleParticle: flag = true + emitterName: string = "blackOrb_main2" + importance: u8 = 3 + IsEmitterSpace: flag = true + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { -6, 0, 3 } + } + primitive: pointer = VfxPrimitiveArbitraryQuad { } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.8901961, 0.09803922, 0.09803922, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.44, 0.50064516 } + values: list[vec4] = { + { 0.59607846, 0.59607846, 0.59607846, 1 } + { 0.8509804, 0.8509804, 0.8509804, 1 } + { 1, 1, 1, 1 } + } + } + } + pass: i16 = 95 + alphaRef: u8 = 0 + 0xcb13aff1: f32 = -3 + particleIsLocalOrientation: flag = true + isUniformScale: flag = true + isRotationEnabled: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 0, 90, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 12, 1, 1 } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Udyr_Base_VGU_GlowMask_Thicc.Zaahen.tex" + } + } + particleName: string = "Zaahen_Base_Q_1_Buff" + particlePath: string = "Characters/Zaahen/Skins/Skin0/Particles/Zaahen_Base_Q_1_Buff" + soundPersistentDefault: string = "Play_sfx_Zaahen_ZaahenQ1_buffactivate" + } + "Characters/Zaahen/Skins/Skin0/Particles/Zaahen_Base_Q_Swipe_02" = VfxSystemDefinitionData { + complexEmitterDefinitionData: list[pointer] = { + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLinger: option[f32] = { 1 } + lifetime: option[f32] = { 1.1 } + isSingleParticle: flag = true + emitterName: string = "MotionBlur6" + importance: u8 = 3 + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, -100, 0 } + } + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/XinZhaoRework_Base_Q_Swipe_03_B.Zaahen.scb" + } + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.9411765, 0.85490197, 0.5254902, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0.071794875, 0.3, 0.6, 0.9, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = 5 + softParticleParams: pointer = VfxSoftParticleDefinitionData { + beginIn: f32 = 10 + deltaIn: f32 = 100 + } + disableBackfaceCull: bool = true + isUniformScale: flag = true + uvScrollClamp: flag = true + isGroundLayer: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 0, 180, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 1.3, 1, 1 } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Skin_06_Spark_Vertical.Zaahen.tex" + birthUVOffset: embed = ValueVector2 { + constantValue: vec2 = { 0, -0.75 } + } + texAddressModeBase: u8 = 2 + particleUVScrollRate: embed = IntegratedValueVector2 { + constantValue: vec2 = { 0, 4 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec2] = { + { 0, 4 } + { 0, 20 } + } + } + } + uvScale: embed = ValueVector2 { + constantValue: vec2 = { 2, 1 } + } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/XinZhaoRework_Base_Q_Swipe_C_Alpha.Zaahen.tex" + texAddressModeMult: u8 = 2 + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 2 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLinger: option[f32] = { 1 } + lifetime: option[f32] = { 1.1 } + isSingleParticle: flag = true + emitterName: string = "MotionBlur7" + importance: u8 = 3 + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, -100, 0 } + } + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/XinZhaoRework_Base_Q_Swipe_03_B.Zaahen.scb" + } + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.636759, 0.55370414, 0.23649958, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0.071794875, 0.3, 0.6, 0.9, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = 2 + softParticleParams: pointer = VfxSoftParticleDefinitionData { + beginIn: f32 = 10 + deltaIn: f32 = 100 + } + disableBackfaceCull: bool = true + isUniformScale: flag = true + uvScrollClamp: flag = true + isGroundLayer: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 0, 180, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 1.3, 1, 1 } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Skin_06_Spark_Vertical.Zaahen.tex" + birthUVOffset: embed = ValueVector2 { + constantValue: vec2 = { 0, -0.75 } + } + texAddressModeBase: u8 = 2 + particleUVScrollRate: embed = IntegratedValueVector2 { + constantValue: vec2 = { 0, 4 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec2] = { + { 0, 4 } + { 0, 20 } + } + } + } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/XinZhaoRework_Base_Q_Swipe_C_Alpha.Zaahen.tex" + texAddressModeMult: u8 = 2 + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 2 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLinger: option[f32] = { 1 } + lifetime: option[f32] = { 1.1 } + isSingleParticle: flag = true + emitterName: string = "MotionBlur8" + importance: u8 = 3 + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, -100, 0 } + } + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/XinZhaoRework_Base_Q_Swipe_03_B.Zaahen.scb" + } + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.5058824, 0.03137255, 0.13333334, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0.071794875, 0.3, 0.6, 0.9, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = -2 + softParticleParams: pointer = VfxSoftParticleDefinitionData { + beginIn: f32 = 10 + deltaIn: f32 = 100 + } + disableBackfaceCull: bool = true + isUniformScale: flag = true + uvScrollClamp: flag = true + isGroundLayer: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 0, 180, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 1.3, 1, 1 } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Skin_06_Spark_Vertical.Zaahen.tex" + birthUVOffset: embed = ValueVector2 { + constantValue: vec2 = { 0, -0.75 } + } + texAddressModeBase: u8 = 2 + particleUVScrollRate: embed = IntegratedValueVector2 { + constantValue: vec2 = { 0, 4 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec2] = { + { 0, 4 } + { 0, 20 } + } + } + } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/XinZhaoRework_Base_Q_Swipe_C_Alpha.Zaahen.tex" + texAddressModeMult: u8 = 2 + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 2 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLinger: option[f32] = { 1 } + lifetime: option[f32] = { 1.1 } + isSingleParticle: flag = true + emitterName: string = "MotionBlur9" + importance: u8 = 3 + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, -100, 0 } + } + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/XinZhaoRework_Base_Q_Swipe_03_B.Zaahen.scb" + } + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.87504387, 0.14206149, 0.24284734, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0.071794875, 0.3, 0.6, 0.9, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = -5 + softParticleParams: pointer = VfxSoftParticleDefinitionData { + beginIn: f32 = 10 + deltaIn: f32 = 100 + } + disableBackfaceCull: bool = true + isUniformScale: flag = true + uvScrollClamp: flag = true + isGroundLayer: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 0, 180, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 1.3, 1, 1 } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Skin_06_Spark_Vertical.Zaahen.tex" + birthUVOffset: embed = ValueVector2 { + constantValue: vec2 = { 0, -0.75 } + } + texAddressModeBase: u8 = 2 + particleUVScrollRate: embed = IntegratedValueVector2 { + constantValue: vec2 = { 0, 4 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec2] = { + { 0, 4 } + { 0, 20 } + } + } + } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/XinZhaoRework_Base_Q_Swipe_C_Alpha.Zaahen.tex" + texAddressModeMult: u8 = 2 + } + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.1 + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.75 + } + particleLinger: option[f32] = { 1.5 } + isSingleParticle: flag = true + emitterLinger: option[f32] = { 1 } + emitterName: string = "groundDecal_erode" + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { -50, 1, -40 } + } + primitive: pointer = VfxPrimitiveArbitraryQuad { } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.68000305, 0.6399939, 0.6200046, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.5, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 0.8504311, 0.8366674, 0.8366674, 1 } + { 0.6733501, 0.6320287, 0.6320287, 0 } + } + } + } + pass: i16 = -10 + alphaRef: u8 = 0 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.8 } + values: list[f32] = { 0, 1 } + } + } + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Q_GroundCrack_Glow.Zaahen.tex" + } + miscRenderFlags: u8 = 1 + isGroundLayer: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 180, 15 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 100, 260, 1 } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Q_GroundCrack.Zaahen.tex" + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.1 + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.5 + } + particleLinger: option[f32] = { 2 } + isSingleParticle: flag = true + emitterLinger: option[f32] = { 1 } + emitterName: string = "groundGlow" + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { -50, 1, -40 } + } + primitive: pointer = VfxPrimitiveArbitraryQuad { } + blendMode: u8 = 1 + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0.03751804, 0.35497835, 0.55, 0.6, 1 } + values: list[vec4] = { + { 0.92156863, 0.7607843, 0.49019608, 0 } + { 0.27450982, 0.06666667, 0.08235294, 1 } + { 0.27450982, 0.06666667, 0.08235294, 1 } + { 0.27450982, 0.06666667, 0.08235294, 1 } + { 0.27450982, 0.06666667, 0.08235294, 0 } + } + } + } + pass: i16 = -9 + alphaRef: u8 = 1 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.05 } + values: list[f32] = { 2, 0 } + } + } + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Augment_CrystalizedWill_rampdown32.Zaahen.tex" + } + miscRenderFlags: u8 = 1 + isGroundLayer: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 180, 15 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 100, 260, 1 } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Q_GroundCrack_Add.Zaahen.tex" + paletteDefinition: pointer = VfxPaletteDefinitionData { + paletteTexture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_W_Gradient_RGB.Zaahen.tex" + palleteSrcMixColor: embed = ValueColor { + constantValue: vec4 = { 0, 0, 0, 1 } + } + paletteSelector: embed = ValueVector3 { + constantValue: vec3 = { 3, 0, 0 } + } + paletteCount: i32 = 8 + } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_E_Nova_Mult.Zaahen.tex" + uvScaleMult: embed = ValueVector2 { + constantValue: vec2 = { 1.5, 1.35 } + } + ParticleIntegratedUvScrollMult: embed = IntegratedValueVector2 { + constantValue: vec2 = { -1.2, -0.5 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 0.30017152, 0.5540309, 0.7838765, 1 } + values: list[vec2] = { + { -1.2, -0.5 } + { -0.99452055, -0.40753424 } + { -0.73550385, -0.2996106 } + { -0.5068305, -0.21117939 } + { -0.33479077, -0.13949615 } + } + } + } + birthUVOffsetMult: embed = ValueVector2 { + constantValue: vec2 = { 1, 1 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec2] = { { 1, 1 } } + } + } + } + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.1 + rate: embed = ValueFloat { + constantValue: f32 = 4 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.4 + } + particleLinger: option[f32] = { 2 } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterLinger: option[f32] = { 1 } + emitterName: string = "groundGlowAdd" + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { -50, 1, -40 } + } + primitive: pointer = VfxPrimitiveArbitraryQuad { } + blendMode: u8 = 4 + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0.03751804, 0.35497835, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 0.8901961, 0.2901961, 0.09803922, 1 } + { 0.49169147, 0.01994354, 0.05557336, 0 } + } + } + } + pass: i16 = -8 + alphaRef: u8 = 1 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0.49, 0.5, 1 } + values: list[f32] = { 0, 0.75, 0.75 } + } + } + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Q_GroundCrack_Add.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + miscRenderFlags: u8 = 1 + isGroundLayer: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 180, 15 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 100, 260, 1 } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Q_GroundCrack_Add.Zaahen.tex" + paletteDefinition: pointer = VfxPaletteDefinitionData { + paletteTexture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_W_Gradient_RGB.Zaahen.tex" + palleteSrcMixColor: embed = ValueColor { + constantValue: vec4 = { 0, 0, 0, 1 } + } + paletteSelector: embed = ValueVector3 { + constantValue: vec3 = { 3, 0, 0 } + } + PaletteUAnimationCurve: embed = ValueFloat { + constantValue: f32 = 0.5 + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 1 } + values: list[f32] = { 0.5, 0.5 } + } + } + paletteCount: i32 = 8 + } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/common_color-rampup.Zaahen.tex" + texAddressModeMult: u8 = 2 + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 60 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 1 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 1 } + } + } + particleLinger: option[f32] = { 1 } + lifetime: option[f32] = { 0.2 } + emitterName: string = "mists" + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, 500, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.4, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 1, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 500, 0 } } + } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 5, 5, 5 } + } + SpawnShape: pointer = VfxShapeLegacy { + emitOffset: embed = ValueVector3 { + constantValue: vec3 = { 10, 0, 0 } + } + emitRotationAngles: list[embed] = { + ValueFloat { } + ValueFloat { } + } + emitRotationAxes: list[vec3] = { + { 0, 0, 0 } + { 0, 0, 0 } + } + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { -80, 0, 200 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { -80, 0, 200 } + { -80, 0, -200 } + } + } + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.27450982, 0.06666667, 0.08235294, 0.5294118 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.13556337, 0.41478872, 0.5556338, 0.893321, 0.96103895, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 0.98751694, 0.98751694, 0.98751694, 0.16964285 } + { 1, 1, 1, 0.86885434 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0.7410714 } + { 1, 1, 1, 0 } + } + } + } + alphaRef: u8 = 0 + softParticleParams: pointer = VfxSoftParticleDefinitionData { + deltaIn: f32 = 30 + } + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0.15, 1 } + values: list[f32] = { 0, 1 } + } + } + erosionFeatherOut: f32 = 0.2 + erosionSliceWidth: f32 = 1.7 + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Base_SmokeErode.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + miscRenderFlags: u8 = 1 + stencilMode: u8 = 3 + stencilRef: u8 = 3 + isDirectionOriented: flag = true + isUniformScale: flag = true + isRandomStartFrame: flag = true + isGroundLayer: flag = true + useNavmeshMask: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 1, 90, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 1, 90, 0 } } + } + } + directionVelocityScale: f32 = 0.002 + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 60, 1, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 1, 2 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 60, 1, 0 } } + } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.5, 1 } + values: list[vec3] = { + { 0.6, 1, 1 } + { 0.8, 2, 2 } + { 1, 1.5, 1.5 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_R_Smoke01_01.Zaahen.tex" + numFrames: u16 = 4 + texDiv: vec2 = { 2, 2 } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 60 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 1.2 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.4, 1.25 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 1.2 } + } + } + lifetime: option[f32] = { 0.2 } + emitterName: string = "smoke1" + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, 800, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.4, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 1, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 800, 0 } } + } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 5, 5, 5 } + } + SpawnShape: pointer = VfxShapeLegacy { + emitOffset: embed = ValueVector3 { + constantValue: vec3 = { 40, 0, 0 } + } + emitRotationAngles: list[embed] = { + ValueFloat { } + ValueFloat { } + } + emitRotationAxes: list[vec3] = { + { 0, 0, 0 } + { 0, 0, 0 } + } + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { -80, 0, 200 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.5, 1 } + values: list[vec3] = { + { -80, 0, 200 } + { -160, 0, 0 } + { -40, 0, -240 } + } + } + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 1, 1, 0.54901963 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 0.4, 0.6, 1 } + values: list[vec4] = { + { 0.8901961, 0.09803922, 0.09803922, 0 } + { 0.8901961, 0.09803922, 0.09803922, 1 } + { 0.8901961, 0.09803922, 0.09803922, 0.6313726 } + { 0.27450982, 0.06666667, 0.08235294, 0.4509804 } + { 0, 0, 0, 0 } + } + } + } + pass: i16 = 151 + alphaRef: u8 = 0 + softParticleParams: pointer = VfxSoftParticleDefinitionData { + deltaIn: f32 = 50 + } + 0xcb13aff1: f32 = -80 + isDirectionOriented: flag = true + directionVelocityScale: f32 = 0.005 + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 130, 150, 130 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.8, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.8, 1.5 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.8, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 130, 150, 130 } } + } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.4, 1 } + values: list[vec3] = { + { 0.6, 0.1, 0.6 } + { 0.8, 0.8, 0.8 } + { 1, 1, 1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Kassadin_Skin14_smoke.Zaahen.tex" + uvMode: u8 = 2 + birthUvScrollRate: embed = ValueVector2 { + constantValue: vec2 = { 0, 0.3 } + } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Kassadin_Skin14_smoke_mult.Zaahen.tex" + birthUvScrollRateMult: embed = ValueVector2 { + constantValue: vec2 = { 0, 0.3 } + } + birthUVOffsetMult: embed = ValueVector2 { + constantValue: vec2 = { 1, 1 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 1, 0 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 1, 0 } + } + } + times: list[f32] = { 0 } + values: list[vec2] = { { 1, 1 } } + } + } + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 20 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.3 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 0.3 } + } + } + particleLinger: option[f32] = { 1 } + lifetime: option[f32] = { 0.2 } + emitterName: string = "smoke2" + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, 1000, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.4, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 1, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 1000, 0 } } + } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 5, 5, 5 } + } + SpawnShape: pointer = VfxShapeLegacy { + emitOffset: embed = ValueVector3 { + constantValue: vec3 = { 40, 0, 0 } + } + emitRotationAngles: list[embed] = { + ValueFloat { } + ValueFloat { } + } + emitRotationAxes: list[vec3] = { + { 0, 0, 0 } + { 0, 0, 0 } + } + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { -80, 0, 200 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.5, 1 } + values: list[vec3] = { + { -80, 0, 200 } + { -160, 0, 0 } + { -40, 0, -240 } + } + } + } + blendMode: u8 = 4 + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 0.47791952, 0.98331696 } + values: list[vec4] = { + { 0.8901961, 0.09803922, 0.09803922, 1 } + { 0.8901961, 0.09803922, 0.09803922, 0.4392157 } + { 0.8901961, 0.09803922, 0.09803922, 1 } + { 0.27450982, 0.06666667, 0.08235294, 0 } + } + } + } + pass: i16 = 152 + softParticleParams: pointer = VfxSoftParticleDefinitionData { + deltaIn: f32 = 50 + } + 0xcb13aff1: f32 = -80 + isDirectionOriented: flag = true + directionVelocityScale: f32 = 0.005 + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 20, 100, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 1, 2 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 20, 100, 0 } } + } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.5, 1 } + values: list[vec3] = { + { 0.6, 0.6, 1 } + { 0.8, 0.8, 2 } + { 0.4, 1, 1.5 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Kassadin_Skin14_smoke.Zaahen.tex" + uvMode: u8 = 2 + birthUvScrollRate: embed = ValueVector2 { + constantValue: vec2 = { 0, 0.3 } + } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Kassadin_Skin14_smoke_mult.Zaahen.tex" + birthUvScrollRateMult: embed = ValueVector2 { + constantValue: vec2 = { 0, 0.3 } + } + birthUVOffsetMult: embed = ValueVector2 { + constantValue: vec2 = { 1, 1 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 1, 0 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 1, 0 } + } + } + times: list[f32] = { 0 } + values: list[vec2] = { { 1, 1 } } + } + } + } + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.05 + rate: embed = ValueFloat { + constantValue: f32 = 2 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.4 + } + particleLinger: option[f32] = { 2 } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterLinger: option[f32] = { 1 } + emitterName: string = "groundGlowAdd1" + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { -50, 1, -40 } + } + primitive: pointer = VfxPrimitiveArbitraryQuad { } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 1, 1, 0.5000076 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0.03751804, 0.35497835, 1 } + values: list[vec4] = { + { 0.8901961, 0.2901961, 0.09803922, 0 } + { 0.8901961, 0.2901961, 0.09803922, 1 } + { 0.49169147, 0.01994354, 0.05557336, 0 } + } + } + } + pass: i16 = -8 + alphaRef: u8 = 1 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.05 } + values: list[f32] = { 1, 0 } + } + } + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_DissolveGradient1.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + miscRenderFlags: u8 = 1 + isGroundLayer: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 180, 15 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 100, 260, 1 } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Q_GroundCrack_Glow.Zaahen.tex" + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/common_color-rampup.Zaahen.tex" + texAddressModeMult: u8 = 2 + } + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.1 + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.75 + } + particleLinger: option[f32] = { 1.5 } + isSingleParticle: flag = true + emitterLinger: option[f32] = { 1 } + emitterName: string = "groundDecal_fade" + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { -50, 1, -40 } + } + primitive: pointer = VfxPrimitiveArbitraryQuad { } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.68000305, 0.6399939, 0.6200046, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.5, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 0.8504311, 0.8366674, 0.8366674, 1 } + { 0.6733501, 0.6320287, 0.6320287, 0 } + } + } + } + pass: i16 = -11 + alphaRef: u8 = 0 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + constantValue: f32 = 0 + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.8 } + values: list[f32] = { 0, 0 } + } + } + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Q_GroundCrack_Glow.Zaahen.tex" + } + miscRenderFlags: u8 = 1 + isGroundLayer: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 180, 15 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 100, 260, 1 } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Q_GroundCrack.Zaahen.tex" + } + } + particleName: string = "Zaahen_Base_Q_Swipe_02" + particlePath: string = "Characters/Zaahen/Skins/Skin0/Particles/Zaahen_Base_Q_Swipe_02" + } + "Characters/Zaahen/Skins/Skin0/Particles/Zaahen_Base_P_MaxStacks_Avatar" = VfxSystemDefinitionData { + complexEmitterDefinitionData: list[pointer] = { + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 2 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = -1 + } + isSingleParticle: flag = true + emitterName: string = "Fresnel4" + importance: u8 = 5 + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 10, 0, 10 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 10, 0, 10 } } + } + } + Linger: pointer = VfxLingerDefinitionData { + UseSeparateLingerColor: flag = true + SeparateLingerColor: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0.5, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + } + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + primitive: pointer = VfxPrimitiveAttachedMesh { + mMesh: embed = VfxMeshDefinitionData { + mLockMeshToAttachment: bool = true + } + } + blendMode: u8 = 2 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.4899977, 0.8200046, 0.919997, 0.93000686 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.3, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + } + } + } + pass: i16 = -4990 + reflectionDefinition: pointer = VfxReflectionDefinitionData { + reflectionMapTexture: string = "ASSETS/Shared/Particles/Generic_White_Cubemap.TFT_Set15.dds" + reflectionOpacityDirect: f32 = -1 + reflectionOpacityGlancing: f32 = 0.1 + reflectionFresnel: f32 = 0.3 + reflectionFresnelColor: vec4 = { 0.4269627, 0.82949567, 0.90286106, 1 } + fresnel: f32 = 0.1 + fresnelColor: vec4 = { 0, 0, 0, 1 } + } + 0xcb13aff1: f32 = -2 + particleIsLocalOrientation: flag = true + isUniformScale: flag = true + hasPostRotateOrientation: flag = true + isRandomStartFrame: flag = true + isRotationEnabled: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 0, 180, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 1.002, 1, 1 } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Base_SmokeErode.Zaahen.tex" + numFrames: u16 = 4 + birthUvScrollRate: embed = ValueVector2 { + constantValue: vec2 = { 0.4, 0.2 } + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 1 + } + emitterName: string = "Dlack_avatar2" + importance: u8 = 3 + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + primitive: pointer = VfxPrimitiveAttachedMesh { + mMesh: embed = VfxMeshDefinitionData { + mSubmeshesToDraw: list[hash] = { "BODY", "Wings", "weapon" } + mLockMeshToAttachment: bool = true + } + } + blendMode: u8 = 2 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.4899977, 0.8200046, 0.919997, 0.2500038 } + } + pass: i16 = -5000 + 0xcb13aff1: f32 = -1 + disableBackfaceCull: bool = true + particleIsLocalOrientation: flag = true + isUniformScale: flag = true + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/color-hold.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 4 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.3 + } + lifetime: option[f32] = { 5 } + isSingleParticle: flag = true + emitterName: string = "DarkGlow1" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + FlexShapeDefinition: pointer = VfxFlexShapeDefinitionData { + scaleBirthScaleByBoundObjectSize: f32 = 0.005 + } + primitive: pointer = VfxPrimitiveArbitraryQuad { } + blendMode: u8 = 2 + Color: embed = ValueColor { + constantValue: vec4 = { 0.666667, 1, 0.952941, 0.8 } + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.3, 1 } + values: list[vec4] = { + { 0.666667, 1, 0.952941, 0.8 } + { 0.666667, 1, 0.952941, 0.8 } + { 0.666667, 1, 0.952941, 0 } + } + } + } + pass: i16 = -5000 + censorModulateValue: vec4 = { 1, 0.5, 0.5, 1 } + 0xcb13aff1: f32 = -20 + isGroundLayer: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 0, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 200, 200, 125 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 0.7, 0.7, 0.7 } + { 1, 1, 1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Naafiri_Base_Foundation_Glow01.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.3 + } + lifetime: option[f32] = { 5 } + isSingleParticle: flag = true + emitterName: string = "flash_distrot" + particleColorTexture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Darius_color-rampdown32_03.Zaahen.tex" + blendMode: u8 = 1 + pass: i16 = 100 + meshRenderFlags: u8 = 0 + distortionDefinition: pointer = VfxDistortionDefinitionData { + distortion: f32 = 0.05 + normalMapTexture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Darius_distort-pinch.Zaahen.tex" + } + miscRenderFlags: u8 = 1 + isUniformScale: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 300, 300, 300 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0, 0.4, 0.6, 1 } + values: list[vec3] = { + { 0, 0, 0 } + { 0.7, 0.7, 0.7 } + { 0.9, 0.9, 0.9 } + { 1, 1, 1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/color-hold.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = -1 + } + lifetime: option[f32] = { 10 } + isSingleParticle: flag = true + emitterName: string = "AVATAR1" + importance: u8 = 3 + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + primitive: pointer = VfxPrimitiveAttachedMesh { + mMesh: embed = VfxMeshDefinitionData { + mSubmeshesToDraw: list[hash] = { "Wings", "BODY" } + mLockMeshToAttachment: bool = true + } + } + blendMode: u8 = 1 + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + } + } + } + pass: i16 = -10 + censorModulateValue: vec4 = { 0.7893797, 0.85181963, 0.30569926, 1 } + modulationFactor: vec4 = { 0.8202487, 0.046143282, 0.046143282, 1 } + 0xcb13aff1: f32 = 50 + particleIsLocalOrientation: flag = true + isUniformScale: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 1.02, 1, 1 } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/color-hold.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 2 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 1.5 + } + emitterName: string = "DarkGlow5" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 1, 0 } + } + FlexShapeDefinition: pointer = VfxFlexShapeDefinitionData { + scaleBirthScaleByBoundObjectSize: f32 = 0.005 + scaleEmitOffsetByBoundObjectSize: f32 = 0.005 + } + primitive: pointer = VfxPrimitiveArbitraryQuad { } + blendMode: u8 = 2 + Color: embed = ValueColor { + constantValue: vec4 = { 0.666667, 1, 0.952941, 0.8 } + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.3, 1 } + values: list[vec4] = { + { 0.666667, 1, 0.952941, 0 } + { 0.666667, 1, 0.952941, 0.8 } + { 0.666667, 1, 0.952941, 0 } + } + } + } + pass: i16 = -5000 + alphaRef: u8 = 0 + 0xcb13aff1: f32 = -20 + miscRenderFlags: u8 = 1 + isGroundLayer: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 0, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 160, 145, 125 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 0.7, 0.7, 0.7 } + { 1, 1, 1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Naafiri_Base_Foundation_Glow01.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 7 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 1 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 1 } + } + } + particleLinger: option[f32] = { 2 } + emitterName: string = "ShadowWisps1" + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, 250, 0 } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 4, 2, 4 } + } + worldAcceleration: embed = IntegratedValueVector3 { + constantValue: vec3 = { 0, -100, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0 } + values: list[vec3] = { { 0, -100, 0 } } + } + } + bindWeight: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 1 } + values: list[f32] = { 0, 0 } + } + } + SpawnShape: pointer = VfxShapeBox { + flags: u8 = 1 + Size: vec3 = { 40, 60, 30 } + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 50, 0 } + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.54985887, 0.043152515, 0.081406884, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.15, 0.5, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0.42000458 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = 23 + alphaRef: u8 = 0 + softParticleParams: pointer = VfxSoftParticleDefinitionData { + beginIn: f32 = 10 + deltaOut: f32 = 50 + } + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 1 } + values: list[f32] = { 0, 1 } + } + } + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Base_SmokeErode.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + isUniformScale: flag = true + isRandomStartFrame: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 0, 360, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 360, 0 } } + } + } + birthRotationalVelocity0: embed = ValueVector3 { + constantValue: vec3 = { 20, 0, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 20, 0, 0 } } + } + } + isLocalOrientation: flag = false + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 60, 60, 30 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.15189302, 0.2885187, 0.4379786, 0.67653877, 1.0122888 } + values: list[vec3] = { + { 0.49325153, 0.49325153, 0.49325153 } + { 0.5917946, 0.59913427, 0.59913427 } + { 0.81314945, 0.81817883, 0.81817883 } + { 0.9906985, 0.9850261, 0.9850261 } + { 1.12698, 1.1474447, 1.1244107 } + { 1.3109593, 1.3109593, 1.3109593 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/zaahen_dust_cloud.Zaahen.tex" + numFrames: u16 = 4 + texDiv: vec2 = { 2, 2 } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 12 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.5 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 0.9, 1 } + keyValues: list[f32] = { 0.2, 1, 1.5 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 0.5 } + } + } + particleLinger: option[f32] = { 1 } + lifetime: option[f32] = { 0.1 } + isSingleParticle: flag = true + emitterName: string = "Sparkles" + birthOrbitalVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, -3, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, -3, 0 } } + } + } + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, 2000, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.2, 1.1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 2000, 0 } } + } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 8, 2, 8 } + } + birthAcceleration: embed = ValueVector3 { + constantValue: vec3 = { 100, 0, 100 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 100, 0, 100 } } + } + } + worldAcceleration: embed = IntegratedValueVector3 { + constantValue: vec3 = { 0, 200, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 200, 0 } } + } + } + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 1 } + values: list[f32] = { 1, 0 } + } + } + SpawnShape: pointer = VfxShapeCylinder { + radius: f32 = 100 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, -50, 0 } + } + blendMode: u8 = 4 + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 0.3, 0.6, 1 } + values: list[vec4] = { + { 0.928069, 0.8185092, 0.6716716, 0 } + { 0.84815747, 0.75295645, 0.50995654, 1 } + { 0.93354696, 0.7692073, 0.4036927, 1 } + { 0.8901961, 0.09803922, 0.09803922, 1 } + { 0.27450982, 0.06666667, 0.08235294, 0 } + } + } + } + pass: i16 = 10 + isDirectionOriented: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 1, 0, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 1, 0, 0 } } + } + } + birthRotationalVelocity0: embed = ValueVector3 { + constantValue: vec3 = { -300, 0, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 25, 50, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.3, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 1, 2 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 25, 50, 0 } } + } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 1, 1, 1 } + { 0, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_R_Sparks.Zaahen.tex" + paletteDefinition: pointer = VfxPaletteDefinitionData { + paletteTexture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_W_Gradient_RGB.Zaahen.tex" + } + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.05 + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.4 + } + particleLinger: option[f32] = { 1 } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "Wave_Pattern" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/fireball.Zaahen.SCB" + } + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.27450982, 0.06666667, 0.08235294, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.4211111, 0.63, 0.80333334, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 0.8545087 } + { 1, 1, 1, 0.3032948 } + { 1, 1, 1, 0.05953757 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = 300 + colorLookUpScales: vec2 = { 1, 0 } + alphaRef: u8 = 0 + disableBackfaceCull: bool = true + miscRenderFlags: u8 = 1 + isGroundLayer: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 300, 0 } + } + isLocalOrientation: flag = false + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 20, 20, 1 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.094444446, 0.37104464, 1 } + values: list[vec3] = { + { 0, 0, 0 } + { 0.8755981, 0.8755981, 0.8755981 } + { 1.1690364, 1.1690364, 1.1690364 } + { 1.2, 1.2, 1.2 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/R_wall_alphaBlend.Zaahen.tex" + birthUvScrollRate: embed = ValueVector2 { + constantValue: vec2 = { -1, 0 } + } + birthUVOffset: embed = ValueVector2 { + constantValue: vec2 = { 1, -0.99 } + } + particleUVScrollRate: embed = IntegratedValueVector2 { + constantValue: vec2 = { -0.3, 0 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 0.094444446, 1 } + values: list[vec2] = { + { -0.6, 0 } + { -0, 0 } + { -0, 0 } + } + } + } + uvScale: embed = ValueVector2 { + constantValue: vec2 = { 3, 3 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 0.075, 0.3 } + values: list[vec2] = { + { 3, 3 } + { 1.5, 3 } + { 1.5, 3 } + } + } + } + uvRotation: embed = ValueFloat { + constantValue: f32 = 90 + } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/2v2Cameo_Jhin_Mult.Zaahen.tex" + texAddressModeMult: u8 = 2 + uvScaleMult: embed = ValueVector2 { + constantValue: vec2 = { 1, 2 } + } + birthUVOffsetMult: embed = ValueVector2 { + constantValue: vec2 = { 0, 0.7 } + } + } + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.05 + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.4 + } + particleLinger: option[f32] = { 1 } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "Wave_Pattern1" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/fireball.Zaahen.SCB" + } + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.27450982, 0.06666667, 0.08235294, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0.5, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = 400 + colorLookUpScales: vec2 = { 1, 0 } + alphaRef: u8 = 0 + disableBackfaceCull: bool = true + miscRenderFlags: u8 = 1 + isGroundLayer: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 300, 0 } + } + isLocalOrientation: flag = false + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 20, 20, 1 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.094444446, 0.37104464, 1 } + values: list[vec3] = { + { 0, 0, 0 } + { 0.8755981, 0.8755981, 0.8755981 } + { 1.1690364, 1.1690364, 1.1690364 } + { 1.2, 1.2, 1.2 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/bloodstrands_bmagic_01.Zaahen.tex" + birthUvScrollRate: embed = ValueVector2 { + constantValue: vec2 = { -1, 0 } + } + birthUVOffset: embed = ValueVector2 { + constantValue: vec2 = { 1, -0.99 } + } + particleUVScrollRate: embed = IntegratedValueVector2 { + constantValue: vec2 = { -0.3, 0 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 0.094444446, 1 } + values: list[vec2] = { + { -0.6, 0 } + { -0, 0 } + { -0, 0 } + } + } + } + uvScale: embed = ValueVector2 { + constantValue: vec2 = { 3, -3 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 0.075, 0.3 } + values: list[vec2] = { + { 3, -3 } + { 1.5, -3 } + { 1.5, -3 } + } + } + } + uvRotation: embed = ValueFloat { + constantValue: f32 = 90 + } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_W_Mask_01.Zaahen.tex" + texAddressModeMult: u8 = 2 + uvScaleMult: embed = ValueVector2 { + constantValue: vec2 = { 1, 2 } + } + birthUVOffsetMult: embed = ValueVector2 { + constantValue: vec2 = { 0, 0.7 } + } + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 6 + } + HasVariableStartTime: flag = true + particleLifetime: embed = ValueFloat { + constantValue: f32 = 1 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 1 } + } + } + emitterName: string = "Back Glow_drk" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + SpawnShape: pointer = VfxShapeBox { + flags: u8 = 1 + Size: vec3 = { 0, 50, 0 } + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 170, 0 } + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 1, 1, 0.4 } + } + Color: embed = ValueColor { + constantValue: vec4 = { 0.8878767, 0.012130923, 0, 1 } + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.48097754, 1 } + values: list[vec4] = { + { 0.8878767, 0.012130923, 0, 0 } + { 0.8878767, 0.012130923, 0, 1 } + { 0.8878767, 0.012130923, 0, 0 } + } + } + } + pass: i16 = -5000 + alphaRef: u8 = 0 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.6389051, 1 } + values: list[f32] = { 0, 0.19183268, 1 } + } + } + erosionFeatherOut: f32 = 0.35 + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Skin01/Particles/Zaahen_Skin01_R_SmokeErode.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + 0xcb13aff1: f32 = -20 + miscRenderFlags: u8 = 1 + isGroundLayer: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 360, 360, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 360, 360, 0 } } + } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 220, 235, 125 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 0.7, 0.7, 0.7 } + { 1, 1, 1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Skin01/Particles/Akali_Base_R_distort.Zaahen.tex" + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Kassadin_Skin14_smoke_mult.Zaahen.tex" + } + } + } + particleName: string = "Zaahen_Base_P_MaxStacks_Avatar" + particlePath: string = "Characters/Zaahen/Skins/Skin0/Particles/Zaahen_Base_P_MaxStacks_Avatar" + soundPersistentDefault: string = "Play_sfx_Zaahen_ZaahenP_loop_stacks_max" + flags: u16 = 1236 + } + "Characters/Zaahen/Skins/Skin0/Particles/Zaahen_Base_Z_Back" = VfxSystemDefinitionData { + complexEmitterDefinitionData: list[pointer] = { + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 3 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 1 + } + lifetime: option[f32] = { 1 } + emitterName: string = "Empowered_Ground2" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Recall_dustRing_geo.Zaahen.scb" + } + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.31999695, 0, 0, 0.8 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.2, 0.5, 0.67711866, 1 } + values: list[vec4] = { + { 1, 1, 1, 0.007843138 } + { 1, 1, 1, 0.7921569 } + { 1, 1, 1, 0.50980395 } + { 1, 1, 1, 0.23921569 } + { 1, 1, 1, 0 } + } + } + } + alphaRef: u8 = 0 + disableBackfaceCull: bool = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 0, 1, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 1, 0 } } + } + } + birthScale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.8, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.6, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.8, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 1, 1, 1 } } + } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 0.8, 0.8, 0.8 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.6, 1 } + values: list[vec3] = { + { 0.48000002, 0.4, 0.48000002 } + { 0.64, 0.8, 0.64 } + { 0.8, 2.4, 0.8 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Ground_Splash.Zaahen.tex" + texDiv: vec2 = { 0.7, 1 } + particleUVScrollRate: embed = IntegratedValueVector2 { + constantValue: vec2 = { 0, 1 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0 } + values: list[vec2] = { { 0, 1 } } + } + } + uvScale: embed = ValueVector2 { + constantValue: vec2 = { 3, 1.5 } + } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_R_Fire_Trail_Up.Zaahen.tex" + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 3 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 1 + } + lifetime: option[f32] = { 1 } + emitterName: string = "Empowered_Ground3" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Recall_dustRing_geo.Zaahen.scb" + } + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 0.22000457, 0.06999313, 0.8 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.2, 0.5, 0.67711866, 1 } + values: list[vec4] = { + { 1, 1, 1, 0.007843138 } + { 1, 1, 1, 0.7921569 } + { 1, 1, 1, 0.50980395 } + { 1, 1, 1, 0.23921569 } + { 1, 1, 1, 0 } + } + } + } + alphaRef: u8 = 0 + disableBackfaceCull: bool = true + isUniformScale: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 0, 1, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 1, 0 } } + } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 0.8, 1, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.8, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.6, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.8, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0.8, 1, 1 } } + } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 0.8, 0.8, 0.8 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.6, 1 } + values: list[vec3] = { + { 0.48000002, 0.4, 0.48000002 } + { 0.64, 0.8, 0.64 } + { 0.8, 2.4, 0.8 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Ground_Splash.Zaahen.tex" + texDiv: vec2 = { 0.7, 1 } + particleUVScrollRate: embed = IntegratedValueVector2 { + constantValue: vec2 = { 0, 1 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0 } + values: list[vec2] = { { 0, 1 } } + } + } + uvScale: embed = ValueVector2 { + constantValue: vec2 = { 3, 1.5 } + } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_R_Fire_Trail_Up.Zaahen.tex" + } + } + } + particleName: string = "Zaahen_Base_Z_Back" + particlePath: string = "Characters/Zaahen/Skins/Skin0/Particles/Zaahen_Base_Z_Back" + flags: u16 = 213 + } + "Characters/Zaahen/Skins/Skin0/Particles/Zaahen_Base_W_Tell" = VfxSystemDefinitionData { + complexEmitterDefinitionData: list[pointer] = { + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.55 + } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterLinger: option[f32] = { 1 } + emitterName: string = "ADD_EdgeGlow5" + importance: u8 = 3 + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 0, 0 } } + } + } + primitive: pointer = VfxPrimitiveAttachedMesh { + mMesh: embed = VfxMeshDefinitionData { + mSubmeshesToDraw: list[hash] = { "weapon" } + mSubmeshesToDrawAlways: list[hash] = { "weapon" } + mLockMeshToAttachment: bool = true + } + UseAvatarSpecificSubmeshMask: bool = true + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 0.78039217, 0.5803922, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + } + } + } + pass: i16 = -4000 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + constantValue: f32 = 0 + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.5, 1 } + values: list[f32] = { 0, 0, 0 } + } + } + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Emote_Einstein_01_mult.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + depthBiasFactors: vec2 = { -1, -15 } + particleIsLocalOrientation: flag = true + isRotationEnabled: flag = true + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Q_Glaive_Mask2.Zaahen.tex" + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/color-hold.Zaahen.tex" + birthUvScrollRateMult: embed = ValueVector2 { + constantValue: vec2 = { 0.5, 0 } + } + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.55 + } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterLinger: option[f32] = { 1 } + emitterName: string = "Blend_EdgeGlow6" + importance: u8 = 3 + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 0, 0 } } + } + } + primitive: pointer = VfxPrimitiveAttachedMesh { + mMesh: embed = VfxMeshDefinitionData { + mSubmeshesToDraw: list[hash] = { "weapon" } + mSubmeshesToDrawAlways: list[hash] = { "weapon" } + mLockMeshToAttachment: bool = true + } + UseAvatarSpecificSubmeshMask: bool = true + } + blendMode: u8 = 1 + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 1 } + values: list[vec4] = { + { 0.55893797, 0.053101398, 0.09129473, 0 } + { 0.27450982, 0.06666667, 0.08235294, 1 } + } + } + } + pass: i16 = -4999 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + constantValue: f32 = 0 + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.5, 1 } + values: list[f32] = { 0, 0, 0 } + } + } + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Emote_Einstein_01_mult.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + depthBiasFactors: vec2 = { -1, -15 } + particleIsLocalOrientation: flag = true + isRotationEnabled: flag = true + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Q_Glaive_Mask3.Zaahen.tex" + textureMult: pointer = VfxTextureMultDefinitionData { + ParticleIntegratedUvScrollMult: embed = IntegratedValueVector2 { + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0 } + values: list[vec2] = { { 0, 0 } } + } + } + birthUVOffsetMult: embed = ValueVector2 { + constantValue: vec2 = { -0.25, 0 } + } + } + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.3 + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.3 + } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "SunSpot" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.8901961, 0.09803922, 0.09803922, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.125, 0.6, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0.8076923 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = 6 + meshRenderFlags: u8 = 0 + miscRenderFlags: u8 = 1 + particleIsLocalOrientation: flag = true + isUniformScale: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 200, 70, 70 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 0.8939759, 1, 1 } + { 1, 0.8, 0.8 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Leona_Base_Z_solar_tag.Zaahen.tex" + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.4 + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.35 + } + lifetime: option[f32] = { 4 } + isSingleParticle: flag = true + emitterName: string = "UnderNeathGlow1" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, -8, 8 } + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.27450982, 0.06666667, 0.08235294, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.9, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + meshRenderFlags: u8 = 0 + alphaRef: u8 = 0 + miscRenderFlags: u8 = 1 + particleIsLocalOrientation: flag = true + isUniformScale: flag = true + isGroundLayer: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 300, 200, 200 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.7, 1 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 300, 200, 200 } } + } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0.5, 1 } + values: list[vec3] = { + { 1, 1, 1 } + { 0, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Aura_Self.Zaahen.tex" + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.3 + rate: embed = ValueFloat { + constantValue: f32 = 2 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.2 + } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "DarkGlow1" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, -8, 8 } + } + FlexShapeDefinition: pointer = VfxFlexShapeDefinitionData { + scaleBirthScaleByBoundObjectSize: f32 = 0.005 + scaleEmitOffsetByBoundObjectSize: f32 = 0.005 + } + blendMode: u8 = 2 + Color: embed = ValueColor { + constantValue: vec4 = { 0.6666667, 1, 0.9331655, 0.8 } + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.16511025, 0.60392994, 1 } + values: list[vec4] = { + { 0.6666667, 1, 0.9331655, 0 } + { 0.6666667, 1, 0.9331655, 0.8 } + { 0.6666667, 1, 0.9331655, 0.15450746 } + { 0.6666667, 1, 0.9331655, 0 } + } + } + } + pass: i16 = -5000 + alphaRef: u8 = 0 + miscRenderFlags: u8 = 1 + isUniformScale: flag = true + isGroundLayer: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 280, 145, 125 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 0.7, 0.7, 0.7 } + { 1, 1, 1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Naafiri_Base_Foundation_Glow01.Zaahen.tex" + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.25 + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.25 + } + particleLinger: option[f32] = { } + lifetime: option[f32] = { 2 } + isSingleParticle: flag = true + emitterName: string = "Flash_Hori_BG1" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, -8, 8 } + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.92156863, 0.7607843, 0.49019608, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.19390403, 0.827406, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = 4 + alphaRef: u8 = 0 + 0xcb13aff1: f32 = -2 + miscRenderFlags: u8 = 1 + particleIsLocalOrientation: flag = true + isUniformScale: flag = true + hasPostRotateOrientation: flag = true + isRotationEnabled: flag = true + birthRotationalVelocity0: embed = ValueVector3 { + constantValue: vec3 = { 300, 0, 0 } + } + rotation0: embed = IntegratedValueVector3 { + constantValue: vec3 = { 3, 0, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.47935104, 0.76, 0.8182006, 1 } + values: list[vec3] = { + { 0, 0, 0 } + { 3, 0, 0 } + { 3, 0, 0 } + { 0, 0, 0 } + { 0, 0, 0 } + } + } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 250, 400, 1 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.45149156, 1 } + values: list[vec3] = { + { 0, 0, 0 } + { 1, 1, 1 } + { 0.4901316, 0.4901316, 0.4901316 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Star_Flare.Zaahen.tex" + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.45 + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.2 + } + particleLinger: option[f32] = { 0.2 } + lifetime: option[f32] = { 2 } + isSingleParticle: flag = true + emitterName: string = "Flash_Hori_FG1" + importance: u8 = 3 + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + SpawnShape: pointer = VfxShapeLegacy { + emitRotationAngles: list[embed] = { + ValueFloat { + constantValue: f32 = 1 + } + } + emitRotationAxes: list[vec3] = { { 0, 1.0000001, 0 } } + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, -8, 8 } + } + primitive: pointer = VfxPrimitiveArbitraryQuad { } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.8901961, 0.09803922, 0.09803922, 1 } + } + pass: i16 = 120 + alphaRef: u8 = 0 + 0xcb13aff1: f32 = -10 + miscRenderFlags: u8 = 1 + particleIsLocalOrientation: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, 90 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 300, 100, 1 } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 1, 2, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.1, 1 } + values: list[vec3] = { + { 0, 0, 0 } + { 1, 2, 1 } + { 0, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/XinZhaoRework_Base_LensFlare.Zaahen.tex" + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.45 + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.2 + } + particleLinger: option[f32] = { 0.2 } + lifetime: option[f32] = { 2 } + isSingleParticle: flag = true + emitterName: string = "Flash_Hori_FG2" + importance: u8 = 3 + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + SpawnShape: pointer = VfxShapeLegacy { + emitRotationAngles: list[embed] = { + ValueFloat { + constantValue: f32 = 1 + } + } + emitRotationAxes: list[vec3] = { { 0, 1.0000001, 0 } } + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, -8, 8 } + } + primitive: pointer = VfxPrimitiveArbitraryQuad { } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.92156863, 0.7607843, 0.49019608, 1 } + } + pass: i16 = 150 + alphaRef: u8 = 0 + 0xcb13aff1: f32 = -11 + miscRenderFlags: u8 = 1 + particleIsLocalOrientation: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, 90 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 300, 100, 1 } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 1, 2, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.1, 1 } + values: list[vec3] = { + { 0, 0, 0 } + { 1, 2, 1 } + { 0, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/XinZhaoRework_Base_LensFlare.Zaahen.tex" + } + } + particleName: string = "Zaahen_Base_W_Tell" + particlePath: string = "Characters/Zaahen/Skins/Skin0/Particles/Zaahen_Base_W_Tell" + } + "Characters/Zaahen/Skins/Skin0/Particles/Zaahen_Base_P_MaxStacks_Will_Revive" = VfxSystemDefinitionData { + complexEmitterDefinitionData: list[pointer] = { + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 2 + } + emitterName: string = "HologramAdd" + IsEmitterSpace: flag = true + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + primitive: pointer = VfxPrimitiveAttachedMesh { + mMesh: embed = VfxMeshDefinitionData { + mSubmeshesToDraw: list[hash] = { "BODY" } + mLockMeshToAttachment: bool = true + } + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.919997, 0.7600061, 0.4899977, 0.2500038 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.05, 0.8, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = -95 + uvParallaxScale: f32 = 0.00075 + 0xcb13aff1: f32 = -4 + disableBackfaceCull: bool = true + particleIsLocalOrientation: flag = true + isUniformScale: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 1.001, 1, 1 } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_E_Body_Mask.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 2 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 1 + } + emitterName: string = "HologramAdd1" + IsEmitterSpace: flag = true + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + primitive: pointer = VfxPrimitiveAttachedMesh { + mMesh: embed = VfxMeshDefinitionData { + mSubmeshesToDraw: list[hash] = { "BODY" } + mLockMeshToAttachment: bool = true + } + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.92156863, 0.7607843, 0.49019608, 0.2509804 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.05, 0.8, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = -95 + uvParallaxScale: f32 = 0.00075 + 0xcb13aff1: f32 = -4 + disableBackfaceCull: bool = true + particleIsLocalOrientation: flag = true + isUniformScale: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 1.001, 1, 1 } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_E_Body_Mask.Zaahen.tex" + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Yasuo_Skin57_3026_Items_Noise_02.Zaahen.tex" + birthUvScrollRateMult: embed = ValueVector2 { + constantValue: vec2 = { 0, 0.5 } + } + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 2 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 1 + } + emitterName: string = "HologramAdd2" + IsEmitterSpace: flag = true + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + primitive: pointer = VfxPrimitiveAttachedMesh { + mMesh: embed = VfxMeshDefinitionData { + mSubmeshesToDraw: list[hash] = { "Wings" } + mLockMeshToAttachment: bool = true + } + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.919997, 0.7600061, 0.4899977, 0.10000763 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.05, 0.8, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = -95 + uvParallaxScale: f32 = 0.00075 + 0xcb13aff1: f32 = -4 + disableBackfaceCull: bool = true + particleIsLocalOrientation: flag = true + isUniformScale: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 1.001, 1, 1 } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_P_Wing_Mask.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 2 + } + emitterName: string = "HologramAdd3" + IsEmitterSpace: flag = true + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + primitive: pointer = VfxPrimitiveAttachedMesh { + mMesh: embed = VfxMeshDefinitionData { + mSubmeshesToDraw: list[hash] = { "Wings" } + mLockMeshToAttachment: bool = true + } + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.919997, 0.7600061, 0.4899977, 0.2500038 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.05, 0.8, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = -95 + uvParallaxScale: f32 = 0.00075 + 0xcb13aff1: f32 = -4 + disableBackfaceCull: bool = true + particleIsLocalOrientation: flag = true + isUniformScale: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 1.001, 1, 1 } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_P_Wing_Mask.Zaahen.tex" + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Yasuo_Skin57_3026_Items_Noise_02.Zaahen.tex" + birthUvScrollRateMult: embed = ValueVector2 { + constantValue: vec2 = { 0.5, 0 } + } + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 1 + } + emitterName: string = "Dlack_avatar" + importance: u8 = 3 + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + primitive: pointer = VfxPrimitiveAttachedMesh { + mMesh: embed = VfxMeshDefinitionData { + mSubmeshesToDraw: list[hash] = { "BODY", "Wings", "weapon" } + mLockMeshToAttachment: bool = true + } + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.23294424, 0.070405126, 0.070405126, 0.42352942 } + } + pass: i16 = -500 + 0xcb13aff1: f32 = -1 + disableBackfaceCull: bool = true + particleIsLocalOrientation: flag = true + isUniformScale: flag = true + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/color-hold.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 2 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = -1 + } + isSingleParticle: flag = true + emitterName: string = "Fresnel" + importance: u8 = 5 + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 10, 0, 10 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 10, 0, 10 } } + } + } + Linger: pointer = VfxLingerDefinitionData { + UseSeparateLingerColor: flag = true + SeparateLingerColor: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0.5, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + } + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + primitive: pointer = VfxPrimitiveAttachedMesh { + mMesh: embed = VfxMeshDefinitionData { + mSubmeshesToDraw: list[hash] = { "BODY", "Wings" } + mLockMeshToAttachment: bool = true + } + } + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.92156863, 0.7607843, 0.49019608, 0.2509804 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.3, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + } + } + } + pass: i16 = 1 + reflectionDefinition: pointer = VfxReflectionDefinitionData { + reflectionMapTexture: string = "ASSETS/Shared/Particles/Generic_White_Cubemap.TFT_Set15.dds" + reflectionOpacityDirect: f32 = -1 + reflectionOpacityGlancing: f32 = 0.1 + reflectionFresnel: f32 = 0.3 + reflectionFresnelColor: vec4 = { 0.90286106, 0.8252079, 0.4269627, 1 } + fresnel: f32 = 0.1 + fresnelColor: vec4 = { 0, 0, 0, 1 } + } + particleIsLocalOrientation: flag = true + isUniformScale: flag = true + hasPostRotateOrientation: flag = true + isRandomStartFrame: flag = true + isRotationEnabled: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 0, 180, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 1.002, 1, 1 } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Base_SmokeErode.Zaahen.tex" + numFrames: u16 = 4 + birthUvScrollRate: embed = ValueVector2 { + constantValue: vec2 = { 0.4, 0.2 } + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = -1 + } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "AVATAR" + importance: u8 = 3 + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + primitive: pointer = VfxPrimitiveAttachedMesh { + mMesh: embed = VfxMeshDefinitionData { + mSubmeshesToDraw: list[hash] = { "Wings", "BODY" } + mLockMeshToAttachment: bool = true + } + } + blendMode: u8 = 1 + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 1 } + values: list[vec4] = { + { 1, 0.78039217, 0.5803922, 1 } + { 1, 0.78039217, 0.5803922, 1 } + { 1, 0.78039217, 0.5803922, 1 } + } + } + } + pass: i16 = -10 + 0xcb13aff1: f32 = 50 + particleIsLocalOrientation: flag = true + isUniformScale: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 1.02, 1, 1 } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/color-hold.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.3 + } + lifetime: option[f32] = { 5 } + isSingleParticle: flag = true + emitterName: string = "flash_distrot" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + FlexShapeDefinition: pointer = VfxFlexShapeDefinitionData { + scaleBirthScaleByBoundObjectSize: f32 = 0.005 + } + particleColorTexture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Darius_color-rampdown32_03.Zaahen.tex" + blendMode: u8 = 1 + pass: i16 = 100 + meshRenderFlags: u8 = 0 + distortionDefinition: pointer = VfxDistortionDefinitionData { + distortion: f32 = 0.05 + normalMapTexture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Darius_distort-pinch.Zaahen.tex" + } + miscRenderFlags: u8 = 1 + isUniformScale: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 300, 300, 300 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0, 0.4, 0.6, 1 } + values: list[vec3] = { + { 0, 0, 0 } + { 0.7, 0.7, 0.7 } + { 0.9, 0.9, 0.9 } + { 1, 1, 1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/color-hold.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 7 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.6 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1.2 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 0.6 } + } + } + particleLinger: option[f32] = { 1 } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "Energy_Flash" + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 10, 20, 10 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.1, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 10, 20, 10 } } + } + } + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + SpawnShape: pointer = VfxShapeLegacy { + emitOffset: embed = ValueVector3 { + constantValue: vec3 = { 20, -5, 0 } + } + emitRotationAngles: list[embed] = { + ValueFloat { + constantValue: f32 = 1 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 1 } + } + } + } + emitRotationAxes: list[vec3] = { { 0, 1.0000001, 0 } } + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 100, 0 } + } + FlexShapeDefinition: pointer = VfxFlexShapeDefinitionData { + scaleBirthScaleByBoundObjectSize: f32 = 0.005 + scaleEmitOffsetByBoundObjectSize: f32 = 0.005 + } + primitive: pointer = VfxPrimitiveArbitraryQuad { } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 0.78039217, 0.5803922, 0.5411765 } + dynamics: pointer = VfxAnimatedColorVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec4] = { { 1, 0.78039217, 0.5803922, 0.5411765 } } + } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = 100 + colorLookUpTypeY: u8 = 3 + softParticleParams: pointer = VfxSoftParticleDefinitionData { + deltaIn: f32 = 60 + } + isRandomStartFrame: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 0, 1, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 1, 0 } } + } + } + isLocalOrientation: flag = false + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 80, 150, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1.5 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 80, 150, 0 } } + } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.3, 1 } + values: list[vec3] = { + { 0.3, 1, 0 } + { 1, 1.8, 0 } + { 1, 3, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_P_Revive_EnergyStreak_2x2_Blend.Zaahen.tex" + numFrames: u16 = 4 + startFrame: u16 = 2 + texDiv: vec2 = { 2, 2 } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 2 + } + particleLinger: option[f32] = { 0.1 } + emitterName: string = "BlckFrame" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + SpawnShape: pointer = 0xee39916f { + emitOffset: vec3 = { 0, 1900, 0 } + } + EmitterPosition: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 0, 0 } } + } + } + primitive: pointer = VfxPrimitiveRay { } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 0.78039217, 0.5803922, 0.03137255 } + } + Color: embed = ValueColor { + constantValue: vec4 = { 1, 0.93000686, 0.68999773, 1 } + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.2, 0.8, 1 } + values: list[vec4] = { + { 1, 0.93000686, 0.68999773, 0 } + { 1, 0.93000686, 0.68999773, 1 } + { 1, 0.93000686, 0.68999773, 1 } + { 1, 0.93000686, 0.68999773, 0 } + } + } + } + pass: i16 = 12 + alphaRef: u8 = 0 + softParticleParams: pointer = VfxSoftParticleDefinitionData { + beginIn: f32 = 10 + deltaIn: f32 = 50 + } + isDirectionOriented: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 0, 0 } + } + directionVelocityScale: f32 = 0.01 + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 400, 1550, 500 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 0.5, 1, 1 } + { 0.8, 1, 1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Wave_Texture.Zaahen.tex" + uvRotation: embed = ValueFloat { + constantValue: f32 = 180 + } + textureMult: pointer = VfxTextureMultDefinitionData { } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 2 + } + particleLinger: option[f32] = { 0.1 } + emitterName: string = "Drop" + birthOrbitalVelocity: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.5 } + values: list[vec3] = { + { 0, 0, 0 } + { 0, 0, 0 } + } + } + } + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + SpawnShape: pointer = 0xee39916f { + emitOffset: vec3 = { 0, 950, 0 } + } + EmitterPosition: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 0, 0 } } + } + } + primitive: pointer = VfxPrimitiveRay { } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 0.80999464, 0.42999923, 0.050003815 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.2, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = 10 + alphaRef: u8 = 0 + softParticleParams: pointer = VfxSoftParticleDefinitionData { + beginIn: f32 = 10 + deltaIn: f32 = 50 + } + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 0, 0 } + } + directionVelocityScale: f32 = 0.01 + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 400, 1300, 500 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 0.3, 1, 0 } + { 1, 1, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_E_Nova_Mult.Zaahen.tex" + birthUvScrollRate: embed = ValueVector2 { + constantValue: vec2 = { 0, -0.5 } + } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Wave_Texture.Zaahen.tex" + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 2 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.15 + } + lifetime: option[f32] = { 0.05 } + isSingleParticle: flag = true + emitterLinger: option[f32] = { 0.1 } + emitterName: string = "Pillar" + importance: u8 = 3 + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + SpawnShape: pointer = VfxShapeLegacy { + emitOffset: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 0, 0 } } + } + } + emitRotationAngles: list[embed] = { + ValueFloat { } + ValueFloat { } + } + emitRotationAxes: list[vec3] = { + { 0, 0, 0 } + { 0, 0, 0 } + } + } + EmitterPosition: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 0, 0 } } + } + } + primitive: pointer = VfxPrimitiveRay { } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 0.77999544, 0.5799954, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0.1, 0.25, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = 55 + softParticleParams: pointer = VfxSoftParticleDefinitionData { + deltaIn: f32 = 40 + } + miscRenderFlags: u8 = 1 + isGroundLayer: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { -90, 0, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 80, 600, 1 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.11140352, 0.21666665, 1 } + values: list[vec3] = { + { 9, 0, 0 } + { 7.779141, 1.2030061, -47.3865 } + { 1.785276, 2.049, -80.06135 } + { 0, 2.5, -100 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_BA_GlowStar_02_Blend.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 2 + } + particleLinger: option[f32] = { 0.1 } + emitterName: string = "Lightning_blend" + importance: u8 = 3 + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + SpawnShape: pointer = 0xee39916f { + emitOffset: vec3 = { 0, 100, 0 } + } + primitive: pointer = VfxPrimitiveRay { } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 0.77999544, 0.5799954, 0.050003815 } + dynamics: pointer = VfxAnimatedColorVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec4] = { { 1, 0.77999544, 0.5799954, 0.050003815 } } + } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.15, 0.8, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = -999 + alphaRef: u8 = 0 + disableBackfaceCull: bool = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { -90, 0, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 220, 1400, 1 } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Diana_Skin27_Particles_1_435.Zaahen.tex" + uvMode: u8 = 2 + texAddressModeBase: u8 = 2 + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 12 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.5 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 0.9, 1 } + keyValues: list[f32] = { 0.2, 1, 1.5 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 0.5 } + } + } + particleLinger: option[f32] = { 1 } + lifetime: option[f32] = { 0.1 } + isSingleParticle: flag = true + emitterName: string = "Sparkles" + birthOrbitalVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, -3, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, -3, 0 } } + } + } + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, 2000, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.2, 1.1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 2000, 0 } } + } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 8, 2, 8 } + } + birthAcceleration: embed = ValueVector3 { + constantValue: vec3 = { 100, 0, 100 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 100, 0, 100 } } + } + } + worldAcceleration: embed = IntegratedValueVector3 { + constantValue: vec3 = { 0, 200, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 200, 0 } } + } + } + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 1 } + values: list[f32] = { 1, 0 } + } + } + SpawnShape: pointer = VfxShapeCylinder { + radius: f32 = 100 + } + blendMode: u8 = 4 + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 0.3, 0.6, 1 } + values: list[vec4] = { + { 0.928069, 0.8185092, 0.6716716, 0 } + { 0.84815747, 0.75295645, 0.50995654, 1 } + { 0.93354696, 0.7692073, 0.4036927, 1 } + { 0.6940261, 0.52054626, 0.23326467, 1 } + { 0.46509498, 0.34778363, 0.1963531, 0 } + } + } + } + pass: i16 = 10 + isDirectionOriented: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 1, 0, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 1, 0, 0 } } + } + } + birthRotationalVelocity0: embed = ValueVector3 { + constantValue: vec3 = { -300, 0, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 25, 50, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.3, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 1, 2 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 25, 50, 0 } } + } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 1, 1, 1 } + { 0, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_R_Sparks.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.3 + } + particleLinger: option[f32] = { 11 } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "SwirlGold" + IsEmitterSpace: flag = true + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 700, 0 } + } + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Darius_R_Swirl_Mesh.Zaahen.scb" + } + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 0.77999544, 0.5799954, 0.2500038 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 1 } + values: list[vec4] = { + { 1, 0.78039217, 0.5803922, 0 } + { 1, 0.78039217, 0.5803922, 1 } + { 0.51999694, 0.39000535, 0.10000763, 0 } + } + } + } + pass: i16 = 4 + alphaRef: u8 = 0 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.6, 1 } + values: list[f32] = { 0, 0.1, 1 } + } + } + erosionFeatherIn: f32 = 0.3 + erosionFeatherOut: f32 = 0.2 + erosionSliceWidth: f32 = 1 + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Emote_Einstein_01_mult.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + disableBackfaceCull: bool = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, 180 } + } + birthRotationalVelocity0: embed = ValueVector3 { + constantValue: vec3 = { 0, 20, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.13, 0.2, 0.3, 0.4 } + values: list[vec3] = { + { 0, 30, 0 } + { 0, 100, 0 } + { 0, 24.237288, 0 } + { 0, 6.6101694, 0 } + { 0, 0, 0 } + } + } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 1, 6, 1 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.3, 1 } + values: list[vec3] = { + { 1, 1, 1 } + { 2.5, 1, 2.5 } + { 1, 1, 1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/common_color-bellcurve.Zaahen.tex" + uvMode: u8 = 2 + texAddressModeBase: u8 = 2 + uvRotation: embed = ValueFloat { + constantValue: f32 = 90 + } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Darius_Skin54_R_Swirl.Zaahen.tex" + texAddressModeMult: u8 = 2 + uvScrollClampMult: flag = true + ParticleIntegratedUvScrollMult: embed = IntegratedValueVector2 { + constantValue: vec2 = { 0, 4 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 0.8 } + values: list[vec2] = { + { 0, 4 } + { 0, 0.2 } + } + } + } + birthUVOffsetMult: embed = ValueVector2 { + constantValue: vec2 = { 0, -0.75 } + } + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 2 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.3 + } + particleLinger: option[f32] = { 11 } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "SwirlGold1" + IsEmitterSpace: flag = true + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 700, 0 } + } + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Darius_R_Swirl_Mesh.Zaahen.scb" + } + } + blendMode: u8 = 5 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 0.77999544, 0.5799954, 0.2500038 } + } + Color: embed = ValueColor { + constantValue: vec4 = { 0.39674982, 0.39674982, 0.39674982, 1 } + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 1 } + values: list[vec4] = { + { 0.39674982, 0.30962044, 0.23027049, 0 } + { 0.39674982, 0.30962044, 0.23027049, 1 } + { 0, 0, 0, 0 } + } + } + } + alphaRef: u8 = 0 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.6, 1 } + values: list[f32] = { 0, 0.1, 1 } + } + } + erosionFeatherIn: f32 = 0.3 + erosionFeatherOut: f32 = 0.2 + erosionSliceWidth: f32 = 1 + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Emote_Einstein_01_mult.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + disableBackfaceCull: bool = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, 180 } + } + birthRotationalVelocity0: embed = ValueVector3 { + constantValue: vec3 = { 0, 20, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.13, 0.2, 0.3, 0.4 } + values: list[vec3] = { + { 0, 30, 0 } + { 0, 100, 0 } + { 0, 24.237288, 0 } + { 0, 6.6101694, 0 } + { 0, 0, 0 } + } + } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 1, 6, 1 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.3, 1 } + values: list[vec3] = { + { 1, 1, 1 } + { 2.5, 1, 2.5 } + { 1, 1, 1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/common_color-bellcurve.Zaahen.tex" + uvMode: u8 = 2 + texAddressModeBase: u8 = 2 + uvRotation: embed = ValueFloat { + constantValue: f32 = 90 + } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Darius_Skin54_R_Swirl.Zaahen.tex" + texAddressModeMult: u8 = 2 + uvScrollClampMult: flag = true + ParticleIntegratedUvScrollMult: embed = IntegratedValueVector2 { + constantValue: vec2 = { 0, 4 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 0.8 } + values: list[vec2] = { + { 0, 4 } + { 0, 0.2 } + } + } + } + birthUVOffsetMult: embed = ValueVector2 { + constantValue: vec2 = { 0, -0.75 } + } + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 2 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.4 + } + lifetime: option[f32] = { 1.1 } + isSingleParticle: flag = true + emitterName: string = "CenterOrb_Out" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 2, 0 } + } + primitive: pointer = VfxPrimitiveArbitraryQuad { } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.919997, 0.7600061, 0.4899977, 0.2500038 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0.0021436226, 0.20134228, 0.8074857, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 0.9809852 } + { 1, 1, 1, 0.095221676 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = 102 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0.1, 1 } + values: list[f32] = { 0, 1 } + } + } + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/frost_cloud_01.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + isUniformScale: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 360, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 90, 360, 0 } } + } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 70, 100, 100 } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 1, 2.3, 2 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.1612886, 0.26015142, 0.3274164, 0.41496012, 0.93728137 } + values: list[vec3] = { + { 0, 0, 0 } + { 1.9806312, 4.555452, 3.9612625 } + { 2.6425319, 6.0651627, 5.2740545 } + { 2.8048756, 6.3952384, 5.561077 } + { 2.960181, 6.7721047, 5.888787 } + { 2.9795203, 6.8528967, 5.9590406 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Swain_Base_Z_HollowOrb.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 2 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.4 + } + lifetime: option[f32] = { 1.1 } + isSingleParticle: flag = true + emitterName: string = "CenterOrb_Out1" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 2, 0 } + } + primitive: pointer = VfxPrimitiveArbitraryQuad { } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.919997, 0.7600061, 0.4899977, 0.2500038 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0.0021436226, 0.20134228, 0.79999906, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 0.9809852 } + { 1, 1, 1, 0.119852215 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = 103 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0.1, 1 } + values: list[f32] = { 0, 1 } + } + } + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/frost_cloud_01.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + isUniformScale: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 360, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 90, 360, 0 } } + } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 70, 100, 100 } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 1, 2.3, 2 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.1612886, 0.26015142, 0.3274164, 0.41496012, 0.93728137 } + values: list[vec3] = { + { 0, 0, 0 } + { 1.9806312, 4.555452, 3.9612625 } + { 2.6425319, 6.0651627, 5.2740545 } + { 2.8048756, 6.3952384, 5.561077 } + { 2.960181, 6.7721047, 5.888787 } + { 2.9795203, 6.8528967, 5.9590406 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Swain_Base_Z_HollowOrb.Zaahen.tex" + } + } + particleName: string = "Zaahen_Base_P_MaxStacks_Will_Revive" + particlePath: string = "Characters/Zaahen/Skins/Skin0/Particles/Zaahen_Base_P_MaxStacks_Will_Revive" + soundPersistentDefault: string = "Play_sfx_Zaahen_ZaahenP_loop_revive_ready" + flags: u16 = 1236 + } + "Characters/Zaahen/Skins/Skin0/Particles/Zaahen_Base_R_AoE" = VfxSystemDefinitionData { + complexEmitterDefinitionData: list[pointer] = { + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.33 + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 1.8 + } + particleLinger: option[f32] = { 12.25 } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "ground_decal" + SpawnShape: pointer = 0xee39916f { + emitOffset: vec3 = { 0, 3, 0 } + } + primitive: pointer = VfxPrimitiveArbitraryQuad { } + particleColorTexture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Garen_Skin46_R_Ground3.Zaahen.tex" + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 1, 1, 0.7300069 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.5, 0.75, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 0.017730983, 0.017730983, 0.017730983, 0 } + } + } + } + pass: i16 = 10 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.2775622, 1 } + values: list[f32] = { 0, 0.44794258, 1 } + } + } + erosionFeatherOut: f32 = 0.3 + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/zaahen_decal_mask.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + miscRenderFlags: u8 = 1 + isUniformScale: flag = true + isGroundLayer: flag = true + useNavmeshMask: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 80, 120 } + } + isLocalOrientation: flag = false + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 490, 490, 490 } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Garen_Skin46_R_Ground2.Zaahen.tex" + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.33 + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 1.3 + } + particleLinger: option[f32] = { 12.25 } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "ground_decal1" + SpawnShape: pointer = 0xee39916f { + emitOffset: vec3 = { 0, 3, 0 } + } + primitive: pointer = VfxPrimitiveArbitraryQuad { } + particleColorTexture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/alphaslice_mesh.Zaahen.tex" + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 0.89050126, 0.7492485, 0.78039217 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0.01, 0.43437386, 0.71664244, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0.90134615 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = 600 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.21448275, 0.41907442, 1 } + values: list[f32] = { 0, 0.02442623, 0.20442623, 1 } + } + } + erosionFeatherOut: f32 = 0.3 + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Yasuo_Skin57_3026_Items_Noise_02.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + miscRenderFlags: u8 = 1 + isUniformScale: flag = true + isFollowingTerrain: flag = true + isGroundLayer: flag = true + useNavmeshMask: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 80, 120 } + } + isLocalOrientation: flag = false + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 490, 490, 490 } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Garen_Skin46_R_Ground3.Zaahen.tex" + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.33 + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 1.8 + } + particleLinger: option[f32] = { 12.25 } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "ground_decal2" + importance: u8 = 3 + SpawnShape: pointer = 0xee39916f { + emitOffset: vec3 = { 0, 3, 0 } + } + primitive: pointer = VfxPrimitiveArbitraryQuad { } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.35124743, 0.35124743, 0.35124743, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.4965035, 0.8426573, 1 } + values: list[vec4] = { + { 0.85490197, 0.85490197, 0.85490197, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.25089553, 1 } + values: list[f32] = { 0.14832535, 0.4774641, 1 } + } + } + erosionFeatherOut: f32 = 0.3 + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/zaahen_decal_mask.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + miscRenderFlags: u8 = 1 + isUniformScale: flag = true + isGroundLayer: flag = true + useNavmeshMask: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 80, 120 } + } + isLocalOrientation: flag = false + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 490, 490, 490 } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Garen_Skin46_R_Ground2.Zaahen.tex" + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.33 + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 1.3 + } + particleLinger: option[f32] = { 12.25 } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "SpikeGroundLine" + importance: u8 = 3 + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { -10, 0, -50 } + } + primitive: pointer = VfxPrimitiveArbitraryQuad { } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 0.7600061, 0.5600061, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.2, 0.6, 0.9 } + values: list[vec4] = { + { 0.9159533, 0.906981, 0.61837184, 1 } + { 1, 0.73333335, 0.3647059, 1 } + { 0.80224305, 0.08323796, 0.08323796, 1 } + { 0, 0, 0, 0 } + } + } + } + pass: i16 = 590 + alphaRef: u8 = 0 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.17, 0.75 } + values: list[f32] = { 0, 0, 1 } + } + } + erosionFeatherOut: f32 = 0.3 + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Emote_ground_crack_04.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + disableBackfaceCull: bool = true + miscRenderFlags: u8 = 1 + isFollowingTerrain: flag = true + isGroundLayer: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 90, 0 } + } + isLocalOrientation: flag = false + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 100, 110, 0 } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 1.06, 1.06, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.03, 0.85, 1 } + values: list[vec3] = { + { 1.06, 0, 0 } + { 1.06, 1.06, 1 } + { 1.06, 0.79499996, 1 } + { 1.06, 0.53, 1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Emote_ground_crack_04.Zaahen.tex" + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.33 + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 1.8 + } + particleLinger: option[f32] = { 12.25 } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "SpikeGroundLine1" + importance: u8 = 3 + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { -10, 0, -50 } + } + primitive: pointer = VfxPrimitiveArbitraryQuad { } + blendMode: u8 = 1 + Color: embed = ValueColor { + constantValue: vec4 = { 0.25490198, 0.25490198, 0.27450982, 1 } + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.2, 0.72, 1 } + values: list[vec4] = { + { 0.25490198, 0.25490198, 0.27450982, 1 } + { 0.25490198, 0.25490198, 0.27450982, 1 } + { 0.19882238, 0.19882238, 0.2141164, 0.9799954 } + { 0.10795849, 0.10795849, 0.11626298, 0 } + } + } + } + pass: i16 = -10 + alphaRef: u8 = 0 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.16791044, 1 } + values: list[f32] = { 0, 0, 1 } + } + } + erosionFeatherOut: f32 = 0.3 + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Cassiopeia_Skin38_color_bellcurve32.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + disableBackfaceCull: bool = true + miscRenderFlags: u8 = 1 + isFollowingTerrain: flag = true + isGroundLayer: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 90, 0 } + } + isLocalOrientation: flag = false + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 100, 110, 0 } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 1.06, 1.06, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.03, 0.85, 1 } + values: list[vec3] = { + { 1.06, 0, 0 } + { 1.06, 1.06, 1 } + { 1.06, 0.79499996, 1 } + { 1.06, 0.53, 1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Emote_ground_crack_03.Zaahen.tex" + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.4 + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 1.75 + } + particleLinger: option[f32] = { 1 } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "ground_decal3" + SpawnShape: pointer = 0xee39916f { + emitOffset: vec3 = { 0, 3, 0 } + } + primitive: pointer = VfxPrimitiveArbitraryQuad { } + particleColorTexture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/alphaslice_mesh.Zaahen.tex" + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.34229037, 0.2569009, 0.2569009, 0.8901961 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.2, 0.62704176, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 0.3529412, 0.3529412, 0.3529412, 0 } + } + } + } + pass: i16 = -500 + alphaRef: u8 = 0 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.48708922, 1 } + values: list[f32] = { 0, 0, 1 } + } + } + erosionFeatherOut: f32 = 0.3 + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/alphaslice_mesh.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + miscRenderFlags: u8 = 1 + isUniformScale: flag = true + isGroundLayer: flag = true + useNavmeshMask: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 0, 120 } + } + isLocalOrientation: flag = false + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 650, 350, 350 } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Garen_Skin33_E_Wall_Erosion.Zaahen.tex" + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Aura_Self.Zaahen.tex" + } + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.08 + rate: embed = ValueFloat { + constantValue: f32 = 60 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 1.35 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.1, 1 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 1.35 } + } + } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "sparks_01" + birthOrbitalVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0.1, 0.2, 0.2 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -2, 2 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0, 0.5 } + values: list[vec3] = { + { 0, 0.2, 0.2 } + { 0.14358975, 0, 0 } + } + } + } + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 3000, 400, 1900 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 3000, 400, 1900 } + { 0, 0, 0 } + } + } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 6, 2, 6 } + } + birthAcceleration: embed = ValueVector3 { + constantValue: vec3 = { 250, 50, 750 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -2, 2 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 250, 50, 750 } } + } + } + worldAcceleration: embed = IntegratedValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -2, 2 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 0, 0 } } + } + } + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + SpawnShape: pointer = VfxShapeCylinder { + flags: u8 = 1 + radius: f32 = 200 + height: f32 = 5 + } + blendMode: u8 = 4 + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0.003937008, 0.023544546, 0.87715983, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 0, 0, 1 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = 600 + colorLookUpScales: vec2 = { 1, 0.8 } + colorLookUpOffsets: vec2 = { 0, 0.3 } + miscRenderFlags: u8 = 1 + isUniformScale: flag = true + isRandomStartFrame: flag = true + isLocalOrientation: flag = false + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 2.5, 40, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 1, 5 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 2.5, 40, 1 } } + } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 1, 1.25, 1.25 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 1, 2 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 1, 2 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 1, 2 } + } + } + times: list[f32] = { 0, 0.20474903, 1 } + values: list[vec3] = { + { 0, 1.25, 0 } + { 1, 0.9940637, 0 } + { 0, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_R_Sparks.Zaahen.tex" + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.1 + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.25 + } + particleLinger: option[f32] = { 1 } + lifetime: option[f32] = { 0.5 } + isSingleParticle: flag = true + emitterLinger: option[f32] = { 1 } + emitterName: string = "Distort_Impact" + importance: u8 = 1 + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + particleColorTexture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Morgana_Base_R_Mark_distort_RGBA.Zaahen.tex" + blendMode: u8 = 1 + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1391833, 0.43752113, 0.7519661, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0.5597015 } + { 1, 1, 1, 0.13432837 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = 3500 + distortionDefinition: pointer = VfxDistortionDefinitionData { + distortion: f32 = 0.01 + normalMapTexture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/distort-soft-shockwave.Zaahen.tex" + } + miscRenderFlags: u8 = 1 + isUniformScale: flag = true + useNavmeshMask: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 0, 0 } + } + isLocalOrientation: flag = false + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 560, 500, 500 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 0.53300864, 0.7309456, 0.27793697 } + { 1.7, 1.7, 0.5 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/color-hold.Zaahen.tex" + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.13 + rate: embed = ValueFloat { + constantValue: f32 = 2 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.43 + } + particleLinger: option[f32] = { 1 } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "Wave_Pattern4" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 3, 0 } + } + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/fireball.Zaahen.SCB" + } + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 0.7300069, 0.42000458, 0.5000076 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.2, 0.597561, 0.8599061, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 0.7889067, 0.7889067, 0.7889067, 1 } + { 0.3063554, 0.3063554, 0.3063554, 0 } + { 0, 0, 0, 0 } + } + } + } + pass: i16 = 1200 + colorLookUpScales: vec2 = { 1, 0 } + alphaRef: u8 = 0 + disableBackfaceCull: bool = true + miscRenderFlags: u8 = 1 + isGroundLayer: flag = true + useNavmeshMask: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 320, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 0 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 90, 320, 0 } } + } + } + isLocalOrientation: flag = false + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 56, 56, 0.5 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.06419929, 0.28144127, 0.99288255 } + values: list[vec3] = { + { 0, 0, 0 } + { 0.9014992, 0.89977586, 0.64 } + { 1.0905261, 1.0905261, 0.78708136 } + { 1.1433333, 1.1433333, 1.1433333 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Ground_Splash_Over.Zaahen.tex" + birthUvScrollRate: embed = ValueVector2 { + constantValue: vec2 = { 2.7, 0 } + } + birthUVOffset: embed = ValueVector2 { + constantValue: vec2 = { 1, 1 } + } + texDiv: vec2 = { 1.05, 0.5 } + particleUVScrollRate: embed = IntegratedValueVector2 { + constantValue: vec2 = { -4.5, 0 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 0.5, 1 } + values: list[vec2] = { + { -9, 0 } + { -4.5, 0 } + { -0, 0 } + } + } + } + uvScale: embed = ValueVector2 { + constantValue: vec2 = { 2.6, 2.5 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 0.3 } + values: list[vec2] = { + { 2.6, 2.5 } + { 1.3, 2.5 } + } + } + } + uvRotation: embed = ValueFloat { + constantValue: f32 = 90 + } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_R_Screen_Flames_Soft.Zaahen.tex" + birthUVOffsetMult: embed = ValueVector2 { + constantValue: vec2 = { 1, 1 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec2] = { { 1, 1 } } + } + } + } + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.14 + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.07 + } + lifetime: option[f32] = { 0.5 } + isSingleParticle: flag = true + emitterName: string = "flash37" + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 15, 15, 15 } + } + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.57328147, 0.090394445, 0, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.011666667, 0.6705989, 0.9009619, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 0.5316396, 0.5316396, 0.5316396, 0.5396532 } + { 0.11372549, 0.10273899, 0.101960786, 0 } + } + } + } + pass: i16 = 4000 + alphaRef: u8 = 0 + miscRenderFlags: u8 = 1 + particleIsLocalOrientation: flag = true + isUniformScale: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 270, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 1000, 450, 0 } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 1, 1.5, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.08219178, 0.4545662, 1 } + values: list[vec3] = { + { 0, 0, 0 } + { 0.91905373, 1.3785806, 0.91905373 } + { 1.258491, 1.8781035, 1.252069 } + { 1.5, 2.25, 1.5 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Aura_Self.Zaahen.tex" + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.13 + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.43 + } + particleLinger: option[f32] = { 1 } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "Wave_Pattern9" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 2, 0 } + } + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/fireball.Zaahen.SCB" + } + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 0.0070038913, 0, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.67875445, 0.9964413 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 0.33301264, 0.31882143, 0.31882143, 1 } + { 0.020833334, 0, 0, 0 } + } + } + } + pass: i16 = 1000 + colorLookUpScales: vec2 = { 1, 0 } + alphaRef: u8 = 0 + disableBackfaceCull: bool = true + miscRenderFlags: u8 = 1 + isGroundLayer: flag = true + useNavmeshMask: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 320, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 0 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 90, 320, 0 } } + } + } + isLocalOrientation: flag = false + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 56, 56, 0.5 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.06419929, 0.28144127, 0.99288255 } + values: list[vec3] = { + { 0, 0, 0 } + { 0.9014992, 0.89977586, 0.64 } + { 1.0905261, 1.0905261, 0.78708136 } + { 1.1433333, 1.1433333, 1.1433333 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Ground_Splash_Over.Zaahen.tex" + birthUvScrollRate: embed = ValueVector2 { + constantValue: vec2 = { 2.7, 0 } + } + birthUVOffset: embed = ValueVector2 { + constantValue: vec2 = { 1, 1 } + } + texDiv: vec2 = { 1.05, 0.5 } + particleUVScrollRate: embed = IntegratedValueVector2 { + constantValue: vec2 = { -4.5, 0 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 0.5, 1 } + values: list[vec2] = { + { -9, 0 } + { -4.5, 0 } + { -0, 0 } + } + } + } + uvScale: embed = ValueVector2 { + constantValue: vec2 = { 2.6, 2.5 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 0.3 } + values: list[vec2] = { + { 2.6, 2.5 } + { 1.3, 2.5 } + } + } + } + uvRotation: embed = ValueFloat { + constantValue: f32 = 90 + } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_R_Screen_Flames_Soft.Zaahen.tex" + birthUVOffsetMult: embed = ValueVector2 { + constantValue: vec2 = { 1, 1 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec2] = { { 1, 1 } } + } + } + } + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.15 + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.6 + } + particleLinger: option[f32] = { } + lifetime: option[f32] = { 0.35 } + emitterLinger: option[f32] = { } + emitterName: string = "EdgeBlnd_Mist" + importance: u8 = 3 + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, 2200, 0 } + } + birthAcceleration: embed = ValueVector3 { + constantValue: vec3 = { 0, -1000, 0 } + } + velocity: embed = ValueVector3 { + constantValue: vec3 = { 0, -1800, 0 } + } + drag: embed = ValueVector3 { + constantValue: vec3 = { 0, 1, 0 } + } + Linger: pointer = VfxLingerDefinitionData { + UseLingerScale: flag = true + LingerScale: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { -0.0014947683, 0.9961555 } + values: list[vec3] = { + { 1.004386, 0, 0 } + { 1.0937816, 0, 0 } + } + } + } + UseSeparateLingerColor: flag = true + SeparateLingerColor: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0.10654686, 0.97175866 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 0.48282596, 0.48282596, 0.48282596, 0 } + } + } + } + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, -100, 0 } + } + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_R_Stormwall_03.Zaahen.scb" + } + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.38057527, 0.008682383, 0.011276417, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.33914423, 0.6680762, 1 } + values: list[vec4] = { + { 0.05, 1, 1, 1 } + { 1, 1, 1, 1 } + { 0.4, 0, 0, 0.8778846 } + { 0, 0, 0, 0 } + } + } + } + pass: i16 = 100 + softParticleParams: pointer = VfxSoftParticleDefinitionData { + beginIn: f32 = 5 + deltaIn: f32 = 20 + 0x3bf176bc: u8 = 2 + } + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + constantValue: f32 = 0.5 + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0.04767519, 0.2171411, 0.40318522, 0.5562851, 0.7991207, 1 } + values: list[f32] = { 0.20535898, 0.14878283, 0.1572603, 0.21412292, 0.3205874, 0.4268455 } + } + } + erosionFeatherIn: f32 = 0.05 + erosionFeatherOut: f32 = 0.3 + erosionSliceWidth: f32 = 1 + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Shyvana_Skin17_Q_Swipe_Mult_01.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + erosionMapAddressMode: u8 = 0 + } + disableBackfaceCull: bool = true + miscRenderFlags: u8 = 1 + isGroundLayer: flag = true + TextureFlipU: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 0, 100, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 0 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 100, 0 } } + } + } + rotation0: embed = IntegratedValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { -0.007677543, 0.22022805, 1 } + values: list[vec3] = { + { 0, 0, 0 } + { 0, 0, 0 } + { 0, 0, 0 } + } + } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 33, 20, 33 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.23, 0.45271185, 0.7198305, 1 } + values: list[vec3] = { + { 1.2036499, 0.45, 1.2036499 } + { 1.2319286, 0.8690396, 1.2319286 } + { 1.2558228, 0.95, 1.2558228 } + { 1.2855722, 0.9813249, 1.2855722 } + { 1.3172138, 0.99264985, 1.3172138 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Ground_Splash.Zaahen.tex" + texDiv: vec2 = { 0.5, 1 } + particleUVScrollRate: embed = IntegratedValueVector2 { + constantValue: vec2 = { -0.5, 0.3 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec2] = { + { -0.5, 0.3 } + { -0, 0 } + } + } + } + uvScale: embed = ValueVector2 { + constantValue: vec2 = { 3, 1 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0.019112809, 0.2533147, 0.43180287, 0.65245116, 0.99424183 } + values: list[vec2] = { + { 2.9842932, 0.9947644 } + { 2.9842932, 0.90575916 } + { 2.9842932, 0.79534554 } + { 2.9842932, 0.6426907 } + { 2.9842932, 0.5741619 } + } + } + } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Wave.Zaahen.tex" + uvScaleMult: embed = ValueVector2 { + constantValue: vec2 = { 2, 0.9 } + } + } + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.15 + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.6 + } + particleLinger: option[f32] = { } + lifetime: option[f32] = { 0.35 } + emitterLinger: option[f32] = { } + emitterName: string = "EdgeBlnd_Mist1" + importance: u8 = 3 + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, 2200, 0 } + } + birthAcceleration: embed = ValueVector3 { + constantValue: vec3 = { 0, -1000, 0 } + } + velocity: embed = ValueVector3 { + constantValue: vec3 = { 0, -1800, 0 } + } + drag: embed = ValueVector3 { + constantValue: vec3 = { 0, 1, 0 } + } + Linger: pointer = VfxLingerDefinitionData { + UseLingerScale: flag = true + LingerScale: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { -0.0014947683, 0.9961555 } + values: list[vec3] = { + { 1.004386, 0, 0 } + { 1.0937816, 0, 0 } + } + } + } + UseSeparateLingerColor: flag = true + SeparateLingerColor: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0.10654686, 0.97175866 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 0.48282596, 0.48282596, 0.48282596, 0 } + } + } + } + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, -100, 0 } + } + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_R_Stormwall_03.Zaahen.scb" + } + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.66329443, 0.061692227, 0, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.33297423, 0.63232964, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 0.5000076 } + { 1, 0.48000306, 0.48000306, 0.14000152 } + { 0, 0, 0, 0 } + } + } + } + pass: i16 = 100 + softParticleParams: pointer = VfxSoftParticleDefinitionData { + beginIn: f32 = 5 + deltaIn: f32 = 20 + } + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + constantValue: f32 = 0.5 + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0.04767519, 0.2171411, 0.40318522, 0.5562851, 0.7991207, 1 } + values: list[f32] = { 0.20535898, 0.14878283, 0.1572603, 0.21412292, 0.3205874, 0.4268455 } + } + } + erosionFeatherIn: f32 = 0.05 + erosionFeatherOut: f32 = 0.3 + erosionSliceWidth: f32 = 1 + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Shyvana_Skin17_Q_Swipe_Mult_01.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + erosionMapAddressMode: u8 = 0 + } + disableBackfaceCull: bool = true + miscRenderFlags: u8 = 1 + isGroundLayer: flag = true + TextureFlipU: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 0, 100, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 0 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 100, 0 } } + } + } + rotation0: embed = IntegratedValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { -0.007677543, 0.22022805, 1 } + values: list[vec3] = { + { 0, 0, 0 } + { 0, 0, 0 } + { 0, 0, 0 } + } + } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 33, 20, 33 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.23, 0.45271185, 0.7198305, 1 } + values: list[vec3] = { + { 1.2036499, 0.45, 1.2036499 } + { 1.2319286, 0.8690396, 1.2319286 } + { 1.2558228, 0.95, 1.2558228 } + { 1.2855722, 0.9813249, 1.2855722 } + { 1.3172138, 0.99264985, 1.3172138 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Ground_Splash.Zaahen.tex" + texDiv: vec2 = { 0.5, 1 } + particleUVScrollRate: embed = IntegratedValueVector2 { + constantValue: vec2 = { -0.5, 0.3 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec2] = { + { -0.5, 0.3 } + { -0, 0 } + } + } + } + uvScale: embed = ValueVector2 { + constantValue: vec2 = { 3, 1 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0.019112809, 0.2533147, 0.43180287, 0.65245116, 0.99424183 } + values: list[vec2] = { + { 2.9842932, 0.9947644 } + { 2.9842932, 0.90575916 } + { 2.9842932, 0.79534554 } + { 2.9842932, 0.6426907 } + { 2.9842932, 0.5741619 } + } + } + } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Wave.Zaahen.tex" + uvScaleMult: embed = ValueVector2 { + constantValue: vec2 = { 2, 0.9 } + } + } + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.13 + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.12 + } + particleLinger: option[f32] = { 2 } + lifetime: option[f32] = { 0.5 } + isSingleParticle: flag = true + emitterName: string = "flash38" + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 15, 15, 15 } + } + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 0.17149615, 0, 0.7294118 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.25, 0.5516432, 0.6889671, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 0.21145953, 0.21145953, 0.21145953, 1 } + { 0, 0, 0, 0 } + } + } + } + pass: i16 = 700 + alphaRef: u8 = 0 + miscRenderFlags: u8 = 1 + particleIsLocalOrientation: flag = true + isUniformScale: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 270, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 750, 1, 1 } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 1, 1.5, 1 } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Aura_Self.Zaahen.tex" + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.12 + rate: embed = ValueFloat { + constantValue: f32 = 35 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 1 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1.25 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 1 } + } + } + particleLinger: option[f32] = { 1 } + lifetime: option[f32] = { 0.2 } + isSingleParticle: flag = true + emitterName: string = "Trench_Smoke" + importance: u8 = 1 + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 200, 200, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.4, 1.2 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 200, 200, 0 } } + } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 5, 1, 1 } + } + velocity: embed = ValueVector3 { + constantValue: vec3 = { 0, -100, 0 } + } + drag: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 0, 0, 0 } + { 0, 0, 0 } + } + } + } + worldAcceleration: embed = IntegratedValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 0, 0 } } + } + } + SpawnShape: pointer = VfxShapeCylinder { + radius: f32 = 425 + height: f32 = 15 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 50, 0 } + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.62961775, 0.62961775, 0.62961775, 1 } + dynamics: pointer = VfxAnimatedColorVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.9, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec4] = { { 0.62961775, 0.62961775, 0.62961775, 1 } } + } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.42711863, 0.5032203, 0.86338985, 1 } + values: list[vec4] = { + { 0.98751813, 0.11386282, 0.00015259022, 1 } + { 0.49213398, 0.084809646, 0.00007693851, 1 } + { 0.4411751, 0.070015736, 0.00006671798, 0.9361538 } + { 0.2, 0, 0.000018346876, 0.033653848 } + { 0, 0, 0, 0 } + } + } + } + pass: i16 = 2000 + meshRenderFlags: u8 = 0 + colorLookUpScales: vec2 = { 0.5, 1 } + alphaRef: u8 = 0 + colorLookUpOffsets: vec2 = { 0.5, 0 } + softParticleParams: pointer = VfxSoftParticleDefinitionData { + beginIn: f32 = 10 + deltaIn: f32 = 100 + } + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + constantValue: f32 = 0.6 + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0.3, 0.34237748, 0.41254082, 0.57, 0.7161887, 0.84127045, 1 } + values: list[f32] = { 0, 0.03416268, 0.12312919, 0.32555026, 0.4551962, 0.5201627, 0.5470335 } + } + } + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Base_SmokeErode.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + miscRenderFlags: u8 = 1 + isDirectionOriented: flag = true + isUniformScale: flag = true + isRandomStartFrame: flag = true + isGroundLayer: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 0, 0 } + } + directionVelocityMinScale: f32 = 0 + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 50, 75, 100 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 2 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 2 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 50, 75, 100 } } + } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.06469484, 1 } + values: list[vec3] = { + { 1, 0.5, 0.5 } + { 2.476923, 1.3653847, 1.3653847 } + { 3.0576923, 1.7, 1.5 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_R_Smoke01_01.Zaahen.tex" + numFrames: u16 = 4 + texDiv: vec2 = { 2, 2 } + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.1 + rate: embed = ValueFloat { + constantValue: f32 = 5 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.4 + } + particleLinger: option[f32] = { 1 } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "Wave_Pattern11" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/fireball.Zaahen.SCB" + } + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.5400015, 0, 0.00999466, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0.85, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = 400 + colorLookUpScales: vec2 = { 1, 0 } + alphaRef: u8 = 0 + disableBackfaceCull: bool = true + miscRenderFlags: u8 = 1 + isGroundLayer: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 300, 0 } + } + isLocalOrientation: flag = false + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 52, 52, 1 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.21954341, 0.5016002, 1 } + values: list[vec3] = { + { 0.79693097, 0.79693097, 0.79693097 } + { 1.0492847, 1.0489929, 1.0489929 } + { 1.1439651, 1.1439651, 1.1439651 } + { 1.2, 1.2, 1.2 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/alphaslice_mesh.Zaahen.tex" + birthUvScrollRate: embed = ValueVector2 { + constantValue: vec2 = { 1, 0 } + } + birthUVOffset: embed = ValueVector2 { + constantValue: vec2 = { 1, -0.99 } + } + uvRotation: embed = ValueFloat { + constantValue: f32 = 90 + } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/2v2Cameo_Jhin_Mult.Zaahen.tex" + texAddressModeMult: u8 = 2 + uvScaleMult: embed = ValueVector2 { + constantValue: vec2 = { 1, 2 } + } + birthUVOffsetMult: embed = ValueVector2 { + constantValue: vec2 = { 0, 0.7 } + } + } + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.1 + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.4 + } + particleLinger: option[f32] = { 1 } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "Wave_Pattern13" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/fireball.Zaahen.SCB" + } + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.5400015, 0, 0.00999466, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.4211111, 0.63, 0.80333334, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 0.8545087 } + { 1, 1, 1, 0.3032948 } + { 1, 1, 1, 0.05953757 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = 600 + colorLookUpScales: vec2 = { 1, 0 } + alphaRef: u8 = 0 + disableBackfaceCull: bool = true + miscRenderFlags: u8 = 1 + isGroundLayer: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 300, 0 } + } + isLocalOrientation: flag = false + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 60, 60, 1 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.094444446, 0.37104464, 1 } + values: list[vec3] = { + { 0, 0, 0 } + { 0.8755981, 0.8755981, 0.8755981 } + { 1.1690364, 1.1690364, 1.1690364 } + { 1.2, 1.2, 1.2 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/R_wall_alphaBlend.Zaahen.tex" + birthUvScrollRate: embed = ValueVector2 { + constantValue: vec2 = { -1, 0 } + } + birthUVOffset: embed = ValueVector2 { + constantValue: vec2 = { 1, -0.99 } + } + particleUVScrollRate: embed = IntegratedValueVector2 { + constantValue: vec2 = { -0.3, 0 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 0.094444446, 1 } + values: list[vec2] = { + { -0.6, 0 } + { -0, 0 } + { -0, 0 } + } + } + } + uvScale: embed = ValueVector2 { + constantValue: vec2 = { 3, 3 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 0.075, 0.3 } + values: list[vec2] = { + { 3, 3 } + { 1.5, 3 } + { 1.5, 3 } + } + } + } + uvRotation: embed = ValueFloat { + constantValue: f32 = 90 + } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/2v2Cameo_Jhin_Mult.Zaahen.tex" + texAddressModeMult: u8 = 2 + uvScaleMult: embed = ValueVector2 { + constantValue: vec2 = { 1, 2 } + } + birthUVOffsetMult: embed = ValueVector2 { + constantValue: vec2 = { 0, 0.7 } + } + } + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.1 + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.4 + } + particleLinger: option[f32] = { 1 } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "Wave_Pattern14" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/fireball.Zaahen.SCB" + } + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.5400015, 0, 0.00999466, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0.85, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = 400 + colorLookUpScales: vec2 = { 1, 0 } + alphaRef: u8 = 0 + disableBackfaceCull: bool = true + miscRenderFlags: u8 = 1 + isGroundLayer: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 300, 0 } + } + isLocalOrientation: flag = false + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 53, 53, 1 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.094444446, 0.37104464, 1 } + values: list[vec3] = { + { 0, 0, 0 } + { 0.8755981, 0.8755981, 0.8755981 } + { 1.1690364, 1.1690364, 1.1690364 } + { 1.2, 1.2, 1.2 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/bloodstrands_bmagic_01.Zaahen.tex" + birthUvScrollRate: embed = ValueVector2 { + constantValue: vec2 = { -1, 0 } + } + birthUVOffset: embed = ValueVector2 { + constantValue: vec2 = { 1, -0.99 } + } + particleUVScrollRate: embed = IntegratedValueVector2 { + constantValue: vec2 = { -0.3, 0 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 0.094444446, 1 } + values: list[vec2] = { + { -0.6, 0 } + { -0, 0 } + { -0, 0 } + } + } + } + uvScale: embed = ValueVector2 { + constantValue: vec2 = { 3, -3 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 0.075, 0.3 } + values: list[vec2] = { + { 3, -3 } + { 1.5, -3 } + { 1.5, -3 } + } + } + } + uvRotation: embed = ValueFloat { + constantValue: f32 = 90 + } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_W_Mask_01.Zaahen.tex" + texAddressModeMult: u8 = 2 + uvScaleMult: embed = ValueVector2 { + constantValue: vec2 = { 1, 2 } + } + birthUVOffsetMult: embed = ValueVector2 { + constantValue: vec2 = { 0, 0.7 } + } + } + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.13 + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.5 + } + particleLinger: option[f32] = { 12.25 } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "ground_decal5" + SpawnShape: pointer = 0xee39916f { + emitOffset: vec3 = { 0, 3, 0 } + } + primitive: pointer = VfxPrimitiveArbitraryQuad { } + particleColorTexture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/alphaslice_mesh.Zaahen.tex" + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.37599757, 0, 0, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.2, 0.44125226, 0.72, 0.95640653, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 0.769074, 0.769074, 0.769074, 0.63 } + { 0.42857307, 0.42857307, 0.42857307, 0.061734103 } + { 0.3529412, 0.3529412, 0.3529412, 0 } + } + } + } + pass: i16 = -500 + alphaRef: u8 = 0 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + constantValue: f32 = 0 + } + erosionFeatherOut: f32 = 0.3 + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/alphaslice_mesh.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + miscRenderFlags: u8 = 1 + isUniformScale: flag = true + isGroundLayer: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 0, 120 } + } + isLocalOrientation: flag = false + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 750, 750, 1 } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Skin01_Z_SeaNoise05.Zaahen.tex" + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/ball32_01.Zaahen.tex" + } + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.13 + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.4 + } + particleLinger: option[f32] = { 1 } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "Wave_Pattern15" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 10, 0 } + } + primitive: pointer = VfxPrimitiveArbitraryQuad { } + particleColorTexture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/alphaslice_mesh.Zaahen.tex" + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.6261234, 0.036209658, 0, 0.56078434 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.2, 0.44125226, 0.73096186, 0.95640653, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 0.769074, 0.769074, 0.769074, 0.72907513 } + { 0.42857307, 0.42857307, 0.42857307, 0.061734103 } + { 0.3529412, 0.3529412, 0.3529412, 0 } + } + } + } + alphaRef: u8 = 0 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + constantValue: f32 = 0 + } + erosionFeatherOut: f32 = 0.3 + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/alphaslice_mesh.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 320, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 0 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 90, 320, 0 } } + } + } + isLocalOrientation: flag = false + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 545, 545, 0.5 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.06419929, 0.28144127, 0.99288255 } + values: list[vec3] = { + { 0, 0, 0 } + { 0.9014992, 0.89977586, 0.64 } + { 1.0905261, 1.0905261, 0.78708136 } + { 1.1433333, 1.1433333, 1.1433333 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Warwick_Skin01_R_DeflectionRipples.Zaahen.tex" + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.13 + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.4 + } + particleLinger: option[f32] = { 0.5 } + isSingleParticle: flag = true + emitterName: string = "Constelations" + importance: u8 = 3 + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 1, 0 } + } + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/XinZhaoRework_Base_R_PortalEdge_Circle.Zaahen.scb" + } + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 0.48000306, 0.14000152, 0.8200046 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.6166062, 0.82444644, 0.9172958, 0.95814884, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0.70705205 } + { 1, 1, 1, 0.17687862 } + { 1, 1, 1, 0.0650289 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = 5000 + colorLookUpScales: vec2 = { 0.3, 0.6 } + alphaRef: u8 = 0 + disableBackfaceCull: bool = true + miscRenderFlags: u8 = 1 + isGroundLayer: flag = true + useNavmeshMask: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 0, 21, 0 } + } + isLocalOrientation: flag = false + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 50.5, 50.5, 50.5 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.06, 0.28180197, 0.99288255 } + values: list[vec3] = { + { 0, 0, 0 } + { 0.9014992, 0.89977586, 0.89164275 } + { 1.0905261, 1.0905261, 1.0908772 } + { 1.1433333, 1.1433333, 1.1433333 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/zaahen_indicator_circle_02.Zaahen.tex" + birthUVOffset: embed = ValueVector2 { + constantValue: vec2 = { 1, 0 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec2] = { { 1, 0 } } + } + } + texDiv: vec2 = { 0.2, 1 } + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.13 + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.5 + } + particleLinger: option[f32] = { 2 } + lifetime: option[f32] = { 0.5 } + isSingleParticle: flag = true + emitterName: string = "flash39" + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 15, 15, 15 } + } + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.80050355, 0, 0.017883575, 0.4509804 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.18555556, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = 4000 + alphaRef: u8 = 0 + miscRenderFlags: u8 = 1 + particleIsLocalOrientation: flag = true + isUniformScale: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 270, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 700, 450, 0 } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 1, 1.5, 1 } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Sett_Base_Glow_Solid.Zaahen.tex" + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.15 + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.15 + } + particleLinger: option[f32] = { 12.25 } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "flash_ground" + SpawnShape: pointer = 0xee39916f { + emitOffset: vec3 = { 0, 3, 0 } + } + primitive: pointer = VfxPrimitiveArbitraryQuad { } + particleColorTexture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/alphaslice_mesh.Zaahen.tex" + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.6599985, 0, 0, 0.8299992 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.2, 0.44125226, 0.72, 0.95640653, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 0.769074, 0.769074, 0.769074, 0.63 } + { 0.42857307, 0.42857307, 0.42857307, 0.061734103 } + { 0.3529412, 0.3529412, 0.3529412, 0 } + } + } + } + pass: i16 = -500 + alphaRef: u8 = 0 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + constantValue: f32 = 0 + } + erosionFeatherOut: f32 = 0.3 + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/alphaslice_mesh.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + miscRenderFlags: u8 = 1 + isUniformScale: flag = true + isGroundLayer: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 0, 120 } + } + isLocalOrientation: flag = false + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 600, 600, 600 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 0, 0, 0 } + { 2.569378, 2.569378, 2.569378 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Skin01_Z_SeaNoise05.Zaahen.tex" + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/ball32_01.Zaahen.tex" + } + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.13 + rate: embed = ValueFloat { + constantValue: f32 = 2 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.43 + } + particleLinger: option[f32] = { 1 } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "Wave_Pattern16" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 3, 0 } + } + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/fireball.Zaahen.SCB" + } + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 0.7300069, 0.42000458, 0.30000764 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.2, 0.597561, 0.8599061, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 0.7889067, 0.7889067, 0.7889067, 1 } + { 0.3063554, 0.3063554, 0.3063554, 0 } + { 0, 0, 0, 0 } + } + } + } + pass: i16 = 1100 + colorLookUpScales: vec2 = { 1, 0 } + alphaRef: u8 = 0 + disableBackfaceCull: bool = true + miscRenderFlags: u8 = 1 + isGroundLayer: flag = true + useNavmeshMask: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 320, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 0 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 90, 320, 0 } } + } + } + isLocalOrientation: flag = false + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 56, 56, 0.5 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.06419929, 0.28144127, 0.99288255 } + values: list[vec3] = { + { 0, 0, 0 } + { 0.9014992, 0.89977586, 0.64 } + { 1.0905261, 1.0905261, 0.78708136 } + { 1.1433333, 1.1433333, 1.1433333 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Ground_Splash_Over.Zaahen.tex" + birthUvScrollRate: embed = ValueVector2 { + constantValue: vec2 = { 2.7, 0 } + } + birthUVOffset: embed = ValueVector2 { + constantValue: vec2 = { 1, 1 } + } + texDiv: vec2 = { 1.05, 0.5 } + particleUVScrollRate: embed = IntegratedValueVector2 { + constantValue: vec2 = { -4.5, 0 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 0.5, 1 } + values: list[vec2] = { + { -9, 0 } + { -4.5, 0 } + { -0, 0 } + } + } + } + uvScale: embed = ValueVector2 { + constantValue: vec2 = { 2.6, 2.5 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 0.3 } + values: list[vec2] = { + { 2.6, 2.5 } + { 1.3, 2.5 } + } + } + } + uvRotation: embed = ValueFloat { + constantValue: f32 = 90 + } + textureMult: pointer = VfxTextureMultDefinitionData { + birthUVOffsetMult: embed = ValueVector2 { + constantValue: vec2 = { 1, 1 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec2] = { { 1, 1 } } + } + } + } + } + } + particleName: string = "Zaahen_Base_R_AoE" + particlePath: string = "Characters/Zaahen/Skins/Skin0/Particles/Zaahen_Base_R_AoE" + flags: u16 = 198 + } + "Characters/Zaahen/Skins/Skin0/Particles/Zaahen_Base_BA_Tar2" = VfxSystemDefinitionData { + complexEmitterDefinitionData: list[pointer] = { + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 1 + } + isSingleParticle: flag = true + childParticleSetDefinition: pointer = VfxChildParticleSetDefinitionData { + childrenIdentifiers: list[embed] = { + VfxChildIdentifier { + effectKey: hash = "Zaahen_BA_Tar_Child" + } + } + } + emitterName: string = "Gimbal" + importance: u8 = 3 + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 0, 180, 0 } + } + } + } + particleName: string = "Zaahen_Base_BA_Tar2" + particlePath: string = "Characters/Zaahen/Skins/Skin0/Particles/Zaahen_Base_BA_Tar2" + } + "Characters/Zaahen/Skins/Skin0/Particles/Zaahen_Base_BA_Tar3" = VfxSystemDefinitionData { + complexEmitterDefinitionData: list[pointer] = { + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.3 + } + particleLinger: option[f32] = { 10.2 } + lifetime: option[f32] = { 1 } + emitterName: string = "Background" + FlexShapeDefinition: pointer = VfxFlexShapeDefinitionData { + scaleEmitOffsetByBoundObjectSize: f32 = 0.005 + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 1, 1, 0.9799954 } + } + Color: embed = ValueColor { + constantValue: vec4 = { 0.24309148, 0.040939957, 0.07330434, 1 } + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.3, 1 } + values: list[vec4] = { + { 0.24309148, 0.040939957, 0.07330434, 1 } + { 0.24309148, 0.040939957, 0.07330434, 0.8399939 } + { 0.24309148, 0.040939957, 0.07330434, 0 } + } + } + } + pass: i16 = -20 + alphaRef: u8 = 4 + miscRenderFlags: u8 = 1 + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 220, 170, 1 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.2, 1 } + values: list[vec3] = { + { 0.3, 0.3, 11 } + { 1, 1, 1 } + { 1.2, 1.2, 1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Aura_Self.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 2 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.35 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.8, 1.1 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 0.35 } + } + } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "Ray_DARK_BLACK" + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, -100, 0 } + } + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + primitive: pointer = VfxPrimitiveRay { } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.9848325, 0.8168002, 0.8168002, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.0927835, 0.18041237, 0.3530928, 0.5, 1 } + values: list[vec4] = { + { 1, 0.9411765, 0.72156864, 1 } + { 0.85156024, 0.6632029, 0.39346913, 1 } + { 0.82023346, 0.44835585, 0.27548638, 1 } + { 0.76092166, 0.124559395, 0.124559395, 1 } + { 0.33070877, 0.13925384, 0.19575799, 1 } + { 0.20851454, 0.08905165, 0.14770733, 1 } + } + } + } + pass: i16 = 50 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.55 } + values: list[f32] = { 0, 1 } + } + } + erosionSliceWidth: f32 = 1 + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Aatrox_Skin11_Einstein_04_mult.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + erosionMapAddressMode: u8 = 0 + } + miscRenderFlags: u8 = 1 + isDirectionOriented: flag = true + isRandomStartFrame: flag = true + isRotationEnabled: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { -90, 0, 360 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 1, 1 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1.5 } + } + } + times: list[f32] = { 0 } + values: list[vec3] = { { -90, 0, 360 } } + } + } + directionVelocityScale: f32 = 1 + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 100, 120, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1.1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.65, 1.1 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 100, 120, 0 } } + } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 1, 1, 1.2 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.1, 1 } + values: list[vec3] = { + { 0, 0, 0 } + { 1, 2, 0 } + { 1, 3, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Aatrox_Skin11_Particles_2_78.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.1 + } + particleLinger: option[f32] = { 0.6 } + lifetime: option[f32] = { 0.7 } + isSingleParticle: flag = true + emitterName: string = "DarkSwipe" + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, -200, 0 } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 3, 3, 3 } + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 1, 1, 0.7019608 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 1 } + values: list[vec4] = { + { 0.939971, 0.8281071, 0.589868, 1 } + { 0.90952927, 0.6944381, 0.40538645, 1 } + { 0.3040818, 0.14012359, 0.14717327, 0 } + } + } + } + pass: i16 = 5 + alphaRef: u8 = 0 + miscRenderFlags: u8 = 1 + particleIsLocalOrientation: flag = true + isDirectionOriented: flag = true + isRotationEnabled: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 0, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 120, 150, 0 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.1, 1 } + values: list[vec3] = { + { 0, 0, 0 } + { 1, 1, 1 } + { 0, 1, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Aura_Self.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 2 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.4 + } + lifetime: option[f32] = { 0.2 } + isSingleParticle: flag = true + emitterName: string = "circleflare_blend1" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + particleColorTexture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/common_color-bellcurve.Zaahen.tex" + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.17181659, 0.07031357, 0.067200735, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.06652807, 0.1964657, 0.38253638, 0.6486486, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0.47272727 } + { 1, 1, 1, 0.21212122 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = -50 + meshRenderFlags: u8 = 0 + alphaRef: u8 = 0 + isUniformScale: flag = true + isRandomStartFrame: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 1, 0, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 1, 0, 0 } } + } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 40, 200, 200 } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 1.5, 1, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.08212058, 0.17525057, 1 } + values: list[vec3] = { + { 0, 1, 1 } + { 2.4626865, 0.9178794, 0.9178794 } + { 3.1791046, 0.8247494, 0.8247494 } + { 4.5, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Thresh_Skin28_Q_Impact_04.Zaahen.tex" + numFrames: u16 = 4 + texDiv: vec2 = { 2, 2 } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.2 + } + particleLinger: option[f32] = { 10.3 } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "flash6" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + FlexShapeDefinition: pointer = VfxFlexShapeDefinitionData { + scaleBirthScaleByBoundObjectSize: f32 = 0.005 + scaleEmitOffsetByBoundObjectSize: f32 = 0.005 + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.9061265, 0.9061265, 0.9061265, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 1 } + values: list[vec4] = { + { 0.8844129, 0.7690547, 0.5053635, 1 } + { 0.5100023, 0.00999466, 0.10000763, 0 } + } + } + } + pass: i16 = 55 + alphaRef: u8 = 0 + miscRenderFlags: u8 = 1 + isUniformScale: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 1, 0, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 1, 0, 0 } } + } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 75, 100, 1 } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 1, 1.5, 2 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.3, 0.6, 1 } + values: list[vec3] = { + { 0, 0, 0 } + { 1, 1.5, 2 } + { 0.2, 0.3, 0.4 } + { 0, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Naafiri_Base_R_Flash_sharp.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.2 + } + particleLinger: option[f32] = { 10.3 } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "flash7" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + FlexShapeDefinition: pointer = VfxFlexShapeDefinitionData { + scaleBirthScaleByBoundObjectSize: f32 = 0.005 + scaleEmitOffsetByBoundObjectSize: f32 = 0.005 + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.8096742, 0.19507134, 0.1309224, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 0.5100023, 0.00999466, 0.10000763, 0 } + } + } + } + pass: i16 = 50 + alphaRef: u8 = 0 + miscRenderFlags: u8 = 1 + isUniformScale: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 1, 0, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 1, 0, 0 } } + } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 100, 100, 1 } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 3, 1.5, 2 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.3, 0.6, 1 } + values: list[vec3] = { + { 0, 0, 0 } + { 3, 1.5, 2 } + { 0.6, 0.3, 0.4 } + { 0, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Naafiri_Base_R_Flash_sharp.Zaahen.tex" + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.05 + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.3 + } + particleLinger: option[f32] = { 10.2 } + lifetime: option[f32] = { 1.05 } + isSingleParticle: flag = true + emitterName: string = "flash_Mult2" + importance: u8 = 3 + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.31302357, 0.013519494, 0.11020066, 1 } + } + Color: embed = ValueColor { + constantValue: vec4 = { 1, 1, 1, 0.7000076 } + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.5, 1 } + values: list[vec4] = { + { 1, 1, 1, 0.7000076 } + { 1, 1, 1, 0.7000076 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = -1 + miscRenderFlags: u8 = 1 + isUniformScale: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 1, 0, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 1, 0, 0 } } + } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 230, 2, 2 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 1, 1, 1 } + { 0.3, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/JarvanIV_Skin35_R_glow.Zaahen.tex" + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.1 + rate: embed = ValueFloat { + constantValue: f32 = 10 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.35 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.2, 1.5 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 0.35 } + } + } + particleLinger: option[f32] = { 1 } + lifetime: option[f32] = { 0.3 } + isSingleParticle: flag = true + emitterName: string = "Embers2" + birthOrbitalVelocity: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 0, 0 } } + } + } + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 1000, 1000, 1000 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.2, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 1000, 1000, 1000 } } + } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 5, 5, 5 } + } + worldAcceleration: embed = IntegratedValueVector3 { + constantValue: vec3 = { 0, 300, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.75, 1.25 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 300, 0 } } + } + } + bindWeight: embed = ValueFloat { + constantValue: f32 = 0.1 + } + SpawnShape: pointer = VfxShapeBox { + flags: u8 = 1 + Size: vec3 = { 10, 10, 10 } + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, -25, 0 } + } + blendMode: u8 = 5 + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 0.3, 0.6, 1 } + values: list[vec4] = { + { 0.9411765, 0.06666667, 0.07450981, 0 } + { 0.9411765, 0.06666667, 0.07450981, 1 } + { 0.9411765, 0.06666667, 0.07450981, 1 } + { 0.23137255, 0, 0.015686275, 1 } + { 0.23137255, 0, 0.015686275, 0 } + } + } + } + pass: i16 = 10 + miscRenderFlags: u8 = 1 + isDirectionOriented: flag = true + isUniformScale: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 1, 0, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 1, 0, 0 } } + } + } + birthRotationalVelocity0: embed = ValueVector3 { + constantValue: vec3 = { 300, 0, 0 } + } + directionVelocityScale: f32 = 0.004 + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 30, 60, 50 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.2, 1 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 30, 60, 50 } } + } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.1, 0.13, 0.4, 0.5, 1 } + values: list[vec3] = { + { 0, 0, 0 } + { 1.2, 1, 1 } + { 1, 1, 1 } + { 1, 0.5, 1 } + { 1, 0.5, 1 } + { 0, 0, 1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Morgana_Base_P_StardustMoteAlpha.Zaahen.tex" + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.1 + rate: embed = ValueFloat { + constantValue: f32 = 7 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.5 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 0.9, 1 } + keyValues: list[f32] = { 0.2, 1, 1.5 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 0.5 } + } + } + particleLinger: option[f32] = { 1 } + lifetime: option[f32] = { 0.3 } + isSingleParticle: flag = true + emitterName: string = "Sparkles" + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 555, 1, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 0.85 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.75, 1.1 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 555, 1, 0 } } + } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 8, 8, 8 } + } + worldAcceleration: embed = IntegratedValueVector3 { + constantValue: vec3 = { 0, 200, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 200, 0 } } + } + } + SpawnShape: pointer = VfxShapeLegacy { + emitOffset: embed = ValueVector3 { + constantValue: vec3 = { 100, 0, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.2, 1 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 100, 0, 0 } } + } + } + emitRotationAngles: list[embed] = { + ValueFloat { + constantValue: f32 = 1 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 1 } + } + } + ValueFloat { + constantValue: f32 = 1 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 1 } + } + } + } + emitRotationAxes: list[vec3] = { + { 0, 1.0000001, 0 } + { 0, 0, 1.0000001 } + } + } + blendMode: u8 = 5 + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 0.3, 0.6, 1 } + values: list[vec4] = { + { 0.9411765, 0.06666667, 0.07450981, 0 } + { 0.9411765, 0.06666667, 0.07450981, 1 } + { 0.9411765, 0.06666667, 0.07450981, 1 } + { 0.23137255, 0, 0.015686275, 1 } + { 0.23137255, 0, 0.015686275, 0 } + } + } + } + pass: i16 = 10 + miscRenderFlags: u8 = 1 + isUniformScale: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 1, 0, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 1, 0, 0 } } + } + } + birthRotationalVelocity0: embed = ValueVector3 { + constantValue: vec3 = { -300, 0, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 50, 65, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 0.9, 1 } + keyValues: list[f32] = { 0.3, 1, 2 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 50, 65, 0 } } + } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.1, 0.19223854, 0.37142858, 1 } + values: list[vec3] = { + { 0, 0, 0 } + { 1, 1, 1 } + { 0.21186441, 0.5, 0.5 } + { 0.56271183, 0.33380866, 0.33380866 } + { 0, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Morgana_Base_P_StardustMoteAlpha.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.85 + } + particleLinger: option[f32] = { } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "StrokeDissolve_primary" + importance: u8 = 3 + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.88000304, 0.2, 0.2, 0.2899977 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.2, 0.8, 1 } + values: list[vec4] = { + { 0.80784315, 0.5137255, 0.42352942, 1 } + { 0.78431374, 0.101960786, 0, 1 } + { 0.78431374, 0.101960786, 0, 1 } + { 0.13725491, 0.007843138, 0.05882353, 1 } + } + } + } + pass: i16 = 5 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.55 } + values: list[f32] = { 0.15, 1 } + } + } + erosionSliceWidth: f32 = 1 + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Aatrox_Skin11_AA_Wall_Erosion.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + erosionMapAddressMode: u8 = 0 + } + disableBackfaceCull: bool = true + isUniformScale: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 360, 1, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 360, 1, 0 } } + } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 100, 120, 120 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.2, 1 } + values: list[vec3] = { + { 0.5, 0.25, 0.1 } + { 0.75, 0.75, 0.5 } + { 1, 1.2, 1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Aatrox_Skin11_AA_Flares_03.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 4 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.1 + } + lifetime: option[f32] = { 0.2 } + isSingleParticle: flag = true + emitterName: string = "circleflare_blend2" + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 0, 1, 0 } + } + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + particleColorTexture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/common_color-bellcurve.Zaahen.tex" + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.8769818, 0.71776915, 0.5003128, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.06652807, 0.1964657, 0.38253638, 0.6486486, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0.47272727 } + { 1, 1, 1, 0.21212122 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = 50 + meshRenderFlags: u8 = 0 + alphaRef: u8 = 0 + miscRenderFlags: u8 = 1 + isRandomStartFrame: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 40, 100, 200 } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Thresh_Skin28_Q_Impact_04.Zaahen.tex" + numFrames: u16 = 4 + texDiv: vec2 = { 2, 2 } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 2 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.2 + } + lifetime: option[f32] = { 0.2 } + isSingleParticle: flag = true + emitterName: string = "circleflare_blend3" + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 0, 1, 0 } + } + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + particleColorTexture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/common_color-bellcurve.Zaahen.tex" + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.92841995, 0.46456093, 0.4678874, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 0.5, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 0.85265887, 0.27139696, 0.27139696, 1 } + { 0.7837034, 0.09224079, 0.09224079, 0 } + } + } + } + pass: i16 = -25 + meshRenderFlags: u8 = 0 + alphaRef: u8 = 0 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + constantValue: f32 = 0 + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0.4, 1 } + values: list[f32] = { 0, 0 } + } + } + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Nebula_Streak_Mult_Vertical.Zaahen.tex" + } + miscRenderFlags: u8 = 1 + isRandomStartFrame: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 20, 100, 200 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.25, 1 } + values: list[vec3] = { + { 1, 1, 0 } + { 1, 1, 1 } + { 1, 1, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Thresh_Skin28_Q_Impact_04.Zaahen.tex" + numFrames: u16 = 4 + texDiv: vec2 = { 2, 2 } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 2 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.3 + } + particleLinger: option[f32] = { 10.2 } + lifetime: option[f32] = { 1.05 } + isSingleParticle: flag = true + emitterName: string = "flash_Mult3" + importance: u8 = 3 + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 1, 1, 0.51999694 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.0927835, 0.18041237, 0.3530928, 0.5, 1 } + values: list[vec4] = { + { 1, 0.94000155, 0.7199969, 0 } + { 0.85000384, 0.6599985, 0.39000535, 0.14999619 } + { 0.82023346, 0.44835585, 0.27548638, 1 } + { 0.76092166, 0.124559395, 0.124559395, 1 } + { 0.33070877, 0.13925384, 0.19575799, 1 } + { 0.20999466, 0.08999771, 0.14999619, 0 } + } + } + } + pass: i16 = -1 + miscRenderFlags: u8 = 1 + isUniformScale: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 1, 0, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 1, 0, 0 } } + } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 100, 2, 2 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 1, 1, 1 } + { 0.3, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Aura_Self.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 8 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.4 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.65, 1 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 0.4 } + } + } + particleLinger: option[f32] = { } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "Smoke_Burst" + importance: u8 = 3 + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 1200, 1000, 1200 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.3, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 1200, 1000, 1200 } } + } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 8, 8, 8 } + } + worldAcceleration: embed = IntegratedValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 0, 0 } } + } + } + SpawnShape: pointer = VfxShapeBox { + flags: u8 = 1 + Size: vec3 = { 10, 10, 10 } + } + primitive: pointer = VfxPrimitiveArbitraryQuad { } + blendMode: u8 = 1 + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.2, 0.5, 1 } + values: list[vec4] = { + { 0.9520409, 0.5544671, 0.5569238, 0 } + { 0.77254903, 0.13725491, 0.14117648, 1 } + { 0.22000457, 0, 0.05070573, 0.43137255 } + { 0.13698024, 0.0508278, 0.073121235, 0 } + } + } + } + pass: i16 = 10 + alphaRef: u8 = 0 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.25633293, 0.6982072, 1 } + values: list[f32] = { 0, 0, 0.2, 0.5 } + } + } + erosionFeatherOut: f32 = 0.2 + erosionSliceWidth: f32 = 2 + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Emote_Flames_02.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + depthBiasFactors: vec2 = { -1, -15 } + disableBackfaceCull: bool = true + miscRenderFlags: u8 = 1 + isDirectionOriented: flag = true + isRandomStartFrame: flag = true + isGroundLayer: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, -90, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 90, -90, 0 } } + } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 160, 120, 100 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.8, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.8, 1 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 160, 120, 100 } } + } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 0.5, 0.5, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.2, 0.5, 1 } + values: list[vec3] = { + { 0.25, 0.3, 0.8 } + { 0.325, 0.375, 0.75 } + { 0.5, 0.55, 1 } + { 0.45, 0.65, 1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Shapes02.Zaahen.tex" + numFrames: u16 = 4 + texDiv: vec2 = { 2, 2 } + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.05 + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.1 + } + particleLinger: option[f32] = { 10.55 } + lifetime: option[f32] = { 0.2 } + isSingleParticle: flag = true + emitterName: string = "VerticalBlack" + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 100, 1000, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.2, 1 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 100, 1000, 0 } } + } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 6, 6, 6 } + } + worldAcceleration: embed = IntegratedValueVector3 { + constantValue: vec3 = { 0, -10, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0 } + values: list[vec3] = { { 0, -10, 0 } } + } + } + SpawnShape: pointer = VfxShapeCylinder { + radius: f32 = 10 + } + FlexShapeDefinition: pointer = VfxFlexShapeDefinitionData { + scaleBirthScaleByBoundObjectSize: f32 = 0.005 + } + primitive: pointer = VfxPrimitiveRay { } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 1, 1, 0.5019608 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.2, 0.5, 1 } + values: list[vec4] = { + { 0.9520409, 0.5544671, 0.5569238, 0 } + { 0.77254903, 0.13725491, 0.14117648, 1 } + { 0.22000457, 0, 0.05070573, 0.43137255 } + { 0.13698024, 0.0508278, 0.073121235, 0 } + } + } + } + pass: i16 = 6 + colorLookUpTypeY: u8 = 3 + alphaRef: u8 = 15 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.3, 1 } + values: list[f32] = { 0, 0, 1 } + } + } + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Garen_Skin24_BA_ErosionShapes01.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + miscRenderFlags: u8 = 1 + isDirectionOriented: flag = true + isRandomStartFrame: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { -90, 0, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 180, 750, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.6, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 180, 750, 1 } } + } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 0.75, 0.75, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 0.75, 0.75, 1 } + { 0.6, 0.75, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Shapes02.Zaahen.tex" + numFrames: u16 = 4 + texDiv: vec2 = { 2, 2 } + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.05 + rate: embed = ValueFloat { + constantValue: f32 = 2 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.3 + } + particleLinger: option[f32] = { 10.55 } + lifetime: option[f32] = { 0.2 } + isSingleParticle: flag = true + emitterName: string = "VerticalColumn" + importance: u8 = 3 + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 100, 1000, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.2, 1 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 100, 1000, 0 } } + } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 6, 6, 6 } + } + worldAcceleration: embed = IntegratedValueVector3 { + constantValue: vec3 = { 0, -10, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0 } + values: list[vec3] = { { 0, -10, 0 } } + } + } + SpawnShape: pointer = VfxShapeCylinder { + radius: f32 = 10 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, -150, 0 } + } + FlexShapeDefinition: pointer = VfxFlexShapeDefinitionData { + scaleBirthScaleByBoundObjectSize: f32 = 0.005 + } + primitive: pointer = VfxPrimitiveRay { } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.77254903, 0.13725491, 0.1419089, 0.47058824 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.2, 0.5, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 0.22000457, 0, 0.05070573, 0.43137255 } + { 0.13698024, 0.0508278, 0.073121235, 0 } + } + } + } + pass: i16 = 1 + colorLookUpTypeY: u8 = 3 + alphaRef: u8 = 15 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.3, 1 } + values: list[f32] = { 0, 0, 1 } + } + } + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Garen_Skin24_BA_ErosionShapes01.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + miscRenderFlags: u8 = 1 + isDirectionOriented: flag = true + isRandomStartFrame: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { -90, 0, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 250, 650, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 250, 650, 1 } } + } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 1, 1, 1 } + { 0.8, 1, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Shapes02.Zaahen.tex" + numFrames: u16 = 4 + texDiv: vec2 = { 2, 2 } + } + } + particleName: string = "Zaahen_Base_BA_Tar3" + particlePath: string = "Characters/Zaahen/Skins/Skin0/Particles/Zaahen_Base_BA_Tar3" + } + "Characters/Zaahen/Skins/Skin0/Particles/Zaahen_Base_W_Cas" = VfxSystemDefinitionData { + complexEmitterDefinitionData: list[pointer] = { + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.2 + rate: embed = ValueFloat { + constantValue: f32 = 10 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.8 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.2, 1 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 0.8 } + } + } + particleLinger: option[f32] = { 1 } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + fieldCollectionDefinition: pointer = VfxFieldCollectionDefinitionData { + fieldNoiseDefinitions: list[embed] = { + VfxFieldNoiseDefinitionData { + radius: embed = ValueFloat { + constantValue: f32 = 1000 + } + frequency: embed = ValueFloat { + constantValue: f32 = 50 + } + velocityDelta: embed = ValueFloat { + constantValue: f32 = 10 + } + axisFraction: vec3 = { 1, 1, 1 } + } + } + } + emitterName: string = "spark_shoot_up" + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 200, 0, 3000 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1.5 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 1, -1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1.5 } + } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 200, 0, 3000 } } + } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 3, 2, 3 } + } + SpawnShape: pointer = VfxShapeBox { + flags: u8 = 1 + Size: vec3 = { 10, 10, 10 } + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, -600 } + } + particleColorTexture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/color-hold.Zaahen.tex" + blendMode: u8 = 4 + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.6 } + values: list[vec4] = { + { 1, 0.9166247, 0.85999846, 1 } + { 0.6838941, 0, 0.08491646, 1 } + } + } + } + pass: i16 = 20 + colorLookUpTypeY: u8 = 3 + softParticleParams: pointer = VfxSoftParticleDefinitionData { + deltaIn: f32 = 25 + } + isDirectionOriented: flag = true + isUniformScale: flag = true + isRandomStartFrame: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 90, 0 } + } + directionVelocityScale: f32 = 0.005 + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 25, 33.75, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 25, 33.75, 0 } } + } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.05, 0.3, 0.5, 0.7, 0.8545454, 1 } + values: list[vec3] = { + { 0, 3, 3 } + { 1.2, 1, 1 } + { 0.5, 0.5, 0.5 } + { 0.8, 1, 1 } + { 0.3, 1, 1 } + { 0.2, 0.9047619, 0.9047619 } + { 0, 0.1, 0.1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Darius_Skin67_Sparks.Zaahen.tex" + } + } + particleName: string = "Zaahen_Base_W_Cas" + particlePath: string = "Characters/Zaahen/Skins/Skin0/Particles/Zaahen_Base_W_Cas" + flags: u16 = 196 + transform: mtx44 = { 0.79999995, 0, 0, 0, 0, 0.79999995, 0, 0, 0, 0, 0.7999999, 0, 0, 0, 0, 1 } + } + "Characters/Zaahen/Skins/Skin0/Particles/Zaahen_Base_Q_2_Buff" = VfxSystemDefinitionData { + complexEmitterDefinitionData: list[pointer] = { + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.15 + } + lifetime: option[f32] = { 4 } + isSingleParticle: flag = true + emitterName: string = "Activate" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + SpawnShape: pointer = VfxShapeBox { + flags: u8 = 1 + } + blendMode: u8 = 1 + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.8, 1 } + values: list[vec4] = { + { 0.259205, 0.15927367, 0.16643015, 1 } + { 0.52156866, 0.22371252, 0.11372549, 0.29803923 } + { 1, 1, 1, 0 } + } + } + } + alphaRef: u8 = 0 + 0xcb13aff1: f32 = -40 + particleIsLocalOrientation: flag = true + isUniformScale: flag = true + isRandomStartFrame: flag = true + isRotationEnabled: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 35, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 50, 1, 1 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.2, 0.3, 1 } + values: list[vec3] = { + { 0.2, 0, 0 } + { 4, 1, 1 } + { 3, 1, 1 } + { 2, 1, 1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Naafiri_Base_Foundation_Glow01.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 2 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = -1 + } + isSingleParticle: flag = true + emitterName: string = "blackOrb_main" + importance: u8 = 3 + IsEmitterSpace: flag = true + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { -5, 0, 0 } + } + primitive: pointer = VfxPrimitiveArbitraryQuad { } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.9254902, 0.7607843, 0.4745098, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.44, 0.50064516 } + values: list[vec4] = { + { 0.59607846, 0.59607846, 0.59607846, 1 } + { 0.8509804, 0.8509804, 0.8509804, 1 } + { 1, 1, 1, 1 } + } + } + } + pass: i16 = 100 + alphaRef: u8 = 0 + 0xcb13aff1: f32 = -40 + particleIsLocalOrientation: flag = true + isUniformScale: flag = true + isRotationEnabled: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 0, 90, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 7, 1, 1 } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Udyr_Base_VGU_GlowMask_Thicc.Zaahen.tex" + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.15 + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = -1 + } + lifetime: option[f32] = { 0.5 } + isSingleParticle: flag = true + emitterName: string = "CameraFacingFlash" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.2, 0.2, 0.30000764, 0.77999544 } + } + pass: i16 = -500 + alphaRef: u8 = 0 + softParticleParams: pointer = VfxSoftParticleDefinitionData { + beginIn: f32 = 10 + deltaIn: f32 = 100 + } + 0xcb13aff1: f32 = -40 + isUniformScale: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 100, 60, 0 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.8, 1 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 1, 1, 1 } } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Aura_Self.Zaahen.tex" + texAddressModeBase: u8 = 2 + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.15 + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = -1 + } + lifetime: option[f32] = { 0.5 } + isSingleParticle: flag = true + emitterName: string = "CameraFacingFlash1" + IsEmitterSpace: flag = true + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.26964217, 0.060883496, 0.05009537, 0.91764706 } + } + pass: i16 = -450 + alphaRef: u8 = 0 + softParticleParams: pointer = VfxSoftParticleDefinitionData { + beginIn: f32 = 10 + deltaIn: f32 = 100 + } + 0xcb13aff1: f32 = -40 + isUniformScale: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 75, 60, 0 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.8, 1 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 1, 1, 1 } } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Aura_Self.Zaahen.tex" + texAddressModeBase: u8 = 2 + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 2 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = -1 + } + isSingleParticle: flag = true + emitterName: string = "blackOrb_main2" + importance: u8 = 3 + IsEmitterSpace: flag = true + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { -5, 0, 0 } + } + primitive: pointer = VfxPrimitiveArbitraryQuad { } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.9254902, 0.7607843, 0.4745098, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.44, 0.50064516 } + values: list[vec4] = { + { 0.59607846, 0.59607846, 0.59607846, 1 } + { 0.8509804, 0.8509804, 0.8509804, 1 } + { 1, 1, 1, 1 } + } + } + } + pass: i16 = 100 + alphaRef: u8 = 0 + 0xcb13aff1: f32 = -40 + particleIsLocalOrientation: flag = true + isUniformScale: flag = true + isRotationEnabled: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 0, 90, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 14, 1, 1 } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Aura_Self.Zaahen.tex" + texAddressModeBase: u8 = 2 + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 8 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.5 + } + emitterName: string = "mesh_ground1" + worldAcceleration: embed = IntegratedValueVector3 { + constantValue: vec3 = { 0, -400, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0 } + values: list[vec3] = { { 0, -400, 0 } } + } + } + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.2 } + values: list[f32] = { 1, 0 } + } + } + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Cassiopeia_Skin20_Q_weaponswipe6.Zaahen.scb" + } + } + blendMode: u8 = 1 + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.2, 0.8, 1 } + values: list[vec4] = { + { 0.9254902, 0.7607843, 0.4745098, 0 } + { 0.9254902, 0.7607843, 0.4745098, 1 } + { 0.10980392, 0, 0.03137255, 1 } + { 0.10980392, 0, 0.03137255, 0 } + } + } + } + pass: i16 = 5 + softParticleParams: pointer = VfxSoftParticleDefinitionData { + deltaIn: f32 = 10 + } + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0.2, 1 } + values: list[f32] = { 0.06, 1 } + } + } + erosionSliceWidth: f32 = 1 + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Udyr_Base_VGU_Awaken_Ribbonmask01.Zaahen.tex" + } + disableBackfaceCull: bool = true + isUniformScale: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 360, 1, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 1, 360 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 360, 1, 0 } } + } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 0.2, 0.63, 0.63 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.8, 1.1 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0.2, 0.63, 0.63 } } + } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 0.7, 1.5, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0.1, 0.3, 1 } + values: list[vec3] = { + { 0.525, 1.3499999, 0.9 } + { 1.05, 1.9499999, 1.3 } + { 1.4, 2.25, 1.6 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Naafiri_Base_Foundation_Missile02.Zaahen.tex" + texAddressModeBase: u8 = 2 + particleUVScrollRate: embed = IntegratedValueVector2 { + constantValue: vec2 = { 1, 0 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec2] = { + { 0.4, 0 } + { 0.1, 0 } + } + } + } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Udyr_Base_VGU_Q_Ele_Flat_Energy.Zaahen.tex" + birthUvScrollRateMult: embed = ValueVector2 { + constantValue: vec2 = { 1, 0 } + } + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 17 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.3 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 0.3 } + } + } + lifetime: option[f32] = { 0.1 } + emitterName: string = "START2" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/fireball.Zaahen.SCB" + } + AlignPitchToCamera: bool = true + AlignYawToCamera: bool = true + 0x6aec9e7a: bool = true + } + blendMode: u8 = 1 + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.2, 0.8, 1 } + values: list[vec4] = { + { 0.10980392, 0, 0.03137255, 0 } + { 0.8841077, 0.7521172, 0.49758145, 1 } + { 0.10980392, 0, 0.03137255, 1 } + { 0.10980392, 0, 0.03137255, 0 } + } + } + } + pass: i16 = 705 + colorLookUpScales: vec2 = { 1, 0 } + alphaRef: u8 = 0 + softParticleParams: pointer = VfxSoftParticleDefinitionData { + deltaIn: f32 = 10 + } + 0xcb13aff1: f32 = -40 + disableBackfaceCull: bool = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 0, 0 } + } + isLocalOrientation: flag = false + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 15, 15, 1 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.3, 1 } + values: list[vec3] = { + { 0, 0, 0 } + { 1.2, 1.2, 1 } + { 0.1, 0.1, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Foundation_Tile01.Zaahen.tex" + birthUVOffset: embed = ValueVector2 { + constantValue: vec2 = { 1, 0.5 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec2] = { { 1, 0.5 } } + } + } + particleUVScrollRate: embed = IntegratedValueVector2 { + constantValue: vec2 = { -1, 0 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 0.5, 1 } + values: list[vec2] = { + { -4, 0 } + { -1, 0 } + { -0, 0 } + } + } + } + uvScale: embed = ValueVector2 { + constantValue: vec2 = { 1.5, 1 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 0.3 } + values: list[vec2] = { + { 1.5, 1 } + { 0.75, 1 } + } + } + } + uvRotation: embed = ValueFloat { + constantValue: f32 = 90 + } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Udyr_Base_VGU_Awaken_Line_Hori.Zaahen.tex" + texAddressModeMult: u8 = 2 + uvScaleMult: embed = ValueVector2 { + constantValue: vec2 = { 1, 2 } + } + birthUVOffsetMult: embed = ValueVector2 { + constantValue: vec2 = { 0, 0.6 } + } + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 200 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.2 + } + emitterName: string = "GOLD_LightTrail1" + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, 125 } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, 0.5 } + } + primitive: pointer = VfxPrimitiveCameraTrail { + mTrail: embed = VfxTrailDefinitionData { + mMode: u8 = 1 + mBirthTilingSize: embed = ValueVector3 { + constantValue: vec3 = { 800, 0, 0 } + } + mSmoothingMode: u8 = 1 + } + } + blendMode: u8 = 4 + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.079535216, 0.18529771, 0.37157086, 0.651592, 1 } + values: list[vec4] = { + { 0.9254902, 0.7607843, 0.4745098, 0 } + { 0.9254902, 0.7607843, 0.4745098, 1 } + { 0.57097733, 0.40239567, 0.109300375, 1 } + { 0.44005492, 0.21713588, 0.059967957, 1 } + { 0.29941252, 0.10383765, 0.070756085, 0.34901962 } + { 0.1244831, 0.061081864, 0.069230184, 0 } + } + } + } + pass: i16 = -10 + alphaRef: u8 = 0 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.2864675, 0.64652014, 1 } + values: list[f32] = { 0.190625, 0.571875, 0.8675568, 1 } + } + } + erosionFeatherIn: f32 = 0.15 + erosionFeatherOut: f32 = 0.15 + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Mordekaiser_Skin54_Noise_keka.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 0, 1, 0, 0 } + } + } + useNavmeshMask: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 20, 2, 2 } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 0.8, 0.8, 0.8 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.07960199, 0.14004976, 0.39004976, 0.75, 1 } + values: list[vec3] = { + { 0.32, 0.32, 0.32 } + { 0.72, 0.72, 0.72 } + { 0.7961644, 0.7961644, 0.7961644 } + { 0.7961644, 0.7961644, 0.7961644 } + { 0.4, 0.4, 0.4 } + { 0.24, 0.24, 0.24 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Mordekaiser_R_Smoke_Trail.Zaahen.tex" + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.2 + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 6 + } + particleLinger: option[f32] = { 0.2 } + lifetime: option[f32] = { 5 } + isSingleParticle: flag = true + emitterLinger: option[f32] = { 0.5 } + emitterName: string = "Trail" + IsEmitterSpace: flag = true + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, -20, 15 } + } + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Q1_Buff_BladeMesh.Zaahen.scb" + } + } + blendMode: u8 = 4 + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.05, 0.9, 1 } + values: list[vec4] = { + { 0.8862745, 0.8784314, 0.4745098, 0 } + { 0.8862745, 0.824918, 0.4745098, 1 } + { 0.8899977, 0.88000304, 0.46999314, 1 } + { 0.8899977, 0.88000304, 0.46999314, 0 } + } + } + } + pass: i16 = 20 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + constantValue: f32 = 0 + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0.1, 0.5, 0.8 } + values: list[f32] = { 0, 0, 0 } + } + } + erosionSliceWidth: f32 = 2 + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_BA_Trail_Darkin_1.Zaahen.tex" + erosionMapAddressMode: u8 = 0 + } + disableBackfaceCull: bool = true + particleIsLocalOrientation: flag = true + isUniformScale: flag = true + isRotationEnabled: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 270, 0, 180 } + } + rotation0: embed = IntegratedValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 0, 0 } } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/common_color-bellcurve32.Zaahen.tex" + birthUvScrollRate: embed = ValueVector2 { + constantValue: vec2 = { -2, 0 } + } + particleUVScrollRate: embed = IntegratedValueVector2 { + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0 } + values: list[vec2] = { { 0, 0 } } + } + } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/common_color-bellcurve32.Zaahen.tex" + texAddressModeMult: u8 = 2 + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 2 + } + emitterLinger: option[f32] = { 1 } + emitterName: string = "ADD_EdgeGlow" + importance: u8 = 3 + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 0, 0 } } + } + } + primitive: pointer = VfxPrimitiveAttachedMesh { + mMesh: embed = VfxMeshDefinitionData { + mSubmeshesToDraw: list[hash] = { "weapon" } + mSubmeshesToDrawAlways: list[hash] = { "weapon" } + mLockMeshToAttachment: bool = true + } + UseAvatarSpecificSubmeshMask: bool = true + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.8399939, 0.7100023, 0.42000458, 0.5000076 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.15, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + } + } + } + pass: i16 = 10 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + constantValue: f32 = 0 + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.5, 1 } + values: list[f32] = { 0, 0, 0 } + } + } + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Emote_Einstein_01_mult.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + depthBiasFactors: vec2 = { -1, -15 } + particleIsLocalOrientation: flag = true + isRotationEnabled: flag = true + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Q_Glaive_Mask2.Zaahen.tex" + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Foundation_Tile01.Zaahen.tex" + birthUvScrollRateMult: embed = ValueVector2 { + constantValue: vec2 = { -0.5, 0 } + } + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 6 + } + isSingleParticle: flag = true + emitterLinger: option[f32] = { 1 } + emitterName: string = "ADD_EdgeGlow1" + importance: u8 = 3 + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 0, 0 } } + } + } + primitive: pointer = VfxPrimitiveAttachedMesh { + mMesh: embed = VfxMeshDefinitionData { + mSubmeshesToDraw: list[hash] = { "weapon" } + mSubmeshesToDrawAlways: list[hash] = { "weapon" } + mLockMeshToAttachment: bool = true + } + UseAvatarSpecificSubmeshMask: bool = true + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.8399939, 0.7100023, 0.42000458, 0.5000076 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.15, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + } + } + } + pass: i16 = 9 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + constantValue: f32 = 0 + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.5, 1 } + values: list[f32] = { 0, 0, 0 } + } + } + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Emote_Einstein_01_mult.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + depthBiasFactors: vec2 = { -1, -15 } + particleIsLocalOrientation: flag = true + isRotationEnabled: flag = true + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Q_Glaive_Mask2.Zaahen.tex" + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/color-hold.Zaahen.tex" + birthUvScrollRateMult: embed = ValueVector2 { + constantValue: vec2 = { 0.5, 0 } + } + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 6 + } + isSingleParticle: flag = true + emitterLinger: option[f32] = { 1 } + emitterName: string = "ADD_EdgeGlow2" + importance: u8 = 3 + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 0, 0 } } + } + } + primitive: pointer = VfxPrimitiveAttachedMesh { + mMesh: embed = VfxMeshDefinitionData { + mSubmeshesToDraw: list[hash] = { "weapon" } + mSubmeshesToDrawAlways: list[hash] = { "weapon" } + mLockMeshToAttachment: bool = true + } + UseAvatarSpecificSubmeshMask: bool = true + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.17999542, 0.08999771, 0.08999771, 0.76862746 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.15, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + } + } + } + pass: i16 = 8 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + constantValue: f32 = 0 + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.5, 1 } + values: list[f32] = { 0, 0, 0 } + } + } + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Emote_Einstein_01_mult.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + depthBiasFactors: vec2 = { -1, -15 } + particleIsLocalOrientation: flag = true + isRotationEnabled: flag = true + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Q_Glaive_Mask3.Zaahen.tex" + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/color-hold.Zaahen.tex" + birthUvScrollRateMult: embed = ValueVector2 { + constantValue: vec2 = { 0.5, 0 } + } + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 6 + } + particleLinger: option[f32] = { 0.2 } + lifetime: option[f32] = { 5 } + isSingleParticle: flag = true + emitterLinger: option[f32] = { 0.5 } + emitterName: string = "Trail1" + IsEmitterSpace: flag = true + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, -20, 15 } + } + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Q1_Buff_BladeMesh.Zaahen.scb" + } + } + blendMode: u8 = 1 + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.05, 0.9, 1 } + values: list[vec4] = { + { 0.6509804, 0.5019608, 0.18039216, 0 } + { 0.6509804, 0.5019608, 0.18039216, 1 } + { 0.6509804, 0.5019608, 0.18039216, 1 } + { 0.6509804, 0.5019608, 0.18039216, 0 } + } + } + } + pass: i16 = 17 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + constantValue: f32 = 0 + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0.1, 0.5, 0.8 } + values: list[f32] = { 0, 0, 0 } + } + } + erosionSliceWidth: f32 = 2 + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_BA_Trail_Darkin_1.Zaahen.tex" + erosionMapAddressMode: u8 = 0 + } + disableBackfaceCull: bool = true + particleIsLocalOrientation: flag = true + isUniformScale: flag = true + isRotationEnabled: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 270, 0, 180 } + } + rotation0: embed = IntegratedValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 0, 0 } } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/common_color-bellcurve32.Zaahen.tex" + particleUVScrollRate: embed = IntegratedValueVector2 { + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0 } + values: list[vec2] = { { 0, 0 } } + } + } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/common_color-bellcurve32.Zaahen.tex" + texAddressModeMult: u8 = 2 + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 2 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = -1 + } + isSingleParticle: flag = true + emitterName: string = "blackOrb_main3" + importance: u8 = 3 + IsEmitterSpace: flag = true + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { -5, 0, 0 } + } + primitive: pointer = VfxPrimitiveArbitraryQuad { } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.93000686, 0.7600061, 0.46999314, 0.5000076 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.44, 0.50064516 } + values: list[vec4] = { + { 0.59607846, 0.59607846, 0.59607846, 1 } + { 0.8509804, 0.8509804, 0.8509804, 1 } + { 1, 1, 1, 1 } + } + } + } + pass: i16 = 100 + alphaRef: u8 = 0 + softParticleParams: pointer = VfxSoftParticleDefinitionData { + beginIn: f32 = 10 + deltaIn: f32 = 100 + } + 0xcb13aff1: f32 = -40 + particleIsLocalOrientation: flag = true + isUniformScale: flag = true + isRotationEnabled: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 0, 90, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 100, 1, 1 } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Aura_Self.Zaahen.tex" + texAddressModeBase: u8 = 2 + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 4 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.35 + } + isSingleParticle: flag = true + emitterLinger: option[f32] = { 1 } + emitterName: string = "ADD_EdgeGlow3" + importance: u8 = 3 + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 0, 0 } } + } + } + primitive: pointer = VfxPrimitiveAttachedMesh { + mMesh: embed = VfxMeshDefinitionData { + mSubmeshesToDraw: list[hash] = { "weapon" } + mSubmeshesToDrawAlways: list[hash] = { "weapon" } + mLockMeshToAttachment: bool = true + } + UseAvatarSpecificSubmeshMask: bool = true + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.8399939, 0.7100023, 0.42000458, 0.5000076 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = 20 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + constantValue: f32 = 0 + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.5, 1 } + values: list[f32] = { 0, 0, 0 } + } + } + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Emote_Einstein_01_mult.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + depthBiasFactors: vec2 = { -1, -15 } + particleIsLocalOrientation: flag = true + isRotationEnabled: flag = true + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Q_Glaive_Mask3.Zaahen.tex" + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Yasuo_Skin57_3026_Items_Noise_02.Zaahen.tex" + UvRotationMult: embed = ValueFloat { + constantValue: f32 = 180 + } + birthUvScrollRateMult: embed = ValueVector2 { + constantValue: vec2 = { 0.5, 0 } + } + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.1 + } + isSingleParticle: flag = true + emitterLinger: option[f32] = { 1 } + emitterName: string = "ADD_EdgeGlow4" + importance: u8 = 3 + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 0, 0 } } + } + } + primitive: pointer = VfxPrimitiveAttachedMesh { + mMesh: embed = VfxMeshDefinitionData { + mSubmeshesToDraw: list[hash] = { "weapon" } + mSubmeshesToDrawAlways: list[hash] = { "weapon" } + mLockMeshToAttachment: bool = true + } + UseAvatarSpecificSubmeshMask: bool = true + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.8399939, 0.7100023, 0.42000458, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = 21 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + constantValue: f32 = 0 + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.5, 1 } + values: list[f32] = { 0, 0, 0 } + } + } + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Emote_Einstein_01_mult.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + depthBiasFactors: vec2 = { -1, -15 } + particleIsLocalOrientation: flag = true + isRotationEnabled: flag = true + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Q_Glaive_Mask3.Zaahen.tex" + textureMult: pointer = VfxTextureMultDefinitionData { + UvRotationMult: embed = ValueFloat { + constantValue: f32 = 180 + } + birthUvScrollRateMult: embed = ValueVector2 { + constantValue: vec2 = { 0.5, 0 } + } + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 10 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.2 + } + emitterName: string = "flash3" + importance: u8 = 3 + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { -5, 0, 0 } + } + FlexShapeDefinition: pointer = VfxFlexShapeDefinitionData { + scaleBirthScaleByBoundObjectSize: f32 = 0.005 + } + blendMode: u8 = 4 + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 0.3, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 0.79681087, 0.6157626, 0.2843824, 0.8509804 } + { 0.38844892, 0.077149615, 0.077149615, 0 } + } + } + } + pass: i16 = 5000 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 1 } + values: list[f32] = { 0.5, 0 } + } + } + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Darius_Skin43_Star_Flash.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + 0xcb13aff1: f32 = -40 + isRandomStartFrame: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 1, 0, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 1, 0, 0 } } + } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 35, 35, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.75, 2 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.75, 2 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 35, 35, 1 } } + } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 0.5, 0.5, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.2, 1 } + values: list[vec3] = { + { 0.1, 0.1, 0.2 } + { 0.5, 0.5, 1 } + { 2, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Darius_Skin43_Star_Flash.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 10 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.2 + } + emitterName: string = "flash4" + importance: u8 = 3 + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { -5, 0, 0 } + } + FlexShapeDefinition: pointer = VfxFlexShapeDefinitionData { + scaleBirthScaleByBoundObjectSize: f32 = 0.005 + } + blendMode: u8 = 4 + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 0.3, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 0.79681087, 0.6157626, 0.2843824, 0.8509804 } + { 0.38844892, 0.077149615, 0.077149615, 0 } + } + } + } + pass: i16 = 5000 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + constantValue: f32 = 0 + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 1 } + values: list[f32] = { 0, 0 } + } + } + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Darius_Skin43_Star_Flash.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + 0xcb13aff1: f32 = -40 + isRandomStartFrame: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 1, 0, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 1, 0, 0 } } + } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 35, 35, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.75, 2 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.75, 2 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 35, 35, 1 } } + } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.2, 1 } + values: list[vec3] = { + { 0.2, 0.2, 0.2 } + { 1, 1, 1 } + { 4, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/BrightGlow.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 17 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.3 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 0.3 } + } + } + lifetime: option[f32] = { 0.1 } + emitterName: string = "START3" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/fireball.Zaahen.SCB" + } + AlignPitchToCamera: bool = true + AlignYawToCamera: bool = true + 0x6aec9e7a: bool = true + } + blendMode: u8 = 4 + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.2, 0.8, 1 } + values: list[vec4] = { + { 0.10980392, 0, 0.03137255, 0 } + { 0.8841077, 0.7521172, 0.49758145, 1 } + { 0.10980392, 0, 0.03137255, 1 } + { 0.10980392, 0, 0.03137255, 0 } + } + } + } + pass: i16 = 710 + colorLookUpScales: vec2 = { 1, 0 } + alphaRef: u8 = 0 + softParticleParams: pointer = VfxSoftParticleDefinitionData { + deltaIn: f32 = 10 + } + 0xcb13aff1: f32 = -40 + disableBackfaceCull: bool = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 0, 0 } + } + isLocalOrientation: flag = false + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 15, 15, 1 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.3, 1 } + values: list[vec3] = { + { 0, 0, 0 } + { 1.2, 1.2, 1 } + { 0.1, 0.1, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Foundation_Tile01.Zaahen.tex" + birthUVOffset: embed = ValueVector2 { + constantValue: vec2 = { 1, 0.5 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec2] = { { 1, 0.5 } } + } + } + particleUVScrollRate: embed = IntegratedValueVector2 { + constantValue: vec2 = { -1, 0 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 0.5, 1 } + values: list[vec2] = { + { -4, 0 } + { -1, 0 } + { -0, 0 } + } + } + } + uvScale: embed = ValueVector2 { + constantValue: vec2 = { 1.5, 1 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 0.3 } + values: list[vec2] = { + { 1.5, 1 } + { 0.75, 1 } + } + } + } + uvRotation: embed = ValueFloat { + constantValue: f32 = 90 + } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Udyr_Base_VGU_Awaken_Line_Hori.Zaahen.tex" + texAddressModeMult: u8 = 2 + uvScaleMult: embed = ValueVector2 { + constantValue: vec2 = { 1, 2 } + } + birthUVOffsetMult: embed = ValueVector2 { + constantValue: vec2 = { 0, 0.6 } + } + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 3 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.1 + } + isSingleParticle: flag = true + emitterName: string = "flash5" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { -5, 0, 0 } + } + FlexShapeDefinition: pointer = VfxFlexShapeDefinitionData { + scaleBirthScaleByBoundObjectSize: f32 = 0.005 + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.92156863, 0.7607843, 0.49019608, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 0.3, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 0.92156863, 0.7607843, 0.49019608, 1 } + { 0.79681087, 0.6157626, 0.2843824, 0.8509804 } + { 0.38844892, 0.077149615, 0.077149615, 0 } + } + } + } + pass: i16 = 5000 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + constantValue: f32 = 0 + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 1 } + values: list[f32] = { 0, 0 } + } + } + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Darius_Skin43_Star_Flash.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + 0xcb13aff1: f32 = -40 + isRandomStartFrame: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 1, 0, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 1, 0, 0 } } + } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 70, 70, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.75, 2 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.75, 2 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 70, 70, 1 } } + } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 1.5, 1.5, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.2, 1 } + values: list[vec3] = { + { 0.3, 0.3, 0.2 } + { 1.5, 1.5, 1 } + { 3, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Darius_Skin43_Star_Flash.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 5 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.25 + } + emitterName: string = "Basic7" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + FlexShapeDefinition: pointer = VfxFlexShapeDefinitionData { + scaleBirthScaleByBoundObjectSize: f32 = 0.01 + scaleEmitOffsetByBoundObjectSize: f32 = 0.01 + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.54509807, 0.41960785, 0.11764706, 0.6313726 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 0.8, 1 } + values: list[vec4] = { + { 0.9292134, 0.8355535, 0.61007094, 0 } + { 0.87878233, 0.7537499, 0.45278096, 0.6313726 } + { 0.54509807, 0.41960785, 0.11764706, 1 } + { 0.20909438, 0.15808347, 0.03527886, 0 } + } + } + } + pass: i16 = 10 + alphaRef: u8 = 0 + softParticleParams: pointer = VfxSoftParticleDefinitionData { + beginIn: f32 = 10 + deltaIn: f32 = 100 + } + 0xcb13aff1: f32 = -40 + isUniformScale: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 360, 0, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 360, 0, 0 } } + } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 100, 10, 0 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 0, 1, 1 } + { 1, 1, 1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Tryndamere_Skin18_Impact_Burst.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 10 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.5 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.2, 1.5 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 0.5 } + } + } + emitterName: string = "Embers" + birthOrbitalVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, 1, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 1, 0 } } + } + } + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 600, 600, 600 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 600, 600, 600 } } + } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 5, 5, 5 } + } + worldAcceleration: embed = IntegratedValueVector3 { + constantValue: vec3 = { 0, 100, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.75, 1.25 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 100, 0 } } + } + } + bindWeight: embed = ValueFloat { + constantValue: f32 = 0.1 + } + SpawnShape: pointer = VfxShapeBox { + flags: u8 = 1 + Size: vec3 = { 10, 10, 10 } + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 50, 0, 0 } + } + blendMode: u8 = 5 + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 0.3, 0.6, 1 } + values: list[vec4] = { + { 0.9254902, 0.7294118, 0.46666667, 0 } + { 0.9254902, 0.7294118, 0.46666667, 1 } + { 0.54509807, 0.41960785, 0.11764706, 1 } + { 0.2901961, 0.21568628, 0.039215688, 1 } + { 0.1686122, 0.12777905, 0.03103685, 0 } + } + } + } + pass: i16 = 10 + softParticleParams: pointer = VfxSoftParticleDefinitionData { + beginIn: f32 = 10 + deltaIn: f32 = 100 + } + isDirectionOriented: flag = true + isUniformScale: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 1, 0, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 1, 0, 0 } } + } + } + birthRotationalVelocity0: embed = ValueVector3 { + constantValue: vec3 = { 300, 0, 0 } + } + directionVelocityScale: f32 = 0.009 + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 30, 60, 50 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.2, 1 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 30, 60, 50 } } + } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.1, 0.13, 0.4, 0.5, 1 } + values: list[vec3] = { + { 0, 0, 0 } + { 1.2, 1, 1 } + { 1, 1, 1 } + { 1, 0.5, 1 } + { 1, 0.5, 1 } + { 0, 0, 1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Morgana_Base_P_StardustMoteAlpha.Zaahen.tex" + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.15 + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = -1 + } + lifetime: option[f32] = { 0.5 } + isSingleParticle: flag = true + emitterName: string = "CameraFacingFlash2" + IsEmitterSpace: flag = true + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.26999313, 0.059998475, 0.050003815, 1 } + } + pass: i16 = -450 + alphaRef: u8 = 0 + softParticleParams: pointer = VfxSoftParticleDefinitionData { + beginIn: f32 = 10 + deltaIn: f32 = 100 + } + 0xcb13aff1: f32 = -40 + isUniformScale: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 200, 60, 0 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.8, 1 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 1, 1, 1 } } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Aura_Self.Zaahen.tex" + texAddressModeBase: u8 = 2 + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 150 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.2 + } + emitterName: string = "GOLD_LightGlow1" + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, 125 } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, 0.5 } + } + primitive: pointer = VfxPrimitiveCameraTrail { + mTrail: embed = VfxTrailDefinitionData { + mMode: u8 = 1 + mBirthTilingSize: embed = ValueVector3 { + constantValue: vec3 = { 800, 0, 0 } + } + mSmoothingMode: u8 = 1 + } + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.26999313, 0.059998475, 0.050003815, 0.4899977 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 0.8, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 0.9254902, 0.7607843, 0.4745098, 1 } + { 0.5600061, 0.41855496, 0.17264058, 0.53333336 } + { 0.16159303, 0.10722515, 0.12523079, 0 } + } + } + } + pass: i16 = -20 + alphaRef: u8 = 0 + useNavmeshMask: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 55, 2, 2 } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 0.8, 0.8, 0.8 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.07960199, 0.14004976, 0.39546493, 0.77527076, 1 } + values: list[vec3] = { + { 0.32000002, 0.32000002, 0.32000002 } + { 0.71999997, 0.71999997, 0.71999997 } + { 0.7961644, 0.7961644, 0.7961644 } + { 0.72706515, 0.7961644, 0.7961644 } + { 0.3814612, 0.4, 0.4 } + { 0.24000001, 0.24000001, 0.24000001 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/common_color-bellcurve32.Zaahen.tex" + uvRotation: embed = ValueFloat { + constantValue: f32 = 90 + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 17 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.3 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 0.3 } + } + } + lifetime: option[f32] = { 0.1 } + emitterName: string = "START4" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/fireball.Zaahen.SCB" + } + AlignPitchToCamera: bool = true + AlignYawToCamera: bool = true + 0x6aec9e7a: bool = true + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 1, 1, 0.2500038 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.2, 0.8, 1 } + values: list[vec4] = { + { 0.10980392, 0, 0.03137255, 0 } + { 0.8841077, 0.7521172, 0.49758145, 1 } + { 0.10980392, 0, 0.03137255, 1 } + { 0.10980392, 0, 0.03137255, 0 } + } + } + } + pass: i16 = 710 + colorLookUpScales: vec2 = { 1, 0 } + alphaRef: u8 = 0 + softParticleParams: pointer = VfxSoftParticleDefinitionData { + deltaIn: f32 = 10 + } + 0xcb13aff1: f32 = -40 + disableBackfaceCull: bool = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 0, 0 } + } + isLocalOrientation: flag = false + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 25, 25, 1 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.3, 1 } + values: list[vec3] = { + { 0, 0, 0 } + { 1.2, 1.2, 1 } + { 0.1, 0.1, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Foundation_Tile01.Zaahen.tex" + birthUVOffset: embed = ValueVector2 { + constantValue: vec2 = { 1, 0.5 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec2] = { { 1, 0.5 } } + } + } + particleUVScrollRate: embed = IntegratedValueVector2 { + constantValue: vec2 = { -1, 0 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec2] = { + { 4, 0 } + { -1, 0 } + } + } + } + uvScale: embed = ValueVector2 { + constantValue: vec2 = { 3, 2 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 0.3 } + values: list[vec2] = { + { 3, 2 } + { 1.5, 2 } + } + } + } + uvRotation: embed = ValueFloat { + constantValue: f32 = 90 + } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Udyr_Base_VGU_Awaken_Line_Hori.Zaahen.tex" + texAddressModeMult: u8 = 2 + uvScaleMult: embed = ValueVector2 { + constantValue: vec2 = { 1, 2 } + } + birthUVOffsetMult: embed = ValueVector2 { + constantValue: vec2 = { 0, 0.6 } + } + } + } + } + particleName: string = "Zaahen_Base_Q_2_Buff" + particlePath: string = "Characters/Zaahen/Skins/Skin0/Particles/Zaahen_Base_Q_2_Buff" + soundPersistentDefault: string = "Play_sfx_Zaahen_ZaahenQ2_buffactivate" + flags: u16 = 1236 + } + "Characters/Zaahen/Skins/Skin0/Particles/Zaahen_Base_R_DR" = VfxSystemDefinitionData { + complexEmitterDefinitionData: list[pointer] = { + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 4 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 1 + } + lifetime: option[f32] = { 2 } + isSingleParticle: flag = true + emitterName: string = "subtract_ring" + importance: u8 = 3 + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 100, 0 } + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.36714733, 0.023498895, 0, 1 } + } + Color: embed = ValueColor { + constantValue: vec4 = { 1, 1, 1, 0.9882353 } + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.25, 0.65254235, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 0.9882353 } + { 1, 1, 1, 0.9882353 } + { 1, 1, 1, 0 } + } + } + } + alphaRef: u8 = 3 + softParticleParams: pointer = VfxSoftParticleDefinitionData { + deltaIn: f32 = 30 + } + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.59021205, 0.7109951, 1 } + values: list[f32] = { 0.2, 0.25477734, 0.8769231, 1.3 } + } + } + erosionFeatherIn: f32 = 0.3 + erosionFeatherOut: f32 = 0.3 + erosionSliceWidth: f32 = 1 + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Skin01/Particles/Warwick_Skin01_R_DeflectionRipples.Zaahen.tex" + erosionMapAddressMode: u8 = 0 + } + 0xcb13aff1: f32 = -50 + miscRenderFlags: u8 = 1 + isUniformScale: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 0, 0 } + } + isLocalOrientation: flag = false + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 145, 90, 1 } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_w_GlowAlpha.Zaahen.tex" + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Idle_Flare01.Zaahen.tex" + } + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.1 + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 1 + } + lifetime: option[f32] = { 2 } + isSingleParticle: flag = true + emitterName: string = "Ripple4" + importance: u8 = 3 + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 100, 0 } + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 0.089662015, 0, 0.7490196 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.17776181, 0.4, 0.70232034, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 0.9098039 } + { 1, 1, 1, 1 } + { 1, 0.48000306, 0, 0.9716599 } + { 0, 0, 0, 0 } + } + } + } + pass: i16 = 300 + alphaRef: u8 = 0 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.59021205, 0.7109951, 1 } + values: list[f32] = { 0.2, 0.25477734, 0.8769231, 1.3 } + } + } + erosionFeatherIn: f32 = 0.3 + erosionFeatherOut: f32 = 0.3 + erosionSliceWidth: f32 = 1 + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Skin01/Particles/Warwick_Skin01_R_DeflectionRipples.Zaahen.tex" + erosionMapAddressMode: u8 = 0 + } + isUniformScale: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 360, 360, 0 } + } + birthRotationalVelocity0: embed = ValueVector3 { + constantValue: vec3 = { -50, 0, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 185, 100, 100 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 0.5, 0.50001 } + keyValues: list[f32] = { -1, -1, 1 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 185, 100, 100 } } + } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { -0.0068547283, 0.052767638, 0.07892721, 0.15084541 } + values: list[vec3] = { + { 1.6340376, 1.6340376, 1.6340376 } + { 1.1262798, 1.1174709, 1.1174709 } + { 1.0541978, 1.0571743, 1.0571743 } + { 1.003959, 1.003959, 1.003959 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/AurelionSol_Base_R_Ringlight.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 1 + } + lifetime: option[f32] = { 2 } + isSingleParticle: flag = true + emitterName: string = "Ripple6" + importance: u8 = 3 + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 100, 0 } + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 0.14633402, 0, 0.3882353 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.25, 0.5, 0.75, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0.42999923 } + { 1, 1, 1, 0.17999542 } + { 0, 0, 0, 0 } + } + } + } + pass: i16 = 105 + alphaRef: u8 = 0 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.59021205, 0.7109951, 1 } + values: list[f32] = { 0.2, 0.25477734, 0.8769231, 1.3 } + } + } + erosionFeatherIn: f32 = 0.3 + erosionFeatherOut: f32 = 0.3 + erosionSliceWidth: f32 = 1 + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Skin01/Particles/Warwick_Skin01_R_DeflectionRipples.Zaahen.tex" + erosionMapAddressMode: u8 = 0 + } + miscRenderFlags: u8 = 1 + isUniformScale: flag = true + isGroundLayer: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 360, 360, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 360, 360, 0 } } + } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 150, 100, 100 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 0.5, 0.50001 } + keyValues: list[f32] = { -1, -1, 1 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 150, 100, 100 } } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Generic_GroundBaseLayer.Zaahen.tex" + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.1 + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.7 + } + isSingleParticle: flag = true + emitterLinger: option[f32] = { -2 } + emitterName: string = "Ripple10" + importance: u8 = 3 + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 100, 0 } + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 0.6070191, 0.2554818, 0.9607843 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.39365673, 0.5541045, 0.76679105, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 0, 0, 0, 0 } + } + } + } + pass: i16 = 500 + alphaRef: u8 = 0 + miscRenderFlags: u8 = 1 + isUniformScale: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 360, 360, 0 } + } + birthRotationalVelocity0: embed = ValueVector3 { + constantValue: vec3 = { -50, 0, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 150, 100, 100 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 0.5, 0.50001 } + keyValues: list[f32] = { -1, -1, 1 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 150, 100, 100 } } + } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.25, 0.5, 1 } + values: list[vec3] = { + { 1, 1, 1 } + { 0.96, 0.96, 0.96 } + { 1, 1, 1 } + { 0.96, 0.96, 0.96 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Aura_Self.Zaahen.tex" + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.1 + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 1 + } + lifetime: option[f32] = { 2 } + isSingleParticle: flag = true + emitterName: string = "Ripple14" + importance: u8 = 3 + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 100, 0 } + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 0.93000686, 0.8299992, 0.5000076 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 0.4205339, 0.5, 1 } + values: list[vec4] = { + { 1, 0.6973373, 0, 0 } + { 1, 0.60999465, 0, 0.4399939 } + { 1, 0.5001602, 0, 1 } + { 1, 0.48000306, 0, 0.6399939 } + { 0, 0, 0, 0 } + } + } + } + pass: i16 = 300 + alphaRef: u8 = 0 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.59021205, 0.7109951, 1 } + values: list[f32] = { 0.2, 0.25477734, 0.8769231, 1.3 } + } + } + erosionFeatherIn: f32 = 0.3 + erosionFeatherOut: f32 = 0.3 + erosionSliceWidth: f32 = 1 + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Skin01/Particles/Warwick_Skin01_R_DeflectionRipples.Zaahen.tex" + erosionMapAddressMode: u8 = 0 + } + particleIsLocalOrientation: flag = true + isUniformScale: flag = true + TextureFlipV: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 30, 0, 0 } + } + isLocalOrientation: flag = false + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 150, 100, 100 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 0.5, 0.50001 } + keyValues: list[f32] = { -1, -1, 1 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 150, 100, 100 } } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_R_Fire_Trail_Up.Zaahen.tex" + birthFrameRate: embed = ValueFloat { + constantValue: f32 = 0 + } + numFrames: u16 = 0 + texAddressModeBase: u8 = 2 + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_R_Warning.Zaahen.tex" + } + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.1 + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.7 + } + isSingleParticle: flag = true + emitterLinger: option[f32] = { -2 } + emitterName: string = "Ripple16" + importance: u8 = 3 + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 100, 0 } + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 0.29575035, 0.24800488, 0.54901963 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.39365673, 0.5541045, 0.76679105, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 0, 0, 0, 0 } + } + } + } + pass: i16 = 500 + alphaRef: u8 = 0 + miscRenderFlags: u8 = 1 + isUniformScale: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 360, 360, 0 } + } + birthRotationalVelocity0: embed = ValueVector3 { + constantValue: vec3 = { -50, 0, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 250, 100, 100 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 0.5, 0.50001 } + keyValues: list[f32] = { -1, -1, 1 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 250, 100, 100 } } + } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0.2979711, 0.58076644, 0.77129585, 1 } + values: list[vec3] = { + { 1.0005662, 1, 1 } + { 1.7895775, 1.7895775, 1.7895775 } + { 1.631811, 1.633711, 1.633711 } + { 0.96, 0.96, 0.96 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Cassiopeia_Skin38_Assets_1_369.Zaahen.tex" + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.1 + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 1 + } + lifetime: option[f32] = { 2 } + isSingleParticle: flag = true + emitterName: string = "Ripple17" + importance: u8 = 3 + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 100, 0 } + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 0.4688487, 0.39424735, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.06811245, 0.23930389, 0.4013387, 0.59243643, 0.8486613, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 0.029160839 } + { 1, 1, 1, 0.993007 } + { 1, 1, 1, 0.95804197 } + { 1, 1, 1, 0.7937063 } + { 0.65897614, 0.65897614, 0.65897614, 0.16853146 } + { 0, 0, 0, 0 } + } + } + } + pass: i16 = 300 + alphaRef: u8 = 0 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.59021205, 0.7109951, 1 } + values: list[f32] = { 0.2, 0.25477734, 0.8769231, 1.3 } + } + } + erosionFeatherIn: f32 = 0.3 + erosionFeatherOut: f32 = 0.3 + erosionSliceWidth: f32 = 1 + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Skin01/Particles/Warwick_Skin01_R_DeflectionRipples.Zaahen.tex" + erosionMapAddressMode: u8 = 0 + } + isUniformScale: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 360, 360, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 360, 360, 0 } } + } + } + birthRotationalVelocity0: embed = ValueVector3 { + constantValue: vec3 = { 15, 0, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 160, 100, 100 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 0.5, 0.50001 } + keyValues: list[f32] = { -1, -1, 1 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 160, 100, 100 } } + } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.25, 0.5, 1 } + values: list[vec3] = { + { 1, 1, 1 } + { 0.96, 0.96, 0.96 } + { 1, 1, 1 } + { 0.96, 0.96, 0.96 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/XinZhaoRework_Base_R_CredscentEdge_FlashFrame.Zaahen.tex" + } + } + particleName: string = "Zaahen_Base_R_DR" + particlePath: string = "Characters/Zaahen/Skins/Skin0/Particles/Zaahen_Base_R_DR" + } + "Characters/Zaahen/Skins/Skin0/Particles/Zaahen_Base_Emote_Joke" = VfxSystemDefinitionData { + complexEmitterDefinitionData: list[pointer] = { + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 25 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.65 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.2, 1 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 0.65 } + } + } + lifetime: option[f32] = { 0.35 } + emitterName: string = "Flames_Head8" + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 200, 80, 50 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 200, 80, 50 } } + } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 4, 4, 4 } + } + worldAcceleration: embed = IntegratedValueVector3 { + constantValue: vec3 = { 0, 150, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 150, 0 } } + } + } + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + SpawnShape: pointer = VfxShapeBox { + flags: u8 = 1 + Size: vec3 = { 2, 2, 2 } + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 5, -1.5, 0 } + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.9085985, 0.56351566, 0.36530098, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 0.4, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 0.33821622, 0.33821622, 0.33821622, 0 } + } + } + } + pass: i16 = 20 + isDirectionOriented: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 1, 1, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 1, 1, 1 } } + } + } + directionVelocityScale: f32 = 0.002 + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 9, 8, 30 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.8, 1.25 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.8, 1.3 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.8, 1.25 } + } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 9, 8, 30 } } + } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 0.5, 0.7, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.4, 0.6, 1 } + values: list[vec3] = { + { 0.25, 0.35, 0.5 } + { 1, 2.1, 2 } + { 0.5, 1.4, 2 } + { 0.25, 0.7, 1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Flames.Zaahen.tex" + uvMode: u8 = 2 + birthUvScrollRate: embed = ValueVector2 { + constantValue: vec2 = { 0.25, 0.55 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 2 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 2 } + } + } + times: list[f32] = { 0 } + values: list[vec2] = { { 0.25, 0.55 } } + } + } + birthUVOffset: embed = ValueVector2 { + constantValue: vec2 = { 1, 1 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec2] = { { 1, 1 } } + } + } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Flames.Zaahen.tex" + birthUvScrollRateMult: embed = ValueVector2 { + constantValue: vec2 = { 0.6, 0.5 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 1, -0.2 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 1, -0.2 } + } + } + times: list[f32] = { 0 } + values: list[vec2] = { { 0.6, 0.5 } } + } + } + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 25 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.65 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.2, 1 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 0.65 } + } + } + lifetime: option[f32] = { 0.35 } + emitterName: string = "Flames_Head9" + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { -200, 80, 50 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec3] = { { -200, 80, 50 } } + } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 4, 4, 4 } + } + worldAcceleration: embed = IntegratedValueVector3 { + constantValue: vec3 = { 0, 150, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 150, 0 } } + } + } + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + SpawnShape: pointer = VfxShapeBox { + flags: u8 = 1 + Size: vec3 = { 2, 2, 2 } + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { -5, -1.5, 0 } + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.9085985, 0.56351566, 0.36530098, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 0.4, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 0.33821622, 0.33821622, 0.33821622, 0 } + } + } + } + pass: i16 = 20 + isDirectionOriented: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 1, 1, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 1, 1, 1 } } + } + } + directionVelocityScale: f32 = 0.002 + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 9, 8, 30 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.8, 1.25 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.8, 1.3 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.8, 1.25 } + } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 9, 8, 30 } } + } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 0.5, 0.7, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.4, 0.6, 1 } + values: list[vec3] = { + { 0.25, 0.35, 0.5 } + { 1, 2.1, 2 } + { 0.5, 1.4, 2 } + { 0.25, 0.7, 1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Flames.Zaahen.tex" + uvMode: u8 = 2 + birthUvScrollRate: embed = ValueVector2 { + constantValue: vec2 = { 0.25, 0.55 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 2 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 2 } + } + } + times: list[f32] = { 0 } + values: list[vec2] = { { 0.25, 0.55 } } + } + } + birthUVOffset: embed = ValueVector2 { + constantValue: vec2 = { 1, 1 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec2] = { { 1, 1 } } + } + } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Flames.Zaahen.tex" + birthUvScrollRateMult: embed = ValueVector2 { + constantValue: vec2 = { 0.6, 0.5 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 1, -0.2 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 1, -0.2 } + } + } + times: list[f32] = { 0 } + values: list[vec2] = { { 0.6, 0.5 } } + } + } + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.55 + } + lifetime: option[f32] = { 0.12 } + isSingleParticle: flag = true + emitterName: string = "glowFast_Add1" + Linger: pointer = VfxLingerDefinitionData { + UseSeparateLingerColor: flag = true + SeparateLingerColor: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + } + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, -1.5, 0 } + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.93333334, 0.85882354, 0.627451, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.01, 0.7, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = 11 + colorLookUpScales: vec2 = { 1, 0.8 } + alphaRef: u8 = 0 + colorLookUpOffsets: vec2 = { 0, 0.3 } + miscRenderFlags: u8 = 1 + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 0, 0 } + } + isLocalOrientation: flag = false + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 13, 16, 1 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.1, 0.5, 1 } + values: list[vec3] = { + { 0.25, 0.25, 1 } + { 4.5, 4.5, 1 } + { 0.25, 5, 1 } + { 0.12, 5, 1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Star_Flare.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 2 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.5 + } + particleLingerType: u8 = 1 + lifetime: option[f32] = { 0.5 } + isSingleParticle: flag = true + emitterName: string = "Flash_Ground5" + importance: u8 = 3 + Linger: pointer = VfxLingerDefinitionData { + UseSeparateLingerColor: flag = true + SeparateLingerColor: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + } + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.9085985, 0.56351566, 0.36530098, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.05, 0.7, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = 15 + miscRenderFlags: u8 = 1 + particleIsLocalOrientation: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 10, 10, 100 } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 0.75, 0.75, 0.75 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 0.375, 0.75, 0 } + { 0.75, 0.75, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Aura_Self.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.5 + } + lifetime: option[f32] = { 0.12 } + isSingleParticle: flag = true + emitterName: string = "SunSpot_arbitrary2" + importance: u8 = 3 + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 0, 0 } } + } + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.8899977, 0.6299992, 0.3600061, 0.8 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 0.8, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = -10 + alphaRef: u8 = 0 + miscRenderFlags: u8 = 1 + particleIsLocalOrientation: flag = true + isUniformScale: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 0, 90, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 15, 70, 1 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 1, 1, 1 } + { 0.8, 0.8, 0.8 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Aura_Self.Zaahen.tex" + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.3 + rate: embed = ValueFloat { + constantValue: f32 = 15 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 1.5 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 1.5 } + } + } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "sparks_2" + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 500, 0, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 500, 0, 0 } } + } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 5, 5, 5 } + } + bindWeight: embed = ValueFloat { + constantValue: f32 = 0.1 + } + SpawnShape: pointer = VfxShapeLegacy { + emitOffset: embed = ValueVector3 { + constantValue: vec3 = { 10, 0, 10 } + } + emitRotationAngles: list[embed] = { + ValueFloat { + constantValue: f32 = 1 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 1 } + } + } + } + emitRotationAxes: list[vec3] = { { 0, 0, 1 } } + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.8, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec4] = { { 1, 1, 1, 1 } } + } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.05, 0.8, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = 20 + colorLookUpScales: vec2 = { 1, 0.8 } + alphaRef: u8 = 0 + colorLookUpOffsets: vec2 = { 0, 0.3 } + 0xcb13aff1: f32 = -20 + miscRenderFlags: u8 = 1 + isDirectionOriented: flag = true + isUniformScale: flag = true + isRandomStartFrame: flag = true + isLocalOrientation: flag = false + directionVelocityScale: f32 = 0.05 + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 5, 40, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 5, 40, 1 } } + } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 1, 1.25, 1.25 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 1, 2 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 1, 2 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 1, 2 } + } + } + times: list[f32] = { 0, 0.20474903, 1 } + values: list[vec3] = { + { 0, 1.25, 0 } + { 1, 1, 0 } + { 0, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_R_Sparks.Zaahen.tex" + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 2.3 + rate: embed = ValueFloat { + constantValue: f32 = 3 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.5 + } + lifetime: option[f32] = { 3.2 } + emitterName: string = "Glow_Light_Flames1" + importance: u8 = 3 + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { -20, 5, 0 } + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.9108568, 0.5272755, 0.12884718, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.5, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = 10 + alphaRef: u8 = 0 + miscRenderFlags: u8 = 1 + particleIsLocalOrientation: flag = true + isUniformScale: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 0, 90, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 25, 70, 1 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 1, 1, 1 } + { 0.8, 0.8, 0.8 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Aura_Self.Zaahen.tex" + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 2.3 + rate: embed = ValueFloat { + constantValue: f32 = 3 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.5 + } + lifetime: option[f32] = { 3.2 } + emitterName: string = "Glow_Light_Flames_2" + importance: u8 = 3 + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 20, 5, 0 } + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.8726787, 0.51500726, 0.14349584, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.5, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = 10 + alphaRef: u8 = 0 + miscRenderFlags: u8 = 1 + particleIsLocalOrientation: flag = true + isUniformScale: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 0, 90, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 25, 70, 1 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 1, 1, 1 } + { 0.8, 0.8, 0.8 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Aura_Self.Zaahen.tex" + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 2.3 + rate: embed = ValueFloat { + constantValue: f32 = 25 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.5 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.2, 1 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 0.5 } + } + } + lifetime: option[f32] = { 3.3 } + emitterName: string = "Flames_Head12" + importance: u8 = 3 + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 230, 80, 50 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 230, 80, 50 } } + } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 4, 4, 4 } + } + worldAcceleration: embed = IntegratedValueVector3 { + constantValue: vec3 = { 0, 150, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 150, 0 } } + } + } + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + SpawnShape: pointer = VfxShapeBox { + flags: u8 = 1 + Size: vec3 = { 2, 2, 2 } + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 5, -1.5, 0 } + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.9882353, 0.81960785, 0.24313726, 0.5882353 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.2, 0.4, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 0.33821622, 0.33821622, 0.33821622, 0 } + } + } + } + pass: i16 = 20 + isDirectionOriented: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 1, 1, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 1, 1, 1 } } + } + } + directionVelocityScale: f32 = 0.002 + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 9, 9, 30 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.8, 1.25 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.8, 1.3 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.8, 1.25 } + } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 9, 9, 30 } } + } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 0.5, 0.8, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.2, 0.6, 1 } + values: list[vec3] = { + { 0.25, 0.4, 0.5 } + { 1, 2.4, 2 } + { 0.5, 1.6, 2 } + { 0.25, 0.8, 1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Flames.Zaahen.tex" + uvMode: u8 = 2 + birthUvScrollRate: embed = ValueVector2 { + constantValue: vec2 = { 0.25, 0.55 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 2 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 2 } + } + } + times: list[f32] = { 0 } + values: list[vec2] = { { 0.25, 0.55 } } + } + } + birthUVOffset: embed = ValueVector2 { + constantValue: vec2 = { 1, 1 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec2] = { { 1, 1 } } + } + } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Flames.Zaahen.tex" + birthUvScrollRateMult: embed = ValueVector2 { + constantValue: vec2 = { 0.6, 0.5 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 1, -0.2 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 1, -0.2 } + } + } + times: list[f32] = { 0 } + values: list[vec2] = { { 0.6, 0.5 } } + } + } + } + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 2.3 + rate: embed = ValueFloat { + constantValue: f32 = 25 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.5 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.2, 1 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 0.5 } + } + } + lifetime: option[f32] = { 3.3 } + emitterName: string = "Flames_Head13" + importance: u8 = 3 + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { -150, 80, 50 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec3] = { { -150, 80, 50 } } + } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 4, 4, 4 } + } + worldAcceleration: embed = IntegratedValueVector3 { + constantValue: vec3 = { 0, 150, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 150, 0 } } + } + } + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + SpawnShape: pointer = VfxShapeBox { + flags: u8 = 1 + Size: vec3 = { 2, 2, 2 } + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { -6, -1.5, 0 } + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.9882353, 0.81960785, 0.24313726, 0.5882353 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.2, 0.4, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 0.33821622, 0.33821622, 0.33821622, 0 } + } + } + } + pass: i16 = 20 + isDirectionOriented: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 1, 1, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 1, 1, 1 } } + } + } + directionVelocityScale: f32 = 0.002 + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 9, 9, 30 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.8, 1.25 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.8, 1.3 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.8, 1.25 } + } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 9, 9, 30 } } + } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 0.5, 0.8, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.2, 0.6, 1 } + values: list[vec3] = { + { 0.25, 0.4, 0.5 } + { 1, 2.4, 2 } + { 0.5, 1.6, 2 } + { 0.25, 0.8, 1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Flames.Zaahen.tex" + uvMode: u8 = 2 + birthUvScrollRate: embed = ValueVector2 { + constantValue: vec2 = { 0.25, 0.55 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 2 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 2 } + } + } + times: list[f32] = { 0 } + values: list[vec2] = { { 0.25, 0.55 } } + } + } + birthUVOffset: embed = ValueVector2 { + constantValue: vec2 = { 1, 1 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec2] = { { 1, 1 } } + } + } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Flames.Zaahen.tex" + birthUvScrollRateMult: embed = ValueVector2 { + constantValue: vec2 = { 0.6, 0.5 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 1, -0.2 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 1, -0.2 } + } + } + times: list[f32] = { 0 } + values: list[vec2] = { { 0.6, 0.5 } } + } + } + } + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 2.3 + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 1.8 + } + lifetime: option[f32] = { 5 } + isSingleParticle: flag = true + emitterName: string = "glowFast5" + importance: u8 = 3 + Linger: pointer = VfxLingerDefinitionData { + UseSeparateLingerColor: flag = true + SeparateLingerColor: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + } + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, -1.5, 0 } + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.93333334, 0.85882354, 0.627451, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.01, 0.6, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = 22 + colorLookUpScales: vec2 = { 1, 0.8 } + alphaRef: u8 = 0 + colorLookUpOffsets: vec2 = { 0, 0.3 } + miscRenderFlags: u8 = 1 + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 0, 0 } + } + isLocalOrientation: flag = false + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 10, 15, 1 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.1, 0.5, 1 } + values: list[vec3] = { + { 0.25, 0.25, 1 } + { 5, 5, 1 } + { 0.2, 5, 1 } + { 0.12, 5, 1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Star_Flare.Zaahen.tex" + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 2.3 + rate: embed = ValueFloat { + constantValue: f32 = 5 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLingerType: u8 = 1 + lifetime: option[f32] = { 5 } + isSingleParticle: flag = true + emitterName: string = "Flash_Ground7" + importance: u8 = 3 + Linger: pointer = VfxLingerDefinitionData { + UseSeparateLingerColor: flag = true + SeparateLingerColor: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + } + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.9085985, 0.56351566, 0.36530098, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.05, 0.7, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = 15 + miscRenderFlags: u8 = 1 + particleIsLocalOrientation: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 10, 10, 100 } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 0.75, 0.75, 0.75 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 0.375, 0.75, 0 } + { 0.75, 0.75, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Aura_Self.Zaahen.tex" + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 3.25 + rate: embed = ValueFloat { + constantValue: f32 = 25 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 2 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 2 } + } + } + lifetime: option[f32] = { 3.5 } + emitterName: string = "sparks_3" + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 800, 0, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 800, 0, 0 } } + } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 7, 7, 7 } + } + bindWeight: embed = ValueFloat { + constantValue: f32 = 0.1 + } + SpawnShape: pointer = VfxShapeLegacy { + emitOffset: embed = ValueVector3 { + constantValue: vec3 = { 10, 0, 10 } + } + emitRotationAngles: list[embed] = { + ValueFloat { + constantValue: f32 = 1 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 1 } + } + } + } + emitRotationAxes: list[vec3] = { { 0, 0, 1 } } + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.8, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec4] = { { 1, 1, 1, 1 } } + } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.05, 0.8, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = 20 + colorLookUpScales: vec2 = { 1, 0.8 } + alphaRef: u8 = 0 + colorLookUpOffsets: vec2 = { 0, 0.3 } + 0xcb13aff1: f32 = -20 + miscRenderFlags: u8 = 1 + isDirectionOriented: flag = true + isUniformScale: flag = true + isRandomStartFrame: flag = true + isLocalOrientation: flag = false + directionVelocityScale: f32 = 0.035 + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 7, 40, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 7, 40, 1 } } + } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 1, 1.25, 1.25 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 1, 2 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 1, 2 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 1, 2 } + } + } + times: list[f32] = { 0, 0.1, 1 } + values: list[vec3] = { + { 0, 1.25, 0 } + { 1, 1, 0 } + { 0, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_R_Sparks.Zaahen.tex" + } + } + particleName: string = "Zaahen_Base_Emote_Joke" + particlePath: string = "Characters/Zaahen/Skins/Skin0/Particles/Zaahen_Base_Emote_Joke" + } + "Characters/Zaahen/Skins/Skin0/Particles/Zaahen_Base_W_Mis_Child" = VfxSystemDefinitionData { + complexEmitterDefinitionData: list[pointer] = { + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.05 + rate: embed = ValueFloat { + constantValue: f32 = 60 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.6 + } + particleLinger: option[f32] = { 1 } + lifetime: option[f32] = { 1.7 } + rateByVelocityFunction: embed = ValueVector2 { + constantValue: vec2 = { 0.1, 60 } + } + emitterName: string = "Trench_Ridges" + importance: u8 = 3 + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 50, 0 } + } + primitive: pointer = VfxPrimitiveArbitraryTrail { + mTrail: embed = VfxTrailDefinitionData { + mMode: u8 = 1 + mBirthTilingSize: embed = ValueVector3 { + constantValue: vec3 = { 700, 0, 0 } + } + } + } + particleColorTexture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/color-eyefade32.Zaahen.tex" + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 0.9328603, 0.79946595, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 0.7, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = -40 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0.3, 0.4, 0.8793395, 1 } + values: list[f32] = { 0, 0.09170306, 2, 1.5 } + } + } + erosionFeatherIn: f32 = 0.5 + erosionFeatherOut: f32 = 0.5 + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Base_SmokeErode.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + depthBiasFactors: vec2 = { -1, -40 } + miscRenderFlags: u8 = 1 + isGroundLayer: flag = true + useNavmeshMask: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 200, 1, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.1, 0.75, 0.9 } + values: list[vec3] = { + { 200, 0, 0 } + { 200, 0, 0 } + { 200, 0, 0 } + { 200, 0, 0 } + } + } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 1, 0, 0 } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_w_Trench1.Zaahen.tex" + texAddressModeBase: u8 = 2 + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 26 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.25 + } + particleLinger: option[f32] = { 10.4 } + lifetime: option[f32] = { 0.72 } + emitterName: string = "Basic" + importance: u8 = 3 + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, -200, 0 } + } + primitive: pointer = VfxPrimitiveArbitraryQuad { } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 1, 1, 0.5000076 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 0.3, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 0.4899977, 0.2, 0, 0 } + } + } + } + pass: i16 = -100 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0.3, 0.4, 1 } + values: list[f32] = { 0, 0.3, 1 } + } + } + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Base_SmokeErode.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + miscRenderFlags: u8 = 1 + particleIsLocalOrientation: flag = true + isRotationEnabled: flag = true + isGroundLayer: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 200, 350, 275 } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 1.2, 1.2, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.2, 1 } + values: list[vec3] = { + { 1.2, 1.2, 1 } + { 1.2, 1.2, 1 } + { 1.2, 1.2, 1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/RekSai_Base_R_ground_burn.Zaahen.tex" + texAddressModeBase: u8 = 2 + uvScale: embed = ValueVector2 { + constantValue: vec2 = { 1.25, 1.25 } + } + uvRotation: embed = ValueFloat { + constantValue: f32 = 360 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 360 } + } + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 25 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.35 + } + lifetime: option[f32] = { 1 } + emitterName: string = "Trench_Wake_Right" + importance: u8 = 3 + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, 50 } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 1, 0, 1 } + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { -100, 10, 0 } + } + primitive: pointer = VfxPrimitiveArbitraryQuad { } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 1, 1, 0.5000076 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 0.5, 1 } + values: list[vec4] = { + { 1, 0.70980394, 0.5803922, 0 } + { 0.60784316, 0.34509805, 0.28627452, 1 } + { 0.5254902, 0.40784314, 0.37254903, 0.5019608 } + { 0.38431373, 0.36862746, 0.36078432, 0 } + } + } + } + pass: i16 = 5 + alphaRef: u8 = 0 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.5, 1 } + values: list[f32] = { 0, 0, 1 } + } + } + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Gradient.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + miscRenderFlags: u8 = 1 + isDirectionOriented: flag = true + isRandomStartFrame: flag = true + isGroundLayer: flag = true + useNavmeshMask: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { -180, -180, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 120, 150, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.4, 1.1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.4, 1 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 120, 150, 0 } } + } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 1, 1, 1 } + { 0.6, 2, 1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Viktor_Base_GroundSmoke02.Zaahen.tex" + numFrames: u16 = 2 + texDiv: vec2 = { 1, 2 } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 25 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.35 + } + lifetime: option[f32] = { 1 } + emitterName: string = "Trench_Wake_Left" + importance: u8 = 3 + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, 50 } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 1, 0, 1 } + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 100, 10, 0 } + } + primitive: pointer = VfxPrimitiveArbitraryQuad { } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 1, 1, 0.5000076 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 0.5, 1 } + values: list[vec4] = { + { 1, 0.70980394, 0.5803922, 0 } + { 0.60784316, 0.34509805, 0.28627452, 1 } + { 0.5254902, 0.40784314, 0.37254903, 0.5019608 } + { 0.38431373, 0.36862746, 0.36078432, 0 } + } + } + } + pass: i16 = 5 + alphaRef: u8 = 0 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.5, 1 } + values: list[f32] = { 0, 0, 1 } + } + } + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Gradient.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + miscRenderFlags: u8 = 1 + isDirectionOriented: flag = true + isRandomStartFrame: flag = true + isGroundLayer: flag = true + useNavmeshMask: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 180, 0, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 120, 150, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.4, 1.1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.4, 1 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 120, 150, 0 } } + } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 1, 1, 1 } + { 0.6, 2, 1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Viktor_Base_GroundSmoke02.Zaahen.tex" + numFrames: u16 = 2 + texDiv: vec2 = { 1, 2 } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 200 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.4 + } + particleLinger: option[f32] = { 0.7 } + lifetime: option[f32] = { 0.3 } + emitterName: string = "Trench_Glow1" + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 1, 2, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.1, 1 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 1, 2, 1 } } + } + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 100, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 0, -200, 0 } + { 0, 50, 0 } + } + } + } + primitive: pointer = VfxPrimitiveArbitraryQuad { } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 1, 1, 0.2509804 } + } + Color: embed = ValueColor { + constantValue: vec4 = { 0.82912946, 0.82912946, 0.82912946, 1 } + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 0.2, 0.3, 1 } + values: list[vec4] = { + { 0.7671108, 0.66262037, 0.46570927, 0 } + { 0.7640997, 0.6307887, 0.406436, 1 } + { 0.7380878, 0.24061012, 0.081287205, 1 } + { 0.5441498, 0.07134296, 0.07134296, 1 } + { 0.1347027, 0.045622047, 0.053023294, 0 } + } + } + } + pass: i16 = -5 + alphaRef: u8 = 0 + miscRenderFlags: u8 = 1 + isRandomStartFrame: flag = true + isGroundLayer: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, 90 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 35, 35, 0 } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 2, 1, 1 } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Aura_Self.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 200 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.4 + } + particleLinger: option[f32] = { 0.1 } + lifetime: option[f32] = { 0.3 } + emitterLinger: option[f32] = { 0.05 } + emitterName: string = "Trench_Glow2" + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 1, 2, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.1, 1 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 1, 2, 1 } } + } + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 100, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 0, -200, 0 } + { 0, 50, 0 } + } + } + } + primitive: pointer = VfxPrimitiveArbitraryQuad { } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 1, 1, 0.6 } + } + Color: embed = ValueColor { + constantValue: vec4 = { 0.82912946, 0.82912946, 0.82912946, 1 } + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 0.2, 0.3, 1 } + values: list[vec4] = { + { 0.7671108, 0.66262037, 0.46570927, 0 } + { 0.7640997, 0.6307887, 0.406436, 1 } + { 0.7380878, 0.24061012, 0.081287205, 1 } + { 0.5441498, 0.07134296, 0.07134296, 1 } + { 0.1347027, 0.045622047, 0.053023294, 0 } + } + } + } + alphaRef: u8 = 0 + miscRenderFlags: u8 = 1 + isRandomStartFrame: flag = true + isGroundLayer: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, 90 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 30, 5, 0 } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 1, 1.5, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 1.5, 2.25, 1 } + { 2, 0.75, 2 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Aura_Self.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 200 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.4 + } + particleLinger: option[f32] = { 0.4 } + lifetime: option[f32] = { 0.4 } + emitterName: string = "Trail" + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, 1 } + } + primitive: pointer = VfxPrimitiveArbitraryTrail { + mTrail: embed = VfxTrailDefinitionData { + mMode: u8 = 1 + mCutoff: f32 = 3000 + mBirthTilingSize: embed = ValueVector3 { + constantValue: vec3 = { 1100, 0, 0 } + } + mSmoothingMode: u8 = 1 + } + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 1, 1, 0.4500038 } + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 0.8, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 0.4500038 } + { 1, 1, 1, 0.15300198 } + { 1, 1, 1, 0 } + } + } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.25, 1 } + values: list[vec4] = { + { 1, 0.87058824, 0.56078434, 0 } + { 1, 0.7647059, 0.38431373, 1 } + { 1, 0.3529412, 0.09803922, 0 } + } + } + } + pass: i16 = 10 + depthBiasFactors: vec2 = { -2, -800 } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 25, 0, 0 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.2, 1 } + values: list[vec3] = { + { 0.8, 0.5, 0.5 } + { 1, 1, 1 } + { 0.5, 0.5, 0.5 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Leona_Base_E_Wisps.Zaahen.tex" + particleUVScrollRate: embed = IntegratedValueVector2 { + constantValue: vec2 = { 0.2, 0 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0 } + values: list[vec2] = { { 0.2, 0 } } + } + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.3 + } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "widerGlow17" + importance: u8 = 3 + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, -400, 0 } + } + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 135, 0 } + } + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_W_Missile2.Zaahen.scb" + } + } + blendMode: u8 = 1 + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.15, 0.3, 0.85, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 0, 0, 0, 0 } + } + } + } + pass: i16 = 200 + meshRenderFlags: u8 = 0 + miscRenderFlags: u8 = 1 + isRotationEnabled: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 0, -90, -90 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 3.25, 4.5, 0.3 } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 1, 0.5, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0.8, 1 } + values: list[vec3] = { + { 1, 0.5, 1 } + { 1, 0, 1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_W_missile.Zaahen.tex" + paletteDefinition: pointer = VfxPaletteDefinitionData { + paletteTexture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_W_Gradient_RGB.Zaahen.tex" + paletteSelector: embed = ValueVector3 { + constantValue: vec3 = { 6, 0, 0 } + } + paletteCount: i32 = 8 + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.3 + } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "widerGlow19" + importance: u8 = 3 + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, -400, 0 } + } + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 135, 0 } + } + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_W_Missile2.Zaahen.scb" + } + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 1, 1, 0.2500038 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.15, 0.3, 0.85, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 0, 0, 0, 0 } + } + } + } + pass: i16 = 205 + meshRenderFlags: u8 = 0 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 1 } + values: list[f32] = { 1, 1 } + } + } + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_W_missile.Zaahen.tex" + } + miscRenderFlags: u8 = 1 + isRotationEnabled: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 0, -90, -90 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 3.25, 4.5, 0.3 } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 1, 0.5, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0.8, 1 } + values: list[vec3] = { + { 1, 0.5, 1 } + { 1, 0, 1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_W_missile.Zaahen.tex" + paletteDefinition: pointer = VfxPaletteDefinitionData { + paletteTexture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_W_Gradient_RGB.Zaahen.tex" + paletteSelector: embed = ValueVector3 { + constantValue: vec3 = { 6, 0, 0 } + } + paletteCount: i32 = 8 + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.3 + } + particleLingerType: u8 = 1 + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "FireSkirt_R_Flat1" + importance: u8 = 3 + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, -350, 0 } + } + Linger: pointer = VfxLingerDefinitionData { + UseKeyedLingerDrag: flag = true + KeyedLingerDrag: embed = ValueVector3 { + constantValue: vec3 = { 0, 1, 0 } + } + UseKeyedLingerVelocity: flag = true + KeyedLingerVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, 350, 0 } + } + SeparateLingerColor: embed = ValueColor { + constantValue: vec4 = { 0.4745098, 0.06666667, 0.06666667, 1 } + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 1 } + values: list[vec4] = { + { 0.4745098, 0.06666667, 0.06666667, 0.5000076 } + { 0.4745098, 0.06666667, 0.06666667, 0 } + } + } + } + } + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, -220, 0 } + } + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_W_MissileSkirt2.Zaahen.scb" + } + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.4745098, 0.06666667, 0.06666667, 1 } + } + pass: i16 = 1 + meshRenderFlags: u8 = 0 + depthBiasFactors: vec2 = { -1, -100 } + disableBackfaceCull: bool = true + isRotationEnabled: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 0, -90, -90 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 3, 5, 3.25 } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 1, 0.75, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 1, 0.75, 0.75 } + { 1, 0, 0.75 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Smolder_R_FireNoise_White_NoBlack.Zaahen.tex" + birthUvScrollRate: embed = ValueVector2 { + constantValue: vec2 = { 0, -2 } + } + birthUVOffset: embed = ValueVector2 { + constantValue: vec2 = { 0.1, 0.5 } + } + uvScale: embed = ValueVector2 { + constantValue: vec2 = { 1, 2 } + } + uvRotation: embed = ValueFloat { + constantValue: f32 = 90 + } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Gradient.Zaahen.tex" + UvRotationMult: embed = ValueFloat { + constantValue: f32 = 90 + } + birthUVOffsetMult: embed = ValueVector2 { + constantValue: vec2 = { 0, 0.25 } + } + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.3 + } + particleLingerType: u8 = 1 + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "FireSkirt_L_Flat1" + importance: u8 = 3 + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, -350, 0 } + } + Linger: pointer = VfxLingerDefinitionData { + UseKeyedLingerDrag: flag = true + KeyedLingerDrag: embed = ValueVector3 { + constantValue: vec3 = { 0, 1, 0 } + } + UseKeyedLingerVelocity: flag = true + KeyedLingerVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, 350, 0 } + } + SeparateLingerColor: embed = ValueColor { + constantValue: vec4 = { 0.4745098, 0.06666667, 0.06666667, 1 } + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 1 } + values: list[vec4] = { + { 0.4745098, 0.06666667, 0.06666667, 0.5000076 } + { 0.4745098, 0.06666667, 0.06666667, 0 } + } + } + } + } + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, -220, 0 } + } + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_W_MissileSkirt2.Zaahen.scb" + } + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.4745098, 0.06666667, 0.06666667, 1 } + } + pass: i16 = 1 + meshRenderFlags: u8 = 0 + depthBiasFactors: vec2 = { -1, -100 } + disableBackfaceCull: bool = true + isRotationEnabled: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 0, -90, -90 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 3, 5, -3.25 } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 1, 0.75, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 1, 0.75, 0.75 } + { 1, 0, 0.75 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Smolder_R_FireNoise_White_NoBlack.Zaahen.tex" + birthUvScrollRate: embed = ValueVector2 { + constantValue: vec2 = { 0, -2 } + } + birthUVOffset: embed = ValueVector2 { + constantValue: vec2 = { 0.1, 0.5 } + } + uvScale: embed = ValueVector2 { + constantValue: vec2 = { 1, 2 } + } + uvRotation: embed = ValueFloat { + constantValue: f32 = 90 + } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Gradient.Zaahen.tex" + UvRotationMult: embed = ValueFloat { + constantValue: f32 = 90 + } + birthUVOffsetMult: embed = ValueVector2 { + constantValue: vec2 = { 0, 0.25 } + } + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.3 + } + particleLingerType: u8 = 1 + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "FireSkirt_R_Flat2" + importance: u8 = 3 + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, -350, 0 } + } + Linger: pointer = VfxLingerDefinitionData { + UseKeyedLingerDrag: flag = true + KeyedLingerDrag: embed = ValueVector3 { + constantValue: vec3 = { 0, 1, 0 } + } + UseKeyedLingerVelocity: flag = true + KeyedLingerVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, 350, 0 } + } + SeparateLingerColor: embed = ValueColor { + constantValue: vec4 = { 0.4745098, 0.06666667, 0.06666667, 1 } + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 1 } + values: list[vec4] = { + { 0.4745098, 0.06666667, 0.06666667, 0.5000076 } + { 0.4745098, 0.06666667, 0.06666667, 0 } + } + } + } + } + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, -220, 0 } + } + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_W_MissileSkirt2.Zaahen.scb" + } + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.4745098, 0.06666667, 0.06666667, 1 } + } + pass: i16 = 1 + meshRenderFlags: u8 = 0 + depthBiasFactors: vec2 = { -1, -100 } + disableBackfaceCull: bool = true + isRotationEnabled: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 0, -90, -90 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 3, 5, 3.25 } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 1, 0.75, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 1, 0.75, 0.75 } + { 1, 0, 0.75 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_E_Gradient.Zaahen.tex" + birthUvScrollRate: embed = ValueVector2 { + constantValue: vec2 = { 0, -2 } + } + birthUVOffset: embed = ValueVector2 { + constantValue: vec2 = { 0.1, 0.5 } + } + texAddressModeBase: u8 = 2 + uvScale: embed = ValueVector2 { + constantValue: vec2 = { 1, 2 } + } + uvRotation: embed = ValueFloat { + constantValue: f32 = 90 + } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Gradient.Zaahen.tex" + UvRotationMult: embed = ValueFloat { + constantValue: f32 = 90 + } + birthUVOffsetMult: embed = ValueVector2 { + constantValue: vec2 = { 0, 0.25 } + } + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.3 + } + particleLingerType: u8 = 1 + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "FireSkirt_L_Flat2" + importance: u8 = 3 + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, -350, 0 } + } + Linger: pointer = VfxLingerDefinitionData { + UseKeyedLingerDrag: flag = true + KeyedLingerDrag: embed = ValueVector3 { + constantValue: vec3 = { 0, 1, 0 } + } + UseKeyedLingerVelocity: flag = true + KeyedLingerVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, 350, 0 } + } + SeparateLingerColor: embed = ValueColor { + constantValue: vec4 = { 0.4745098, 0.06666667, 0.06666667, 1 } + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 1 } + values: list[vec4] = { + { 0.4745098, 0.06666667, 0.06666667, 0.5000076 } + { 0.4745098, 0.06666667, 0.06666667, 0 } + } + } + } + } + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, -220, 0 } + } + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_W_MissileSkirt2.Zaahen.scb" + } + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.4745098, 0.06666667, 0.06666667, 1 } + } + pass: i16 = 1 + meshRenderFlags: u8 = 0 + depthBiasFactors: vec2 = { -1, -100 } + disableBackfaceCull: bool = true + isRotationEnabled: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 0, -90, -90 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 3, 5, -3.25 } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 1, 0.75, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 1, 0.75, 0.75 } + { 1, 0, 0.75 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_E_Gradient.Zaahen.tex" + birthUvScrollRate: embed = ValueVector2 { + constantValue: vec2 = { 0, -2 } + } + birthUVOffset: embed = ValueVector2 { + constantValue: vec2 = { 0.1, 0.5 } + } + texAddressModeBase: u8 = 2 + uvScale: embed = ValueVector2 { + constantValue: vec2 = { 1, 2 } + } + uvRotation: embed = ValueFloat { + constantValue: f32 = 90 + } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Gradient.Zaahen.tex" + UvRotationMult: embed = ValueFloat { + constantValue: f32 = 90 + } + birthUVOffsetMult: embed = ValueVector2 { + constantValue: vec2 = { 0, 0.25 } + } + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.3 + } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "widerGlow21" + importance: u8 = 3 + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, -400, 0 } + } + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + primitive: pointer = VfxPrimitiveArbitraryQuad { } + blendMode: u8 = 1 + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.15, 0.3, 0.85, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 0, 0, 0, 0 } + } + } + } + pass: i16 = 190 + meshRenderFlags: u8 = 0 + miscRenderFlags: u8 = 1 + isRotationEnabled: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 35, 150, 1 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0.8, 1 } + values: list[vec3] = { + { 1, 1, 1 } + { 0.5, 1, 1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_W_MissileHooks.Zaahen.tex" + paletteDefinition: pointer = VfxPaletteDefinitionData { + paletteTexture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_W_Gradient_RGB.Zaahen.tex" + paletteSelector: embed = ValueVector3 { + constantValue: vec3 = { 6, 0, 0 } + } + paletteCount: i32 = 8 + } + texAddressModeBase: u8 = 2 + uvRotation: embed = ValueFloat { + constantValue: f32 = 90 + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.3 + } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "widerGlow23" + importance: u8 = 3 + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, -400, 0 } + } + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + primitive: pointer = VfxPrimitiveArbitraryQuad { } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 1, 1, 0.2500038 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.15, 0.3, 0.85, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 0, 0, 0, 0 } + } + } + } + pass: i16 = 195 + meshRenderFlags: u8 = 0 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + constantValue: f32 = 0.75 + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 1 } + values: list[f32] = { 0.75, 0.75 } + } + } + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_W_MissileHooks.Zaahen.tex" + } + miscRenderFlags: u8 = 1 + isRotationEnabled: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 35, 150, 1 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0.8, 1 } + values: list[vec3] = { + { 1, 1, 1 } + { 0.5, 1, 1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_W_MissileHooks.Zaahen.tex" + paletteDefinition: pointer = VfxPaletteDefinitionData { + paletteTexture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_W_Gradient_RGB.Zaahen.tex" + paletteSelector: embed = ValueVector3 { + constantValue: vec3 = { 6, 0, 0 } + } + paletteCount: i32 = 8 + } + texAddressModeBase: u8 = 2 + uvRotation: embed = ValueFloat { + constantValue: f32 = 90 + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.35 + } + particleLinger: option[f32] = { 0.2 } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterLinger: option[f32] = { 0.2 } + emitterName: string = "ADD_Fire_Glow3" + importance: u8 = 3 + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, -400, 0 } + } + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + primitive: pointer = VfxPrimitiveArbitraryQuad { } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.77999544, 0.4500038, 0.11000229, 0.34999618 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.75, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 0, 0, 0, 0 } + } + } + } + pass: i16 = 500 + alphaRef: u8 = 0 + miscRenderFlags: u8 = 1 + particleIsLocalOrientation: flag = true + isRotationEnabled: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 0, 90, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 200, 300, 400 } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Aura_Self.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.35 + } + particleLinger: option[f32] = { 0.2 } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterLinger: option[f32] = { 0.2 } + emitterName: string = "ADD_Fire_Glow4" + importance: u8 = 3 + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, -400, 0 } + } + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + primitive: pointer = VfxPrimitiveArbitraryQuad { } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.77999544, 0.4500038, 0.11000229, 0.34999618 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.75, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 0, 0, 0, 0 } + } + } + } + alphaRef: u8 = 0 + miscRenderFlags: u8 = 1 + particleIsLocalOrientation: flag = true + isLocalOrientation: flag = false + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 200, 300, 400 } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Aura_Self.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.3 + } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "widerGlow25" + importance: u8 = 3 + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, -400, 0 } + } + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 130, 0 } + } + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_W_Missile2.Zaahen.scb" + } + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.7100023, 0.059998475, 0.059998475, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.15, 0.3, 0.85, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 0, 0, 0, 0 } + } + } + } + pass: i16 = 185 + meshRenderFlags: u8 = 0 + miscRenderFlags: u8 = 1 + isRotationEnabled: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 0, -90, -90 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 3.25, 4.5, 0.3 } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 1, 0.465, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0.8, 1 } + values: list[vec3] = { + { 1, 0.465, 1 } + { 1, 0, 1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_R_Slash_glow.Zaahen.tex" + paletteDefinition: pointer = VfxPaletteDefinitionData { + paletteTexture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_W_Gradient_RGB.Zaahen.tex" + paletteSelector: embed = ValueVector3 { + constantValue: vec3 = { 6, 0, 0 } + } + paletteCount: i32 = 8 + } + texAddressModeBase: u8 = 2 + uvRotation: embed = ValueFloat { + constantValue: f32 = 90 + } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Emote_Einstein_01_mult.Zaahen.tex" + birthUvScrollRateMult: embed = ValueVector2 { + constantValue: vec2 = { -2, 0 } + } + birthUvRotateRateMult: embed = ValueFloat { + constantValue: f32 = 180 + } + birthUVOffsetMult: embed = ValueVector2 { + constantValue: vec2 = { 1, 1 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec2] = { { 1, 1 } } + } + } + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.3 + } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "widerGlow29" + importance: u8 = 3 + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, -400, 0 } + } + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + primitive: pointer = VfxPrimitiveArbitraryQuad { } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 1, 1, 0.7199969 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.15, 0.3, 0.85, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 0, 0, 0, 0 } + } + } + } + pass: i16 = 197 + meshRenderFlags: u8 = 0 + alphaRef: u8 = 0 + miscRenderFlags: u8 = 1 + isRotationEnabled: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 35, 150, 1 } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 1.2, 1.1, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0.8, 1 } + values: list[vec3] = { + { 1.2, 1.1, 1 } + { 0.6, 1.1, 1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_W_MissileHooks_Glow.Zaahen.tex" + paletteDefinition: pointer = VfxPaletteDefinitionData { + paletteTexture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_W_Gradient_RGB.Zaahen.tex" + paletteSelector: embed = ValueVector3 { + constantValue: vec3 = { 6, 0, 0 } + } + paletteCount: i32 = 8 + } + texAddressModeBase: u8 = 2 + uvRotation: embed = ValueFloat { + constantValue: f32 = 90 + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.3 + } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "Trail2" + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, -400, 0 } + } + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 135, 0 } + } + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_W_MIssile3.Zaahen.scb" + } + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.919997, 0.7600061, 0.4899977, 0.4 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.15, 0.3, 0.85, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 0, 0, 0, 0 } + } + } + } + pass: i16 = 17 + alphaRef: u8 = 0 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + constantValue: f32 = 0 + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0.1, 0.5, 0.8 } + values: list[f32] = { 0, 0, 0 } + } + } + erosionSliceWidth: f32 = 2 + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_BA_Trail_Darkin_1.Zaahen.tex" + erosionMapAddressMode: u8 = 0 + } + disableBackfaceCull: bool = true + isRotationEnabled: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 0, -90, -90 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 3, 4.5, 0.3 } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 1, 0.5, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0.8, 1 } + values: list[vec3] = { + { 1, 0.5, 1 } + { 1, 0, 1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/common_color-bellcurve32.Zaahen.tex" + particleUVScrollRate: embed = IntegratedValueVector2 { + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0 } + values: list[vec2] = { { 0, 0 } } + } + } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/common_color-bellcurve32.Zaahen.tex" + texAddressModeMult: u8 = 2 + UvRotationMult: embed = ValueFloat { + constantValue: f32 = 90 + } + uvScaleMult: embed = ValueVector2 { + constantValue: vec2 = { 0.5, 1 } + } + birthUVOffsetMult: embed = ValueVector2 { + constantValue: vec2 = { -0.25, 0 } + } + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.35 + } + particleLinger: option[f32] = { 0.2 } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterLinger: option[f32] = { 0.2 } + emitterName: string = "ADD_Fire_Glow5" + importance: u8 = 3 + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, -400, 0 } + } + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + primitive: pointer = VfxPrimitiveArbitraryQuad { } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.77999544, 0.4500038, 0.11000229, 0.34999618 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.75, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 0, 0, 0, 0 } + } + } + } + pass: i16 = 500 + alphaRef: u8 = 0 + particleIsLocalOrientation: flag = true + isLocalOrientation: flag = false + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 200, 300, 400 } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Aura_Self.Zaahen.tex" + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.05 + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.3 + } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "widerGlow30" + importance: u8 = 3 + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, -400, 0 } + } + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 0.4399939, 0, 0.20999466 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.15, 0.3, 0.85, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0.7600061 } + { 0, 0, 0, 0 } + } + } + } + pass: i16 = 500 + meshRenderFlags: u8 = 0 + alphaRef: u8 = 0 + miscRenderFlags: u8 = 1 + isRotationEnabled: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 250, 250, 0 } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 1.2, 1.1, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0.8, 1 } + values: list[vec3] = { + { 1.2, 1.1, 1 } + { 0.6, 1.1, 1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Naafiri_Base_Foundation_Glow01.Zaahen.tex" + paletteDefinition: pointer = VfxPaletteDefinitionData { + paletteTexture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_W_Gradient_RGB.Zaahen.tex" + paletteSelector: embed = ValueVector3 { + constantValue: vec3 = { 6, 0, 0 } + } + paletteCount: i32 = 8 + } + texAddressModeBase: u8 = 2 + uvRotation: embed = ValueFloat { + constantValue: f32 = 90 + } + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.05 + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.3 + } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "widerGlow31" + importance: u8 = 3 + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, -400, 0 } + } + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 0.4399939, 0, 0.06999313 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.15, 0.3, 0.85, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0.7600061 } + { 0, 0, 0, 0 } + } + } + } + pass: i16 = 500 + meshRenderFlags: u8 = 0 + alphaRef: u8 = 0 + miscRenderFlags: u8 = 1 + isRotationEnabled: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 800, 800, 1 } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 1.2, 1.1, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.25, 0.5, 0.75, 1 } + values: list[vec3] = { + { 1.2, 1.1, 1 } + { 0.90000004, 0.82500005, 0.75 } + { 1.2, 1.1, 1 } + { 0.90000004, 0.82500005, 0.75 } + { 1.2, 1.1, 1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Naafiri_Base_Foundation_Glow01.Zaahen.tex" + paletteDefinition: pointer = VfxPaletteDefinitionData { + paletteTexture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_W_Gradient_RGB.Zaahen.tex" + paletteSelector: embed = ValueVector3 { + constantValue: vec3 = { 6, 0, 0 } + } + paletteCount: i32 = 8 + } + texAddressModeBase: u8 = 2 + uvRotation: embed = ValueFloat { + constantValue: f32 = 90 + } + } + } + particleName: string = "Zaahen_Base_W_Mis_Child" + particlePath: string = "Characters/Zaahen/Skins/Skin0/Particles/Zaahen_Base_W_Mis_Child" + } + "Characters/Zaahen/Skins/Skin0/Particles/Zaahen_Base_R_AOE_Indicator_Enemy" = VfxSystemDefinitionData { + complexEmitterDefinitionData: list[pointer] = { + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 1.75 + } + particleLingerType: u8 = 1 + particleLinger: option[f32] = { 0.25 } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "AoE_Edge" + importance: u8 = 3 + Linger: pointer = VfxLingerDefinitionData { + UseSeparateLingerColor: flag = true + SeparateLingerColor: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 1, 0 } + } + primitive: pointer = VfxPrimitiveArbitraryQuad { } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.8901961, 0.09803922, 0.09803922, 0.32941177 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0.2, 0.8, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 0.6429694, 0.6429694, 0.6429694, 0 } + } + } + } + pass: i16 = 500 + alphaRef: u8 = 0 + miscRenderFlags: u8 = 1 + isUniformScale: flag = true + isGroundLayer: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 0, 90 } + } + isLocalOrientation: flag = false + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 499, 390, 0 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 1, 0, 0 } + { 1, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/ViktorR_GlowRing.Zaahen.tex" + birthUVOffset: embed = ValueVector2 { + constantValue: vec2 = { 0.5, 0.5 } + } + texAddressModeBase: u8 = 1 + uvScale: embed = ValueVector2 { + constantValue: vec2 = { 2, 2 } + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 1.65 + } + lifetime: option[f32] = { 8 } + isSingleParticle: flag = true + emitterName: string = "Center" + primitive: pointer = VfxPrimitiveArbitraryQuad { } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.8901961, 0.09803922, 0.09803922, 0.30980393 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 0.8, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + miscRenderFlags: u8 = 1 + isUniformScale: flag = true + isGroundLayer: flag = true + useNavmeshMask: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 0, 90 } + } + isLocalOrientation: flag = false + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 550, 330, 330 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 1, 1, 1 } + { 1, 1, 1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Aura_Self.Zaahen.tex" + texDiv: vec2 = { 1, -1 } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 1.75 + } + particleLinger: option[f32] = { 0.5 } + isSingleParticle: flag = true + emitterName: string = "Constelations5" + importance: u8 = 3 + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 1, 0 } + } + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/XinZhaoRework_Base_R_PortalEdge_Circle.Zaahen.scb" + } + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.8901961, 0.09803922, 0.09803922, 0.4 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.25, 0.85, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = 30 + colorLookUpScales: vec2 = { 0.3, 0.6 } + alphaRef: u8 = 0 + disableBackfaceCull: bool = true + miscRenderFlags: u8 = 1 + isUniformScale: flag = true + isGroundLayer: flag = true + useNavmeshMask: flag = true + birthRotationalVelocity0: embed = ValueVector3 { + constantValue: vec3 = { 0, 8, 0 } + } + isLocalOrientation: flag = false + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 52, 52, 52 } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/XinZhaoRework_Skin27_R_Line_2.Zaahen.tex" + birthUVOffset: embed = ValueVector2 { + constantValue: vec2 = { 1, 0 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec2] = { { 1, 0 } } + } + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 1.65 + } + lifetime: option[f32] = { 8 } + isSingleParticle: flag = true + emitterName: string = "Center1" + primitive: pointer = VfxPrimitiveArbitraryQuad { } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.17000076, 0.08999771, 0, 0.6399939 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 0.8, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + miscRenderFlags: u8 = 1 + isUniformScale: flag = true + isGroundLayer: flag = true + useNavmeshMask: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 0, 90 } + } + isLocalOrientation: flag = false + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 610, 330, 330 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 1, 1, 1 } + { 1, 1, 1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_R_Warning.Zaahen.tex" + texDiv: vec2 = { 1, -1 } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 1.65 + } + lifetime: option[f32] = { 8 } + isSingleParticle: flag = true + emitterName: string = "Center4" + primitive: pointer = VfxPrimitiveArbitraryQuad { } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.54901963, 0.043137256, 0.08235294, 0.56078434 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 0.8, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 0.9100023 } + { 1, 1, 1, 0.5400015 } + { 1, 1, 1, 0 } + } + } + } + miscRenderFlags: u8 = 1 + isUniformScale: flag = true + isGroundLayer: flag = true + useNavmeshMask: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 0, 90 } + } + isLocalOrientation: flag = false + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 600, 330, 330 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 1, 1, 1 } + { 1, 1, 1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Swain_Base_Z_HollowOrb.Zaahen.tex" + texDiv: vec2 = { 1, -1 } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Emote_Einstein_01_mult.Zaahen.tex" + texDivMult: vec2 = { 2, 2 } + uvScaleMult: embed = ValueVector2 { + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec2] = { + { 1, 1 } + { 1.5, 1.5 } + } + } + } + birthUvRotateRateMult: embed = ValueFloat { + constantValue: f32 = 5 + } + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 1.65 + } + lifetime: option[f32] = { 8 } + isSingleParticle: flag = true + emitterName: string = "Center5" + primitive: pointer = VfxPrimitiveArbitraryQuad { } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.8901961, 0.09803922, 0.09803922, 0.52156866 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 0.8, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 0.85000384 } + { 1, 1, 1, 0.5799954 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = 30 + miscRenderFlags: u8 = 1 + isUniformScale: flag = true + isGroundLayer: flag = true + useNavmeshMask: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 35, 90 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 30, 600 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 90, 35, 90 } } + } + } + isLocalOrientation: flag = false + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 600, 330, 330 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 1, 1, 1 } + { 1, 1, 1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Swain_Base_Z_HollowOrb.Zaahen.tex" + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Emote_Einstein_01_mult.Zaahen.tex" + texDivMult: vec2 = { 0.75, 0.75 } + uvScaleMult: embed = ValueVector2 { + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec2] = { + { 1, 1 } + { 1.5, 1.5 } + } + } + } + birthUvRotateRateMult: embed = ValueFloat { + constantValue: f32 = -5 + } + } + } + } + particleName: string = "Zaahen_Base_R_AOE_Indicator_Enemy" + particlePath: string = "Characters/Zaahen/Skins/Skin0/Particles/Zaahen_Base_R_AOE_Indicator_Enemy" + flags: u16 = 198 + } + "Characters/Zaahen/Skins/Skin0/Particles/Zaahen_Base_Q_1_Trail" = VfxSystemDefinitionData { + complexEmitterDefinitionData: list[pointer] = { + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.2 + } + particleLinger: option[f32] = { 0.2 } + lifetime: option[f32] = { 0.5 } + isSingleParticle: flag = true + emitterLinger: option[f32] = { 0.5 } + emitterName: string = "Trail_Red" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, -25 } + } + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_BA_SwipeMesh1.Zaahen.scb" + } + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 1, 1, 0.5000076 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.75, 1 } + values: list[vec4] = { + { 0.3019608, 0.078431375, 0.11372549, 1 } + { 0.3019608, 0.078431375, 0.11372549, 1 } + { 0.3019608, 0.078431375, 0.11372549, 0 } + } + } + } + pass: i16 = 15 + softParticleParams: pointer = VfxSoftParticleDefinitionData { + beginIn: f32 = 10 + deltaIn: f32 = 50 + } + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.85 } + values: list[f32] = { 0.3, 1 } + } + } + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Mordekaiser_Skin54_Noise_keka.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + disableBackfaceCull: bool = true + isUniformScale: flag = true + TextureFlipU: flag = true + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 1, 1, 1 } + { 1.2, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/color-hold.Zaahen.tex" + birthUVOffset: embed = ValueVector2 { + constantValue: vec2 = { 0.5, 0 } + } + uvRotation: embed = ValueFloat { + constantValue: f32 = 90 + } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Ambessa_Base_P_SpecialAttack_Swipe_shape1.Zaahen.tex" + texAddressModeMult: u8 = 2 + uvScaleMult: embed = ValueVector2 { + constantValue: vec2 = { 0.5, 1 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec2] = { + { 0.5, 1 } + { 1, 1 } + } + } + } + ParticleIntegratedUvScrollMult: embed = IntegratedValueVector2 { + constantValue: vec2 = { 0, 1 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec2] = { + { 0, 1 } + { 0, 0 } + } + } + } + birthUVOffsetMult: embed = ValueVector2 { + constantValue: vec2 = { 0.1, -0.25 } + } + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 2 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.2 + } + particleLinger: option[f32] = { 0.2 } + lifetime: option[f32] = { 0.5 } + isSingleParticle: flag = true + emitterLinger: option[f32] = { 0.5 } + emitterName: string = "Trail_Gold1" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, -25 } + } + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_BA_SwipeMesh1.Zaahen.scb" + } + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 1, 1, 0.7900053 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.2, 0.5 } + values: list[vec4] = { + { 0.7882353, 0.53333336, 0.29411766, 1 } + { 0.7882353, 0.53333336, 0.29411766, 1 } + { 0.30000764, 0.10000763, 0.08000305, 0 } + } + } + } + pass: i16 = 30 + softParticleParams: pointer = VfxSoftParticleDefinitionData { + beginIn: f32 = 10 + deltaIn: f32 = 50 + } + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.5 } + values: list[f32] = { 0.5, 0.9907834 } + } + } + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Mordekaiser_Skin54_Noise_keka.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + disableBackfaceCull: bool = true + isUniformScale: flag = true + TextureFlipU: flag = true + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 1, 1, 1 } + { 1.2, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_W_Color_aatrox_W_blood.Zaahen.tex" + birthUVOffset: embed = ValueVector2 { + constantValue: vec2 = { 0.5, 0 } + } + uvRotation: embed = ValueFloat { + constantValue: f32 = 90 + } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Ambessa_Base_P_SpecialAttack_Swipe_shape1.Zaahen.tex" + texAddressModeMult: u8 = 2 + uvScaleMult: embed = ValueVector2 { + constantValue: vec2 = { 0.5, 1 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec2] = { + { 0.5, 1 } + { 1, 1 } + } + } + } + ParticleIntegratedUvScrollMult: embed = IntegratedValueVector2 { + constantValue: vec2 = { 0, 1 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec2] = { + { 0, 1 } + { 0, 0 } + } + } + } + birthUVOffsetMult: embed = ValueVector2 { + constantValue: vec2 = { 0, -0.25 } + } + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.2 + } + particleLinger: option[f32] = { 0.2 } + lifetime: option[f32] = { 0.5 } + isSingleParticle: flag = true + emitterLinger: option[f32] = { 0.5 } + emitterName: string = "Trail_Red2" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, -25 } + } + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_BA_SwipeMesh1.Zaahen.scb" + } + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 1, 1, 0.5000076 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.75, 1 } + values: list[vec4] = { + { 0.3019608, 0.101960786, 0.078431375, 1 } + { 0.3019608, 0.101960786, 0.078431375, 1 } + { 0.30000764, 0.10000763, 0.08000305, 0 } + } + } + } + pass: i16 = 10 + softParticleParams: pointer = VfxSoftParticleDefinitionData { + beginIn: f32 = 10 + deltaIn: f32 = 50 + } + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.85 } + values: list[f32] = { 0, 1 } + } + } + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Mordekaiser_Skin54_Noise_keka.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + disableBackfaceCull: bool = true + isUniformScale: flag = true + TextureFlipU: flag = true + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 1, 1, 1 } + { 1.2, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_R_Screen_Flames_Soft.Zaahen.tex" + birthUVOffset: embed = ValueVector2 { + constantValue: vec2 = { 0.5, 0 } + } + particleUVScrollRate: embed = IntegratedValueVector2 { + constantValue: vec2 = { 1, 0 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec2] = { + { 1, 0 } + { 0, 0 } + } + } + } + uvRotation: embed = ValueFloat { + constantValue: f32 = 90 + } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Ambessa_Base_P_SpecialAttack_Swipe_shape1.Zaahen.tex" + texAddressModeMult: u8 = 2 + uvScaleMult: embed = ValueVector2 { + constantValue: vec2 = { 0.5, 1 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec2] = { + { 0.5, 1 } + { 1, 1 } + } + } + } + ParticleIntegratedUvScrollMult: embed = IntegratedValueVector2 { + constantValue: vec2 = { 0, 1 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec2] = { + { 0, 1 } + { 0, 0 } + } + } + } + birthUVOffsetMult: embed = ValueVector2 { + constantValue: vec2 = { 0.1, -0.25 } + } + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.2 + } + particleLinger: option[f32] = { 0.2 } + lifetime: option[f32] = { 0.5 } + isSingleParticle: flag = true + emitterLinger: option[f32] = { 0.5 } + emitterName: string = "Trail16" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, -25 } + } + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_BA_SwipeMesh1.Zaahen.scb" + } + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 1, 1, 0.7600061 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.05, 0.5, 0.9 } + values: list[vec4] = { + { 0.6509804, 0.1764706, 0.1764706, 0 } + { 0.6509804, 0.1764706, 0.1764706, 1 } + { 0.4905165, 0.08004883, 0.08004883, 1 } + { 0.2509804, 0.03137255, 0.03137255, 0 } + } + } + } + pass: i16 = 17 + softParticleParams: pointer = VfxSoftParticleDefinitionData { + beginIn: f32 = 10 + deltaIn: f32 = 50 + } + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0.1, 0.5, 0.8 } + values: list[f32] = { 0.8, 1, 1 } + } + } + erosionSliceWidth: f32 = 2 + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_BA_Trail_Darkin_1.Zaahen.tex" + erosionMapAddressMode: u8 = 0 + } + disableBackfaceCull: bool = true + isUniformScale: flag = true + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 1, 1, 1 } + { 1.2, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_BA_Trail_Darkin_1.Zaahen.tex" + birthUVOffset: embed = ValueVector2 { + constantValue: vec2 = { -0.5, 0 } + } + particleUVScrollRate: embed = IntegratedValueVector2 { + constantValue: vec2 = { 16, 0 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec2] = { + { 16, 0 } + { 0, 0 } + } + } + } + uvScale: embed = ValueVector2 { + constantValue: vec2 = { 10, 1 } + } + uvRotation: embed = ValueFloat { + constantValue: f32 = 90 + } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Ambessa_Base_P_SpecialAttack_Swipe_shape.Zaahen.tex" + texAddressModeMult: u8 = 2 + ParticleIntegratedUvScrollMult: embed = IntegratedValueVector2 { + constantValue: vec2 = { 0, 1.5 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec2] = { + { 0, 1.5 } + { 0, 0 } + } + } + } + birthUVOffsetMult: embed = ValueVector2 { + constantValue: vec2 = { 0, -0.4 } + } + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 2 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.2 + } + particleLinger: option[f32] = { 0.2 } + lifetime: option[f32] = { 0.5 } + isSingleParticle: flag = true + emitterLinger: option[f32] = { 0.5 } + emitterName: string = "Trail_Gold5" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, -25 } + } + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_BA_SwipeMesh1.Zaahen.scb" + } + } + blendMode: u8 = 1 + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.2, 0.4 } + values: list[vec4] = { + { 0.88235295, 0.078431375, 0.2784314, 1 } + { 0.88235295, 0.078431375, 0.2784314, 0.7372549 } + { 0.35487908, 0.08720531, 0.14024568, 0 } + } + } + } + pass: i16 = 28 + alphaRef: u8 = 15 + softParticleParams: pointer = VfxSoftParticleDefinitionData { + beginIn: f32 = 10 + deltaIn: f32 = 50 + } + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0.5, 1 } + values: list[f32] = { 0, 0.9907834 } + } + } + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Mordekaiser_Skin54_Noise_keka.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + disableBackfaceCull: bool = true + isUniformScale: flag = true + TextureFlipU: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 1.1, 1, 1 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 1, 1, 1 } + { 1.2, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/common_color-bellcurve.Zaahen.tex" + birthUVOffset: embed = ValueVector2 { + constantValue: vec2 = { -0.6, 0 } + } + texAddressModeBase: u8 = 2 + uvScale: embed = ValueVector2 { + constantValue: vec2 = { 2, 1 } + } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Udyr_Base_VGU_GlowMask_Thicc.Zaahen.tex" + texAddressModeMult: u8 = 2 + uvScaleMult: embed = ValueVector2 { + constantValue: vec2 = { 2, 1 } + } + ParticleIntegratedUvScrollMult: embed = IntegratedValueVector2 { + constantValue: vec2 = { 0.5, 1 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0 } + values: list[vec2] = { { 0.5, 1 } } + } + } + birthUVOffsetMult: embed = ValueVector2 { + constantValue: vec2 = { -0.5, 0 } + } + } + } + } + particleName: string = "Zaahen_Base_Q_1_Trail" + particlePath: string = "Characters/Zaahen/Skins/Skin0/Particles/Zaahen_Base_Q_1_Trail" + } + "Characters/Zaahen/Skins/Skin0/Particles/Zaahen_Base_W_Mis_Tar" = VfxSystemDefinitionData { + complexEmitterDefinitionData: list[pointer] = { + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.17 + } + particleLinger: option[f32] = { } + lifetime: option[f32] = { 0.2 } + isSingleParticle: flag = true + emitterName: string = "flash17" + importance: u8 = 3 + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.92156863, 0.7607843, 0.49019608, 1 } + } + pass: i16 = 500 + alphaRef: u8 = 0 + miscRenderFlags: u8 = 1 + particleIsLocalOrientation: flag = true + isUniformScale: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 1, 90, 90 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 1, 90, 90 } } + } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 200, 79.25, 0.84 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.5, 1 } + values: list[vec3] = { + { 0, 0, 0 } + { 1, 1, 1 } + { 0, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Darius_Skin43_Star_Flash.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.25 + } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "RisingSun" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.8901961, 0.2901961, 0.09803922, 0.5019608 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 0.49557522, 0.75737464, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 0.15555556, 0.15555556, 0.15555556, 0.15555556 } + { 0, 0, 0, 0 } + } + } + } + pass: i16 = 490 + alphaRef: u8 = 0 + miscRenderFlags: u8 = 1 + isUniformScale: flag = true + isGroundLayer: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 300, 80, 80 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 1, 1, 1 } + { 0.5, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Aura_Self.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.5 + } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "Horizon" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, -100, 0 } + } + primitive: pointer = VfxPrimitiveArbitraryQuad { } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.26999313, 0.06999313, 0.08000305, 0.4599985 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + } + } + } + alphaRef: u8 = 0 + miscRenderFlags: u8 = 1 + isUniformScale: flag = true + isGroundLayer: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 0, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 300, 80, 80 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 1, 1, 1 } + { 0.5, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Aura_Self.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.4 + } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "RisingSun1" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.26999313, 0.06999313, 0.08000305, 0.59000534 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 0.7, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + alphaRef: u8 = 0 + miscRenderFlags: u8 = 1 + isUniformScale: flag = true + isGroundLayer: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 200, 80, 80 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 1, 1, 1 } + { 0.5, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Aura_Self.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.4 + } + lifetime: option[f32] = { 0.1 } + isSingleParticle: flag = true + emitterName: string = "Purple Ring" + importance: u8 = 3 + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { -10, 10, -10 } + } + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Chogath_R_yuan_di_02.Zaahen.scb" + } + AlignPitchToCamera: bool = true + AlignYawToCamera: bool = true + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.92156863, 0.7607843, 0.49019608, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.06198327, 0.21481246, 0.3710934, 0.5, 0.9999 } + values: list[vec4] = { + { 0, 0, 0, 0 } + { 1, 1, 1, 0.6666667 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0.7058824 } + { 1, 1, 1, 0.06999313 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = 80 + 0xcb13aff1: f32 = -10 + disableBackfaceCull: bool = true + miscRenderFlags: u8 = 1 + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 0, 0 } + } + isLocalOrientation: flag = false + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 4, 0.2, 4 } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 1.25, 1, 1.25 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.6 } + values: list[vec3] = { + { 1.25, 1, 1.25 } + { 0.125, 0.3, 0.125 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Leona_Base_E_Wisps.Zaahen.tex" + birthUVOffset: embed = ValueVector2 { + constantValue: vec2 = { 1, 0 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec2] = { { 1, 0 } } + } + } + particleUVScrollRate: embed = IntegratedValueVector2 { + constantValue: vec2 = { 0.2, 0.2 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec2] = { + { 0.2, 0.2 } + { 0.060000002, 0.060000002 } + } + } + } + uvScale: embed = ValueVector2 { + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec2] = { + { 1, 1 } + { 1.3, 2 } + } + } + } + particleUVRotateRate: embed = IntegratedValueFloat { + constantValue: f32 = -300 + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0.5, 1 } + values: list[f32] = { -300, -150 } + } + } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Naafiri_Base_Foundation_Glow01.Zaahen.tex" + texAddressModeMult: u8 = 3 + uvScaleMult: embed = ValueVector2 { + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 0.5, 1 } + values: list[vec2] = { + { 1, 1 } + { 1, 1 } + { 1.8, 1.8 } + } + } + } + ParticleIntegratedUvRotateMult: embed = IntegratedValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0 } + values: list[f32] = { 0 } + } + } + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.4 + } + lifetime: option[f32] = { 0.1 } + isSingleParticle: flag = true + emitterName: string = "Purple Ring1" + importance: u8 = 3 + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { -10, 10, -10 } + } + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Chogath_R_yuan_di_02.Zaahen.scb" + } + AlignPitchToCamera: bool = true + AlignYawToCamera: bool = true + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.545388, 0.072312504, 0.109300375, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.06198327, 0.21481246, 0.3710934, 0.5, 0.9999 } + values: list[vec4] = { + { 0, 0, 0, 0 } + { 1, 1, 1, 0.6666667 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0.7058824 } + { 1, 1, 1, 0.06999313 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = 60 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0.3, 0.8 } + values: list[f32] = { 0, 1.3 } + } + } + erosionFeatherOut: f32 = 0.5 + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Base_SmokeErode.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0.020004578, 0 } + } + } + 0xcb13aff1: f32 = -10 + disableBackfaceCull: bool = true + miscRenderFlags: u8 = 1 + isGroundLayer: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 0, 0 } + } + isLocalOrientation: flag = false + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 4, 0.2, 4 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 1, 1, 1 } + { 0, 0.3, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Emote_Einstein_01_mult.Zaahen.tex" + particleUVScrollRate: embed = IntegratedValueVector2 { + constantValue: vec2 = { 0.2, 0.2 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec2] = { + { 0.2, 0.2 } + { 0.060000002, 0.060000002 } + } + } + } + uvScale: embed = ValueVector2 { + constantValue: vec2 = { 0.5, 0.5 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec2] = { + { 0.5, 0.5 } + { 0.65, 1 } + } + } + } + particleUVRotateRate: embed = IntegratedValueFloat { + constantValue: f32 = -300 + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0.5, 1 } + values: list[f32] = { -300, -150 } + } + } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Naafiri_Base_Foundation_Glow01.Zaahen.tex" + texAddressModeMult: u8 = 3 + uvScaleMult: embed = ValueVector2 { + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 0.5, 1 } + values: list[vec2] = { + { 1, 1 } + { 1, 1 } + { 1.8, 1.8 } + } + } + } + ParticleIntegratedUvRotateMult: embed = IntegratedValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0 } + values: list[f32] = { 0 } + } + } + } + } + } + particleName: string = "Zaahen_Base_W_Mis_Tar" + particlePath: string = "Characters/Zaahen/Skins/Skin0/Particles/Zaahen_Base_W_Mis_Tar" + flags: u16 = 196 + } + "Characters/Zaahen/Skins/Skin0/Particles/Zaahen_Base_R_AOE_Indicator_Ally" = VfxSystemDefinitionData { + complexEmitterDefinitionData: list[pointer] = { + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 1.75 + } + particleLingerType: u8 = 1 + particleLinger: option[f32] = { 0.25 } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "AoE_Edge" + importance: u8 = 3 + Linger: pointer = VfxLingerDefinitionData { + UseSeparateLingerColor: flag = true + SeparateLingerColor: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 1, 0 } + } + primitive: pointer = VfxPrimitiveArbitraryQuad { } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 0.7400015, 0.37999544, 0.33000687 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0.2, 0.8, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 0.6429694, 0.6429694, 0.6429694, 0 } + } + } + } + pass: i16 = 500 + alphaRef: u8 = 0 + miscRenderFlags: u8 = 1 + isUniformScale: flag = true + isGroundLayer: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 0, 90 } + } + isLocalOrientation: flag = false + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 499, 390, 0 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 1, 0, 0 } + { 1, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/ViktorR_GlowRing.Zaahen.tex" + birthUVOffset: embed = ValueVector2 { + constantValue: vec2 = { 0.5, 0.5 } + } + texAddressModeBase: u8 = 1 + uvScale: embed = ValueVector2 { + constantValue: vec2 = { 2, 2 } + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 1.65 + } + lifetime: option[f32] = { 8 } + isSingleParticle: flag = true + emitterName: string = "Center" + primitive: pointer = VfxPrimitiveArbitraryQuad { } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.91639584, 0.56049436, 0.10478371, 0.30980393 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 0.8, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + miscRenderFlags: u8 = 1 + isUniformScale: flag = true + isGroundLayer: flag = true + useNavmeshMask: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 0, 90 } + } + isLocalOrientation: flag = false + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 550, 330, 330 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 1, 1, 1 } + { 1, 1, 1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Aura_Self.Zaahen.tex" + texDiv: vec2 = { 1, -1 } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 1.75 + } + particleLinger: option[f32] = { 0.5 } + isSingleParticle: flag = true + emitterName: string = "Constelations5" + importance: u8 = 3 + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 1, 0 } + } + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/XinZhaoRework_Base_R_PortalEdge_Circle.Zaahen.scb" + } + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 0.50482947, 0, 0.4 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.25, 0.85, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = 30 + colorLookUpScales: vec2 = { 0.3, 0.6 } + alphaRef: u8 = 0 + disableBackfaceCull: bool = true + miscRenderFlags: u8 = 1 + isUniformScale: flag = true + isGroundLayer: flag = true + useNavmeshMask: flag = true + birthRotationalVelocity0: embed = ValueVector3 { + constantValue: vec3 = { 0, 8, 0 } + } + isLocalOrientation: flag = false + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 52, 52, 52 } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/XinZhaoRework_Skin27_R_Line_2.Zaahen.tex" + birthUVOffset: embed = ValueVector2 { + constantValue: vec2 = { 1, 0 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec2] = { { 1, 0 } } + } + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 1.65 + } + lifetime: option[f32] = { 8 } + isSingleParticle: flag = true + emitterName: string = "Center1" + primitive: pointer = VfxPrimitiveArbitraryQuad { } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.17000076, 0.08999771, 0, 0.6399939 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 0.8, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + miscRenderFlags: u8 = 1 + isUniformScale: flag = true + isGroundLayer: flag = true + useNavmeshMask: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 0, 90 } + } + isLocalOrientation: flag = false + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 610, 330, 330 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 1, 1, 1 } + { 1, 1, 1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_R_Warning.Zaahen.tex" + texDiv: vec2 = { 1, -1 } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 1.65 + } + lifetime: option[f32] = { 8 } + isSingleParticle: flag = true + emitterName: string = "Center4" + primitive: pointer = VfxPrimitiveArbitraryQuad { } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.6500038, 0.2399939, 0, 0.5600061 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 0.8, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 0.9100023 } + { 1, 1, 1, 0.5400015 } + { 1, 1, 1, 0 } + } + } + } + miscRenderFlags: u8 = 1 + isUniformScale: flag = true + isGroundLayer: flag = true + useNavmeshMask: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 0, 90 } + } + isLocalOrientation: flag = false + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 600, 330, 330 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 1, 1, 1 } + { 1, 1, 1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Swain_Base_Z_HollowOrb.Zaahen.tex" + texDiv: vec2 = { 1, -1 } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Emote_Einstein_01_mult.Zaahen.tex" + texDivMult: vec2 = { 2, 2 } + uvScaleMult: embed = ValueVector2 { + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec2] = { + { 1, 1 } + { 1.5, 1.5 } + } + } + } + birthUvRotateRateMult: embed = ValueFloat { + constantValue: f32 = 5 + } + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 1.65 + } + lifetime: option[f32] = { 8 } + isSingleParticle: flag = true + emitterName: string = "Center5" + primitive: pointer = VfxPrimitiveArbitraryQuad { } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 0.7499962, 0.34000152, 0.51999694 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 0.8, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 0.85000384 } + { 1, 1, 1, 0.5799954 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = 30 + miscRenderFlags: u8 = 1 + isUniformScale: flag = true + isGroundLayer: flag = true + useNavmeshMask: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 35, 90 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 30, 600 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 90, 35, 90 } } + } + } + isLocalOrientation: flag = false + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 600, 330, 330 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 1, 1, 1 } + { 1, 1, 1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Swain_Base_Z_HollowOrb.Zaahen.tex" + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Emote_Einstein_01_mult.Zaahen.tex" + texDivMult: vec2 = { 0.75, 0.75 } + uvScaleMult: embed = ValueVector2 { + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec2] = { + { 1, 1 } + { 1.5, 1.5 } + } + } + } + birthUvRotateRateMult: embed = ValueFloat { + constantValue: f32 = -5 + } + } + } + } + particleName: string = "Zaahen_Base_R_AOE_Indicator_Ally" + particlePath: string = "Characters/Zaahen/Skins/Skin0/Particles/Zaahen_Base_R_AOE_Indicator_Ally" + soundOnCreateDefault: string = "Play_sfx_Zaahen_ZaahenR_AoE_warning" + flags: u16 = 198 + } + "Characters/Zaahen/Skins/Skin0/Particles/Zaahen_Base_BA_Tar" = VfxSystemDefinitionData { + complexEmitterDefinitionData: list[pointer] = { + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 1 + } + isSingleParticle: flag = true + childParticleSetDefinition: pointer = VfxChildParticleSetDefinitionData { + childrenIdentifiers: list[embed] = { + VfxChildIdentifier { + effectKey: hash = "Zaahen_BA_Tar_Child" + } + } + } + emitterName: string = "Gimbal" + importance: u8 = 3 + primitive: pointer = VfxPrimitiveArbitraryQuad { } + blendMode: u8 = 1 + } + } + particleName: string = "Zaahen_Base_BA_Tar" + particlePath: string = "Characters/Zaahen/Skins/Skin0/Particles/Zaahen_Base_BA_Tar" + } + "Characters/Zaahen/Skins/Skin0/Particles/Zaahen_Base_BA_Swipe_Crit" = VfxSystemDefinitionData { + complexEmitterDefinitionData: list[pointer] = { + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLinger: option[f32] = { } + isSingleParticle: flag = true + childParticleSetDefinition: pointer = VfxChildParticleSetDefinitionData { + childrenIdentifiers: list[embed] = { + VfxChildIdentifier { + effectKey: hash = "Zaahen_BA_Swipe_child" + } + } + } + emitterName: string = "Gimbal" + importance: u8 = 3 + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 120, 120, 25 } + } + primitive: pointer = VfxPrimitiveArbitraryQuad { } + blendMode: u8 = 1 + pass: i16 = 500 + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 30, 0, 120 } + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.2 + } + particleLinger: option[f32] = { } + lifetime: option[f32] = { 0.5 } + isSingleParticle: flag = true + emitterLinger: option[f32] = { 0.5 } + emitterName: string = "Trail_Red7" + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 120, 120, 25 } + } + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_BA_SwipeMesh1.Zaahen.scb" + } + } + blendMode: u8 = 5 + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.25180027, 0.50830483, 1 } + values: list[vec4] = { + { 0.85490197, 0.1624628, 0.050980393, 1 } + { 0.65078205, 0.15800717, 0.091554135, 0.92156863 } + { 0.34117648, 0.06666667, 0.11764706, 1 } + { 0, 0, 0, 0 } + } + } + } + pass: i16 = 29 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + constantValue: f32 = 0.5 + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.85 } + values: list[f32] = { 0, 0.5 } + } + } + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Mordekaiser_Skin54_Noise_keka.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + disableBackfaceCull: bool = true + isUniformScale: flag = true + TextureFlipU: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 40, 0, 120 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 1, 1, 1 } + { 1.2, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Chogath_Skin14_R_Ribbon_01.Zaahen.tex" + birthUVOffset: embed = ValueVector2 { + constantValue: vec2 = { 0.5, 0 } + } + particleUVScrollRate: embed = IntegratedValueVector2 { + constantValue: vec2 = { 4, 0 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec2] = { + { 4, 0 } + { 0, 0 } + } + } + } + uvRotation: embed = ValueFloat { + constantValue: f32 = 90 + } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Ambessa_Base_P_SpecialAttack_Swipe_shape1.Zaahen.tex" + texAddressModeMult: u8 = 2 + uvScaleMult: embed = ValueVector2 { + constantValue: vec2 = { 0.5, 1 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec2] = { + { 0.5, 1 } + { 1, 1 } + } + } + } + ParticleIntegratedUvScrollMult: embed = IntegratedValueVector2 { + constantValue: vec2 = { 0, 1 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec2] = { + { 0, 1 } + { 0, 0 } + } + } + } + birthUVOffsetMult: embed = ValueVector2 { + constantValue: vec2 = { 0.1, -0.25 } + } + } + } + } + particleName: string = "Zaahen_Base_BA_Swipe_Crit" + particlePath: string = "Characters/Zaahen/Skins/Skin0/Particles/Zaahen_Base_BA_Swipe_Crit" + } + "Characters/Zaahen/Skins/Skin0/Particles/Zaahen_Base_P_Revive_End" = VfxSystemDefinitionData { + complexEmitterDefinitionData: list[pointer] = { + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 2 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.15 + } + lifetime: option[f32] = { 5 } + isSingleParticle: flag = true + emitterLinger: option[f32] = { 0.1 } + emitterName: string = "Pillar" + importance: u8 = 3 + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + SpawnShape: pointer = VfxShapeLegacy { + emitOffset: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 0, 0 } } + } + } + emitRotationAngles: list[embed] = { + ValueFloat { } + ValueFloat { } + } + emitRotationAxes: list[vec3] = { + { 0, 0, 0 } + { 0, 0, 0 } + } + } + EmitterPosition: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 0, 0 } } + } + } + primitive: pointer = VfxPrimitiveRay { } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.89132524, 0.12774853, 0.11004806, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0.1, 0.25, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = 55 + softParticleParams: pointer = VfxSoftParticleDefinitionData { + deltaIn: f32 = 40 + } + miscRenderFlags: u8 = 1 + isGroundLayer: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { -90, 0, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 80, 600, 1 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.11140352, 0.21666665, 1 } + values: list[vec3] = { + { 9, 0, 0 } + { 7.779141, 1.2030061, -47.3865 } + { 1.785276, 2.049, -80.06135 } + { 0, 2.5, -100 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_BA_GlowStar_02_Blend.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 2 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.3 + } + particleLinger: option[f32] = { 11 } + lifetime: option[f32] = { 5 } + isSingleParticle: flag = true + emitterName: string = "SwirlGold" + IsEmitterSpace: flag = true + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 700, 0 } + } + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Darius_R_Swirl_Mesh.Zaahen.scb" + } + } + blendMode: u8 = 5 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.4599985, 0.06999313, 0.059998475, 1 } + } + Color: embed = ValueColor { + constantValue: vec4 = { 0.65366596, 0.65366596, 0.65366596, 1 } + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 1 } + values: list[vec4] = { + { 0.65366596, 0.5101158, 0.3793826, 0 } + { 0.65366596, 0.5101158, 0.3793826, 1 } + { 0, 0, 0, 0 } + } + } + } + alphaRef: u8 = 0 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.6, 1 } + values: list[f32] = { 0, 0.1, 1 } + } + } + erosionFeatherIn: f32 = 0.3 + erosionFeatherOut: f32 = 0.2 + erosionSliceWidth: f32 = 1 + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Emote_Einstein_01_mult.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + disableBackfaceCull: bool = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, 180 } + } + birthRotationalVelocity0: embed = ValueVector3 { + constantValue: vec3 = { 0, 20, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.13, 0.2, 0.3, 0.4 } + values: list[vec3] = { + { 0, 30, 0 } + { 0, 100, 0 } + { 0, 24.237288, 0 } + { 0, 6.6101694, 0 } + { 0, 0, 0 } + } + } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 1, 6, 1 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.3, 1 } + values: list[vec3] = { + { 1, 1, 1 } + { 2.5, 1, 2.5 } + { 1, 1, 1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/common_color-bellcurve.Zaahen.tex" + uvMode: u8 = 2 + texAddressModeBase: u8 = 2 + uvRotation: embed = ValueFloat { + constantValue: f32 = 90 + } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Darius_Skin54_R_Swirl.Zaahen.tex" + texAddressModeMult: u8 = 2 + uvScrollClampMult: flag = true + ParticleIntegratedUvScrollMult: embed = IntegratedValueVector2 { + constantValue: vec2 = { 0, 4 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 0.8 } + values: list[vec2] = { + { 0, 4 } + { 0, 0.2 } + } + } + } + birthUVOffsetMult: embed = ValueVector2 { + constantValue: vec2 = { 0, -0.75 } + } + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.3 + } + particleLinger: option[f32] = { 11 } + lifetime: option[f32] = { 5 } + isSingleParticle: flag = true + emitterName: string = "SwirlGold1" + IsEmitterSpace: flag = true + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 700, 0 } + } + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Darius_R_Swirl_Mesh.Zaahen.scb" + } + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.8899977, 0.13000686, 0.11000229, 0.19000535 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 1 } + values: list[vec4] = { + { 1, 0.78039217, 0.5803922, 0 } + { 1, 0.78039217, 0.5803922, 1 } + { 0.51999694, 0.39000535, 0.10000763, 0 } + } + } + } + pass: i16 = 4 + alphaRef: u8 = 0 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.6, 1 } + values: list[f32] = { 0, 0.1, 1 } + } + } + erosionFeatherIn: f32 = 0.3 + erosionFeatherOut: f32 = 0.2 + erosionSliceWidth: f32 = 1 + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Emote_Einstein_01_mult.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + disableBackfaceCull: bool = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, 180 } + } + birthRotationalVelocity0: embed = ValueVector3 { + constantValue: vec3 = { 0, 20, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.13, 0.2, 0.3, 0.4 } + values: list[vec3] = { + { 0, 30, 0 } + { 0, 100, 0 } + { 0, 24.237288, 0 } + { 0, 6.6101694, 0 } + { 0, 0, 0 } + } + } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 1, 6, 1 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.3, 1 } + values: list[vec3] = { + { 1, 1, 1 } + { 2.5, 1, 2.5 } + { 1, 1, 1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/common_color-bellcurve.Zaahen.tex" + uvMode: u8 = 2 + texAddressModeBase: u8 = 2 + uvRotation: embed = ValueFloat { + constantValue: f32 = 90 + } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Darius_Skin54_R_Swirl.Zaahen.tex" + texAddressModeMult: u8 = 2 + uvScrollClampMult: flag = true + ParticleIntegratedUvScrollMult: embed = IntegratedValueVector2 { + constantValue: vec2 = { 0, 4 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 0.8 } + values: list[vec2] = { + { 0, 4 } + { 0, 0.2 } + } + } + } + birthUVOffsetMult: embed = ValueVector2 { + constantValue: vec2 = { 0, -0.75 } + } + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 25 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.5 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 0.9, 1 } + keyValues: list[f32] = { 0.2, 1, 1.5 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 0.5 } + } + } + particleLinger: option[f32] = { 1 } + lifetime: option[f32] = { 5 } + isSingleParticle: flag = true + emitterName: string = "Sparkles" + birthOrbitalVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, -3, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, -3, 0 } } + } + } + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 1000, 2000, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.2, 1.1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 1000, 2000, 0 } } + } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 8, 2, 8 } + } + birthAcceleration: embed = ValueVector3 { + constantValue: vec3 = { 100, 0, 100 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 100, 0, 100 } } + } + } + worldAcceleration: embed = IntegratedValueVector3 { + constantValue: vec3 = { 0, 200, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 200, 0 } } + } + } + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 1 } + values: list[f32] = { 1, 0 } + } + } + SpawnShape: pointer = VfxShapeCylinder { + radius: f32 = 100 + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.59607846, 0.043137256, 0.03137255, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.5, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 0, 0, 0, 0 } + } + } + } + pass: i16 = 10 + isDirectionOriented: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 1, 0, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 1, 0, 0 } } + } + } + birthRotationalVelocity0: embed = ValueVector3 { + constantValue: vec3 = { -300, 0, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 50, 100, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.3, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 1, 2 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 50, 100, 0 } } + } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 1, 1, 1 } + { 0, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Sparks_Gray.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.25 + } + particleLinger: option[f32] = { 0.1 } + lifetime: option[f32] = { 5 } + isSingleParticle: flag = true + emitterName: string = "BlckFrame" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + SpawnShape: pointer = 0xee39916f { + emitOffset: vec3 = { 0, 1900, 0 } + } + EmitterPosition: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 0, 0 } } + } + } + primitive: pointer = VfxPrimitiveRay { } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.2, 0.059998475, 0.08000305, 0.7100023 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.2, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = -1000 + alphaRef: u8 = 0 + isDirectionOriented: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 0, 0 } + } + directionVelocityScale: f32 = 0.01 + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 400, 1550, 500 } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Wave_Texture.Zaahen.tex" + uvRotation: embed = ValueFloat { + constantValue: f32 = 180 + } + textureMult: pointer = VfxTextureMultDefinitionData { + texAddressModeMult: u8 = 2 + UvRotationMult: embed = ValueFloat { + constantValue: f32 = 90 + } + birthUvScrollRateMult: embed = ValueVector2 { + constantValue: vec2 = { -4, 0 } + } + birthUVOffsetMult: embed = ValueVector2 { + constantValue: vec2 = { 2, 0 } + } + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.5 + } + particleLinger: option[f32] = { 0.1 } + lifetime: option[f32] = { 5 } + isSingleParticle: flag = true + emitterName: string = "Drop" + birthOrbitalVelocity: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.5 } + values: list[vec3] = { + { 0, 0, 0 } + { 0, 0, 0 } + } + } + } + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 1400, 0 } + } + primitive: pointer = VfxPrimitiveRay { } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.2, 0.059998475, 0.08000305, 0.37000075 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.2, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = 10 + alphaRef: u8 = 0 + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 0, 0 } + } + directionVelocityScale: f32 = 0.01 + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 400, 1300, 500 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 1, 1, 0 } + { 0.5, 2, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_E_Nova_Mult.Zaahen.tex" + birthUVOffset: embed = ValueVector2 { + constantValue: vec2 = { 1, 1 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec2] = { { 1, 1 } } + } + } + particleUVScrollRate: embed = IntegratedValueVector2 { + constantValue: vec2 = { 0, -4 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec2] = { + { 0, -4 } + { 0, -0 } + } + } + } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Wave_Texture.Zaahen.tex" + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 7 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.75 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1.2 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 0.75 } + } + } + particleLinger: option[f32] = { 1 } + lifetime: option[f32] = { 5 } + isSingleParticle: flag = true + emitterName: string = "Energy_Flash" + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 10, 20, 10 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.1, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 10, 20, 10 } } + } + } + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + SpawnShape: pointer = VfxShapeLegacy { + emitOffset: embed = ValueVector3 { + constantValue: vec3 = { 20, -5, 0 } + } + emitRotationAngles: list[embed] = { + ValueFloat { + constantValue: f32 = 1 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 1 } + } + } + } + emitRotationAxes: list[vec3] = { { 0, 1.0000001, 0 } } + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 100, 0 } + } + FlexShapeDefinition: pointer = VfxFlexShapeDefinitionData { + scaleBirthScaleByBoundObjectSize: f32 = 0.005 + scaleEmitOffsetByBoundObjectSize: f32 = 0.005 + } + primitive: pointer = VfxPrimitiveArbitraryQuad { } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.42999923, 0.08999771, 0.06999313, 0.94000155 } + dynamics: pointer = VfxAnimatedColorVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec4] = { { 0.42999923, 0.08999771, 0.06999313, 0.94000155 } } + } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = 100 + colorLookUpTypeY: u8 = 3 + softParticleParams: pointer = VfxSoftParticleDefinitionData { + deltaIn: f32 = 60 + } + isRandomStartFrame: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 0, 1, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 1, 0 } } + } + } + isLocalOrientation: flag = false + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 80, 150, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1.5 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 80, 150, 0 } } + } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.3, 1 } + values: list[vec3] = { + { 0.3, 1, 0 } + { 1, 1.8, 0 } + { 1, 3, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_P_Revive_EnergyStreak_2x2_Blend.Zaahen.tex" + numFrames: u16 = 4 + startFrame: u16 = 2 + texDiv: vec2 = { 2, 2 } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.25 + } + lifetime: option[f32] = { 5 } + isSingleParticle: flag = true + emitterName: string = "AVATAR1" + importance: u8 = 3 + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + primitive: pointer = VfxPrimitiveAttachedMesh { + mMesh: embed = VfxMeshDefinitionData { + mLockMeshToAttachment: bool = true + } + } + blendMode: u8 = 1 + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 0, 0, 0, 0 } + } + } + } + pass: i16 = -10 + alphaRef: u8 = 0 + censorModulateValue: vec4 = { 0.7893797, 0.85181963, 0.30569926, 1 } + modulationFactor: vec4 = { 0.8202487, 0.046143282, 0.046143282, 1 } + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 1 } + values: list[f32] = { 0, 1 } + } + } + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Base_SmokeErode.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + miscRenderFlags: u8 = 1 + particleIsLocalOrientation: flag = true + isUniformScale: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 1.02, 1, 1 } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/color-hold.Zaahen.tex" + uvMode: u8 = 1 + uvScale: embed = ValueVector2 { + constantValue: vec2 = { 2, 2 } + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.25 + } + isSingleParticle: flag = true + emitterName: string = "FlashGlow" + importance: u8 = 3 + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 150, 0 } + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.9198291, 0.068162054, 0.09185931, 0.6 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0.5, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + miscRenderFlags: u8 = 1 + isUniformScale: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 250, 1000, 0 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.2, 1 } + values: list[vec3] = { + { 2, 0, 0 } + { 1, 0, 0 } + { 0.5, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Naafiri_Base_R_Flash_sharp.Zaahen.tex" + } + } + particleName: string = "Zaahen_Base_P_Revive_End" + particlePath: string = "Characters/Zaahen/Skins/Skin0/Particles/Zaahen_Base_P_Revive_End" + } + "Characters/Zaahen/Skins/Skin0/Particles/Zaahen_Base_P_buf" = VfxSystemDefinitionData { + complexEmitterDefinitionData: list[pointer] = { + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 120 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.8 + } + particleLingerType: u8 = 1 + particleLinger: option[f32] = { 0.2 } + emitterLinger: option[f32] = { 1 } + emitterName: string = "EyeTrail1" + importance: u8 = 3 + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, 100, 100 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 1, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.9, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 100, 100 } } + } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 1, 2, 1 } + } + birthAcceleration: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, 60 } + } + worldAcceleration: embed = IntegratedValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 0, 0 } } + } + } + Linger: pointer = VfxLingerDefinitionData { + UseSeparateLingerColor: flag = true + SeparateLingerColor: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 1 } + values: list[vec4] = { + { 0.75686276, 0.18431373, 0.14901961, 1 } + { 0, 0, 0, 0 } + } + } + } + } + bindWeight: embed = ValueFloat { + constantValue: f32 = 0.6 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, -5 } + } + primitive: pointer = VfxPrimitiveCameraTrail { + mTrail: embed = VfxTrailDefinitionData { + mCutoff: f32 = 200 + mBirthTilingSize: embed = ValueVector3 { + constantValue: vec3 = { 200, 0, 0 } + } + mSmoothingMode: u8 = 1 + } + } + blendMode: u8 = 4 + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.3, 0.6, 1 } + values: list[vec4] = { + { 0.93000686, 0.85999846, 0.6299992, 0 } + { 0.8862745, 0.6294194, 0.35686275, 1 } + { 0.81960785, 0.078431375, 0.10980392, 1 } + { 0, 0, 0, 0 } + } + } + } + pass: i16 = -10 + alphaRef: u8 = 0 + censorModulateValue: vec4 = { 0.3, 2, 2, 1 } + 0xcb13aff1: f32 = -5 + isUniformScale: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 15, 9, 9 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.305026, 0.7, 1 } + values: list[vec3] = { + { 0.5, 0.5, 0 } + { 0.80851066, 0.43575144, 0.43575144 } + { 1, 1, 1 } + { 0.5, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Leona_Base_E_Wisps.Zaahen.tex" + emitterUvScrollRate: vec2 = { -0.3, 0 } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 120 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.8 + } + particleLingerType: u8 = 1 + particleLinger: option[f32] = { 0.2 } + emitterLinger: option[f32] = { 1 } + emitterName: string = "EyeTrail2" + importance: u8 = 3 + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, 100, 100 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 1, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.9, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 100, 100 } } + } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 1, 2, 1 } + } + birthAcceleration: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, 60 } + } + worldAcceleration: embed = IntegratedValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 0, 0 } } + } + } + Linger: pointer = VfxLingerDefinitionData { + UseSeparateLingerColor: flag = true + SeparateLingerColor: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 1 } + values: list[vec4] = { + { 0.75686276, 0.18431373, 0.14901961, 1 } + { 0, 0, 0, 0 } + } + } + } + } + bindWeight: embed = ValueFloat { + constantValue: f32 = 0.6 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, -5 } + } + primitive: pointer = VfxPrimitiveCameraTrail { + mTrail: embed = VfxTrailDefinitionData { + mCutoff: f32 = 200 + mBirthTilingSize: embed = ValueVector3 { + constantValue: vec3 = { 200, 0, 0 } + } + mSmoothingMode: u8 = 1 + } + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.81960785, 0.078431375, 0.10980392, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.3, 0.4, 1 } + values: list[vec4] = { + { 0.13000686, 0.13000686, 0.13000686, 0 } + { 0.8862745, 0.5529412, 0.35686275, 1 } + { 0.75686276, 0.18431373, 0.14901961, 1 } + { 0, 0, 0, 0 } + } + } + } + pass: i16 = -15 + alphaRef: u8 = 0 + censorModulateValue: vec4 = { 0.3, 2, 2, 1 } + 0xcb13aff1: f32 = -5 + isUniformScale: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 15, 9, 9 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.305026, 0.7, 1 } + values: list[vec3] = { + { 0.5, 0.5, 0 } + { 0.80851066, 0.43575144, 0.43575144 } + { 1, 1, 1 } + { 0.5, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Leona_Base_E_Wisps.Zaahen.tex" + emitterUvScrollRate: vec2 = { -0.3, 0 } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = -1 + } + particleLinger: option[f32] = { 0.5 } + isSingleParticle: flag = true + emitterName: string = "Activate" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, -1 } + } + FlexShapeDefinition: pointer = VfxFlexShapeDefinitionData { + scaleBirthScaleByBoundObjectSize: f32 = 0.005 + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.8901961, 0.09803922, 0.09803922, 0.3019608 } + } + pass: i16 = 9700 + alphaRef: u8 = 0 + 0xcb13aff1: f32 = -5 + particleIsLocalOrientation: flag = true + isUniformScale: flag = true + hasPostRotateOrientation: flag = true + isRandomStartFrame: flag = true + isRotationEnabled: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 10, 20, 1 } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Naafiri_Base_Foundation_Glow01.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = -1 + } + particleLinger: option[f32] = { 0.5 } + isSingleParticle: flag = true + emitterName: string = "Activate1" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, -1 } + } + FlexShapeDefinition: pointer = VfxFlexShapeDefinitionData { + scaleBirthScaleByBoundObjectSize: f32 = 0.005 + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.92156863, 0.7607843, 0.49019608, 0.5019608 } + } + pass: i16 = 9805 + alphaRef: u8 = 0 + 0xcb13aff1: f32 = -5 + particleIsLocalOrientation: flag = true + isUniformScale: flag = true + hasPostRotateOrientation: flag = true + isRandomStartFrame: flag = true + isRotationEnabled: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 5, 10, 1 } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Naafiri_Base_Foundation_Glow01.Zaahen.tex" + } + } + particleName: string = "Zaahen_Base_P_buf" + particlePath: string = "Characters/Zaahen/Skins/Skin0/Particles/Zaahen_Base_P_buf" + flags: u16 = 1236 + } + "Characters/Zaahen/Skins/Skin0/Particles/Zaahen_Base_E_AoE_Slow" = VfxSystemDefinitionData { + complexEmitterDefinitionData: list[pointer] = { + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.17 + } + particleLinger: option[f32] = { } + lifetime: option[f32] = { 0.2 } + isSingleParticle: flag = true + emitterName: string = "flash2" + importance: u8 = 3 + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.8876783, 0.8072633, 0.45801482, 1 } + } + Color: embed = ValueColor { + constantValue: vec4 = { 0.969604, 0.969604, 0.969604, 0.84313726 } + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.2, 1 } + values: list[vec4] = { + { 0.969604, 0.969604, 0.969604, 0.84313726 } + { 0.969604, 0.969604, 0.969604, 0.84313726 } + { 0.969604, 0.969604, 0.969604, 0.84313726 } + } + } + } + pass: i16 = 700 + alphaRef: u8 = 0 + miscRenderFlags: u8 = 1 + isUniformScale: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 1, 90, 90 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 1, 90, 90 } } + } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 200, 200, 0.84 } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 1, 1.5, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.3, 1 } + values: list[vec3] = { + { 1, 0, 0 } + { 0.6, 1.5, 0 } + { 0, 2.25, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Darius_Skin43_Star_Flash.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.5 + } + particleLinger: option[f32] = { 10.2 } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "Background" + FlexShapeDefinition: pointer = VfxFlexShapeDefinitionData { + scaleEmitOffsetByBoundObjectSize: f32 = 0.005 + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 1, 1, 0.5600061 } + } + Color: embed = ValueColor { + constantValue: vec4 = { 0.24309148, 0.040939957, 0.07330434, 1 } + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.6, 1 } + values: list[vec4] = { + { 0.24309148, 0.040939957, 0.07330434, 1 } + { 0.24309148, 0.040939957, 0.07330434, 0.8399939 } + { 0.24309148, 0.040939957, 0.07330434, 0 } + } + } + } + pass: i16 = -50 + alphaRef: u8 = 0 + 0xcb13aff1: f32 = -25 + miscRenderFlags: u8 = 1 + isGroundLayer: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 220, 170, 1 } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 1.25, 1.25, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.2, 1 } + values: list[vec3] = { + { 0.75, 0.75, 11 } + { 1.25, 1.25, 1 } + { 1.5, 1.5, 1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Aura_Self.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 2 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.1 + } + lifetime: option[f32] = { 0.2 } + isSingleParticle: flag = true + emitterName: string = "circleflare_blend" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 12.815607, 0 } + } + particleColorTexture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/common_color-bellcurve.Zaahen.tex" + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.91340506, 0.8514229, 0.64872205, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.06652807, 0.1964657, 0.38253638, 0.6486486, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0.47272727 } + { 1, 1, 1, 0.21212122 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = -50 + meshRenderFlags: u8 = 0 + alphaRef: u8 = 0 + miscRenderFlags: u8 = 1 + isUniformScale: flag = true + isRandomStartFrame: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 1, 0, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 1, 0, 0 } } + } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 40, 200, 200 } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 2, 1, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.08212058, 0.17525057, 1 } + values: list[vec3] = { + { 0, 1, 1 } + { 3.283582, 0.9178794, 0.9178794 } + { 4.238806, 0.8247494, 0.8247494 } + { 6, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Thresh_Skin28_Q_Impact_04.Zaahen.tex" + numFrames: u16 = 4 + texDiv: vec2 = { 2, 2 } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 2 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.4 + } + lifetime: option[f32] = { 0.2 } + isSingleParticle: flag = true + emitterName: string = "circleflare_blend1" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 12.815607, 0 } + } + particleColorTexture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/common_color-bellcurve.Zaahen.tex" + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.33153278, 0.086350806, 0.14413673, 0.6392157 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.06652807, 0.1964657, 0.38253638, 0.6486486, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0.48000306 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = -50 + meshRenderFlags: u8 = 0 + alphaRef: u8 = 0 + miscRenderFlags: u8 = 1 + isUniformScale: flag = true + isRandomStartFrame: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 1, 0, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 1, 0, 0 } } + } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 40, 200, 200 } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 2, 1, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.08212058, 0.17525057, 1 } + values: list[vec3] = { + { 0, 1, 1 } + { 3.283582, 0.9178794, 0.9178794 } + { 4.238806, 0.8247494, 0.8247494 } + { 6, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Thresh_Skin28_Q_Impact_04.Zaahen.tex" + numFrames: u16 = 4 + texDiv: vec2 = { 2, 2 } + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.05 + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.3 + } + particleLinger: option[f32] = { 10.2 } + lifetime: option[f32] = { 1.05 } + isSingleParticle: flag = true + emitterName: string = "flash_Mult" + importance: u8 = 3 + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.31302357, 0.013519494, 0.11020066, 1 } + } + Color: embed = ValueColor { + constantValue: vec4 = { 1, 1, 1, 0.7000076 } + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.5, 1 } + values: list[vec4] = { + { 1, 1, 1, 0.7000076 } + { 1, 1, 1, 0.7000076 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = -1 + alphaRef: u8 = 0 + miscRenderFlags: u8 = 1 + isUniformScale: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 1, 0, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 1, 0, 0 } } + } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 230, 2, 2 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 1, 1, 1 } + { 0.3, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/JarvanIV_Skin35_R_glow.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.85 + } + particleLinger: option[f32] = { } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "StrokeDissolve_primary" + importance: u8 = 3 + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + FlexShapeDefinition: pointer = VfxFlexShapeDefinitionData { + scaleBirthScaleByBoundObjectSize: f32 = 0.005 + } + blendMode: u8 = 1 + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.2, 0.6, 1 } + values: list[vec4] = { + { 0.8774701, 0.19977112, 0.18512246, 0.47058824 } + { 0.6200046, 0.13000686, 0.11999695, 0.6399939 } + { 0.2399939, 0.08999771, 0.13000686, 0.2399939 } + { 0.14000152, 0.00999466, 0.059998475, 0 } + } + } + } + pass: i16 = 5 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.55 } + values: list[f32] = { 0.15, 1 } + } + } + erosionSliceWidth: f32 = 1 + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Aatrox_Skin11_AA_Wall_Erosion.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + erosionMapAddressMode: u8 = 0 + } + disableBackfaceCull: bool = true + miscRenderFlags: u8 = 1 + isUniformScale: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 360, 1, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 360, 1, 0 } } + } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 150, 120, 120 } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 1.5, 1.5, 2 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.2, 1 } + values: list[vec3] = { + { 0.75, 0.375, 0.2 } + { 1.125, 1.125, 1 } + { 1.5, 1.8000001, 2 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Aatrox_Skin11_AA_Flares_03.Zaahen.tex" + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.05 + rate: embed = ValueFloat { + constantValue: f32 = 200 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.5 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 0.9, 1 } + keyValues: list[f32] = { 0.2, 1, 1.5 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 0.5 } + } + } + particleLinger: option[f32] = { 1 } + lifetime: option[f32] = { 0.1 } + emitterName: string = "Sparkles" + birthOrbitalVelocity: embed = ValueVector3 { + constantValue: vec3 = { 1, 1, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 1, 1, 1 } } + } + } + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 1000, 500, 1000 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1.1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 1000, 500, 1000 } } + } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 8, 2, 8 } + } + worldAcceleration: embed = IntegratedValueVector3 { + constantValue: vec3 = { 0, 200, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 200, 0 } } + } + } + SpawnShape: pointer = VfxShapeBox { + flags: u8 = 1 + Size: vec3 = { 50, 50, 50 } + } + blendMode: u8 = 4 + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 0.3, 0.6, 1 } + values: list[vec4] = { + { 0.928069, 0.8185092, 0.6716716, 0 } + { 0.91024643, 0.65159076, 0.65392536, 1 } + { 0.93354696, 0.4036927, 0.4084535, 1 } + { 0.9411765, 0.06666667, 0.07450981, 1 } + { 0.23137255, 0, 0.015686275, 0 } + } + } + } + pass: i16 = 10 + miscRenderFlags: u8 = 1 + isDirectionOriented: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 1, 0, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 1, 0, 0 } } + } + } + birthRotationalVelocity0: embed = ValueVector3 { + constantValue: vec3 = { -300, 0, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 25, 50, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.3, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 1, 2 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 25, 50, 0 } } + } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.1, 0.19223854, 0.37142858, 1 } + values: list[vec3] = { + { 0, 0, 0 } + { 1, 1, 1 } + { 0.21186441, 0.5, 0.5 } + { 0.56271183, 0.33380866, 0.33380866 } + { 0, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_R_Sparks.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 5 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.1 + } + particleLinger: option[f32] = { 1 } + lifetime: option[f32] = { 0.25 } + isSingleParticle: flag = true + emitterName: string = "Flash7" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.92156863, 0.7607843, 0.49019608, 1 } + } + Color: embed = ValueColor { + constantValue: vec4 = { 1, 1, 1, 0.972549 } + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 1 } + values: list[vec4] = { + { 1, 1, 1, 0.972549 } + { 1, 1, 1, 0.972549 } + } + } + } + pass: i16 = 500 + meshRenderFlags: u8 = 0 + alphaRef: u8 = 0 + depthBiasFactors: vec2 = { -1, -20 } + miscRenderFlags: u8 = 1 + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 300, 100, 300 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 0.5, 0.5, 0.5 } + { 1, 1, 0.25 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/TahmKench_Skin30_bigglow023.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 10 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.4 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.4, 1 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 0.4 } + } + } + particleLinger: option[f32] = { 10.6 } + lifetime: option[f32] = { 0.2 } + isSingleParticle: flag = true + emitterLinger: option[f32] = { 1 } + emitterName: string = "Spark" + birthVelocity: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.85, 1 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 0, 0 } } + } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 1, 1, 1 } + } + drag: embed = ValueVector3 { + constantValue: vec3 = { 1, 1, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.15, 0.2 } + values: list[vec3] = { + { 0, 0, 0 } + { 1, 1, 1 } + { 2, 2, 2 } + } + } + } + SpawnShape: pointer = VfxShapeLegacy { + emitRotationAngles: list[embed] = { + ValueFloat { + constantValue: f32 = 1 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 1 } + } + } + } + emitRotationAxes: list[vec3] = { { 0, 0, 1 } } + } + FlexShapeDefinition: pointer = VfxFlexShapeDefinitionData { + scaleEmitOffsetByBoundObjectSize: f32 = 0.005 + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.92156863, 0.7607843, 0.49019608, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.15, 1 } + values: list[vec4] = { + { 0.92156863, 0.7607843, 0.49019608, 0 } + { 0.919997, 0.7600061, 0.4899977, 1 } + { 0.61960787, 0.08627451, 0.015686275, 0 } + } + } + } + pass: i16 = 50 + colorLookUpTypeY: u8 = 3 + 0xcb13aff1: f32 = -10 + miscRenderFlags: u8 = 1 + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 360, 0, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 360, 0, 0 } } + } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 30, 60, 10 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.3, 2 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 30, 60, 10 } } + } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.7, 1 } + values: list[vec3] = { + { 1, 2, 0 } + { 0.8, 1, 2 } + { 0, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Darius_Skin43_Star_Flash.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 2 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.5 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 0.5 } + } + } + particleLinger: option[f32] = { 0.4 } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "mesh_ground2" + worldAcceleration: embed = IntegratedValueVector3 { + constantValue: vec3 = { 0, 50, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 50, 0 } } + } + } + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + FlexShapeDefinition: pointer = VfxFlexShapeDefinitionData { + scaleBirthScaleByBoundObjectSize: f32 = 0.005 + } + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Cassiopeia_Skin20_Q_weaponswipe6.Zaahen.scb" + } + } + blendMode: u8 = 1 + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.4, 0.8, 1 } + values: list[vec4] = { + { 0.80784315, 0.5137255, 0.42352942, 1 } + { 0.9257801, 0.107393, 0.063096054, 1 } + { 0.27513543, 0, 0.011642634, 0.45882353 } + { 0.14000152, 0.00999466, 0.059998475, 0 } + } + } + } + pass: i16 = 100 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0.2, 1 } + values: list[f32] = { 0.06, 1 } + } + } + erosionSliceWidth: f32 = 1 + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Udyr_Base_VGU_Awaken_Ribbonmask01.Zaahen.tex" + } + disableBackfaceCull: bool = true + miscRenderFlags: u8 = 1 + isUniformScale: flag = true + isGroundLayer: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 0, 1, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 1, 360 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 1, 0 } } + } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 0.2, 0.63, 0.63 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.8, 1.1 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0.2, 0.63, 0.63 } } + } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 1.5, 2, 2 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.3, 1 } + values: list[vec3] = { + { 0, 1.8, 1.8 } + { 1.9499999, 2.6, 2.6 } + { 2.4, 3, 3.2 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Naafiri_Base_Foundation_Missile02.Zaahen.tex" + texAddressModeBase: u8 = 2 + particleUVScrollRate: embed = IntegratedValueVector2 { + constantValue: vec2 = { 1, 0 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec2] = { + { 0.4, 0 } + { 0.1, 0 } + } + } + } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Udyr_Base_VGU_Q_Ele_Flat_Energy.Zaahen.tex" + birthUvScrollRateMult: embed = ValueVector2 { + constantValue: vec2 = { 1, 0 } + } + } + } + } + particleName: string = "Zaahen_Base_E_AoE_Slow" + particlePath: string = "Characters/Zaahen/Skins/Skin0/Particles/Zaahen_Base_E_AoE_Slow" + soundPersistentDefault: string = "Play_sfx_Zaahen_ZaahenEAttack_hit_outer" + flags: u16 = 198 + } + "Characters/Zaahen/Skins/Skin0/Particles/Zaahen_Base_BA_Swipe_1" = VfxSystemDefinitionData { + complexEmitterDefinitionData: list[pointer] = { + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLinger: option[f32] = { } + isSingleParticle: flag = true + childParticleSetDefinition: pointer = VfxChildParticleSetDefinitionData { + childrenIdentifiers: list[embed] = { + VfxChildIdentifier { + effectKey: hash = "Zaahen_BA_Swipe_child" + } + } + } + emitterName: string = "Gimbal" + importance: u8 = 3 + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { -40, 200, -45 } + } + primitive: pointer = VfxPrimitiveArbitraryQuad { } + blendMode: u8 = 1 + pass: i16 = 500 + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 0, -10, 200 } + } + } + } + particleName: string = "Zaahen_Base_BA_Swipe_1" + particlePath: string = "Characters/Zaahen/Skins/Skin0/Particles/Zaahen_Base_BA_Swipe_1" + } + "Characters/Zaahen/Skins/Skin0/Particles/Zaahen_Base_BA_Swipe_2" = VfxSystemDefinitionData { + complexEmitterDefinitionData: list[pointer] = { + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLinger: option[f32] = { } + isSingleParticle: flag = true + childParticleSetDefinition: pointer = VfxChildParticleSetDefinitionData { + childrenIdentifiers: list[embed] = { + VfxChildIdentifier { + effectKey: hash = "Zaahen_BA_Swipe_child" + } + } + } + emitterName: string = "Gimbal" + importance: u8 = 3 + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, 16 } + } + primitive: pointer = VfxPrimitiveArbitraryQuad { } + blendMode: u8 = 1 + pass: i16 = 500 + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, -20 } + } + } + } + particleName: string = "Zaahen_Base_BA_Swipe_2" + particlePath: string = "Characters/Zaahen/Skins/Skin0/Particles/Zaahen_Base_BA_Swipe_2" + } + "Characters/Zaahen/Skins/Skin0/Particles/Zaahen_Base_BA_Swipe_3" = VfxSystemDefinitionData { + complexEmitterDefinitionData: list[pointer] = { + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLinger: option[f32] = { } + isSingleParticle: flag = true + childParticleSetDefinition: pointer = VfxChildParticleSetDefinitionData { + childrenIdentifiers: list[embed] = { + VfxChildIdentifier { + effectKey: hash = "Zaahen_BA_Swipe_child" + } + } + } + emitterName: string = "Gimbal" + importance: u8 = 3 + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 120, 150, -25 } + } + primitive: pointer = VfxPrimitiveArbitraryQuad { } + blendMode: u8 = 1 + pass: i16 = 500 + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 30, 0, 90 } + } + } + } + particleName: string = "Zaahen_Base_BA_Swipe_3" + particlePath: string = "Characters/Zaahen/Skins/Skin0/Particles/Zaahen_Base_BA_Swipe_3" + } + "Characters/Zaahen/Skins/Skin0/Particles/Zaahen_Base_R_Tar" = VfxSystemDefinitionData { + complexEmitterDefinitionData: list[pointer] = { + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.3 + } + particleLinger: option[f32] = { 10.2 } + lifetime: option[f32] = { 1 } + emitterName: string = "Background" + FlexShapeDefinition: pointer = VfxFlexShapeDefinitionData { + scaleEmitOffsetByBoundObjectSize: f32 = 0.005 + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 1, 1, 0.9799954 } + } + Color: embed = ValueColor { + constantValue: vec4 = { 0.24309148, 0.040939957, 0.07330434, 1 } + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.3, 1 } + values: list[vec4] = { + { 0.24309148, 0.040939957, 0.07330434, 1 } + { 0.24309148, 0.040939957, 0.07330434, 0.8399939 } + { 0.24309148, 0.040939957, 0.07330434, 0 } + } + } + } + pass: i16 = -20 + alphaRef: u8 = 4 + miscRenderFlags: u8 = 1 + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 220, 170, 1 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.2, 1 } + values: list[vec3] = { + { 0.7, 0.7, 11 } + { 1, 1, 1 } + { 1.2, 1.2, 1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Aura_Self.Zaahen.tex" + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.05 + rate: embed = ValueFloat { + constantValue: f32 = 2 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.3 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.8, 1.1 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 0.3 } + } + } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "Ray_DARK_BLACK" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + primitive: pointer = VfxPrimitiveRay { } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 1, 1, 0.46999314 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.18041237, 0.3530928, 0.5, 1 } + values: list[vec4] = { + { 0.9385977, 0.8865492, 0.7429465, 1 } + { 0.91660947, 0.8155032, 0.5897612, 1 } + { 0.6117647, 0.40392157, 0.21960784, 1 } + { 0.5065385, 0.10806439, 0.04835584, 1 } + { 0.20851454, 0.08905165, 0.14770733, 1 } + } + } + } + pass: i16 = 50 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + } + times: list[f32] = { 0, 0.55 } + values: list[f32] = { 0, 1 } + } + } + erosionSliceWidth: f32 = 1 + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Aatrox_Skin11_Einstein_04_mult.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + erosionMapAddressMode: u8 = 0 + } + miscRenderFlags: u8 = 1 + isDirectionOriented: flag = true + isRandomStartFrame: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 0, 180, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.9, 1.1 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 180, 0 } } + } + } + directionVelocityScale: f32 = 1 + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 100, 120, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1.1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.65, 1.1 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 100, 120, 0 } } + } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 0.75, 0.75, 1.2 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.1, 1 } + values: list[vec3] = { + { 0, 0, 0 } + { 0.75, 1.5, 0 } + { 0.75, 2.25, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Aatrox_Skin11_Particles_2_78.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 2 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.2 + } + particleLinger: option[f32] = { 0.6 } + lifetime: option[f32] = { 0.7 } + isSingleParticle: flag = true + emitterName: string = "DarkSwipe1" + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, -1200 } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 3, 4, 4 } + } + blendMode: u8 = 5 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 1, 1, 0.7019608 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 1 } + values: list[vec4] = { + { 0.939971, 0.8281071, 0.589868, 1 } + { 0.8783551, 0.6787518, 0.37810332, 1 } + { 0.3507744, 0.08462653, 0.09616236, 1 } + } + } + } + pass: i16 = 5 + alphaRef: u8 = 0 + miscRenderFlags: u8 = 1 + particleIsLocalOrientation: flag = true + isDirectionOriented: flag = true + isRotationEnabled: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 0, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 80, 150, 0 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.1, 1 } + values: list[vec3] = { + { 0, 0, 0 } + { 1, 1, 1 } + { 0, 1, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Skin_06_Spark_Vertical.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 2 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.4 + } + lifetime: option[f32] = { 0.2 } + isSingleParticle: flag = true + emitterName: string = "circleflare_blend1" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 12.815607, 0 } + } + particleColorTexture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/common_color-bellcurve.Zaahen.tex" + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.17181659, 0.07031357, 0.067200735, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.06652807, 0.1964657, 0.38253638, 0.6486486, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0.47272727 } + { 1, 1, 1, 0.21212122 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = -50 + meshRenderFlags: u8 = 0 + alphaRef: u8 = 0 + isUniformScale: flag = true + isRandomStartFrame: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 1, 0, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 1, 0, 0 } } + } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 40, 200, 200 } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 1.5, 1, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.08212058, 0.17525057, 1 } + values: list[vec3] = { + { 0, 1, 1 } + { 2.4626865, 0.9178794, 0.9178794 } + { 3.1791046, 0.8247494, 0.8247494 } + { 4.5, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Thresh_Skin28_Q_Impact_04.Zaahen.tex" + numFrames: u16 = 4 + texDiv: vec2 = { 2, 2 } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.3 + } + particleLinger: option[f32] = { 10.3 } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "flash6" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + FlexShapeDefinition: pointer = VfxFlexShapeDefinitionData { + scaleBirthScaleByBoundObjectSize: f32 = 0.005 + scaleEmitOffsetByBoundObjectSize: f32 = 0.005 + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.9061265, 0.9061265, 0.9061265, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 1 } + values: list[vec4] = { + { 0.8862745, 0.76862746, 0.5058824, 1 } + { 0.8862745, 0.76862746, 0.5058824, 1 } + } + } + } + pass: i16 = 55 + alphaRef: u8 = 0 + miscRenderFlags: u8 = 1 + isUniformScale: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 1, 0, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 1, 0, 0 } } + } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 75, 100, 1 } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 1, 1.5, 2 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.3, 0.6, 1 } + values: list[vec3] = { + { 0, 0, 0 } + { 1, 1.5, 2 } + { 0.2, 0.3, 0.4 } + { 0, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Naafiri_Base_R_Flash_sharp.Zaahen.tex" + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.05 + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.3 + } + particleLinger: option[f32] = { 10.2 } + lifetime: option[f32] = { 1.05 } + isSingleParticle: flag = true + emitterName: string = "flash_Mult" + importance: u8 = 3 + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.31302357, 0.013519494, 0.11020066, 1 } + } + Color: embed = ValueColor { + constantValue: vec4 = { 1, 1, 1, 0.7000076 } + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.5, 1 } + values: list[vec4] = { + { 1, 1, 1, 0.7000076 } + { 1, 1, 1, 0.7000076 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = -1 + miscRenderFlags: u8 = 1 + isUniformScale: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 1, 0, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 1, 0, 0 } } + } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 230, 2, 2 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 1, 1, 1 } + { 0.3, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/JarvanIV_Skin35_R_glow.Zaahen.tex" + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.1 + rate: embed = ValueFloat { + constantValue: f32 = 10 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.4 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.2, 1.5 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 0.4 } + } + } + particleLinger: option[f32] = { 1 } + lifetime: option[f32] = { 0.3 } + isSingleParticle: flag = true + emitterName: string = "Embers1" + birthOrbitalVelocity: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 0, 0 } } + } + } + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 500, 0, -2000 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.2, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 500, 0, -2000 } } + } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 2.5, 1, 2.5 } + } + birthAcceleration: embed = ValueVector3 { + constantValue: vec3 = { 0, -100, 0 } + } + worldAcceleration: embed = IntegratedValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.75, 1.25 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 0, 0 } } + } + } + bindWeight: embed = ValueFloat { + constantValue: f32 = 0.1 + } + SpawnShape: pointer = VfxShapeBox { + flags: u8 = 1 + Size: vec3 = { 10, 10, 10 } + } + blendMode: u8 = 5 + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 0.3, 0.6, 1 } + values: list[vec4] = { + { 0.9411765, 0.06666667, 0.07450981, 0 } + { 0.9411765, 0.06666667, 0.07450981, 1 } + { 0.9411765, 0.06666667, 0.07450981, 1 } + { 0.23137255, 0, 0.015686275, 1 } + { 0.23137255, 0, 0.015686275, 0 } + } + } + } + pass: i16 = 10 + miscRenderFlags: u8 = 1 + isDirectionOriented: flag = true + isUniformScale: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 1, 0, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 1, 0, 0 } } + } + } + birthRotationalVelocity0: embed = ValueVector3 { + constantValue: vec3 = { 300, 0, 0 } + } + directionVelocityScale: f32 = 0.004 + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 30, 60, 50 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.2, 1 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 30, 60, 50 } } + } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.1, 0.13, 0.4, 0.5, 1 } + values: list[vec3] = { + { 0, 0, 0 } + { 1.2, 1, 1 } + { 1, 1, 1 } + { 1, 0.5, 1 } + { 1, 0.5, 1 } + { 0, 0, 1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Morgana_Base_P_StardustMoteAlpha.Zaahen.tex" + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.05 + rate: embed = ValueFloat { + constantValue: f32 = 5 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 1 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 0.85, 1 } + keyValues: list[f32] = { 0.4, 0.6, 0.9 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 1 } + } + } + particleLinger: option[f32] = { 2 } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "DustSpikes1" + SpawnShape: pointer = VfxShapeCylinder { + radius: f32 = 10 + height: f32 = 10 + } + primitive: pointer = VfxPrimitiveRay { } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.57019913, 0.09764248, 0.18066682, 0.47058824 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.2, 0.5, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 0.22000457, 0, 0.05070573, 0.43137255 } + { 0.13698024, 0.0508278, 0.073121235, 0 } + } + } + } + alphaRef: u8 = 50 + censorModulateValue: vec4 = { 0.3, 1, 1, 0.988 } + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.25633293, 0.6982072, 1 } + values: list[f32] = { 0, 0, 0.2, 0.5 } + } + } + erosionFeatherOut: f32 = 0.2 + erosionSliceWidth: f32 = 2 + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Emote_Flames_02.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + isRandomStartFrame: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 1, 180, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -10, 0 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.9, 1.1 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 1, 180, 1 } } + } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 15, 50, 70 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.75, 1.4 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 0.2, 0.8, 1 } + keyValues: list[f32] = { 0.3, 0.6, 1, 1 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 15, 50, 70 } } + } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.2, 0.85, 1 } + values: list[vec3] = { + { 2, 0, 0 } + { 5, 5.5, 0 } + { 6, 5.75, 1 } + { 6.5, 6, 1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Shapes02.Zaahen.tex" + birthFrameRate: embed = ValueFloat { + constantValue: f32 = 0 + } + numFrames: u16 = 4 + texDiv: vec2 = { 4, 2 } + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.05 + rate: embed = ValueFloat { + constantValue: f32 = 5 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 1 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 0.85, 1 } + keyValues: list[f32] = { 0.4, 0.6, 0.9 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 1 } + } + } + particleLinger: option[f32] = { 2 } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "DustSpikes2" + SpawnShape: pointer = VfxShapeCylinder { + radius: f32 = 10 + height: f32 = 10 + } + primitive: pointer = VfxPrimitiveRay { } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.77254903, 0.13725491, 0.1419089, 0.47058824 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.2, 0.5, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 0.22000457, 0, 0.05070573, 0.43137255 } + { 0.13698024, 0.0508278, 0.073121235, 0 } + } + } + } + alphaRef: u8 = 50 + censorModulateValue: vec4 = { 0.3, 1, 1, 0.988 } + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.25633293, 0.6982072, 1 } + values: list[f32] = { 0, 0, 0.2, 0.5 } + } + } + erosionFeatherOut: f32 = 0.2 + erosionSliceWidth: f32 = 2 + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Emote_Flames_02.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + isRandomStartFrame: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 1, 180, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -10, 0 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.9, 1.1 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 1, 180, 1 } } + } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 15, 85, 70 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.75, 1.4 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 0.2, 0.8, 1 } + keyValues: list[f32] = { 0.3, 0.6, 1, 1.2 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 15, 85, 70 } } + } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.2, 0.85, 1 } + values: list[vec3] = { + { 2, 0, 0 } + { 5, 5.5, 0 } + { 6, 5.75, 1 } + { 6.5, 6, 1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Shapes02.Zaahen.tex" + birthFrameRate: embed = ValueFloat { + constantValue: f32 = 0 + } + numFrames: u16 = 4 + texDiv: vec2 = { 4, 2 } + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.05 + rate: embed = ValueFloat { + constantValue: f32 = 5 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.25 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.4, 0.75 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 0.25 } + } + } + lifetime: option[f32] = { 0.98 } + isSingleParticle: flag = true + emitterName: string = "SolidBeams" + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 500, 0, -2000 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.2, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 500, 0, -2000 } } + } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 5, 1, 5 } + } + birthAcceleration: embed = ValueVector3 { + constantValue: vec3 = { 0, -100, 0 } + } + worldAcceleration: embed = IntegratedValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.75, 1.25 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 0, 0 } } + } + } + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + SpawnShape: pointer = VfxShapeBox { + flags: u8 = 1 + Size: vec3 = { 10, 10, 10 } + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.8862745, 0.76862746, 0.5058824, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.3, 1 } + values: list[vec4] = { + { 1, 0.84705883, 0.5411765, 0 } + { 0.9019608, 0.74509805, 0.5411765, 1 } + { 0.8715038, 0.16140993, 0.08235294, 0.45882353 } + } + } + } + pass: i16 = 55 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + constantValue: f32 = 0 + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 1 } + values: list[f32] = { 0, 0 } + } + } + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/AlphaSlice_bubbles_02.Zaahen.tex" + } + miscRenderFlags: u8 = 1 + isDirectionOriented: flag = true + isRandomStartFrame: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 1, 1, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 1, 1, 0 } } + } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 13, 18, 38 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1.5 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 13, 18, 38 } } + } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.2, 0.75, 1 } + values: list[vec3] = { + { 0, 0, 0 } + { 5, 3, 0 } + { 4, 5, 1 } + { 0, 7, 1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/JarvanIV_Skin35_bolts_HitEffect_Physical_S_01.Zaahen.tex" + numFrames: u16 = 4 + texDiv: vec2 = { 4, 1 } + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.1 + rate: embed = ValueFloat { + constantValue: f32 = 7 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.5 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 0.9, 1 } + keyValues: list[f32] = { 0.2, 1, 1.5 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 0.5 } + } + } + particleLinger: option[f32] = { 1 } + lifetime: option[f32] = { 0.3 } + isSingleParticle: flag = true + emitterName: string = "Sparkles3" + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 555, 1, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 0.85 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.75, 1.1 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 555, 1, 0 } } + } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 8, 8, 8 } + } + worldAcceleration: embed = IntegratedValueVector3 { + constantValue: vec3 = { 0, 200, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 200, 0 } } + } + } + SpawnShape: pointer = VfxShapeLegacy { + emitOffset: embed = ValueVector3 { + constantValue: vec3 = { 100, 0, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.2, 1 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 100, 0, 0 } } + } + } + emitRotationAngles: list[embed] = { + ValueFloat { + constantValue: f32 = 1 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 1 } + } + } + ValueFloat { + constantValue: f32 = 1 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 1 } + } + } + } + emitRotationAxes: list[vec3] = { + { 0, 1.0000001, 0 } + { 0, 0, 1.0000001 } + } + } + blendMode: u8 = 5 + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 0.3, 0.6, 1 } + values: list[vec4] = { + { 0.9411765, 0.06666667, 0.07450981, 0 } + { 0.9411765, 0.06666667, 0.07450981, 1 } + { 0.9411765, 0.06666667, 0.07450981, 1 } + { 0.23137255, 0, 0.015686275, 1 } + { 0.23137255, 0, 0.015686275, 0 } + } + } + } + pass: i16 = 10 + miscRenderFlags: u8 = 1 + isUniformScale: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 1, 0, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 1, 0, 0 } } + } + } + birthRotationalVelocity0: embed = ValueVector3 { + constantValue: vec3 = { -300, 0, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 50, 65, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 0.9, 1 } + keyValues: list[f32] = { 0.3, 1, 2 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 50, 65, 0 } } + } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.1, 0.19223854, 0.37142858, 1 } + values: list[vec3] = { + { 0, 0, 0 } + { 1, 1, 1 } + { 0.21186441, 0.5, 0.5 } + { 0.56271183, 0.33380866, 0.33380866 } + { 0, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Morgana_Base_P_StardustMoteAlpha.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.85 + } + particleLinger: option[f32] = { } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "StrokeDissolve_primary" + importance: u8 = 3 + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.88000304, 0.2, 0.2, 0.2899977 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.2, 0.8, 1 } + values: list[vec4] = { + { 0.80784315, 0.5137255, 0.42352942, 1 } + { 0.78431374, 0.101960786, 0, 1 } + { 0.78431374, 0.101960786, 0, 1 } + { 0.13725491, 0.007843138, 0.05882353, 1 } + } + } + } + pass: i16 = 5 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.55 } + values: list[f32] = { 0.15, 1 } + } + } + erosionSliceWidth: f32 = 1 + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Aatrox_Skin11_AA_Wall_Erosion.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + erosionMapAddressMode: u8 = 0 + } + disableBackfaceCull: bool = true + isUniformScale: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 360, 1, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 360, 1, 0 } } + } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 100, 120, 120 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.2, 1 } + values: list[vec3] = { + { 0.5, 0.25, 0.1 } + { 0.75, 0.75, 0.5 } + { 1, 1.2, 1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Aatrox_Skin11_AA_Flares_03.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 2 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.2 + } + particleLinger: option[f32] = { } + lifetime: option[f32] = { 0.2 } + isSingleParticle: flag = true + emitterName: string = "flash9" + importance: u8 = 3 + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.8399939, 0.6599985, 0.48000306, 0.4899977 } + } + Color: embed = ValueColor { + constantValue: vec4 = { 0.9486839, 0.9486839, 0.9486839, 1 } + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.5, 1 } + values: list[vec4] = { + { 0.8407944, 0.7291845, 0.47992244, 1 } + { 0.71735764, 0.58465624, 0.28837618, 1 } + { 0.27479768, 0.09717731, 0.0944703, 0 } + } + } + } + pass: i16 = 600 + alphaRef: u8 = 0 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + constantValue: f32 = 0 + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 1 } + values: list[f32] = { 0, 0 } + } + } + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Darius_Skin43_Star_Flash.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + miscRenderFlags: u8 = 1 + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 1, 90, 90 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 1, 90, 90 } } + } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 200, 200, 0.84 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.3, 1 } + values: list[vec3] = { + { 2, 0, 0 } + { 0.5, 0.5, 0 } + { 0, 1.5, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Darius_Skin43_Star_Flash.Zaahen.tex" + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.1 + rate: embed = ValueFloat { + constantValue: f32 = 3 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.2 + } + particleLinger: option[f32] = { 0.13 } + lifetime: option[f32] = { 0.2 } + isSingleParticle: flag = true + emitterName: string = "Glow" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.86723125, 0.10414282, 0.10414282, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.3, 0.5, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0.17999542 } + { 0.33333334, 0, 0, 0 } + } + } + } + miscRenderFlags: u8 = 1 + isUniformScale: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 1, 0, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 1, 0, 0 } } + } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 75, 1, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.9, 1 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 75, 1, 1 } } + } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.25, 1 } + values: list[vec3] = { + { 0.5, 1, 1 } + { 1, 1, 1 } + { 2, 2, 1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Sett_Base_BA_Ring.Zaahen.tex" + } + } + particleName: string = "Zaahen_Base_R_Tar" + particlePath: string = "Characters/Zaahen/Skins/Skin0/Particles/Zaahen_Base_R_Tar" + flags: u16 = 199 + } + "Characters/Zaahen/Skins/Skin0/Particles/Zaahen_Base_Emote_Taunt" = VfxSystemDefinitionData { + complexEmitterDefinitionData: list[pointer] = { + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 4 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.6 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1.5 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 0.6 } + } + } + particleLinger: option[f32] = { 10.5 } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "impactStones2" + importance: u8 = 1 + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 300, 600, 400 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -0.1, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.8, 1.5 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 0.9, 1 } + keyValues: list[f32] = { 0.2, 1, 1.4 } + } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 300, 600, 400 } } + } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 6, 6, 6 } + } + worldAcceleration: embed = IntegratedValueVector3 { + constantValue: vec3 = { 0, -500, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0 } + values: list[vec3] = { { 0, -500, 0 } } + } + } + SpawnShape: pointer = VfxShapeCylinder { + radius: f32 = 25 + height: f32 = 10 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, -5 } + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.60442513, 0.6222324, 0.58165866, 1 } + } + pass: i16 = 1 + miscRenderFlags: u8 = 1 + isDirectionOriented: flag = true + isUniformScale: flag = true + isRandomStartFrame: flag = true + directionVelocityScale: f32 = 0.001 + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 15, 15, 15 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 0.8, 1 } + keyValues: list[f32] = { 0, 0.5, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 15, 15, 15 } } + } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.5, 1 } + values: list[vec3] = { + { 0, 0, 0 } + { 1, 1, 1 } + { 0, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Emote_Pebbles.Zaahen.tex" + numFrames: u16 = 16 + texDiv: vec2 = { 4, 4 } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = -1 + } + particleLinger: option[f32] = { 0.3 } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "SpikeGroundLine5" + importance: u8 = 3 + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 10, -15, -5 } + } + primitive: pointer = VfxPrimitiveArbitraryQuad { } + blendMode: u8 = 1 + Color: embed = ValueColor { + constantValue: vec4 = { 0.25490198, 0.25490198, 0.27450982, 1 } + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.2, 0.72, 1 } + values: list[vec4] = { + { 0.25490198, 0.25490198, 0.27450982, 1 } + { 0.25490198, 0.25490198, 0.27450982, 1 } + { 0.19882238, 0.19882238, 0.2141164, 0.9799954 } + { 0.10795849, 0.10795849, 0.11626298, 0 } + } + } + } + pass: i16 = -3 + alphaRef: u8 = 0 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0 } + values: list[f32] = { 0 } + } + } + UseLingerErosionDriveCurve: bool = true + LingerErosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.23250808, 0.57911736, 1.0010765 } + values: list[f32] = { 0.0028735632, 0.22701149, 0.7643678, 1.0660919 } + } + } + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Skin01/Particles/Zaahen_Skin01_R_SmokeErode.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + disableBackfaceCull: bool = true + miscRenderFlags: u8 = 1 + particleIsLocalOrientation: flag = true + isGroundLayer: flag = true + useNavmeshMask: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 10, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 80, 150, 0 } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 1, 2, 1 } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Emote_ground_crack_03.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = -1 + } + particleLingerType: u8 = 1 + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "ground_decal10" + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, -5 } + } + primitive: pointer = VfxPrimitiveArbitraryQuad { } + particleColorTexture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/alphaslice_mesh.Zaahen.tex" + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.08000305, 0.08000305, 0.08000305, 0.30000764 } + } + pass: i16 = -10 + alphaRef: u8 = 0 + isUniformScale: flag = true + isGroundLayer: flag = true + useNavmeshMask: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 0, 120 } + } + isLocalOrientation: flag = false + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 150, 350, 350 } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Aura_Self.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 2 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.3 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.4, 1.2 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 0.3 } + } + } + lifetime: option[f32] = { 0.2 } + isSingleParticle: flag = true + emitterName: string = "Smoke3" + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 200, 400, 200 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.4, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 200, 400, 200 } } + } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 5, 5, 5 } + } + SpawnShape: pointer = VfxShapeLegacy { + emitOffset: embed = ValueVector3 { + constantValue: vec3 = { 20, 0, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 20, 0, 0 } } + } + } + emitRotationAngles: list[embed] = { + ValueFloat { } + ValueFloat { } + } + emitRotationAxes: list[vec3] = { + { 0, 0, 0 } + { 0, 0, 0 } + } + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 15, -2.5 } + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.919997, 0.8399939, 0.7000076, 1 } + } + Color: embed = ValueColor { + constantValue: vec4 = { 0.8352941, 0.8352941, 0.8352941, 1 } + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.15, 0.5, 1 } + values: list[vec4] = { + { 0.8352941, 0.76322955, 0.64203, 1 } + { 0.4651442, 0.41236395, 0.35205096, 1 } + { 0.5339331, 0.4167485, 0.3810858, 0.67058825 } + { 0.12529093, 0.075174555, 0.025058188, 0.4500038 } + } + } + } + pass: i16 = 10 + colorLookUpTypeY: u8 = 3 + alphaRef: u8 = 2 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.1, 1 } + values: list[f32] = { 0, 0, 1 } + } + } + erosionFeatherIn: f32 = 0.2 + erosionFeatherOut: f32 = 0.2 + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Base_SmokeErode.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + 0xcb13aff1: f32 = 20 + isDirectionOriented: flag = true + isRandomStartFrame: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { -135, 0, 0 } + } + directionVelocityScale: f32 = 0.002 + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 80, 125, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.6, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 80, 125, 1 } } + } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.034759358, 0.080213904, 0.14438502, 0.24919786, 0.3657754, 1 } + values: list[vec3] = { + { 0, 0, 0 } + { 0.2682927, 0.2682927, 0.2682927 } + { 0.5, 0.5027579, 0.5027579 } + { 0.6585366, 0.6535755, 0.6535755 } + { 0.76829267, 0.76648456, 0.76648456 } + { 0.80487806, 0.8275755, 0.8275755 } + { 1, 1, 1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_R_Smoke01_01.Zaahen.tex" + numFrames: u16 = 4 + texDiv: vec2 = { 2, 2 } + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.05 + rate: embed = ValueFloat { + constantValue: f32 = 5 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.4 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.65, 1 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 0.4 } + } + } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "Smoke_Burst3" + importance: u8 = 3 + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 500, 400, 500 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.3, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 500, 400, 500 } } + } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 8, 8, 8 } + } + worldAcceleration: embed = IntegratedValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 0, 0 } } + } + } + SpawnShape: pointer = VfxShapeBox { + flags: u8 = 1 + Size: vec3 = { 1.5, 1.5, 1.5 } + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, -2.5 } + } + primitive: pointer = VfxPrimitiveArbitraryQuad { } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 1, 1, 0.5000076 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 1 } + values: list[vec4] = { + { 0.9370413, 0.8512093, 0.70670635, 0 } + { 0.92156863, 0.7607843, 0.49019608, 1 } + { 0.24054322, 0.17172503, 0.057663843, 0 } + } + } + } + pass: i16 = 20 + alphaRef: u8 = 0 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0.25, 1 } + values: list[f32] = { 0, 1 } + } + } + erosionFeatherOut: f32 = 0.2 + erosionSliceWidth: f32 = 2 + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Emote_Flames_02.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + depthBiasFactors: vec2 = { -1, -15 } + disableBackfaceCull: bool = true + miscRenderFlags: u8 = 1 + isDirectionOriented: flag = true + isRandomStartFrame: flag = true + isGroundLayer: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, -90, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 90, -90, 0 } } + } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 80, 60, 40 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.8, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.8, 1 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 80, 60, 40 } } + } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 0.5, 0.5, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.2, 0.5, 1 } + values: list[vec3] = { + { 0.25, 0.3, 0.8 } + { 0.325, 0.375, 0.75 } + { 0.5, 0.55, 1 } + { 0.45, 0.65, 1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Shapes02.Zaahen.tex" + numFrames: u16 = 4 + texDiv: vec2 = { 2, 2 } + } + } + particleName: string = "Zaahen_Base_Emote_Taunt" + particlePath: string = "Characters/Zaahen/Skins/Skin0/Particles/Zaahen_Base_Emote_Taunt" + flags: u16 = 213 + } + "Characters/Zaahen/Skins/Skin0/Particles/Zaahen_Base_E_AoE" = VfxSystemDefinitionData { + complexEmitterDefinitionData: list[pointer] = { + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.04 + rate: embed = ValueFloat { + constantValue: f32 = 4 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.15 + } + particleLinger: option[f32] = { 1 } + lifetime: option[f32] = { 1.1 } + isSingleParticle: flag = true + emitterName: string = "REDSwipe1" + importance: u8 = 3 + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, -100 } + } + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_E_Swipe1.Zaahen.scb" + } + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.9100023, 0.08999771, 0.06999313, 0.5000076 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0.071794875, 0.3, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = 5 + softParticleParams: pointer = VfxSoftParticleDefinitionData { + beginIn: f32 = 10 + deltaIn: f32 = 100 + } + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + constantValue: f32 = 0 + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { + 0.013461539 + 0.18642013 + 0.30038393 + 0.46961468 + 0.61538464 + 0.7903846 + 1.0115385 + } + values: list[f32] = { 0, 0, 0, 0, 0, 0, 0 } + } + } + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Ambessa_Base_E_OneShot_Ring_Swipe_shapeB.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + disableBackfaceCull: bool = true + isUniformScale: flag = true + uvScrollClamp: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 45, 90, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 1.6, 1, 1 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 1, 1, 1 } + { 1.1, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Ambessa_Base_E_OneShot_Ring_Swipe_shape.Zaahen.tex" + birthUvScrollRate: embed = ValueVector2 { + constantValue: vec2 = { 0, 3 } + } + birthUVOffset: embed = ValueVector2 { + constantValue: vec2 = { 0, -0.1 } + } + texAddressModeBase: u8 = 2 + uvScale: embed = ValueVector2 { + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec2] = { + { 1, 2 } + { 1, 1 } + } + } + } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Q_Trail10.Zaahen.tex" + UvRotationMult: embed = ValueFloat { + constantValue: f32 = 90 + } + uvScaleMult: embed = ValueVector2 { + constantValue: vec2 = { 5, 1 } + } + TextureMultFilpV: flag = true + } + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.04 + rate: embed = ValueFloat { + constantValue: f32 = 4 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.15 + } + particleLinger: option[f32] = { 1 } + lifetime: option[f32] = { 1.1 } + isSingleParticle: flag = true + emitterName: string = "REDSwipe2" + importance: u8 = 3 + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, -100 } + } + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_E_Swipe1.Zaahen.scb" + } + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.9100023, 0.08999771, 0.06999313, 0.5000076 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0.071794875, 0.3, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = 5 + softParticleParams: pointer = VfxSoftParticleDefinitionData { + beginIn: f32 = 10 + deltaIn: f32 = 100 + } + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + constantValue: f32 = 0 + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { + 0.013461539 + 0.18642013 + 0.30038393 + 0.46961468 + 0.61538464 + 0.7903846 + 1.0115385 + } + values: list[f32] = { 0, 0, 0, 0, 0, 0, 0 } + } + } + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Ambessa_Base_E_OneShot_Ring_Swipe_shapeB.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + disableBackfaceCull: bool = true + isUniformScale: flag = true + uvScrollClamp: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 135, 90, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 1.6, 1, 1 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 1, 1, 1 } + { 1.1, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Ambessa_Base_E_OneShot_Ring_Swipe_shape.Zaahen.tex" + birthUvScrollRate: embed = ValueVector2 { + constantValue: vec2 = { 0, 3 } + } + birthUVOffset: embed = ValueVector2 { + constantValue: vec2 = { 0, -0.1 } + } + texAddressModeBase: u8 = 2 + uvScale: embed = ValueVector2 { + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec2] = { + { 1, 2 } + { 1, 1 } + } + } + } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_E_Swipe_DarkinTrail.Zaahen.tex" + UvRotationMult: embed = ValueFloat { + constantValue: f32 = 80 + } + uvScaleMult: embed = ValueVector2 { + constantValue: vec2 = { 5, 1 } + } + TextureMultFilpV: flag = true + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.4 + } + particleLinger: option[f32] = { 0.5 } + isSingleParticle: flag = true + emitterName: string = "Indicator_INNER" + importance: u8 = 3 + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 1, 0 } + } + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/XinZhaoRework_Base_R_PortalEdge_Circle.Zaahen.scb" + } + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 1, 1, 0.4399939 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0.0116959065, 0.18567252, 0.2, 0.6, 1 } + values: list[vec4] = { + { 0.9098039, 0.09411765, 0.07058824, 0.23137255 } + { 0.9098039, 0.09411765, 0.07058824, 1 } + { 0.4500038, 0.08999771, 0.08000305, 1 } + { 0.17254902, 0.09019608, 0.08235294, 1 } + { 0.17254902, 0.09019608, 0.08235294, 0 } + } + } + } + pass: i16 = 1 + colorLookUpScales: vec2 = { 0.3, 0.6 } + alphaRef: u8 = 0 + disableBackfaceCull: bool = true + miscRenderFlags: u8 = 1 + isUniformScale: flag = true + isGroundLayer: flag = true + useNavmeshMask: flag = true + birthRotationalVelocity0: embed = ValueVector3 { + constantValue: vec3 = { 0, 8, 0 } + } + isLocalOrientation: flag = false + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 21.5, 38, 38 } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/XinZhaoRework_Skin27_R_Line_2.Zaahen.tex" + birthUVOffset: embed = ValueVector2 { + constantValue: vec2 = { 1, 0 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec2] = { { 1, 0 } } + } + } + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.05 + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.3 + } + particleLinger: option[f32] = { 1 } + lifetime: option[f32] = { 0.5 } + isSingleParticle: flag = true + emitterName: string = "swirlMeshLeft_Blend4" + importance: u8 = 3 + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 1, 0 } + } + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_E_Swirl_X2.Zaahen.scb" + } + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.5573816, 0.06363012, 0.056534678, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0.0843949, 0.18949045, 0.5, 0.6, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = -50 + alphaRef: u8 = 0 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.4, 0.6 } + values: list[f32] = { 0, 0.4, 0.6 } + } + } + erosionFeatherIn: f32 = 0.15 + erosionFeatherOut: f32 = 0.15 + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Ambessa_Base_E_OneShot_Ring_Swipe_shapeB.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + miscRenderFlags: u8 = 1 + isGroundLayer: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 0, -180, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 1.2, 0, 1.2 } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Ambessa_Base_E_OneShot_Ring_Swipe_shape.Zaahen.tex" + birthUVOffset: embed = ValueVector2 { + constantValue: vec2 = { 0, -0.05 } + } + texAddressModeBase: u8 = 2 + particleUVScrollRate: embed = IntegratedValueVector2 { + constantValue: vec2 = { 0, 2 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec2] = { + { 0, 2 } + { 0, 0.4 } + } + } + } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Garen_Skin46_E_Trail_01_010.Zaahen.tex" + UvRotationMult: embed = ValueFloat { + constantValue: f32 = 90 + } + ParticleIntegratedUvScrollMult: embed = IntegratedValueVector2 { + constantValue: vec2 = { 4, 0 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 0.75 } + values: list[vec2] = { + { 4, 0 } + { 0, 0 } + } + } + } + birthUVOffsetMult: embed = ValueVector2 { + constantValue: vec2 = { 0.5, 0 } + } + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.25 + } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "Slashes_LEFT2" + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 1, 0 } + } + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Tryndamere_Base_E_Slashes.Zaahen.scb" + } + } + particleColorTexture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Lux_Skin07_W_Distort_RGBA_2.Zaahen.tex" + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.9100023, 0.5799954, 0.2399939, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.6, 0.8 } + values: list[vec4] = { + { 1, 0.85999846, 0.85999846, 0.2500038 } + { 1, 0.7000076, 0.8200046, 1 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = 110 + colorLookUpTypeY: u8 = 3 + disableBackfaceCull: bool = true + miscRenderFlags: u8 = 1 + isUniformScale: flag = true + isGroundLayer: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 0, 180, 0 } + } + birthRotationalVelocity0: embed = ValueVector3 { + constantValue: vec3 = { 0, 10, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 0, 10, 0 } + { 0, 10, 0 } + } + } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 7.7, 600, 150 } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Tryndamere_Base_E_SlashUlt.Zaahen.tex" + particleUVScrollRate: embed = IntegratedValueVector2 { + constantValue: vec2 = { 4, 0 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec2] = { + { 4, 0 } + { 0, 0 } + } + } + } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/2v2Cameo_Jhin_Mult.Zaahen.tex" + UvRotationMult: embed = ValueFloat { + constantValue: f32 = 90 + } + birthUVOffsetMult: embed = ValueVector2 { + constantValue: vec2 = { 0, 0.5 } + } + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.6 + } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "darkgroundglow" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 10, 0 } + } + FlexShapeDefinition: pointer = VfxFlexShapeDefinitionData { + scaleBirthScaleByBoundObjectSize: f32 = 0.005 + scaleEmitOffsetByBoundObjectSize: f32 = 0.005 + } + primitive: pointer = VfxPrimitiveArbitraryQuad { } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.19478141, 0.032242313, 0.06379797, 0.76862746 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.05, 0.2, 0.5, 0.6 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0.42000458 } + { 0.12959488, 0.049698636, 0.060120545, 0 } + } + } + } + pass: i16 = -300 + meshRenderFlags: u8 = 0 + alphaRef: u8 = 0 + miscRenderFlags: u8 = 1 + isUniformScale: flag = true + isGroundLayer: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { -90, 270, 0 } + } + isLocalOrientation: flag = false + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 465, 200, 200 } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Idle_Flare01.Zaahen.tex" + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.05 + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.3 + } + particleLinger: option[f32] = { 1 } + lifetime: option[f32] = { 0.5 } + isSingleParticle: flag = true + emitterName: string = "swirlMeshLeft_Blend10" + importance: u8 = 3 + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 1, 0 } + } + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Ambessa_Base_E_Swirl_X.Zaahen.scb" + } + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.5573816, 0.06363012, 0.056534678, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0.0843949, 0.18949045, 0.5, 0.6, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = -50 + alphaRef: u8 = 0 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.4, 0.6 } + values: list[f32] = { 0, 0.4, 0.6 } + } + } + erosionFeatherIn: f32 = 0.15 + erosionFeatherOut: f32 = 0.15 + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Ambessa_Base_E_OneShot_Ring_Swipe_shapeB.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + miscRenderFlags: u8 = 1 + isGroundLayer: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 1.1, 0, 1.2 } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Ambessa_Base_E_OneShot_Ring_Swipe_shape.Zaahen.tex" + birthUVOffset: embed = ValueVector2 { + constantValue: vec2 = { 0, -0.05 } + } + texAddressModeBase: u8 = 2 + particleUVScrollRate: embed = IntegratedValueVector2 { + constantValue: vec2 = { 0, 2 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec2] = { + { 0, 2 } + { 0, 0.4 } + } + } + } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Garen_Skin46_E_Trail_01_010.Zaahen.tex" + UvRotationMult: embed = ValueFloat { + constantValue: f32 = 90 + } + ParticleIntegratedUvScrollMult: embed = IntegratedValueVector2 { + constantValue: vec2 = { 4, 0 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 0.75 } + values: list[vec2] = { + { 4, 0 } + { 0, 0 } + } + } + } + birthUVOffsetMult: embed = ValueVector2 { + constantValue: vec2 = { 0.5, 0 } + } + } + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.05 + rate: embed = ValueFloat { + constantValue: f32 = 4 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.4 + } + particleLinger: option[f32] = { 1 } + lifetime: option[f32] = { 0.5 } + isSingleParticle: flag = true + emitterName: string = "swirlMeshLeft_Blend11" + importance: u8 = 3 + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 1, 0 } + } + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_E_Swirl_X2.Zaahen.scb" + } + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.5803922, 0.09019608, 0.15686275, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 0.34235668, 0.6, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0.5000076 } + { 1, 1, 1, 0 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = 150 + alphaRef: u8 = 0 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.4, 0.6 } + values: list[f32] = { 0, 0.4, 1 } + } + } + erosionFeatherIn: f32 = 0.15 + erosionFeatherOut: f32 = 0.15 + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Ambessa_Base_E_OneShot_Ring_Swipe_shapeB.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + miscRenderFlags: u8 = 1 + isGroundLayer: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 0, -145, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 1.1, 0, 1.1 } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Ambessa_Base_E_OneShot_Ring_Swipe_shape.Zaahen.tex" + birthUVOffset: embed = ValueVector2 { + constantValue: vec2 = { 0, 0.05 } + } + texAddressModeBase: u8 = 2 + particleUVScrollRate: embed = IntegratedValueVector2 { + constantValue: vec2 = { 0, 0.5 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 0.5 } + values: list[vec2] = { + { 0, 0.5 } + { 0, 0.1 } + } + } + } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_E_Swipe_Mask.Zaahen.tex" + UvRotationMult: embed = ValueFloat { + constantValue: f32 = 90 + } + ParticleIntegratedUvScrollMult: embed = IntegratedValueVector2 { + constantValue: vec2 = { 2, 0 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 0.75 } + values: list[vec2] = { + { 2, 0 } + { 0, 0 } + } + } + } + birthUVOffsetMult: embed = ValueVector2 { + constantValue: vec2 = { 0.5, 0 } + } + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 8 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.1 + } + particleLinger: option[f32] = { 3 } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "rimRed_FILL3" + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Ambessa_Base_E_Polar_Decal_B.Zaahen.scb" + } + } + blendMode: u8 = 1 + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.2, 0.58, 1 } + values: list[vec4] = { + { 0.4647135, 0.028732738, 0.022552835, 1 } + { 0.4259556, 0.13327229, 0.11764706, 1 } + { 0.28059816, 0.04263371, 0.08911269, 0.69411767 } + { 0.059998475, 0, 0.024841689, 0 } + } + } + } + pass: i16 = -600 + disableBackfaceCull: bool = true + miscRenderFlags: u8 = 1 + isUniformScale: flag = true + isGroundLayer: flag = true + useNavmeshMask: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 0, 360, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 360, 0 } } + } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 0.98, 1, 1 } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/color-hold.Zaahen.tex" + birthUVOffset: embed = ValueVector2 { + constantValue: vec2 = { 1, 1 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec2] = { { 1, 1 } } + } + } + particleUVScrollRate: embed = IntegratedValueVector2 { + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0 } + values: list[vec2] = { { 0, 0 } } + } + } + uvRotation: embed = ValueFloat { + constantValue: f32 = 90 + } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Gradient.Zaahen.tex" + texAddressModeMult: u8 = 2 + ParticleIntegratedUvScrollMult: embed = IntegratedValueVector2 { + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0 } + values: list[vec2] = { { 0, 0 } } + } + } + TextureMultFilpV: flag = true + birthUVOffsetMult: embed = ValueVector2 { + constantValue: vec2 = { 0, 0.2 } + } + } + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.05 + rate: embed = ValueFloat { + constantValue: f32 = 4 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.4 + } + particleLinger: option[f32] = { 1 } + lifetime: option[f32] = { 0.5 } + isSingleParticle: flag = true + emitterName: string = "swirlMeshLeft_Blend12" + importance: u8 = 3 + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 1, 0 } + } + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Ambessa_Base_E_Swirl_X.Zaahen.scb" + } + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.5803922, 0.09019608, 0.15686275, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 0.34235668, 0.6, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0.5000076 } + { 1, 1, 1, 0 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = 150 + alphaRef: u8 = 0 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.4, 0.6 } + values: list[f32] = { 0, 0.4, 0.6 } + } + } + erosionFeatherIn: f32 = 0.15 + erosionFeatherOut: f32 = 0.15 + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Ambessa_Base_E_OneShot_Ring_Swipe_shapeB.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + miscRenderFlags: u8 = 1 + isGroundLayer: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 0, -20, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 1.1, 0, 1.1 } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Ambessa_Base_E_OneShot_Ring_Swipe_shape.Zaahen.tex" + birthUVOffset: embed = ValueVector2 { + constantValue: vec2 = { 0, 0.05 } + } + texAddressModeBase: u8 = 2 + particleUVScrollRate: embed = IntegratedValueVector2 { + constantValue: vec2 = { 0, 1 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 0.5 } + values: list[vec2] = { + { 0, 1 } + { 0, 0.2 } + } + } + } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_E_Swipe_Mask.Zaahen.tex" + UvRotationMult: embed = ValueFloat { + constantValue: f32 = 90 + } + ParticleIntegratedUvScrollMult: embed = IntegratedValueVector2 { + constantValue: vec2 = { 2, 0 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 0.75 } + values: list[vec2] = { + { 2, 0 } + { 0, 0 } + } + } + } + birthUVOffsetMult: embed = ValueVector2 { + constantValue: vec2 = { 0.5, 0 } + } + } + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.075 + rate: embed = ValueFloat { + constantValue: f32 = 5 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.2 + } + particleLinger: option[f32] = { 1 } + lifetime: option[f32] = { 0.5 } + isSingleParticle: flag = true + emitterName: string = "swirlMeshLeft_Blend16" + importance: u8 = 3 + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 1, 0 } + } + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_E_Swirl_X2.Zaahen.scb" + } + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.8901961, 0.05490196, 0.07450981, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 0.5, 0.6 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0.1600061 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = -75 + alphaRef: u8 = 0 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + constantValue: f32 = 0 + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.4, 0.6 } + values: list[f32] = { 0, 0, 0 } + } + } + erosionFeatherIn: f32 = 0.15 + erosionFeatherOut: f32 = 0.15 + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Ambessa_Base_E_OneShot_Ring_Swipe_shapeB.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + miscRenderFlags: u8 = 1 + isGroundLayer: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 0, -180, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 1.1, 0, 1.2 } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_R_Screen_Flames_Soft.Zaahen.tex" + birthUVOffset: embed = ValueVector2 { + constantValue: vec2 = { 1, 1 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec2] = { { 1, 1 } } + } + } + particleUVScrollRate: embed = IntegratedValueVector2 { + constantValue: vec2 = { 0, 4 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 0.5 } + values: list[vec2] = { + { 0, 4 } + { 0, 0.8 } + } + } + } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_E_Swipe_Mask.Zaahen.tex" + texAddressModeMult: u8 = 2 + UvRotationMult: embed = ValueFloat { + constantValue: f32 = 90 + } + uvScaleMult: embed = ValueVector2 { + constantValue: vec2 = { 1.5, 1.25 } + } + } + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.075 + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.5 + } + particleLinger: option[f32] = { 1 } + lifetime: option[f32] = { 0.5 } + isSingleParticle: flag = true + emitterName: string = "swirlMeshLeft_Blend17" + importance: u8 = 3 + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 1, 0 } + } + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_E_Swirl_X2.Zaahen.scb" + } + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.54529643, 0.1616083, 0.14331274, 0.5019608 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 0.5, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0.5000076 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = -150 + alphaRef: u8 = 0 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.4, 0.6 } + values: list[f32] = { 0, 0.4, 1 } + } + } + erosionFeatherIn: f32 = 0.15 + erosionFeatherOut: f32 = 0.15 + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_R_Screen_Flames_Soft.Zaahen.tex" + } + miscRenderFlags: u8 = 1 + isGroundLayer: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 0, -180, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 1.2, 0, 1.2 } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_R_Screen_Flames_Soft.Zaahen.tex" + birthUVOffset: embed = ValueVector2 { + constantValue: vec2 = { 1, 1 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec2] = { { 1, 1 } } + } + } + particleUVScrollRate: embed = IntegratedValueVector2 { + constantValue: vec2 = { 0, 4 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 0.5 } + values: list[vec2] = { + { 0, 4 } + { 0, 0 } + } + } + } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_E_Swipe_Mask.Zaahen.tex" + texAddressModeMult: u8 = 2 + UvRotationMult: embed = ValueFloat { + constantValue: f32 = 90 + } + uvScaleMult: embed = ValueVector2 { + constantValue: vec2 = { 1.5, 1.25 } + } + ParticleIntegratedUvScrollMult: embed = IntegratedValueVector2 { + constantValue: vec2 = { 1, 0 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 0.5 } + values: list[vec2] = { + { 1, 0 } + { 0, 0 } + } + } + } + birthUVOffsetMult: embed = ValueVector2 { + constantValue: vec2 = { -0.2, 0 } + } + } + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.075 + rate: embed = ValueFloat { + constantValue: f32 = 5 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.2 + } + particleLinger: option[f32] = { 1 } + lifetime: option[f32] = { 0.5 } + isSingleParticle: flag = true + emitterName: string = "swirlMeshLeft_Blend22" + importance: u8 = 3 + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 1, 0 } + } + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Ambessa_Base_E_Swirl_X.Zaahen.scb" + } + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.8901961, 0.05490196, 0.07450981, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 0.5, 0.6 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0.1600061 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = -75 + alphaRef: u8 = 0 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + constantValue: f32 = 0 + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.4, 0.6 } + values: list[f32] = { 0, 0, 0 } + } + } + erosionFeatherIn: f32 = 0.15 + erosionFeatherOut: f32 = 0.15 + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Ambessa_Base_E_OneShot_Ring_Swipe_shapeB.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + miscRenderFlags: u8 = 1 + isGroundLayer: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 1.1, 0, 1.2 } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_R_Screen_Flames_Soft.Zaahen.tex" + birthUVOffset: embed = ValueVector2 { + constantValue: vec2 = { 1, 1 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec2] = { { 1, 1 } } + } + } + particleUVScrollRate: embed = IntegratedValueVector2 { + constantValue: vec2 = { 0, 4 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 0.5 } + values: list[vec2] = { + { 0, 4 } + { 0, 0.8 } + } + } + } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_E_Swipe_Mask.Zaahen.tex" + texAddressModeMult: u8 = 2 + UvRotationMult: embed = ValueFloat { + constantValue: f32 = 90 + } + uvScaleMult: embed = ValueVector2 { + constantValue: vec2 = { 1.5, 1.25 } + } + } + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.075 + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.75 + } + particleLinger: option[f32] = { 1 } + lifetime: option[f32] = { 0.5 } + isSingleParticle: flag = true + emitterName: string = "swirlMeshLeft_Blend23" + importance: u8 = 3 + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 1, 0 } + } + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Ambessa_Base_E_Swirl_X.Zaahen.scb" + } + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.54529643, 0.1616083, 0.14331274, 0.5019608 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 0.5, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0.5000076 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = -150 + alphaRef: u8 = 0 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.4, 0.6 } + values: list[f32] = { 0, 0.4, 1 } + } + } + erosionFeatherIn: f32 = 0.15 + erosionFeatherOut: f32 = 0.15 + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_R_Screen_Flames_Soft.Zaahen.tex" + } + miscRenderFlags: u8 = 1 + isGroundLayer: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 1.2, 0, 1.2 } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_R_Screen_Flames_Soft.Zaahen.tex" + birthUVOffset: embed = ValueVector2 { + constantValue: vec2 = { 1, 1 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec2] = { { 1, 1 } } + } + } + particleUVScrollRate: embed = IntegratedValueVector2 { + constantValue: vec2 = { 0, 4 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 0.5 } + values: list[vec2] = { + { 0, 4 } + { 0, 0 } + } + } + } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_E_Swipe_Mask.Zaahen.tex" + texAddressModeMult: u8 = 2 + UvRotationMult: embed = ValueFloat { + constantValue: f32 = 90 + } + uvScaleMult: embed = ValueVector2 { + constantValue: vec2 = { 1.5, 1.25 } + } + ParticleIntegratedUvScrollMult: embed = IntegratedValueVector2 { + constantValue: vec2 = { 1, 0 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 0.5 } + values: list[vec2] = { + { 1, 0 } + { 0, 0 } + } + } + } + birthUVOffsetMult: embed = ValueVector2 { + constantValue: vec2 = { -0.2, 0 } + } + } + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.04 + rate: embed = ValueFloat { + constantValue: f32 = 6 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.15 + } + particleLinger: option[f32] = { } + lifetime: option[f32] = { 1.1 } + isSingleParticle: flag = true + emitterName: string = "Swipe" + importance: u8 = 3 + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, -100 } + } + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_E_Swipe1.Zaahen.scb" + } + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 0.57354087, 0.4582437, 0.5803922 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0.071794875, 0.4, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = 15 + softParticleParams: pointer = VfxSoftParticleDefinitionData { + beginIn: f32 = 10 + deltaIn: f32 = 100 + } + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + constantValue: f32 = 0 + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { + 0.013461539 + 0.18642013 + 0.30038393 + 0.46961468 + 0.61538464 + 0.7903846 + 1.0115385 + } + values: list[f32] = { 0, 0, 0, 0, 0, 0, 0 } + } + } + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Ambessa_Base_E_OneShot_Ring_Swipe_shapeB.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + disableBackfaceCull: bool = true + isUniformScale: flag = true + uvScrollClamp: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 45, 90, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 1.6, 1, 1 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 1, 1, 1 } + { 1.1, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_swipe_trail.Zaahen.tex" + birthUVOffset: embed = ValueVector2 { + constantValue: vec2 = { 0.2, 0.35 } + } + texAddressModeBase: u8 = 2 + particleUVScrollRate: embed = IntegratedValueVector2 { + constantValue: vec2 = { 0, -2.5 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec2] = { + { 0, -5 } + { 0, -7.5 } + } + } + } + uvScale: embed = ValueVector2 { + constantValue: vec2 = { 1, 2 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec2] = { + { 1, 4 } + { 1, 2 } + } + } + } + uvRotation: embed = ValueFloat { + constantValue: f32 = 180 + } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/2v2Cameo_Jhin_Mult.Zaahen.tex" + } + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.04 + rate: embed = ValueFloat { + constantValue: f32 = 4 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.15 + } + particleLinger: option[f32] = { } + lifetime: option[f32] = { 1.1 } + isSingleParticle: flag = true + emitterName: string = "Swipe1" + importance: u8 = 3 + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, -100 } + } + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_E_Swipe1.Zaahen.scb" + } + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 0.57254905, 0.45882353, 0.5019608 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0.071794875, 0.4, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = 15 + softParticleParams: pointer = VfxSoftParticleDefinitionData { + beginIn: f32 = 10 + deltaIn: f32 = 100 + } + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + constantValue: f32 = 0 + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { + 0.013461539 + 0.18642013 + 0.30038393 + 0.46961468 + 0.61538464 + 0.7903846 + 1.0115385 + } + values: list[f32] = { 0, 0, 0, 0, 0, 0, 0 } + } + } + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Ambessa_Base_E_OneShot_Ring_Swipe_shapeB.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + disableBackfaceCull: bool = true + isUniformScale: flag = true + uvScrollClamp: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 135, 90, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 1.6, 1, 1 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 1, 1, 1 } + { 1.1, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_swipe_trail.Zaahen.tex" + birthUVOffset: embed = ValueVector2 { + constantValue: vec2 = { 0.2, 0.35 } + } + texAddressModeBase: u8 = 2 + particleUVScrollRate: embed = IntegratedValueVector2 { + constantValue: vec2 = { 0, -2.5 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec2] = { + { 0, -5 } + { 0, -7.5 } + } + } + } + uvScale: embed = ValueVector2 { + constantValue: vec2 = { 1, 2 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec2] = { + { 1, 4 } + { 1, 2 } + } + } + } + uvRotation: embed = ValueFloat { + constantValue: f32 = 180 + } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/2v2Cameo_Jhin_Mult.Zaahen.tex" + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 2 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.3 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 0.3 } + } + } + particleLinger: option[f32] = { } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "End_forward" + importance: u8 = 3 + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, 110 } + } + primitive: pointer = VfxPrimitiveRay { } + blendMode: u8 = 1 + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 0.15, 0.5, 1 } + values: list[vec4] = { + { 0.7607843, 0.05882353, 0.039215688, 0 } + { 0.7607843, 0.05882353, 0.039215688, 1 } + { 0.21960784, 0, 0.050980393, 0.52156866 } + { 0.21960784, 0, 0.050980393, 0.43137255 } + { 0.13698024, 0.0508278, 0.073121235, 0 } + } + } + } + pass: i16 = 200 + alphaRef: u8 = 0 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.25633293, 0.6982072, 1 } + values: list[f32] = { 0, 0, 0.2, 0.5 } + } + } + erosionFeatherOut: f32 = 0.2 + erosionSliceWidth: f32 = 2 + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Emote_Flames_02.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + depthBiasFactors: vec2 = { -1, -15 } + disableBackfaceCull: bool = true + miscRenderFlags: u8 = 1 + isRandomStartFrame: flag = true + isGroundLayer: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 0, 180, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.8, 1.2 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 180, 0 } } + } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 200, 80, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 0.1, 0.5, 0.5001, 0.9, 1 } + keyValues: list[f32] = { 1.5, 1, 0.65, -0.65, -1, 1.5 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 1.1052631, 2 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 200, 80, 0 } } + } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 1, -1, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.2, 1 } + values: list[vec3] = { + { 1, -0.2, 0 } + { 1.5, -3, 1 } + { 1, -4, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Shapes02.Zaahen.tex" + numFrames: u16 = 4 + texDiv: vec2 = { 2, 2 } + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.04 + rate: embed = ValueFloat { + constantValue: f32 = 4 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.15 + } + particleLinger: option[f32] = { 1 } + lifetime: option[f32] = { 1.1 } + isSingleParticle: flag = true + emitterName: string = "REDSwipe10" + importance: u8 = 3 + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, -100 } + } + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_E_Swipe1.Zaahen.scb" + } + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.9229419, 0.07159533, 0.08393988, 0.7019608 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0.071794875, 0.3, 1 } + values: list[vec4] = { + { 0.85000384, 0.10000763, 0.08000305, 1 } + { 0.94546425, 0.6564431, 0.4115511, 1 } + { 0.96568245, 0.94583046, 0.5262074, 0 } + } + } + } + pass: i16 = 7 + softParticleParams: pointer = VfxSoftParticleDefinitionData { + beginIn: f32 = 10 + deltaIn: f32 = 100 + } + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + constantValue: f32 = 0.5 + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { + 0.013461539 + 0.18642013 + 0.30038393 + 0.46961468 + 0.61538464 + 0.7903846 + 1.0115385 + } + values: list[f32] = { + 0.36068934 + 0.25643992 + 0.24799684 + 0.31251296 + 0.25576037 + 0.4078341 + 0.48156682 + } + } + } + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Ambessa_Base_E_OneShot_Ring_Swipe_shapeB.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + disableBackfaceCull: bool = true + isUniformScale: flag = true + uvScrollClamp: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 45, 90, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 1.6, 1, 1 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 1, 1, 1 } + { 1.1, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Ambessa_Base_E_OneShot_Ring_Swipe_shape.Zaahen.tex" + birthUvScrollRate: embed = ValueVector2 { + constantValue: vec2 = { 0, 3 } + } + birthUVOffset: embed = ValueVector2 { + constantValue: vec2 = { 0, -0.1 } + } + texAddressModeBase: u8 = 2 + uvScale: embed = ValueVector2 { + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec2] = { + { 1, 2 } + { 1, 1 } + } + } + } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Q_Trail10.Zaahen.tex" + UvRotationMult: embed = ValueFloat { + constantValue: f32 = 90 + } + uvScaleMult: embed = ValueVector2 { + constantValue: vec2 = { 5, 1 } + } + TextureMultFilpV: flag = true + } + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.04 + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.2 + } + particleLinger: option[f32] = { 1 } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "swirlMesh_Glow" + importance: u8 = 3 + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, -100 } + } + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_E_Swipe2.Zaahen.scb" + } + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.92156863, 0.5764706, 0.49019608, 0.12941177 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.18949045, 0.46676514, 0.66912854 } + values: list[vec4] = { + { 0.92156863, 0.7607843, 0.49019608, 0 } + { 0.92156863, 0.7607843, 0.49019608, 1 } + { 0.8210269, 0.6649424, 0.40221256, 1 } + { 0.2741741, 0.22761883, 0.19931334, 0 } + } + } + } + pass: i16 = 10 + alphaRef: u8 = 0 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + constantValue: f32 = 0 + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0.013461539, 0.125, 0.30576923, 0.475, 0.61713874, 0.79740095, 1.0115385 } + values: list[f32] = { 0, 0, 0, 0, 0, 0, 0 } + } + } + erosionFeatherIn: f32 = 0.24 + erosionFeatherOut: f32 = 0.24 + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Ambessa_Base_E_OneShot_Ring_Swipe_shape1B.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + disableBackfaceCull: bool = true + miscRenderFlags: u8 = 1 + isUniformScale: flag = true + TextureFlipV: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 45, 90, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 1.55, 1.6, 1 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 1, 1, 1 } + { 1.1, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_R_Slam_Glow.Zaahen.tex" + birthUvScrollRate: embed = ValueVector2 { + constantValue: vec2 = { 0, 8 } + } + birthUVOffset: embed = ValueVector2 { + constantValue: vec2 = { -0.05, -0.4 } + } + texAddressModeBase: u8 = 3 + uvScale: embed = ValueVector2 { + constantValue: vec2 = { 1, 2 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec2] = { + { 1, 4 } + { 1, 2 } + } + } + } + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.04 + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.2 + } + particleLinger: option[f32] = { 1 } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "swirlMesh_Glow2" + importance: u8 = 3 + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, -100 } + } + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_E_Swipe2.Zaahen.scb" + } + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.92156863, 0.5764706, 0.49019608, 0.12941177 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.18949045, 0.46676514, 0.66912854 } + values: list[vec4] = { + { 0.919997, 0.7600061, 0.4899977, 1 } + { 0.92156863, 0.7607843, 0.49019608, 1 } + { 0.8210269, 0.6649424, 0.40221256, 1 } + { 0.2741741, 0.22761883, 0.19931334, 0 } + } + } + } + pass: i16 = 10 + alphaRef: u8 = 0 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + constantValue: f32 = 0 + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0.013461539, 0.125, 0.30576923, 0.475, 0.61713874, 0.79740095, 1.0115385 } + values: list[f32] = { 0, 0, 0, 0, 0, 0, 0 } + } + } + erosionFeatherIn: f32 = 0.24 + erosionFeatherOut: f32 = 0.24 + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Ambessa_Base_E_OneShot_Ring_Swipe_shape1B.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + disableBackfaceCull: bool = true + miscRenderFlags: u8 = 1 + isUniformScale: flag = true + TextureFlipV: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 135, 90, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 1.55, 1.6, 1 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 1, 1, 1 } + { 1.1, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_R_Slam_Glow.Zaahen.tex" + birthUvScrollRate: embed = ValueVector2 { + constantValue: vec2 = { 0, 8 } + } + birthUVOffset: embed = ValueVector2 { + constantValue: vec2 = { -0.05, -0.4 } + } + texAddressModeBase: u8 = 3 + uvScale: embed = ValueVector2 { + constantValue: vec2 = { 1, 2 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec2] = { + { 1, 4 } + { 1, 2 } + } + } + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.1 + } + particleLinger: option[f32] = { 1 } + lifetime: option[f32] = { 0.5 } + isSingleParticle: flag = true + emitterName: string = "swirlMeshLeft_Blend36" + importance: u8 = 3 + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 1, 0 } + } + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_E_Swirl_X2.Zaahen.scb" + } + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.101289384, 0.057663843, 0.077729456, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 0.75, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = -155 + alphaRef: u8 = 0 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + constantValue: f32 = 0 + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.4, 0.6 } + values: list[f32] = { 0, 0, 0 } + } + } + erosionFeatherIn: f32 = 0.15 + erosionFeatherOut: f32 = 0.15 + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Nebula_Streak_Mult_Vertical.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + miscRenderFlags: u8 = 1 + isGroundLayer: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 0, -180, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 1.1, 0, 1.1 } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_E_GradientVertical_Blend.Zaahen.tex" + particleUVScrollRate: embed = IntegratedValueVector2 { + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 0.5 } + values: list[vec2] = { + { 0, 0 } + { 0, 0 } + } + } + } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_E_Swipe_GlaiveShape.Zaahen.tex" + texAddressModeMult: u8 = 2 + UvRotationMult: embed = ValueFloat { + constantValue: f32 = 90 + } + uvScaleMult: embed = ValueVector2 { + constantValue: vec2 = { 2, 1 } + } + ParticleIntegratedUvScrollMult: embed = IntegratedValueVector2 { + constantValue: vec2 = { 2, 2 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec2] = { + { 2, 2 } + { 2, 2 } + } + } + } + TextureMultFilpV: flag = true + birthUVOffsetMult: embed = ValueVector2 { + constantValue: vec2 = { -0.4, 0 } + } + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.15 + } + particleLinger: option[f32] = { 1 } + lifetime: option[f32] = { 0.5 } + isSingleParticle: flag = true + emitterName: string = "swirlMeshLeft_Blend37" + importance: u8 = 3 + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 1, 0 } + } + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_E_Swirl_X2.Zaahen.scb" + } + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.8901961, 0.101960786, 0.08627451, 1 } + dynamics: pointer = VfxAnimatedColorVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.6, 1.5 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 0.5 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.6, 1.5 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec4] = { { 0.8901961, 0.101960786, 0.08627451, 1 } } + } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0.25, 0.5, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = -150 + alphaRef: u8 = 0 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + constantValue: f32 = 0 + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.4, 0.6 } + values: list[f32] = { 0, 0, 0 } + } + } + erosionFeatherIn: f32 = 0.15 + erosionFeatherOut: f32 = 0.15 + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Nebula_Streak_Mult_Vertical.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + miscRenderFlags: u8 = 1 + isGroundLayer: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 0, -180, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 1.1, 0, 1.1 } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_E_GradientVertical_Blend.Zaahen.tex" + particleUVScrollRate: embed = IntegratedValueVector2 { + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 0.5 } + values: list[vec2] = { + { 0, 0 } + { 0, 0 } + } + } + } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_E_Swipe_GlaiveShape.Zaahen.tex" + texAddressModeMult: u8 = 2 + UvRotationMult: embed = ValueFloat { + constantValue: f32 = 90 + } + uvScaleMult: embed = ValueVector2 { + constantValue: vec2 = { 2, 1 } + } + ParticleIntegratedUvScrollMult: embed = IntegratedValueVector2 { + constantValue: vec2 = { 2, 2 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec2] = { + { 2, 2 } + { 2, 2 } + } + } + } + TextureMultFilpV: flag = true + birthUVOffsetMult: embed = ValueVector2 { + constantValue: vec2 = { -0.4, 0 } + } + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 8 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.15 + } + particleLinger: option[f32] = { 1 } + lifetime: option[f32] = { 0.5 } + isSingleParticle: flag = true + emitterName: string = "swirlMeshLeft_Blend38" + importance: u8 = 3 + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 1, 0 } + } + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_E_Swirl_X2.Zaahen.scb" + } + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.8901961, 0.101960786, 0.08627451, 1 } + dynamics: pointer = VfxAnimatedColorVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.6, 1.5 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 0.5 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.6, 1.5 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec4] = { { 0.8901961, 0.101960786, 0.08627451, 1 } } + } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0.25, 0.5, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = -145 + alphaRef: u8 = 0 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + constantValue: f32 = 0 + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 1 } + values: list[f32] = { 0, 0 } + } + } + erosionFeatherIn: f32 = 0.15 + erosionFeatherOut: f32 = 0.15 + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Nebula_Streak_Mult_Vertical.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + miscRenderFlags: u8 = 1 + isGroundLayer: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 0, -180, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 1.1, 0, 1.1 } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Cape_Nebula.Zaahen.tex" + birthUVOffset: embed = ValueVector2 { + constantValue: vec2 = { 1, 1 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec2] = { { 1, 1 } } + } + } + particleUVScrollRate: embed = IntegratedValueVector2 { + constantValue: vec2 = { 0, -2 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 0.5 } + values: list[vec2] = { + { 0, -2 } + { 0, -2 } + } + } + } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_E_Swipe_GlaiveShape.Zaahen.tex" + texAddressModeMult: u8 = 2 + UvRotationMult: embed = ValueFloat { + constantValue: f32 = 90 + } + uvScaleMult: embed = ValueVector2 { + constantValue: vec2 = { 2, 1 } + } + ParticleIntegratedUvScrollMult: embed = IntegratedValueVector2 { + constantValue: vec2 = { 2, 2 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec2] = { + { 2, 2 } + { 2, 2 } + } + } + } + TextureMultFilpV: flag = true + birthUVOffsetMult: embed = ValueVector2 { + constantValue: vec2 = { -0.4, 0 } + } + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.1 + } + particleLinger: option[f32] = { 1 } + lifetime: option[f32] = { 0.5 } + isSingleParticle: flag = true + emitterName: string = "swirlMeshLeft_Blend39" + importance: u8 = 3 + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 1, 0 } + } + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Ambessa_Base_E_Swirl_X.Zaahen.scb" + } + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.101289384, 0.057663843, 0.077729456, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 0.75, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = -155 + alphaRef: u8 = 0 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + constantValue: f32 = 0 + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 1 } + values: list[f32] = { 0, 0 } + } + } + erosionFeatherIn: f32 = 0.15 + erosionFeatherOut: f32 = 0.15 + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Nebula_Streak_Mult_Vertical.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + miscRenderFlags: u8 = 1 + isGroundLayer: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 1.1, 0, 1.1 } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_E_GradientVertical_Blend.Zaahen.tex" + particleUVScrollRate: embed = IntegratedValueVector2 { + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 0.5 } + values: list[vec2] = { + { 0, 0 } + { 0, 0 } + } + } + } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_E_Swipe_GlaiveShape.Zaahen.tex" + texAddressModeMult: u8 = 2 + UvRotationMult: embed = ValueFloat { + constantValue: f32 = 90 + } + uvScaleMult: embed = ValueVector2 { + constantValue: vec2 = { 2, 1 } + } + ParticleIntegratedUvScrollMult: embed = IntegratedValueVector2 { + constantValue: vec2 = { 2, 2 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec2] = { + { 2, 2 } + { 2, 2 } + } + } + } + TextureMultFilpV: flag = true + birthUVOffsetMult: embed = ValueVector2 { + constantValue: vec2 = { -0.4, 0 } + } + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.15 + } + particleLinger: option[f32] = { 1 } + lifetime: option[f32] = { 0.5 } + isSingleParticle: flag = true + emitterName: string = "swirlMeshLeft_Blend40" + importance: u8 = 3 + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 1, 0 } + } + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Ambessa_Base_E_Swirl_X.Zaahen.scb" + } + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.8901961, 0.101960786, 0.08627451, 1 } + dynamics: pointer = VfxAnimatedColorVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.6, 1.5 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 0.5 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.6, 1.5 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec4] = { { 0.8901961, 0.101960786, 0.08627451, 1 } } + } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0.25, 0.5, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = -150 + alphaRef: u8 = 0 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + constantValue: f32 = 0 + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 1 } + values: list[f32] = { 0, 0 } + } + } + erosionFeatherIn: f32 = 0.15 + erosionFeatherOut: f32 = 0.15 + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Nebula_Streak_Mult_Vertical.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + miscRenderFlags: u8 = 1 + isGroundLayer: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 1.1, 0, 1.1 } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_E_GradientVertical_Blend.Zaahen.tex" + particleUVScrollRate: embed = IntegratedValueVector2 { + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 0.5 } + values: list[vec2] = { + { 0, 0 } + { 0, 0 } + } + } + } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_E_Swipe_GlaiveShape.Zaahen.tex" + texAddressModeMult: u8 = 2 + UvRotationMult: embed = ValueFloat { + constantValue: f32 = 90 + } + uvScaleMult: embed = ValueVector2 { + constantValue: vec2 = { 2, 1 } + } + ParticleIntegratedUvScrollMult: embed = IntegratedValueVector2 { + constantValue: vec2 = { 2, 2 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec2] = { + { 2, 2 } + { 2, 2 } + } + } + } + TextureMultFilpV: flag = true + birthUVOffsetMult: embed = ValueVector2 { + constantValue: vec2 = { -0.4, 0 } + } + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 8 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.15 + } + particleLinger: option[f32] = { 1 } + lifetime: option[f32] = { 0.5 } + isSingleParticle: flag = true + emitterName: string = "swirlMeshLeft_Blend41" + importance: u8 = 3 + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 1, 0 } + } + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Ambessa_Base_E_Swirl_X.Zaahen.scb" + } + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.8901961, 0.101960786, 0.08627451, 1 } + dynamics: pointer = VfxAnimatedColorVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.6, 1.5 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 0.5 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.6, 1.5 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec4] = { { 0.8901961, 0.101960786, 0.08627451, 1 } } + } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0.25, 0.5, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = -145 + alphaRef: u8 = 0 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + constantValue: f32 = 0 + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 1 } + values: list[f32] = { 0, 0 } + } + } + erosionFeatherIn: f32 = 0.15 + erosionFeatherOut: f32 = 0.15 + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Nebula_Streak_Mult_Vertical.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + miscRenderFlags: u8 = 1 + isGroundLayer: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 1.1, 0, 1.1 } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Cape_Nebula.Zaahen.tex" + birthUVOffset: embed = ValueVector2 { + constantValue: vec2 = { 1, 1 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec2] = { { 1, 1 } } + } + } + particleUVScrollRate: embed = IntegratedValueVector2 { + constantValue: vec2 = { 0, -2 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 0.5 } + values: list[vec2] = { + { 0, -2 } + { 0, -2 } + } + } + } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_E_Swipe_GlaiveShape.Zaahen.tex" + texAddressModeMult: u8 = 2 + UvRotationMult: embed = ValueFloat { + constantValue: f32 = 90 + } + uvScaleMult: embed = ValueVector2 { + constantValue: vec2 = { 2, 1 } + } + ParticleIntegratedUvScrollMult: embed = IntegratedValueVector2 { + constantValue: vec2 = { 2, 2 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec2] = { + { 2, 2 } + { 2, 2 } + } + } + } + TextureMultFilpV: flag = true + birthUVOffsetMult: embed = ValueVector2 { + constantValue: vec2 = { -0.4, 0 } + } + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.35 + } + isSingleParticle: flag = true + emitterName: string = "End_drk" + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, 300 } + } + primitive: pointer = VfxPrimitiveArbitraryQuad { } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.17030594, 0.031586174, 0.03759823, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.30363637, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = 100 + alphaRef: u8 = 0 + isUniformScale: flag = true + isGroundLayer: flag = true + TextureFlipV: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 0, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 250, 150, 250 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 1, 1, 1 } + { 0, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Naafiri_Base_Foundation_Glow01.Zaahen.tex" + texAddressModeBase: u8 = 2 + uvRotation: embed = ValueFloat { + constantValue: f32 = -45 + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 2 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.25 + } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "Slashes_RIGHT3" + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 1, 0 } + } + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Tryndamere_Base_E_Slashes.Zaahen.scb" + } + } + particleColorTexture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Lux_Skin07_W_Distort_RGBA_2.Zaahen.tex" + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.9100023, 0.5799954, 0.2399939, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.6, 0.8 } + values: list[vec4] = { + { 1, 0.85882354, 0.85882354, 1 } + { 1, 0.7000076, 0.8200046, 1 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = 110 + colorLookUpTypeY: u8 = 3 + disableBackfaceCull: bool = true + miscRenderFlags: u8 = 1 + isUniformScale: flag = true + isGroundLayer: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 0, 180, 180 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 7.7, 600, 150 } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Tryndamere_Base_E_SlashUlt.Zaahen.tex" + birthUVOffset: embed = ValueVector2 { + constantValue: vec2 = { 0.455, 0 } + } + particleUVScrollRate: embed = IntegratedValueVector2 { + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec2] = { + { 0, 0 } + { 0, 0 } + } + } + } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/2v2Cameo_Jhin_Mult.Zaahen.tex" + UvRotationMult: embed = ValueFloat { + constantValue: f32 = 90 + } + birthUVOffsetMult: embed = ValueVector2 { + constantValue: vec2 = { 0, 0.5 } + } + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 4 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.3 + } + particleLinger: option[f32] = { 0.5 } + isSingleParticle: flag = true + emitterName: string = "Indicator_INNER2" + importance: u8 = 3 + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 1, 0 } + } + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/XinZhaoRework_Base_R_PortalEdge_Circle.Zaahen.scb" + } + } + blendMode: u8 = 4 + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0.0116959065, 0.18567252, 0.2, 0.99122804 } + values: list[vec4] = { + { 0.9100023, 0.08999771, 0.06999313, 0 } + { 0.9100023, 0.08999771, 0.06999313, 0.6599985 } + { 0.4500038, 0.08999771, 0.08000305, 0.39000535 } + { 0.4500038, 0.08999771, 0.08000305, 0 } + } + } + } + pass: i16 = 2 + colorLookUpScales: vec2 = { 0.3, 0.6 } + alphaRef: u8 = 0 + disableBackfaceCull: bool = true + miscRenderFlags: u8 = 1 + isUniformScale: flag = true + isGroundLayer: flag = true + useNavmeshMask: flag = true + birthRotationalVelocity0: embed = ValueVector3 { + constantValue: vec3 = { 0, 8, 0 } + } + isLocalOrientation: flag = false + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 21.5, 38, 38 } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/XinZhaoRework_Skin27_R_Line_2.Zaahen.tex" + birthUVOffset: embed = ValueVector2 { + constantValue: vec2 = { 1, 0 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec2] = { { 1, 0 } } + } + } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_R_Screen_Flames_Soft.Zaahen.tex" + ParticleIntegratedUvScrollMult: embed = IntegratedValueVector2 { + constantValue: vec2 = { 1, 0 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec2] = { { 1, 0 } } + } + } + birthUVOffsetMult: embed = ValueVector2 { + constantValue: vec2 = { -0.2, 0 } + } + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 4 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.3 + } + particleLinger: option[f32] = { 0.5 } + isSingleParticle: flag = true + emitterName: string = "Indicator_OUTER2" + importance: u8 = 3 + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 1, 0 } + } + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/XinZhaoRework_Base_R_PortalEdge_Circle.Zaahen.scb" + } + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 1, 1, 0.2500038 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0.0116959065, 0.18567252, 0.2, 0.99122804 } + values: list[vec4] = { + { 0.9100023, 0.08999771, 0.06999313, 0 } + { 0.9100023, 0.08999771, 0.06999313, 0.46999314 } + { 0.4500038, 0.08999771, 0.08000305, 0.26999313 } + { 0.4500038, 0.08999771, 0.08000305, 0 } + } + } + } + pass: i16 = 2 + colorLookUpScales: vec2 = { 0.3, 0.6 } + alphaRef: u8 = 0 + disableBackfaceCull: bool = true + miscRenderFlags: u8 = 1 + isUniformScale: flag = true + isGroundLayer: flag = true + useNavmeshMask: flag = true + birthRotationalVelocity0: embed = ValueVector3 { + constantValue: vec3 = { 0, 8, 0 } + } + isLocalOrientation: flag = false + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 40.5, 38, 38 } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/XinZhaoRework_Skin27_R_Line_2.Zaahen.tex" + birthUVOffset: embed = ValueVector2 { + constantValue: vec2 = { 1, 0 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec2] = { { 1, 0 } } + } + } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_R_Screen_Flames_Soft.Zaahen.tex" + ParticleIntegratedUvScrollMult: embed = IntegratedValueVector2 { + constantValue: vec2 = { 1, 0 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec2] = { { 1, 0 } } + } + } + birthUVOffsetMult: embed = ValueVector2 { + constantValue: vec2 = { -0.2, 0 } + } + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.3 + } + particleLinger: option[f32] = { 1 } + lifetime: option[f32] = { 0.5 } + isSingleParticle: flag = true + emitterName: string = "swirlMeshLeft_Blend45" + importance: u8 = 3 + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 1, 0 } + } + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Ambessa_Base_E_Swirl_X.Zaahen.scb" + } + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 0.9100023, 0.39000535, 0.2 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0.0843949, 0.18949045, 0.5, 0.6, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = -30 + alphaRef: u8 = 0 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.4, 0.6 } + values: list[f32] = { 0, 0.4, 0.6 } + } + } + erosionFeatherIn: f32 = 0.15 + erosionFeatherOut: f32 = 0.15 + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Ambessa_Base_E_OneShot_Ring_Swipe_shapeB.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + disableBackfaceCull: bool = true + miscRenderFlags: u8 = 1 + isGroundLayer: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { -1.2, 0, 1.2 } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Ground_Splash.Zaahen.tex" + birthUVOffset: embed = ValueVector2 { + constantValue: vec2 = { 0, -0.05 } + } + texAddressModeBase: u8 = 2 + particleUVScrollRate: embed = IntegratedValueVector2 { + constantValue: vec2 = { 0, 2 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec2] = { + { 0, 2 } + { 0, 0.4 } + } + } + } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Yasuo_Skin57_3026_Items_Noise_02.Zaahen.tex" + texAddressModeMult: u8 = 2 + UvRotationMult: embed = ValueFloat { + constantValue: f32 = 90 + } + uvScaleMult: embed = ValueVector2 { + constantValue: vec2 = { 1, 2 } + } + ParticleIntegratedUvScrollMult: embed = IntegratedValueVector2 { + constantValue: vec2 = { 4, 1 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 0.75 } + values: list[vec2] = { + { 4, 1 } + { 0, 0 } + } + } + } + birthUVOffsetMult: embed = ValueVector2 { + constantValue: vec2 = { 0, -0.1 } + } + } + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.04 + rate: embed = ValueFloat { + constantValue: f32 = 4 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.15 + } + particleLinger: option[f32] = { 1 } + lifetime: option[f32] = { 1.1 } + isSingleParticle: flag = true + emitterName: string = "REDSwipe11" + importance: u8 = 3 + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, -100 } + } + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_E_Swipe1.Zaahen.scb" + } + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.9229419, 0.07159533, 0.08393988, 0.7019608 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0.071794875, 0.3, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = 7 + softParticleParams: pointer = VfxSoftParticleDefinitionData { + beginIn: f32 = 10 + deltaIn: f32 = 100 + } + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + constantValue: f32 = 0 + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { + 0.013461539 + 0.18642013 + 0.30038393 + 0.46961468 + 0.61538464 + 0.7903846 + 1.0115385 + } + values: list[f32] = { 0, 0, 0, 0, 0, 0, 0 } + } + } + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Ambessa_Base_E_OneShot_Ring_Swipe_shapeB.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + disableBackfaceCull: bool = true + isUniformScale: flag = true + uvScrollClamp: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 135, 90, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 1.6, 1, 1 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 1, 1, 1 } + { 1.1, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Ambessa_Base_E_OneShot_Ring_Swipe_shape.Zaahen.tex" + birthUvScrollRate: embed = ValueVector2 { + constantValue: vec2 = { 0, 3 } + } + birthUVOffset: embed = ValueVector2 { + constantValue: vec2 = { 0, -0.1 } + } + texAddressModeBase: u8 = 2 + uvScale: embed = ValueVector2 { + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec2] = { + { 1, 2 } + { 1, 1 } + } + } + } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_E_Swipe_DarkinTrail.Zaahen.tex" + UvRotationMult: embed = ValueFloat { + constantValue: f32 = 80 + } + uvScaleMult: embed = ValueVector2 { + constantValue: vec2 = { 5, 1 } + } + TextureMultFilpV: flag = true + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.3 + } + particleLinger: option[f32] = { 1 } + lifetime: option[f32] = { 0.5 } + isSingleParticle: flag = true + emitterName: string = "swirlMeshLeft_Blend46" + importance: u8 = 3 + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 1, 0 } + } + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Ambessa_Base_E_Swirl_X.Zaahen.scb" + } + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.9148699, 0.2121004, 0.30438697, 0.2 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0.0843949, 0.18949045, 0.5, 0.6, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = -35 + alphaRef: u8 = 0 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.4, 0.6 } + values: list[f32] = { 0, 0.4, 0.6 } + } + } + erosionFeatherIn: f32 = 0.15 + erosionFeatherOut: f32 = 0.15 + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Ambessa_Base_E_OneShot_Ring_Swipe_shapeB.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + disableBackfaceCull: bool = true + miscRenderFlags: u8 = 1 + isGroundLayer: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { -1.2, 0, 1.2 } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Ground_Splash.Zaahen.tex" + birthUVOffset: embed = ValueVector2 { + constantValue: vec2 = { 0, -0.05 } + } + texAddressModeBase: u8 = 2 + particleUVScrollRate: embed = IntegratedValueVector2 { + constantValue: vec2 = { 0, 2 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec2] = { + { 0, 2 } + { 0, 0.4 } + } + } + } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_R_Screen_Flames_Soft.Zaahen.tex" + texAddressModeMult: u8 = 2 + UvRotationMult: embed = ValueFloat { + constantValue: f32 = 90 + } + uvScaleMult: embed = ValueVector2 { + constantValue: vec2 = { 1, 2 } + } + ParticleIntegratedUvScrollMult: embed = IntegratedValueVector2 { + constantValue: vec2 = { 4, 1 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 0.75 } + values: list[vec2] = { + { 4, 1 } + { 0, 0 } + } + } + } + birthUVOffsetMult: embed = ValueVector2 { + constantValue: vec2 = { 1, 1 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec2] = { { 1, 1 } } + } + } + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.3 + } + particleLinger: option[f32] = { 1 } + lifetime: option[f32] = { 0.5 } + isSingleParticle: flag = true + emitterName: string = "swirlMeshLeft_Blend47" + importance: u8 = 3 + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 1, 0 } + } + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Ambessa_Base_E_Swirl_X.Zaahen.scb" + } + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.9148699, 0.2121004, 0.30438697, 0.2 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0.0843949, 0.18949045, 0.5, 0.6, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = -35 + alphaRef: u8 = 0 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.4, 0.6 } + values: list[f32] = { 0, 0.4, 0.6 } + } + } + erosionFeatherIn: f32 = 0.15 + erosionFeatherOut: f32 = 0.15 + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Ambessa_Base_E_OneShot_Ring_Swipe_shapeB.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + disableBackfaceCull: bool = true + miscRenderFlags: u8 = 1 + isGroundLayer: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 1.2, 0, 1.2 } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Ground_Splash.Zaahen.tex" + birthUVOffset: embed = ValueVector2 { + constantValue: vec2 = { 0, -0.05 } + } + texAddressModeBase: u8 = 2 + particleUVScrollRate: embed = IntegratedValueVector2 { + constantValue: vec2 = { 0, 2 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec2] = { + { 0, 2 } + { 0, 0.4 } + } + } + } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_R_Screen_Flames_Soft.Zaahen.tex" + texAddressModeMult: u8 = 2 + UvRotationMult: embed = ValueFloat { + constantValue: f32 = 90 + } + uvScaleMult: embed = ValueVector2 { + constantValue: vec2 = { 1, 2 } + } + ParticleIntegratedUvScrollMult: embed = IntegratedValueVector2 { + constantValue: vec2 = { 4, 1 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 0.75 } + values: list[vec2] = { + { 4, 1 } + { 0, 0 } + } + } + } + birthUVOffsetMult: embed = ValueVector2 { + constantValue: vec2 = { 1, 1 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec2] = { { 1, 1 } } + } + } + } + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.04 + rate: embed = ValueFloat { + constantValue: f32 = 5 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.15 + } + particleLinger: option[f32] = { 1 } + lifetime: option[f32] = { 1.1 } + isSingleParticle: flag = true + emitterName: string = "REDSwipe12" + importance: u8 = 3 + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, -100 } + } + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_E_Swipe1.Zaahen.scb" + } + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.8904402, 0.22595559, 0.15266651, 0.7019608 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0.071794875, 0.3, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = 10 + softParticleParams: pointer = VfxSoftParticleDefinitionData { + beginIn: f32 = 10 + deltaIn: f32 = 100 + } + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + constantValue: f32 = 0 + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { + 0.013461539 + 0.18642013 + 0.30038393 + 0.46961468 + 0.61538464 + 0.7903846 + 1.0115385 + } + values: list[f32] = { 0, 0, 0, 0, 0, 0, 0 } + } + } + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Ambessa_Base_E_OneShot_Ring_Swipe_shapeB.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + disableBackfaceCull: bool = true + isUniformScale: flag = true + uvScrollClamp: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 135, 90, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 1.6, 1, 1 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 1, 1, 1 } + { 1.1, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Ambessa_Base_E_OneShot_Ring_Swipe_shape.Zaahen.tex" + birthUvScrollRate: embed = ValueVector2 { + constantValue: vec2 = { 0, 3 } + } + birthUVOffset: embed = ValueVector2 { + constantValue: vec2 = { 0, -0.1 } + } + texAddressModeBase: u8 = 2 + uvScale: embed = ValueVector2 { + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec2] = { + { 1, 2 } + { 1, 1 } + } + } + } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_E_Swipe_DarkinTrail_Add.Zaahen.tex" + UvRotationMult: embed = ValueFloat { + constantValue: f32 = 80 + } + uvScaleMult: embed = ValueVector2 { + constantValue: vec2 = { 5, 1 } + } + TextureMultFilpV: flag = true + } + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.04 + rate: embed = ValueFloat { + constantValue: f32 = 3 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.15 + } + particleLinger: option[f32] = { 1 } + lifetime: option[f32] = { 1.1 } + isSingleParticle: flag = true + emitterName: string = "REDSwipe13" + importance: u8 = 3 + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, -100 } + } + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_E_Swipe1.Zaahen.scb" + } + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.8904402, 0.22595559, 0.15266651, 0.7019608 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0.071794875, 0.3, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = 10 + softParticleParams: pointer = VfxSoftParticleDefinitionData { + beginIn: f32 = 10 + deltaIn: f32 = 100 + } + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + constantValue: f32 = 0 + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { + 0.013461539 + 0.18642013 + 0.30038393 + 0.46961468 + 0.61538464 + 0.7903846 + 1.0115385 + } + values: list[f32] = { 0, 0, 0, 0, 0, 0, 0 } + } + } + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Ambessa_Base_E_OneShot_Ring_Swipe_shapeB.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + disableBackfaceCull: bool = true + isUniformScale: flag = true + uvScrollClamp: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 45, 90, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 1.6, 1, 1 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 1, 1, 1 } + { 1.1, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Ambessa_Base_E_OneShot_Ring_Swipe_shape.Zaahen.tex" + birthUvScrollRate: embed = ValueVector2 { + constantValue: vec2 = { 0, 3 } + } + birthUVOffset: embed = ValueVector2 { + constantValue: vec2 = { 0, -0.1 } + } + texAddressModeBase: u8 = 2 + uvScale: embed = ValueVector2 { + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec2] = { + { 1, 2 } + { 1, 1 } + } + } + } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_E_Swipe_DarkinTrail_Add.Zaahen.tex" + UvRotationMult: embed = ValueFloat { + constantValue: f32 = 80 + } + uvScaleMult: embed = ValueVector2 { + constantValue: vec2 = { 5, 1 } + } + TextureMultFilpV: flag = true + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 10 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 10 } + } + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.3 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 0.3 } + } + } + particleLinger: option[f32] = { } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "End_forward2" + importance: u8 = 3 + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 250, 250, 3000 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.2, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 250, 250, 3000 } } + } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, 5 } + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 20, 20, 200 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.9, 1.1 } + } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 20, 20, 200 } } + } + } + blendMode: u8 = 4 + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 0.3, 0.6, 1 } + values: list[vec4] = { + { 0.928069, 0.8185092, 0.6716716, 0 } + { 0.91024643, 0.65159076, 0.65392536, 1 } + { 0.93354696, 0.4036927, 0.4084535, 1 } + { 0.9411765, 0.06666667, 0.07450981, 1 } + { 0.23137255, 0, 0.015686275, 0 } + } + } + } + pass: i16 = 100 + colorLookUpTypeY: u8 = 3 + miscRenderFlags: u8 = 1 + isDirectionOriented: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 0, 180, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.8, 1.2 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 180, 0 } } + } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 5, 20, 10 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.4, 1.5 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.4, 1.5 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 5, 20, 10 } } + } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 3, 3, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 3, 3, 1 } + { 3, 3, 1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_R_Sparks.Zaahen.tex" + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.075 + rate: embed = ValueFloat { + constantValue: f32 = 2 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.4 + } + particleLinger: option[f32] = { 1 } + lifetime: option[f32] = { 0.5 } + isSingleParticle: flag = true + emitterName: string = "swirlMeshLeft_Blend48" + importance: u8 = 3 + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 1, 0 } + } + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_E_Swirl_X2.Zaahen.scb" + } + } + blendMode: u8 = 1 + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 0.3, 0.6, 0.8 } + values: list[vec4] = { + { 0.8901961, 0.05490196, 0.07450981, 0 } + { 0.8901961, 0.05490196, 0.07450981, 1 } + { 0.8899977, 0.050003815, 0.06999313, 0.5000076 } + { 0.4500038, 0.08999771, 0.19000535, 0.2500038 } + { 0.30901045, 0.12587167, 0.1763943, 0 } + } + } + } + pass: i16 = -100 + alphaRef: u8 = 0 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.4, 0.6 } + values: list[f32] = { 0, 0.4, 1 } + } + } + erosionFeatherIn: f32 = 0.15 + erosionFeatherOut: f32 = 0.15 + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_E_Swipe_Mask.Zaahen.tex" + } + miscRenderFlags: u8 = 1 + isGroundLayer: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 0, -180, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 1.1, 0, 1.2 } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_E_Swipe_Mask.Zaahen.tex" + texAddressModeBase: u8 = 2 + uvScale: embed = ValueVector2 { + constantValue: vec2 = { 1.5, 1.25 } + } + uvRotation: embed = ValueFloat { + constantValue: f32 = 90 + } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_R_Screen_Flames_Soft.Zaahen.tex" + texAddressModeMult: u8 = 2 + birthUvScrollRateMult: embed = ValueVector2 { + constantValue: vec2 = { 0, 4 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 0.5 } + values: list[vec2] = { + { 0, 4 } + { 0, 0 } + } + } + } + birthUVOffsetMult: embed = ValueVector2 { + constantValue: vec2 = { 1, 1 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec2] = { { 1, 1 } } + } + } + } + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.075 + rate: embed = ValueFloat { + constantValue: f32 = 2 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.4 + } + particleLinger: option[f32] = { 1 } + lifetime: option[f32] = { 0.5 } + isSingleParticle: flag = true + emitterName: string = "swirlMeshLeft_Blend49" + importance: u8 = 3 + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 1, 0 } + } + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Ambessa_Base_E_Swirl_X.Zaahen.scb" + } + } + blendMode: u8 = 1 + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 0.3, 0.6, 0.8 } + values: list[vec4] = { + { 0.8901961, 0.05490196, 0.07450981, 0 } + { 0.8901961, 0.05490196, 0.07450981, 1 } + { 0.8899977, 0.050003815, 0.06999313, 0.5000076 } + { 0.4500038, 0.08999771, 0.19000535, 0.2500038 } + { 0.30901045, 0.12587167, 0.1763943, 0 } + } + } + } + pass: i16 = -100 + alphaRef: u8 = 0 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.4, 0.6 } + values: list[f32] = { 0, 0.4, 1 } + } + } + erosionFeatherIn: f32 = 0.15 + erosionFeatherOut: f32 = 0.15 + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_E_Swipe_Mask.Zaahen.tex" + } + miscRenderFlags: u8 = 1 + isGroundLayer: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 1.1, 0, 1.2 } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_E_Swipe_Mask.Zaahen.tex" + texAddressModeBase: u8 = 2 + uvScale: embed = ValueVector2 { + constantValue: vec2 = { 1.5, 1.25 } + } + uvRotation: embed = ValueFloat { + constantValue: f32 = 90 + } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_R_Screen_Flames_Soft.Zaahen.tex" + texAddressModeMult: u8 = 2 + birthUvScrollRateMult: embed = ValueVector2 { + constantValue: vec2 = { 0, 4 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 0.5 } + values: list[vec2] = { + { 0, 4 } + { 0, 0 } + } + } + } + birthUVOffsetMult: embed = ValueVector2 { + constantValue: vec2 = { 1, 1 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec2] = { { 1, 1 } } + } + } + } + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.06 + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.06 + } + lifetime: option[f32] = { 0.5 } + isSingleParticle: flag = true + emitterName: string = "flash" + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 15, 15, 15 } + } + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.75190353, 0.12381171, 0, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.011666667, 0.6705989, 0.9009619, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 0.5316396, 0.5316396, 0.5316396, 0.5396532 } + { 0.11372549, 0.10273899, 0.101960786, 0 } + } + } + } + pass: i16 = 200 + alphaRef: u8 = 0 + miscRenderFlags: u8 = 1 + particleIsLocalOrientation: flag = true + isUniformScale: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 270, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 800, 450, 0 } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 1, 1.5, 1 } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Aura_Self.Zaahen.tex" + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.04 + rate: embed = ValueFloat { + constantValue: f32 = 2 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.3 + } + particleLinger: option[f32] = { } + lifetime: option[f32] = { 1.1 } + isSingleParticle: flag = true + emitterName: string = "Swipe4" + importance: u8 = 3 + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, -100 } + } + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_E_Swipe1.Zaahen.scb" + } + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 0.57000077, 0.1600061, 0.88000304 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0.071794875, 0.4, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = 15 + softParticleParams: pointer = VfxSoftParticleDefinitionData { + beginIn: f32 = 10 + deltaIn: f32 = 100 + } + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + constantValue: f32 = 0 + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { + 0.013461539 + 0.18642013 + 0.30038393 + 0.46961468 + 0.61538464 + 0.7903846 + 1.0115385 + } + values: list[f32] = { 0, 0, 0, 0, 0, 0, 0 } + } + } + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Ambessa_Base_E_OneShot_Ring_Swipe_shapeB.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + disableBackfaceCull: bool = true + isUniformScale: flag = true + uvScrollClamp: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 45, 90, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 1.6, 1, 1 } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_E_Gradient.Zaahen.tex" + birthUVOffset: embed = ValueVector2 { + constantValue: vec2 = { 0.2, 0.35 } + } + texAddressModeBase: u8 = 2 + texDiv: vec2 = { 2.25, 1 } + particleUVScrollRate: embed = IntegratedValueVector2 { + constantValue: vec2 = { 0, -2.5 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec2] = { + { 0, -5 } + { 0, -7.5 } + } + } + } + uvScale: embed = ValueVector2 { + constantValue: vec2 = { 1, 2 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec2] = { + { 1, 4 } + { 1, 2 } + } + } + } + uvRotation: embed = ValueFloat { + constantValue: f32 = 180 + } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/2v2Cameo_Jhin_Mult.Zaahen.tex" + } + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.04 + rate: embed = ValueFloat { + constantValue: f32 = 4 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.2 + } + particleLinger: option[f32] = { } + lifetime: option[f32] = { 1.1 } + isSingleParticle: flag = true + emitterName: string = "Swipe5" + importance: u8 = 3 + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, -100 } + } + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_E_Swipe1.Zaahen.scb" + } + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 0.57000077, 0.1600061, 0.86999315 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0.071794875, 0.4, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = 15 + softParticleParams: pointer = VfxSoftParticleDefinitionData { + beginIn: f32 = 10 + deltaIn: f32 = 100 + } + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + constantValue: f32 = 0 + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { + 0.013461539 + 0.18642013 + 0.30038393 + 0.46961468 + 0.61538464 + 0.7903846 + 1.0115385 + } + values: list[f32] = { 0, 0, 0, 0, 0, 0, 0 } + } + } + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Ambessa_Base_E_OneShot_Ring_Swipe_shapeB.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + disableBackfaceCull: bool = true + isUniformScale: flag = true + uvScrollClamp: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 135, 90, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 1.6, 1, 1 } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_E_Gradient.Zaahen.tex" + birthUVOffset: embed = ValueVector2 { + constantValue: vec2 = { 0.2, 0.35 } + } + texAddressModeBase: u8 = 2 + texDiv: vec2 = { 2.25, 1 } + particleUVScrollRate: embed = IntegratedValueVector2 { + constantValue: vec2 = { 0, -2.5 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec2] = { + { 0, -5 } + { 0, -7.5 } + } + } + } + uvScale: embed = ValueVector2 { + constantValue: vec2 = { 1, 2 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec2] = { + { 1, 4 } + { 1, 2 } + } + } + } + uvRotation: embed = ValueFloat { + constantValue: f32 = 180 + } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/2v2Cameo_Jhin_Mult.Zaahen.tex" + } + } + } + particleName: string = "Zaahen_Base_E_AoE" + particlePath: string = "Characters/Zaahen/Skins/Skin0/Particles/Zaahen_Base_E_AoE" + soundOnCreateDefault: string = "Play_sfx_Zaahen_ZaahenEAttack_aoe_buffactivate" + flags: u16 = 198 + } + "Characters/Zaahen/Skins/Skin0/Particles/Zaahen_Base_R_Trail" = VfxSystemDefinitionData { + complexEmitterDefinitionData: list[pointer] = { + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 250 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.2 + } + lifetime: option[f32] = { 0.75 } + emitterName: string = "Flash_GoldGlow" + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, 0.5 } + } + primitive: pointer = VfxPrimitiveCameraTrail { + mTrail: embed = VfxTrailDefinitionData { + mBirthTilingSize: embed = ValueVector3 { + constantValue: vec3 = { 800, 0, 0 } + } + mSmoothingMode: u8 = 2 + } + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 0.83979553, 0.40698862, 0.58431375 } + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 1 } + values: list[vec4] = { + { 1, 0.83979553, 0.40698862, 0 } + { 1, 0.83979553, 0.40698862, 0.58431375 } + { 1, 0.83979553, 0.40698862, 0.58431375 } + } + } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 0.8, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 0.9254902, 0.7607843, 0.4745098, 1 } + { 0.5600061, 0.41855496, 0.17264058, 0.53333336 } + { 0.16159303, 0.10722515, 0.12523079, 0 } + } + } + } + pass: i16 = -15 + alphaRef: u8 = 0 + useNavmeshMask: flag = true + isLocalOrientation: flag = false + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 100, 2, 2 } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 0.8, 0.8, 0.8 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.1, 0.14004976, 0.39546493, 0.77527076, 1 } + values: list[vec3] = { + { 0, 0, 0 } + { 0.71999997, 0.71999997, 0.71999997 } + { 0.7961644, 0.7961644, 0.7961644 } + { 0.7270652, 0.7961644, 0.7961644 } + { 0.3814612, 0.4, 0.4 } + { 0.24000001, 0.24000001, 0.24000001 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/common_color-bellcurve32.Zaahen.tex" + uvRotation: embed = ValueFloat { + constantValue: f32 = 90 + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 250 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.3 + } + lifetime: option[f32] = { 0.75 } + emitterName: string = "GOLD_LightTrail" + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, 0.5 } + } + primitive: pointer = VfxPrimitiveCameraTrail { + mTrail: embed = VfxTrailDefinitionData { + mBirthTilingSize: embed = ValueVector3 { + constantValue: vec3 = { 800, 0, 0 } + } + mSmoothingMode: u8 = 2 + } + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + } + } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.079535216, 0.18529771, 0.37157086, 0.651592, 1 } + values: list[vec4] = { + { 0.9254902, 0.7607843, 0.4745098, 0 } + { 0.9254902, 0.7607843, 0.4745098, 1 } + { 0.57097733, 0.40239567, 0.109300375, 1 } + { 0.44005492, 0.21713588, 0.059967957, 1 } + { 0.29941252, 0.10383765, 0.070756085, 0.34901962 } + { 0.1244831, 0.061081864, 0.069230184, 0 } + } + } + } + pass: i16 = -10 + alphaRef: u8 = 0 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.2864675, 0.64652014, 1 } + values: list[f32] = { 0.190625, 0.571875, 0.8675568, 1 } + } + } + erosionFeatherIn: f32 = 0.15 + erosionFeatherOut: f32 = 0.15 + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Mordekaiser_Skin54_Noise_keka.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 0, 1, 0, 0 } + } + } + useNavmeshMask: flag = true + isLocalOrientation: flag = false + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 30, 1, 2 } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 0.8, 0.8, 0.8 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.1, 0.14004976, 0.39004976, 0.75, 1 } + values: list[vec3] = { + { 0, 0, 0.32 } + { 0.71999997, 0.71999997, 0.71999997 } + { 0.7961644, 0.7961644, 0.7961644 } + { 0.7961644, 0.7961644, 0.7961644 } + { 0.4, 0.4, 0.4 } + { 0.24000001, 0.24000001, 0.24000001 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Mordekaiser_R_Smoke_Trail.Zaahen.tex" + } + } + visibilityRadius: f32 = 1000 + particleName: string = "Zaahen_Base_R_Trail" + particlePath: string = "Characters/Zaahen/Skins/Skin0/Particles/Zaahen_Base_R_Trail" + flags: u16 = 197 + transform: mtx44 = { 0.74999994, 0, 0, 0, 0, 0.74999994, 0, 0, 0, 0, 0.7499999, 0, 0, 0, 0, 1 } + } + "Characters/Zaahen/Skins/Skin0/Particles/Zaahen_Base_Z_Recall" = VfxSystemDefinitionData { + complexEmitterDefinitionData: list[pointer] = { + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 5 + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + lifetime: option[f32] = { 6 } + isSingleParticle: flag = true + emitterName: string = "Glow_Empowered1" + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, 10 } + } + primitive: pointer = VfxPrimitiveArbitraryQuad { } + blendMode: u8 = 1 + Color: embed = ValueColor { + constantValue: vec4 = { 0.42404822, 0.13347067, 0.075135425, 0.5019608 } + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 0.8, 1 } + values: list[vec4] = { + { 0.42404822, 0.13347067, 0.075135425, 0 } + { 0.42404822, 0.13347067, 0.075135425, 0.5019608 } + { 0.42404822, 0.13347067, 0.075135425, 0.5019608 } + { 0.42404822, 0.13347067, 0.075135425, 0 } + } + } + } + pass: i16 = -10 + alphaRef: u8 = 0 + reflectionDefinition: pointer = VfxReflectionDefinitionData { + fresnelColor: vec4 = { 0, 0, 0, 1 } + } + particleIsLocalOrientation: flag = true + isUniformScale: flag = true + isRotationEnabled: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 0, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 300, 1.2, 1.2 } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Aura_Self.Zaahen.tex" + texAddressModeBase: u8 = 2 + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 5 + rate: embed = ValueFloat { + constantValue: f32 = 10 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 1.5 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 1.5 } + } + } + lifetime: option[f32] = { 7.5 } + emitterName: string = "Start_Embers" + importance: u8 = 1 + Filtering: pointer = VfxEmitterFiltering { + spectatorPolicy: u8 = 1 + } + birthOrbitalVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, 0.5, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.25, 1.25 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 0.5, 0 } } + } + } + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 100, 0, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.35, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 100, 0, 0 } } + } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 6, 0, 6 } + } + worldAcceleration: embed = IntegratedValueVector3 { + constantValue: vec3 = { 0, 200, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 1, 0.5 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 200, 0 } } + } + } + SpawnShape: pointer = VfxShapeLegacy { + emitOffset: embed = ValueVector3 { + constantValue: vec3 = { 100, 10, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.7, 1 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0, 0.03, 1 } + values: list[vec3] = { + { 0, 10, 0 } + { 100, 10, 0 } + { 120.00001, 10, 0 } + } + } + } + emitRotationAngles: list[embed] = { + ValueFloat { + constantValue: f32 = 1 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 1 } + } + } + } + emitRotationAxes: list[vec3] = { { 0, 1, 0 } } + } + primitive: pointer = VfxPrimitiveArbitraryQuad { } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec4] = { { 1, 1, 1, 1 } } + } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 0.2, 0.3, 0.5, 1 } + values: list[vec4] = { + { 1, 0.5686275, 0.36862746, 0 } + { 1, 0.53333336, 0.29803923, 1 } + { 1, 0.43176928, 0.15294118, 1 } + { 1, 0.2784314, 0.15294118, 1 } + { 0.7298543, 0.09130999, 0.037170976, 1 } + { 0.21976043, 0, 0.0031128405, 0 } + } + } + } + pass: i16 = 20 + disableBackfaceCull: bool = true + miscRenderFlags: u8 = 1 + isDirectionOriented: flag = true + isUniformScale: flag = true + isRandomStartFrame: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 360, 360, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 360, 360, 0 } } + } + } + birthRotationalVelocity0: embed = ValueVector3 { + constantValue: vec3 = { 50, 50, 50 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 20, 0, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.3, 1 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 20, 0, 0 } } + } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.4, 1 } + values: list[vec3] = { + { 0.5, 0, 0 } + { 1, 0, 0 } + { 0, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Ash.Zaahen.tex" + numFrames: u16 = 4 + texDiv: vec2 = { 2, 2 } + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 5 + rate: embed = ValueFloat { + constantValue: f32 = 20 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.5 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 0.5 } + } + } + lifetime: option[f32] = { 8 } + emitterName: string = "Sparkles_Empowered" + importance: u8 = 1 + Filtering: pointer = VfxEmitterFiltering { + spectatorPolicy: u8 = 1 + } + birthOrbitalVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, 0.5, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.25, 1.25 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 0.5, 0 } } + } + } + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 200, 2000, 200 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.35, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 200, 2000, 200 } } + } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 3, 6, 3 } + } + worldAcceleration: embed = IntegratedValueVector3 { + constantValue: vec3 = { 0, 200, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 1, 0.5 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 200, 0 } } + } + } + SpawnShape: pointer = VfxShapeCylinder { + radius: f32 = 50 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 100, 0 } + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec4] = { { 1, 1, 1, 1 } } + } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 0.2, 0.3, 0.5, 1 } + values: list[vec4] = { + { 1, 0.5686275, 0.36862746, 0 } + { 1, 0.53333336, 0.29803923, 1 } + { 1, 0.43176928, 0.15294118, 1 } + { 1, 0.2784314, 0.15294118, 1 } + { 0.7298543, 0.09130999, 0.037170976, 1 } + { 0.21976043, 0, 0.0031128405, 0 } + } + } + } + pass: i16 = 20 + alphaRef: u8 = 0 + disableBackfaceCull: bool = true + isDirectionOriented: flag = true + isUniformScale: flag = true + isRandomStartFrame: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 360, 360, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 360, 360, 0 } } + } + } + birthRotationalVelocity0: embed = ValueVector3 { + constantValue: vec3 = { 50, 50, 50 } + } + directionVelocityScale: f32 = 0.01 + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 30, 0, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.3, 1 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 30, 0, 0 } } + } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.4, 1 } + values: list[vec3] = { + { 0.5, 0, 0 } + { 1, 0, 0 } + { 0, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_R_Cross_Spark.Zaahen.tex" + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 6.7 + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 1.7 + } + lifetime: option[f32] = { 7 } + emitterName: string = "Temp_Ray_Empowered" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 150, 0 } + } + primitive: pointer = VfxPrimitiveRay { } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 0.60328066, 0.2399939, 0.5019608 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.5, 0.8, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0.30000764 } + { 1, 1, 1, 0 } + } + } + } + alphaRef: u8 = 0 + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { -90, 0, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 300, 400, 50 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.1, 1 } + values: list[vec3] = { + { 0.8, 0, 0 } + { 1, 1, 1 } + { 1, 1, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_E_Nova_Mult.Zaahen.tex" + birthUvScrollRate: embed = ValueVector2 { + constantValue: vec2 = { 0, 1 } + } + birthUVOffset: embed = ValueVector2 { + constantValue: vec2 = { 0.5, 0 } + } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Aura_Self.Zaahen.tex" + } + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 5.3 + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + lifetime: option[f32] = { 7 } + isSingleParticle: flag = true + emitterName: string = "Glow_Empowered" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 250, 0 } + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.4599985, 0.039993897, 0, 0.4 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.2, 0.8, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = -5 + alphaRef: u8 = 0 + particleIsLocalOrientation: flag = true + isRotationEnabled: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 200, 250, 250 } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Aura_Self.Zaahen.tex" + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 5.3 + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 2.5 + } + lifetime: option[f32] = { 6.5 } + isSingleParticle: flag = true + emitterName: string = "SmokeUp" + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, 250, 0 } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 0, 5, 0 } + } + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 220, 0 } + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.9499962, 0.7499962, 0.46999314, 0.30000764 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 0.7, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = 15 + alphaRef: u8 = 0 + 0xcb13aff1: f32 = 50 + isDirectionOriented: flag = true + directionVelocityScale: f32 = 0.002 + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 100, 150, 1 } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 0.75, 0.75, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 0.75, 0.75, 0 } + { 2.25, 2.25, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Aura_Self.Zaahen.tex" + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 6.7 + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 1.5 + } + lifetime: option[f32] = { 7.3 } + emitterName: string = "flareRing" + importance: u8 = 1 + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 300, 0 } + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 1, 1, 0.8 } + } + Color: embed = ValueColor { + constantValue: vec4 = { 0.92156863, 0.7607843, 0.49019608, 1 } + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.5, 1 } + values: list[vec4] = { + { 0.92156863, 0.7607843, 0.49019608, 0 } + { 0.92156863, 0.7607843, 0.49019608, 1 } + { 0.92156863, 0.7607843, 0.49019608, 0 } + } + } + } + pass: i16 = 18 + softParticleParams: pointer = VfxSoftParticleDefinitionData { + beginIn: f32 = 0.7 + deltaIn: f32 = 0.3 + deltaOut: f32 = 0.3 + } + miscRenderFlags: u8 = 1 + isUniformScale: flag = true + isGroundLayer: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 360, 0, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 360, 0, 0 } } + } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 150, 250, 1 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.5, 1 } + values: list[vec3] = { + { 0.8, 1, 1 } + { 1, 0, 0 } + { 1.2, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_lens-rainbow.Zaahen.tex" + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 5 + rate: embed = ValueFloat { + constantValue: f32 = 5 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 1.5 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 1.5 } + } + } + lifetime: option[f32] = { 8 } + emitterName: string = "Start_Smoke" + birthOrbitalVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, -0.3, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, -0.3, 0 } } + } + } + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 33, 22, 33 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.7, 1 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 12 } + keyValues: list[f32] = { 0.7, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 33, 22, 33 } } + } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 6, 0, 6 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.25, 1 } + values: list[vec3] = { + { 5.1, 0, 5.1 } + { 6, 0, 6 } + { 30, 0, 30 } + } + } + } + worldAcceleration: embed = IntegratedValueVector3 { + constantValue: vec3 = { 0, 5, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 5, 0 } } + } + } + SpawnShape: pointer = VfxShapeCylinder { + radius: f32 = 70 + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.45214006, 0.15732051, 0.13888761, 0.6 } + dynamics: pointer = VfxAnimatedColorVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 0.8 } + } + } + times: list[f32] = { 0 } + values: list[vec4] = { { 0.45214006, 0.15732051, 0.13888761, 0.6 } } + } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.5, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 0.28627452, 0.28627452, 0.28627452, 0 } + } + } + } + alphaRef: u8 = 0 + softParticleParams: pointer = VfxSoftParticleDefinitionData { + deltaIn: f32 = 40 + deltaOut: f32 = 30 + } + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0.15, 1 } + values: list[f32] = { 0, 1 } + } + } + erosionFeatherOut: f32 = 0.3 + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Base_SmokeErode.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + isUniformScale: flag = true + isRandomStartFrame: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 1, 90, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 1, 90, 0 } } + } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 100, 1, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 100, 1, 0 } } + } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.36370158, 1 } + values: list[vec3] = { + { 0.8, 1, 1 } + { 1.2283237, 2, 2 } + { 1.5, 1.5, 1.5 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_R_Smoke01_01.Zaahen.tex" + texDiv: vec2 = { 2, 2 } + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 2.22 + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.5 + } + lifetime: option[f32] = { 8 } + isSingleParticle: flag = true + childParticleSetDefinition: pointer = VfxChildParticleSetDefinitionData { + childrenIdentifiers: list[embed] = { + VfxChildIdentifier { + effectKey: hash = "Zaahen_Z_RecallSwipe1VFX" + } + } + } + emitterName: string = "Basic3" + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { -50.998295, 3.230702, 29.574717 } + } + blendMode: u8 = 1 + alphaRef: u8 = 0 + miscRenderFlags: u8 = 1 + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 5.953829, 166.84642, -5.18869 } + } + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 2.83 + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.5 + } + lifetime: option[f32] = { 8 } + isSingleParticle: flag = true + childParticleSetDefinition: pointer = VfxChildParticleSetDefinitionData { + childrenIdentifiers: list[embed] = { + VfxChildIdentifier { + effectKey: hash = "Zaahen_Z_RecallSwipe1VFX" + } + } + } + emitterName: string = "Basic4" + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { -108.43851, 292.36896, 44.87865 } + } + blendMode: u8 = 1 + alphaRef: u8 = 0 + miscRenderFlags: u8 = 1 + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { -8.907178, -157.99586, 99.48942 } + } + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 3.98 + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.5 + } + lifetime: option[f32] = { 8 } + isSingleParticle: flag = true + childParticleSetDefinition: pointer = VfxChildParticleSetDefinitionData { + childrenIdentifiers: list[embed] = { + VfxChildIdentifier { + effectKey: hash = "Zaahen_Z_RecallSwipe1VFX" + } + } + } + emitterName: string = "Basic5" + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 11.770025, 13.89, -19.066792 } + } + blendMode: u8 = 1 + alphaRef: u8 = 0 + miscRenderFlags: u8 = 1 + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 11.749916, 151.59692, -26.3757 } + } + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 5 + rate: embed = ValueFloat { + constantValue: f32 = 8 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.8 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.7, 1 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 0.8 } + } + } + lifetime: option[f32] = { 8 } + emitterName: string = "StarsUp_Center" + birthAcceleration: embed = ValueVector3 { + constantValue: vec3 = { 0, 50, 0 } + } + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + SpawnShape: pointer = VfxShapeLegacy { + emitOffset: embed = ValueVector3 { + constantValue: vec3 = { 50, 50, 50 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 50, 50, 50 } } + } + } + emitRotationAngles: list[embed] = { + ValueFloat { + constantValue: f32 = 1 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 1 } + } + } + ValueFloat { } + } + emitRotationAxes: list[vec3] = { + { 0, 1, 0 } + { 0, 0, 0 } + } + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 270, 0 } + } + blendMode: u8 = 4 + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.3, 0.75 } + values: list[vec4] = { + { 0.94509804, 0.76862746, 0.36078432, 1 } + { 0.9254902, 0.73333335, 0.4, 1 } + { 0.9137255, 0.54509807, 0.28235295, 0.5803922 } + } + } + } + pass: i16 = 52 + depthBiasFactors: vec2 = { -1, -5 } + isUniformScale: flag = true + isRandomStartFrame: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 1, 0, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 1, 0, 0 } } + } + } + isLocalOrientation: flag = false + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 15, 1, 1 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.4, 0.45, 0.5, 1 } + values: list[vec3] = { + { 0, 0, 0 } + { 1, 0, 0 } + { 3, 0, 0 } + { 1, 0, 0 } + { 0, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Glow5.Zaahen.tex" + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.46 + rate: embed = ValueFloat { + constantValue: f32 = 5 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.5 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 0.5 } + } + } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "sparks" + birthOrbitalVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0.5, 0.3, 0.1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -2, 2 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0.5, 0.3, 0.1 } } + } + } + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 500, 100, 500 } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 7, 5, 7 } + } + birthAcceleration: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -2, 2 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 0, 0 } } + } + } + worldAcceleration: embed = IntegratedValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -2, 2 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 0, 0 } } + } + } + SpawnShape: pointer = VfxShapeCylinder { } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 70, 0, -50 } + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 0.70409703, 0.36862746, 1 } + } + Color: embed = ValueColor { + constantValue: vec4 = { 1, 1, 1, 0.5000076 } + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.2, 0.8, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 0.5000076 } + { 1, 1, 1, 0.5000076 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = 21 + colorLookUpScales: vec2 = { 1, 0.8 } + alphaRef: u8 = 0 + colorLookUpOffsets: vec2 = { 0, 0.3 } + 0xcb13aff1: f32 = -80 + isDirectionOriented: flag = true + isUniformScale: flag = true + isRandomStartFrame: flag = true + directionVelocityScale: f32 = 0.01 + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 10, 40, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 1, 5 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 10, 40, 1 } } + } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 1, 1.25, 1.25 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 1, 1.2 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 1, 1.2 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 1, 1.2 } + } + } + times: list[f32] = { 0, 0.20474903, 1 } + values: list[vec3] = { + { 0.5, 1.25, 0 } + { 1, 0.9940637, 0 } + { 0.5, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_R_Cross_Spark.Zaahen.tex" + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.45 + rate: embed = ValueFloat { + constantValue: f32 = 3 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 1 + } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "Smoke_Burst1" + birthOrbitalVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0.2, 0.3, 0.1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -2, 2 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0.2, 0.3, 0.1 } } + } + } + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 300, 100, 300 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 300, 100, 300 } } + } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 5, 5, 5 } + } + SpawnShape: pointer = VfxShapeCylinder { + radius: f32 = 20 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 70, 0, -50 } + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.66999316, 0.2500038, 0.08000305, 0.5000076 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 0.5, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0.30000764 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = 21 + colorLookUpScales: vec2 = { 1, 0.8 } + alphaRef: u8 = 0 + colorLookUpOffsets: vec2 = { 0, 0.3 } + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 1 } + values: list[f32] = { 0, 1 } + } + } + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Emote_Einstein_01_mult.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + miscRenderFlags: u8 = 1 + isUniformScale: flag = true + isRandomStartFrame: flag = true + isGroundLayer: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 1, 1, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 1, 1, 0 } } + } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 40, 40, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 1, 2 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 40, 40, 1 } } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_R_Smoke01_01.Zaahen.tex" + texDiv: vec2 = { 2, 2 } + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.46 + rate: embed = ValueFloat { + constantValue: f32 = 3 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.4 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.65, 1 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 0.4 } + } + } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "sparks_Impact" + importance: u8 = 3 + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 600, 600, 600 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.3, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 600, 600, 600 } } + } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 7, 7, 7 } + } + worldAcceleration: embed = IntegratedValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 0, 0 } } + } + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 70, 0, -50 } + } + primitive: pointer = VfxPrimitiveArbitraryQuad { } + blendMode: u8 = 4 + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.2, 0.5, 1 } + values: list[vec4] = { + { 0.9370413, 0.8512093, 0.70670635, 0 } + { 0.92156863, 0.7607843, 0.49019608, 1 } + { 0.6374914, 0.50202185, 0.273991, 0.5019608 } + { 0.13698024, 0.0508278, 0.073121235, 0 } + } + } + } + pass: i16 = 20 + alphaRef: u8 = 0 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.5, 1 } + values: list[f32] = { 0, 0, 1 } + } + } + erosionFeatherOut: f32 = 0.2 + erosionSliceWidth: f32 = 2 + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Base_SmokeErode.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + depthBiasFactors: vec2 = { -1, -15 } + disableBackfaceCull: bool = true + miscRenderFlags: u8 = 1 + isDirectionOriented: flag = true + isRandomStartFrame: flag = true + isGroundLayer: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, -90, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 90, -90, 0 } } + } + } + directionVelocityScale: f32 = 0.007 + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 70, 40, 70 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.8, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.8, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.8, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 70, 40, 70 } } + } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 0.5, 0.5, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.2, 0.5, 1 } + values: list[vec3] = { + { 0.25, 0.4, 0.8 } + { 0.325, 0.5, 0.75 } + { 0.5, 0.6, 1 } + { 0.45, 0.65, 1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Z_BlastShapes.Zaahen.tex" + numFrames: u16 = 4 + texDiv: vec2 = { 2, 2 } + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.45 + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.2 + } + lifetime: option[f32] = { 8 } + isSingleParticle: flag = true + emitterName: string = "Crack_Impact1" + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 70, 0, -50 } + } + primitive: pointer = VfxPrimitiveArbitraryQuad { } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 0.70818645, 0.331487, 0.7019608 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 0.3, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = -19 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.03, 0.5, 1 } + values: list[f32] = { 1, 0, 0, 1 } + } + } + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Base_SmokeErode.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + particleIsLocalOrientation: flag = true + isUniformScale: flag = true + isRotationEnabled: flag = true + isGroundLayer: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 180, 90 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 70, 60, 0 } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_R_EyeMask.Zaahen.tex" + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.45 + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 1.2 + } + lifetime: option[f32] = { 8 } + isSingleParticle: flag = true + emitterName: string = "Crack_Impact2" + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 70, 0, -50 } + } + primitive: pointer = VfxPrimitiveArbitraryQuad { } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.34000152, 0.28000304, 0.22999924, 0.7000076 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.01, 0.6, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = -20 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.03, 0.5, 1 } + values: list[f32] = { 1, 0, 0, 1 } + } + } + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Base_SmokeErode.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + particleIsLocalOrientation: flag = true + isUniformScale: flag = true + isRotationEnabled: flag = true + isGroundLayer: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 180, 90 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 80, -860, 0 } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Z_Cracks_4.Zaahen.tex" + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 5 + rate: embed = ValueFloat { + constantValue: f32 = 20 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.5 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 0.5 } + } + } + lifetime: option[f32] = { 8 } + emitterName: string = "Embers_Empowered1" + importance: u8 = 1 + Filtering: pointer = VfxEmitterFiltering { + spectatorPolicy: u8 = 1 + } + birthOrbitalVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, 2, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.25, 1.25 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 2, 0 } } + } + } + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 100, 1000, 200 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.35, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 100, 1000, 200 } } + } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 6, 6, 6 } + } + worldAcceleration: embed = IntegratedValueVector3 { + constantValue: vec3 = { 0, 200, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 1, 0.5 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 200, 0 } } + } + } + SpawnShape: pointer = VfxShapeCylinder { + radius: f32 = 50 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 100, 0 } + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.30083162, 0.19339284, 0.19339284, 1 } + dynamics: pointer = VfxAnimatedColorVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec4] = { { 0.30083162, 0.19339284, 0.19339284, 1 } } + } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 0.8, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = 20 + alphaRef: u8 = 0 + disableBackfaceCull: bool = true + isDirectionOriented: flag = true + isUniformScale: flag = true + isRandomStartFrame: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 360, 360, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 360, 360, 0 } } + } + } + birthRotationalVelocity0: embed = ValueVector3 { + constantValue: vec3 = { 50, 50, 50 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 20, 0, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.3, 1 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 20, 0, 0 } } + } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.4, 1 } + values: list[vec3] = { + { 0.5, 0, 0 } + { 1, 0, 0 } + { 0, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Ash.Zaahen.tex" + numFrames: u16 = 4 + texDiv: vec2 = { 2, 2 } + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 5 + rate: embed = ValueFloat { + constantValue: f32 = 1 + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.5, 1 } + values: list[f32] = { 1, 5, 10 } + } + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 2.5 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.6, 1 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 2.5 } + } + } + lifetime: option[f32] = { 6.2 } + emitterName: string = "Start_Swirl1" + SpawnShape: pointer = VfxShapeCylinder { + flags: u8 = 1 + height: f32 = 30 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 110, 0 } + } + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Z_Alley_Absorb.Zaahen.scb" + } + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 0.6827039, 0.34599832, 1 } + dynamics: pointer = VfxAnimatedColorVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.3, 0.6 } + } + } + times: list[f32] = { 0 } + values: list[vec4] = { { 1, 0.6827039, 0.34599832, 1 } } + } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.5, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + alphaRef: u8 = 0 + disableBackfaceCull: bool = true + particleIsLocalOrientation: flag = true + isRotationEnabled: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 0, -1, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, -1, 0 } } + } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 0.4, 0.7, 0.4 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.7, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.6, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.7, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0.4, 0.7, 0.4 } } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Z_Streak.Zaahen.tex" + particleUVScrollRate: embed = IntegratedValueVector2 { + constantValue: vec2 = { 0, 0.5 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 0.293, 1 } + values: list[vec2] = { + { 0, 0.25 } + { 0, 1.341 } + { 0, 1.5 } + } + } + } + uvRotation: embed = ValueFloat { + constantValue: f32 = 90 + } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Aura_Self.Zaahen.tex" + } + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 7 + rate: embed = ValueFloat { + constantValue: f32 = 20 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 1.5 + } + lifetime: option[f32] = { 7.3 } + emitterName: string = "rays1" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 300, 0 } + } + FlexShapeDefinition: pointer = VfxFlexShapeDefinitionData { + scaleBirthScaleByBoundObjectSize: f32 = 0.005 + } + primitive: pointer = VfxPrimitiveRay { } + particleColorTexture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/color-rampdown.Zaahen.tex" + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.919997, 0.7600061, 0.4899977, 0.8 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 1, 1, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 1, 1, 1 } } + } + } + isLocalOrientation: flag = false + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 200, 80, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.8, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.8, 1 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 200, 80, 0 } } + } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 0.4, 0.4, 0.8 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.25, 1 } + values: list[vec3] = { + { 0.8, 3.2, 0 } + { 0.8, 2.4, 0 } + { 0.16, 1.6, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Z_RainbowRay.Zaahen.tex" + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.46 + rate: embed = ValueFloat { + constantValue: f32 = 3 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.6 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1.5 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 0.6 } + } + } + particleLinger: option[f32] = { 10.5 } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "impactStones1" + importance: u8 = 1 + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 300, 600, 400 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -0.1, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.8, 1.5 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 0.9, 1 } + keyValues: list[f32] = { 0.2, 1, 1.4 } + } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 300, 600, 400 } } + } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 8, 8, 8 } + } + worldAcceleration: embed = IntegratedValueVector3 { + constantValue: vec3 = { 0, -300, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0 } + values: list[vec3] = { { 0, -300, 0 } } + } + } + SpawnShape: pointer = VfxShapeCylinder { + radius: f32 = 50 + height: f32 = 20 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 70, 0, -50 } + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.61960787, 0.49411765, 0.30588236, 1 } + dynamics: pointer = VfxAnimatedColorVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 1, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.8, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.9, 1 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec4] = { { 0.61960787, 0.49411765, 0.30588236, 1 } } + } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 0.8, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = 1 + miscRenderFlags: u8 = 1 + isDirectionOriented: flag = true + isUniformScale: flag = true + isRandomStartFrame: flag = true + directionVelocityScale: f32 = 0.001 + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 15, 15, 15 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 15, 15, 15 } } + } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.5, 1 } + values: list[vec3] = { + { 0.5, 0, 0 } + { 1, 1, 1 } + { 0.3, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Emote_Pebbles.Zaahen.tex" + numFrames: u16 = 16 + texDiv: vec2 = { 4, 4 } + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 5 + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.8, 1 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 3 } + } + } + particleLingerType: u8 = 1 + lifetime: option[f32] = { 5.5 } + emitterName: string = "Empowered_Ground7" + importance: u8 = 3 + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Recall_mis_energyflame.Zaahen.scb" + } + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 0.7400015, 0.39000535, 0.30000764 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.2, 0.6, 0.8, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0.6299992 } + { 1, 1, 1, 0.22000457 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = 20 + alphaRef: u8 = 0 + disableBackfaceCull: bool = true + particleIsLocalOrientation: flag = true + isUniformScale: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 180, 0, 0 } + } + birthRotationalVelocity0: embed = ValueVector3 { + constantValue: vec3 = { 0, 20, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 7, 15, 7 } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Yasuo_Skin57_3026_Items_Noise_02.Zaahen.tex" + birthUvScrollRate: embed = ValueVector2 { + constantValue: vec2 = { 0, -0.3 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.7, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec2] = { { 0, -0.3 } } + } + } + uvScale: embed = ValueVector2 { + constantValue: vec2 = { 3, 2 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.6, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.6, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec2] = { { 3, 2 } } + } + } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/2v2Cameo_Jhin_Mult.Zaahen.tex" + texAddressModeMult: u8 = 2 + ParticleIntegratedUvScrollMult: embed = IntegratedValueVector2 { + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0 } + values: list[vec2] = { { 0, 0 } } + } + } + birthUVOffsetMult: embed = ValueVector2 { + constantValue: vec2 = { 0, 0.4 } + } + } + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 5 + rate: embed = ValueFloat { + constantValue: f32 = 2 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 3.5 + } + lifetime: option[f32] = { 5.5 } + emitterName: string = "Empowered_Ground8" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Recall_dustRing_geo.Zaahen.scb" + } + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.31999695, 0, 0, 0.6 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.2, 0.5, 0.67711866, 1 } + values: list[vec4] = { + { 1, 1, 1, 0.007843138 } + { 1, 1, 1, 0.7921569 } + { 1, 1, 1, 0.50980395 } + { 1, 1, 1, 0.23921569 } + { 1, 1, 1, 0 } + } + } + } + alphaRef: u8 = 0 + disableBackfaceCull: bool = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 0, 1, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 1, 0 } } + } + } + birthScale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.8, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.6, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.8, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 1, 1, 1 } } + } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 0.8, 0.8, 0.8 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.6, 1 } + values: list[vec3] = { + { 0.48000002, 0.4, 0.48000002 } + { 0.64, 0.8, 0.64 } + { 0.8, 2.4, 0.8 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Ground_Splash.Zaahen.tex" + texDiv: vec2 = { 0.7, 1 } + particleUVScrollRate: embed = IntegratedValueVector2 { + constantValue: vec2 = { 0, 1 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0 } + values: list[vec2] = { { 0, 1 } } + } + } + uvScale: embed = ValueVector2 { + constantValue: vec2 = { 3, 1.5 } + } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_R_Fire_Trail_Up.Zaahen.tex" + } + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 5 + rate: embed = ValueFloat { + constantValue: f32 = 2 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 3.5 + } + lifetime: option[f32] = { 5.5 } + emitterName: string = "Empowered_Ground9" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Recall_dustRing_geo.Zaahen.scb" + } + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 0.22000457, 0.06999313, 0.6 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.2, 0.5, 0.67711866, 1 } + values: list[vec4] = { + { 1, 1, 1, 0.007843138 } + { 1, 1, 1, 0.7921569 } + { 1, 1, 1, 0.50980395 } + { 1, 1, 1, 0.23921569 } + { 1, 1, 1, 0 } + } + } + } + alphaRef: u8 = 0 + disableBackfaceCull: bool = true + isUniformScale: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 0, 1, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 1, 0 } } + } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 0.8, 1, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.8, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.6, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.8, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0.8, 1, 1 } } + } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 0.8, 0.8, 0.8 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.6, 1 } + values: list[vec3] = { + { 0.48000002, 0.4, 0.48000002 } + { 0.64, 0.8, 0.64 } + { 0.8, 2.4, 0.8 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Ground_Splash.Zaahen.tex" + texDiv: vec2 = { 0.7, 1 } + particleUVScrollRate: embed = IntegratedValueVector2 { + constantValue: vec2 = { 0, 1 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0 } + values: list[vec2] = { { 0, 1 } } + } + } + uvScale: embed = ValueVector2 { + constantValue: vec2 = { 3, 1.5 } + } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_R_Fire_Trail_Up.Zaahen.tex" + } + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 5 + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 5 + } + lifetime: option[f32] = { 8 } + isSingleParticle: flag = true + emitterName: string = "Fresnel1" + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 10, 0, 10 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 10, 0, 10 } } + } + } + Linger: pointer = VfxLingerDefinitionData { + UseSeparateLingerColor: flag = true + SeparateLingerColor: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0.5, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + } + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + primitive: pointer = VfxPrimitiveAttachedMesh { + mMesh: embed = VfxMeshDefinitionData { + mSubmeshesToDraw: list[hash] = { "BODY", "Wings" } + mSubmeshesToDrawAlways: list[hash] = { "BODY", "Wings" } + mLockMeshToAttachment: bool = true + } + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 0.8399939, 0.4899977, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 0.8, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = 20 + alphaRef: u8 = 0 + reflectionDefinition: pointer = VfxReflectionDefinitionData { + reflectionMapTexture: string = "ASSETS/Shared/Particles/Generic_White_Cubemap.TFT_Set15.dds" + reflectionOpacityDirect: f32 = -1 + reflectionOpacityGlancing: f32 = 0.1 + reflectionFresnel: f32 = 0.3 + reflectionFresnelColor: vec4 = { 1, 0.74509805, 0.49019608, 1 } + fresnel: f32 = 0.05 + fresnelColor: vec4 = { 0, 0, 0, 1 } + } + 0xcb13aff1: f32 = -1 + particleIsLocalOrientation: flag = true + isUniformScale: flag = true + hasPostRotateOrientation: flag = true + isRandomStartFrame: flag = true + isRotationEnabled: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 0, 180, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 1.002, 1, 1 } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_R_Fire_Trail_Up.Zaahen.tex" + numFrames: u16 = 4 + birthUvScrollRate: embed = ValueVector2 { + constantValue: vec2 = { 0.4, 0.2 } + } + } + } + particleName: string = "Zaahen_Base_Z_Recall" + particlePath: string = "Characters/Zaahen/Skins/Skin0/Particles/Zaahen_Base_Z_Recall" + flags: u16 = 213 + } + "Characters/Zaahen/Skins/Skin0/Particles/Zaahen_Base_W_Mis_Death" = VfxSystemDefinitionData { + complexEmitterDefinitionData: list[pointer] = { + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 10 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.75 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.2, 1.5 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 0.75 } + } + } + particleLinger: option[f32] = { 1 } + lifetime: option[f32] = { 0.3 } + isSingleParticle: flag = true + emitterName: string = "Embers1" + birthOrbitalVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, 3, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 3, 0 } } + } + } + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 40, 600, 40 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.2, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 40, 600, 40 } } + } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 0, 1, 0 } + } + birthAcceleration: embed = ValueVector3 { + constantValue: vec3 = { 0, -100, 0 } + } + worldAcceleration: embed = IntegratedValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.75, 1.25 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 0, 0 } } + } + } + bindWeight: embed = ValueFloat { + constantValue: f32 = 0.1 + } + SpawnShape: pointer = VfxShapeBox { + flags: u8 = 1 + Size: vec3 = { 60, 200, 60 } + } + blendMode: u8 = 5 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.8621195, 0.5827268, 0.32483405, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = 10 + miscRenderFlags: u8 = 1 + isDirectionOriented: flag = true + isUniformScale: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 1, 0, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 1, 0, 0 } } + } + } + birthRotationalVelocity0: embed = ValueVector3 { + constantValue: vec3 = { 300, 0, 0 } + } + directionVelocityScale: f32 = 0.009 + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 30, 60, 50 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.2, 1 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 30, 60, 50 } } + } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.1, 0.13, 0.4, 0.5, 1 } + values: list[vec3] = { + { 0, 0, 0 } + { 1.2, 1, 1 } + { 1, 1, 1 } + { 1, 0.5, 1 } + { 1, 0.5, 1 } + { 0, 0, 1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Morgana_Base_P_StardustMoteAlpha.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 8 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.4 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.65, 1 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 0.4 } + } + } + particleLinger: option[f32] = { } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "Smoke_Burst" + importance: u8 = 3 + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 750, 1000, 750 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 750, 1000, 750 } } + } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 8, 8, 8 } + } + worldAcceleration: embed = IntegratedValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 0, 0 } } + } + } + SpawnShape: pointer = VfxShapeBox { + flags: u8 = 1 + Size: vec3 = { 10, 100, 10 } + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 50, 0 } + } + primitive: pointer = VfxPrimitiveArbitraryQuad { } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.85999846, 0.5799954, 0.31999695, 0.4899977 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.2, 0.5, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0.43137255 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = 10 + alphaRef: u8 = 0 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.25633293, 0.6982072, 1 } + values: list[f32] = { 0, 0, 0.2, 0.5 } + } + } + erosionFeatherOut: f32 = 0.2 + erosionSliceWidth: f32 = 2 + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Emote_Flames_02.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + depthBiasFactors: vec2 = { -1, -15 } + disableBackfaceCull: bool = true + miscRenderFlags: u8 = 1 + isDirectionOriented: flag = true + isRandomStartFrame: flag = true + isGroundLayer: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, -90, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 90, -90, 0 } } + } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 160, 120, 100 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.8, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.8, 1 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 160, 120, 100 } } + } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 0.5, 0.5, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.2, 0.5, 1 } + values: list[vec3] = { + { 0.25, 0.3, 0.8 } + { 0.325, 0.375, 0.75 } + { 0.5, 0.55, 1 } + { 0.45, 0.65, 1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Shapes02.Zaahen.tex" + numFrames: u16 = 4 + texDiv: vec2 = { 2, 2 } + } + } + particleName: string = "Zaahen_Base_W_Mis_Death" + particlePath: string = "Characters/Zaahen/Skins/Skin0/Particles/Zaahen_Base_W_Mis_Death" + } + "Characters/Zaahen/Skins/Skin0/Particles/Zaahen_Base_Emote_Death" = VfxSystemDefinitionData { + particleName: string = "Zaahen_Base_Emote_Death" + particlePath: string = "Characters/Zaahen/Skins/Skin0/Particles/Zaahen_Base_Emote_Death" + flags: u16 = 199 + } + "Characters/Zaahen/Skins/Skin0/Particles/Zaahen_Base_W_Pull_Tar_Chest" = VfxSystemDefinitionData { + complexEmitterDefinitionData: list[pointer] = { + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.1 + rate: embed = ValueFloat { + constantValue: f32 = 80 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.3 + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 1 } + values: list[f32] = { 0.3, 0 } + } + } + particleLinger: option[f32] = { 0.125 } + lifetime: option[f32] = { 0.4 } + emitterName: string = "Trail3" + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, 1000 } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, 0.5 } + } + Linger: pointer = VfxLingerDefinitionData { + UseKeyedLingerVelocity: flag = true + KeyedLingerVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, -500 } + } + SeparateLingerColor: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.13009709, 0.6097087, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 0.6814815 } + { 1, 1, 1, 0.16296296 } + { 1, 1, 1, 0 } + } + } + } + } + IsEmitterSpace: flag = true + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + FlexShapeDefinition: pointer = VfxFlexShapeDefinitionData { + scaleBirthScaleByBoundObjectSize: f32 = 0.004 + scaleEmitOffsetByBoundObjectSize: f32 = 0.004 + } + primitive: pointer = VfxPrimitiveCameraTrail { + mTrail: embed = VfxTrailDefinitionData { + mBirthTilingSize: embed = ValueVector3 { + constantValue: vec3 = { 800, 0, 0 } + } + mSmoothingMode: u8 = 1 + } + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.30226597, 0.047089342, 0.06443885, 0.6627451 } + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.44707358, 1 } + values: list[vec4] = { + { 0.30226597, 0.047089342, 0.06443885, 0 } + { 0.30226597, 0.047089342, 0.06443885, 0.6627451 } + { 0.30226597, 0.047089342, 0.06443885, 0 } + } + } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 0.7, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0.34000152 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = 80 + alphaRef: u8 = 0 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + constantValue: f32 = 0 + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.07158352, 0.19088937, 0.37744033, 1 } + values: list[f32] = { 0, 0, 0, 0, 0 } + } + } + UseLingerErosionDriveCurve: bool = true + LingerErosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 1 } + values: list[f32] = { 1, 0 } + } + } + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Base_SmokeErode.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + miscRenderFlags: u8 = 1 + particleIsLocalOrientation: flag = true + isGroundLayer: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 60, 2, 2 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 1, 1, 1 } + { 1.3, 1.5, 1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/common_color-bellcurve32.Zaahen.tex" + emitterUvScrollRate: vec2 = { 0, -2 } + uvRotation: embed = ValueFloat { + constantValue: f32 = 90 + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 200 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.3 + } + particleLinger: option[f32] = { 0.2 } + lifetime: option[f32] = { 0.4 } + emitterName: string = "Butterfly Trail - Magic" + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, 1000 } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, 0.5 } + } + Linger: pointer = VfxLingerDefinitionData { + UseKeyedLingerVelocity: flag = true + KeyedLingerVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, -500 } + } + SeparateLingerColor: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.13009709, 0.6097087, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 0.6814815 } + { 1, 1, 1, 0.16296296 } + { 1, 1, 1, 0 } + } + } + } + } + IsEmitterSpace: flag = true + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + FlexShapeDefinition: pointer = VfxFlexShapeDefinitionData { + scaleBirthScaleByBoundObjectSize: f32 = 0.004 + scaleEmitOffsetByBoundObjectSize: f32 = 0.004 + } + primitive: pointer = VfxPrimitiveCameraTrail { + mTrail: embed = VfxTrailDefinitionData { + mBirthTilingSize: embed = ValueVector3 { + constantValue: vec3 = { 800, 0, 0 } + } + mSmoothingMode: u8 = 1 + } + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.919997, 0.7600061, 0.4899977, 0.5000076 } + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 0.3, 1 } + values: list[vec4] = { + { 0.919997, 0.7600061, 0.4899977, 0 } + { 0.919997, 0.7600061, 0.4899977, 0.5000076 } + { 0.919997, 0.7600061, 0.4899977, 0.5000076 } + { 0.919997, 0.7600061, 0.4899977, 0 } + } + } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 0.4, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 0.6117647, 0.6117647, 0.6117647, 0 } + } + } + } + pass: i16 = 600 + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 60, 2, 2 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 1, 1, 1 } + { 1.3, 1.5, 1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_WispTrail_BW.Zaahen.tex" + emitterUvScrollRate: vec2 = { -4, 0 } + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.1 + rate: embed = ValueFloat { + constantValue: f32 = 80 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.3 + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 1 } + values: list[f32] = { 0.3, 0 } + } + } + particleLinger: option[f32] = { 0.125 } + lifetime: option[f32] = { 0.4 } + emitterName: string = "Butterfly Trail - Magic1" + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, 1000 } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, 0.5 } + } + Linger: pointer = VfxLingerDefinitionData { + UseKeyedLingerVelocity: flag = true + KeyedLingerVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, -500 } + } + SeparateLingerColor: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.13009709, 0.6097087, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 0.6814815 } + { 1, 1, 1, 0.16296296 } + { 1, 1, 1, 0 } + } + } + } + } + IsEmitterSpace: flag = true + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + FlexShapeDefinition: pointer = VfxFlexShapeDefinitionData { + scaleBirthScaleByBoundObjectSize: f32 = 0.004 + scaleEmitOffsetByBoundObjectSize: f32 = 0.004 + } + primitive: pointer = VfxPrimitiveCameraTrail { + mTrail: embed = VfxTrailDefinitionData { + mBirthTilingSize: embed = ValueVector3 { + constantValue: vec3 = { 800, 0, 0 } + } + mSmoothingMode: u8 = 1 + } + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.919997, 0.7600061, 0.4899977, 0.5000076 } + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 0.3, 1 } + values: list[vec4] = { + { 0.919997, 0.7600061, 0.4899977, 0 } + { 0.919997, 0.7600061, 0.4899977, 0.5000076 } + { 0.919997, 0.7600061, 0.4899977, 0.5000076 } + { 0.919997, 0.7600061, 0.4899977, 0 } + } + } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 0.4, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 0.6117647, 0.6117647, 0.6117647, 0 } + } + } + } + pass: i16 = 600 + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 60, 2, 2 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 1, 1, 1 } + { 1.3, 1.5, 1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_WispTrail_BW.Zaahen.tex" + birthUvScrollRate: embed = ValueVector2 { + constantValue: vec2 = { 0.5, 0 } + } + emitterUvScrollRate: vec2 = { -4, 0 } + } + } + particleName: string = "Zaahen_Base_W_Pull_Tar_Chest" + particlePath: string = "Characters/Zaahen/Skins/Skin0/Particles/Zaahen_Base_W_Pull_Tar_Chest" + flags: u16 = 198 + } + "Characters/Zaahen/Skins/Skin0/Particles/Zaahen_Base_E_Cas" = VfxSystemDefinitionData { + complexEmitterDefinitionData: list[pointer] = { + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + HasVariableStartTime: flag = true + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.3 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 1, 1.5 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 0.3 } + } + } + particleLinger: option[f32] = { 0.7 } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "Big Boom" + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, -200 } + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 100, 0 } + } + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Skarner_Rework_Base_sk.Zaahen.scb" + } + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.65882355, 0.63529414, 0.6, 0.45882353 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.2, 0.5, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0.4 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = 501 + softParticleParams: pointer = VfxSoftParticleDefinitionData { + deltaIn: f32 = 40 + } + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.1, 1 } + values: list[f32] = { 0.1, 0.25, 1 } + } + } + erosionFeatherOut: f32 = 0.15 + erosionSliceWidth: f32 = 1 + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Skarner_Rework_Base_P_Erode.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 0, 0, 1, 0 } + } + } + depthBiasFactors: vec2 = { 0, -80 } + disableBackfaceCull: bool = true + miscRenderFlags: u8 = 1 + isRotationEnabled: flag = true + birthRotation0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 0, 0 } } + } + } + rotation0: embed = IntegratedValueVector3 { + constantValue: vec3 = { 0, 0, 10 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.35, 1 } + values: list[vec3] = { + { 0, 0, 10 } + { 0, 0, 1 } + { 0, 0, 0 } + } + } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 1, 1, 6 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 0.8, 0.8, 0.8 } + { 4, 4, 4 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Skarner_Rework_Base_Noise3.Zaahen.tex" + birthUvScrollRate: embed = ValueVector2 { + constantValue: vec2 = { 0.75, 0 } + } + texAddressModeBase: u8 = 2 + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 3 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.3 + } + particleLinger: option[f32] = { 1 } + lifetime: option[f32] = { 0.2 } + isSingleParticle: flag = true + emitterName: string = "Temp_Mesh3" + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, 4000 } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, 12 } + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, -1100 } + } + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Yone_Base_Q_Cylinder.Zaahen.scb" + } + } + Color: embed = ValueColor { + constantValue: vec4 = { 0.827451, 0.6784314, 0.5568628, 0.2 } + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.078125, 0.17633928, 0.3348214, 0.54464287, 1 } + values: list[vec4] = { + { 0.827451, 0.6784314, 0.5568628, 0 } + { 0.827451, 0.6784314, 0.5568628, 0.043097638 } + { 0.827451, 0.6784314, 0.5568628, 0.2 } + { 0.827451, 0.6784314, 0.5568628, 0.2 } + { 0.827451, 0.6784314, 0.5568628, 0.075308636 } + { 0.827451, 0.6784314, 0.5568628, 0 } + } + } + } + pass: i16 = 1 + disableBackfaceCull: bool = true + miscRenderFlags: u8 = 1 + isGroundLayer: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, 360 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 0, 360 } } + } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 24, 22, 24 } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 1, 1, 3 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.32142857, 1 } + values: list[vec3] = { + { 1, 0.5934066, 3 } + { 1, 0.7218407, 3 } + { 1, 1, 3 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Yone_Base_Wind_Blend.Zaahen.tex" + birthUVOffset: embed = ValueVector2 { + constantValue: vec2 = { 0.5, 0.6 } + } + particleUVScrollRate: embed = IntegratedValueVector2 { + constantValue: vec2 = { 1, 0 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 0.16294643, 0.578125, 1 } + values: list[vec2] = { + { 2, 0 } + { 2, 0 } + { 0.3956044, 0 } + { 0.5, 0 } + } + } + } + uvScale: embed = ValueVector2 { + constantValue: vec2 = { 0.5, 0.8 } + } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Naafiri_Base_Foundation_Glow01.Zaahen.tex" + texAddressModeMult: u8 = 2 + uvScaleMult: embed = ValueVector2 { + constantValue: vec2 = { 1, 1.5 } + } + ParticleIntegratedUvScrollMult: embed = IntegratedValueVector2 { + constantValue: vec2 = { 0, 2 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0 } + values: list[vec2] = { { 0, 2 } } + } + } + birthUVOffsetMult: embed = ValueVector2 { + constantValue: vec2 = { 0, -0.7 } + } + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 15 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.5 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.4, 1 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 0.5 } + } + } + particleLinger: option[f32] = { 0.25 } + lifetime: option[f32] = { 0.4 } + emitterName: string = "CubePathParticlesDigi" + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -20, 20 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -50, -300 } + } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 0, 1 } } + } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, 1 } + } + SpawnShape: pointer = VfxShapeBox { + flags: u8 = 1 + Size: vec3 = { 30, 55, 40 } + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 125, 0 } + } + primitive: pointer = VfxPrimitiveArbitraryQuad { } + blendMode: u8 = 1 + Color: embed = ValueColor { + constantValue: vec4 = { 0.60534066, 0.09550622, 0.15463492, 1 } + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.05, 1 } + values: list[vec4] = { + { 0.60534066, 0.09550622, 0.15463492, 0 } + { 0.60534066, 0.09550622, 0.15463492, 1 } + { 0.60534066, 0.09550622, 0.15463492, 0 } + } + } + } + pass: i16 = 1 + disableBackfaceCull: bool = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 0, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 6, 6, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.4, 1 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 6, 6, 0 } } + } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.2, 1 } + values: list[vec3] = { + { 0.8, 8, 0 } + { 0.7, 1, 0 } + { 0, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Ekko_Skin18_Z_LongDot.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 15 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.5 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.4, 1 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 0.5 } + } + } + particleLinger: option[f32] = { 0.25 } + lifetime: option[f32] = { 0.4 } + emitterName: string = "CubePathParticlesDigi1" + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -20, 20 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -50, -300 } + } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 0, 1 } } + } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, 1 } + } + SpawnShape: pointer = VfxShapeBox { + flags: u8 = 1 + Size: vec3 = { 30, 55, 40 } + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 125, 0 } + } + primitive: pointer = VfxPrimitiveArbitraryQuad { } + blendMode: u8 = 1 + Color: embed = ValueColor { + constantValue: vec4 = { 0.20392157, 0.007843138, 0.047058824, 1 } + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.05, 1 } + values: list[vec4] = { + { 0.20392157, 0.007843138, 0.047058824, 0 } + { 0.20392157, 0.007843138, 0.047058824, 1 } + { 0.20392157, 0.007843138, 0.047058824, 0 } + } + } + } + pass: i16 = 1 + disableBackfaceCull: bool = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 0, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 6, 6, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.4, 1 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 6, 6, 0 } } + } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.2, 1 } + values: list[vec3] = { + { 0.8, 8, 0 } + { 0.7, 1, 0 } + { 0, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Ekko_Skin18_Z_LongDot.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 25 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.5 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.4, 1 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 0.5 } + } + } + particleLinger: option[f32] = { 0.25 } + lifetime: option[f32] = { 0.4 } + emitterName: string = "CubePathParticlesDigi2" + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -20, 20 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -50, -300 } + } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 0, 1 } } + } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, 1 } + } + SpawnShape: pointer = VfxShapeBox { + flags: u8 = 1 + Size: vec3 = { 30, 55, 40 } + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 125, 0 } + } + primitive: pointer = VfxPrimitiveArbitraryQuad { } + blendMode: u8 = 1 + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.2, 0.5 } + values: list[vec4] = { + { 0.8509804, 0, 0.3137255, 0 } + { 0.2, 0.2, 0.3019608, 1 } + { 0.8509804, 0, 0.3137255, 1 } + } + } + } + pass: i16 = 1 + disableBackfaceCull: bool = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 0, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 3, 20, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.4, 1 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 3, 20, 0 } } + } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.2, 1 } + values: list[vec3] = { + { 0.8, 8, 0 } + { 0.7, 1, 0 } + { 0, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Ekko_Skin18_Z_LongDot.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.35 + } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "Dlack_avatar" + importance: u8 = 3 + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + primitive: pointer = VfxPrimitiveAttachedMesh { + mMesh: embed = VfxMeshDefinitionData { + mLockMeshToAttachment: bool = true + } + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.37016863, 0.028717479, 0.031158922, 1 } + } + Color: embed = ValueColor { + constantValue: vec4 = { 1, 1, 1, 0.9100023 } + } + pass: i16 = -100 + alphaRef: u8 = 0 + reflectionDefinition: pointer = VfxReflectionDefinitionData { + reflectionMapTexture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/AurelionSol_Skin20_Avatar_CubeMap.Zaahen.dds" + reflectionOpacityDirect: f32 = -1 + reflectionOpacityGlancing: f32 = 2 + reflectionFresnel: f32 = 0.1 + reflectionFresnelColor: vec4 = { 0.54901963, 0.046845198, 0.043137256, 1 } + fresnelColor: vec4 = { 0.19607843, 0.047058824, 0.08810559, 0 } + } + 0xcb13aff1: f32 = -5 + disableBackfaceCull: bool = true + particleIsLocalOrientation: flag = true + isUniformScale: flag = true + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/color-hold.Zaahen.tex" + birthUvScrollRate: embed = ValueVector2 { + constantValue: vec2 = { 0.021, 0.051 } + } + texDiv: vec2 = { 0.8, 0.8 } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 3 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.3 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.4, 1 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 0.3 } + } + } + particleLinger: option[f32] = { 10.3 } + lifetime: option[f32] = { 0.1 } + isSingleParticle: flag = true + emitterName: string = "SpeedLine_B1" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + SpawnShape: pointer = VfxShapeBox { + flags: u8 = 1 + Size: vec3 = { 60, 100, 0 } + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 40, -100 } + } + primitive: pointer = VfxPrimitiveArbitraryQuad { } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 1, 1, 0.2 } + } + Color: embed = ValueColor { + constantValue: vec4 = { 0.9607843, 0.9607843, 0.9607843, 1 } + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.2, 0.5, 1 } + values: list[vec4] = { + { 0.61038065, 0.67443293, 0.58023834, 0 } + { 0.61038065, 0.67443293, 0.58023834, 0.7254902 } + { 0.43505415, 0.49067658, 0.40888494, 0.53333336 } + { 0.61038065, 0.67443293, 0.58023834, 0 } + } + } + } + pass: i16 = 7 + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 90, 0 } + } + directionVelocityMinScale: f32 = 0 + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 50, 15, 10 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 1, 1 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 50, 15, 10 } } + } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 1.5, 2, 2 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 16.5, 3, 3 } + { 7.5, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Skin_06_Spark_Vertical.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 25 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.35 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.75, 1 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 0.35 } + } + } + particleLinger: option[f32] = { 1 } + lifetime: option[f32] = { 0.25 } + emitterName: string = "RainbowTrail" + velocity: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, -3000 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.3 } + values: list[vec3] = { + { 0, 0, -3000 } + { 0, 0, -12.195122 } + } + } + } + SpawnShape: pointer = VfxShapeBox { + flags: u8 = 1 + Size: vec3 = { 0, 75, 0 } + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 150, 200 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 0, 0, 0 } + { 0, 150, 200 } + } + } + } + primitive: pointer = VfxPrimitiveRay { } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec4] = { { 1, 1, 1, 1 } } + } + } + Color: embed = ValueColor { + constantValue: vec4 = { 0.27450982, 0.06666667, 0.08235294, 1 } + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.17303666, 0.2777487, 0.64659685, 1 } + values: list[vec4] = { + { 0.27450982, 0.06666667, 0.08235294, 0 } + { 0.27450982, 0.06666667, 0.08235294, 1 } + { 0.27450982, 0.06666667, 0.08235294, 0.8 } + { 0.27450982, 0.06666667, 0.08235294, 0.32380953 } + { 0.27450982, 0.06666667, 0.08235294, 0 } + } + } + } + pass: i16 = 2 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.5 } + values: list[f32] = { 0, 1 } + } + } + erosionFeatherOut: f32 = 0.4 + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_R_Fire_Trail_Up.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + 0xcb13aff1: f32 = -30 + isRandomStartFrame: flag = true + TextureFlipV: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 100, -400, 30 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.8, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.8, 1 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 100, -400, 30 } } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/XinZhaoRework_Skin20_W_SmokeTip.Zaahen.tex" + numFrames: u16 = 2 + texDiv: vec2 = { 2, 1 } + textureMult: pointer = VfxTextureMultDefinitionData { + uvScaleMult: embed = ValueVector2 { + constantValue: vec2 = { 0.5, 0.5 } + } + birthUvScrollRateMult: embed = ValueVector2 { + constantValue: vec2 = { 0, 1 } + } + birthUVOffsetMult: embed = ValueVector2 { + constantValue: vec2 = { 0, 1 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec2] = { { 0, 1 } } + } + } + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 2 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.35 + } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "HologramAdd7" + IsEmitterSpace: flag = true + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + primitive: pointer = VfxPrimitiveAttachedMesh { + mMesh: embed = VfxMeshDefinitionData { + mSubmeshesToDraw: list[hash] = { "BODY" } + mLockMeshToAttachment: bool = true + } + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.8901961, 0.09803922, 0.09803922, 0.2509804 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.05, 0.8, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = -95 + alphaRef: u8 = 0 + uvParallaxScale: f32 = 0.00075 + 0xcb13aff1: f32 = -6 + disableBackfaceCull: bool = true + particleIsLocalOrientation: flag = true + isUniformScale: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 1.001, 1, 1 } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_E_Body_Mask.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 2 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.35 + } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "HologramAdd8" + IsEmitterSpace: flag = true + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + primitive: pointer = VfxPrimitiveAttachedMesh { + mMesh: embed = VfxMeshDefinitionData { + mSubmeshesToDraw: list[hash] = { "Wings" } + mLockMeshToAttachment: bool = true + } + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.8901961, 0.09803922, 0.09803922, 0.2509804 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.05, 0.8, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = -95 + alphaRef: u8 = 0 + uvParallaxScale: f32 = 0.00075 + 0xcb13aff1: f32 = -6 + disableBackfaceCull: bool = true + particleIsLocalOrientation: flag = true + isUniformScale: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 1.001, 1, 1 } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_P_Wing_Mask.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 2 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.35 + } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "HologramAdd9" + IsEmitterSpace: flag = true + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + primitive: pointer = VfxPrimitiveAttachedMesh { + mMesh: embed = VfxMeshDefinitionData { + mSubmeshesToDraw: list[hash] = { "weapon" } + mLockMeshToAttachment: bool = true + } + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.8901961, 0.09803922, 0.09803922, 0.5019608 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.05, 0.8, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = -95 + alphaRef: u8 = 0 + uvParallaxScale: f32 = 0.00075 + 0xcb13aff1: f32 = -6 + disableBackfaceCull: bool = true + particleIsLocalOrientation: flag = true + isUniformScale: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 1.001, 1, 1 } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Q_Glaive_Mask2.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 200 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.1 + } + particleLinger: option[f32] = { 0.5 } + lifetime: option[f32] = { 0.25 } + emitterName: string = "MotionBlur7" + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, 50 } + } + primitive: pointer = VfxPrimitiveAttachedMesh { } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.54901963, 0.043137256, 0.08235294, 0.5019608 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = -200 + reflectionDefinition: pointer = VfxReflectionDefinitionData { + reflectionMapTexture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/AurelionSol_Skin20_Avatar_CubeMap.Zaahen.dds" + reflectionOpacityDirect: f32 = -1 + reflectionOpacityGlancing: f32 = 2 + reflectionFresnel: f32 = 0.1 + reflectionFresnelColor: vec4 = { 0.64705884, 0.08235294, 0.16244754, 1 } + fresnelColor: vec4 = { 0.27450982, 0.06666667, 0.08235294, 0 } + } + depthBiasFactors: vec2 = { -1, -2 } + particleIsLocalOrientation: flag = true + isUniformScale: flag = true + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Emote_Einstein_01_mult.Zaahen.tex" + birthUvScrollRate: embed = ValueVector2 { + constantValue: vec2 = { 0.021, 0.051 } + } + texDiv: vec2 = { 0.8, 0.8 } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 200 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.1 + } + particleLinger: option[f32] = { 0.5 } + lifetime: option[f32] = { 0.25 } + emitterName: string = "MotionBlur8" + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, 50 } + } + primitive: pointer = VfxPrimitiveAttachedMesh { } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.39261463, 0.044602122, 0.070878156, 0.5019608 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = -1000 + reflectionDefinition: pointer = VfxReflectionDefinitionData { + reflectionMapTexture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/AurelionSol_Skin20_Avatar_CubeMap.Zaahen.dds" + reflectionOpacityDirect: f32 = -1 + reflectionOpacityGlancing: f32 = 2 + reflectionFresnel: f32 = 0.1 + reflectionFresnelColor: vec4 = { 0.64705884, 0.08235294, 0.16244754, 1 } + fresnelColor: vec4 = { 0.27450982, 0.06666667, 0.08235294, 0 } + } + depthBiasFactors: vec2 = { -1, -2 } + particleIsLocalOrientation: flag = true + isUniformScale: flag = true + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/color-hold.Zaahen.tex" + birthUvScrollRate: embed = ValueVector2 { + constantValue: vec2 = { 0.021, 0.051 } + } + texDiv: vec2 = { 0.8, 0.8 } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 10 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.35 + } + lifetime: option[f32] = { 0.15 } + emitterName: string = "Trench_Wake_Right" + importance: u8 = 3 + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, -1000 } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 1, 0, 1 } + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { -100, 10, 0 } + } + primitive: pointer = VfxPrimitiveArbitraryQuad { } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.5400015, 0.4599985, 0.37999544, 0.5000076 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.25733334, 0.5426667, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0.48859268 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = 5 + alphaRef: u8 = 0 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.5, 1 } + values: list[f32] = { 0, 0, 1 } + } + } + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Viktor_Base_GroundSmoke02.Zaahen.tex" + } + miscRenderFlags: u8 = 1 + isDirectionOriented: flag = true + isRandomStartFrame: flag = true + isGroundLayer: flag = true + useNavmeshMask: flag = true + TextureFlipU: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { -90, 0, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 120, 150, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.4, 1.1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.4, 1 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 120, 150, 0 } } + } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 1, 1, 1 } + { 0.6, 2, 1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Viktor_Base_GroundSmoke02.Zaahen.tex" + numFrames: u16 = 2 + texDiv: vec2 = { 1, 2 } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 10 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.35 + } + lifetime: option[f32] = { 0.15 } + emitterName: string = "Trench_Wake_Left" + importance: u8 = 3 + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, -1000 } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 1, 0, 1 } + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 100, 10, 0 } + } + primitive: pointer = VfxPrimitiveArbitraryQuad { } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.5400015, 0.4599985, 0.37999544, 0.5000076 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.25733334, 0.5426667, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0.48859268 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = 5 + alphaRef: u8 = 0 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.5, 1 } + values: list[f32] = { 0, 0, 1 } + } + } + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Viktor_Base_GroundSmoke02.Zaahen.tex" + } + miscRenderFlags: u8 = 1 + isDirectionOriented: flag = true + isRandomStartFrame: flag = true + isGroundLayer: flag = true + useNavmeshMask: flag = true + TextureFlipU: flag = true + TextureFlipV: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { -90, 0, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 120, 150, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.4, 1.1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.4, 1 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 120, 150, 0 } } + } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 1, 1, 1 } + { 0.6, 2, 1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Viktor_Base_GroundSmoke02.Zaahen.tex" + numFrames: u16 = 2 + texDiv: vec2 = { 1, 2 } + } + } + particleName: string = "Zaahen_Base_E_Cas" + particlePath: string = "Characters/Zaahen/Skins/Skin0/Particles/Zaahen_Base_E_Cas" + flags: u16 = 198 + } + "Characters/Zaahen/Skins/Skin0/Particles/Zaahen_Base_P_WillRevive_ShoulderR" = VfxSystemDefinitionData { + complexEmitterDefinitionData: list[pointer] = { + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 25 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.8 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 0.8 } + } + } + particleLinger: option[f32] = { 1 } + emitterLinger: option[f32] = { 1 } + emitterName: string = "rays2" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + FlexShapeDefinition: pointer = VfxFlexShapeDefinitionData { + scaleBirthScaleByBoundObjectSize: f32 = 0.005 + } + primitive: pointer = VfxPrimitiveRay { } + particleColorTexture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/color-rampdown.Zaahen.tex" + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.92156863, 0.7607843, 0.49019608, 0.8 } + } + Color: embed = ValueColor { + constantValue: vec4 = { 0.92156863, 0.7607843, 0.49019608, 1 } + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 1 } + values: list[vec4] = { + { 0.92156863, 0.7607843, 0.49019608, 0 } + { 0.92156863, 0.7607843, 0.49019608, 1 } + { 0.92156863, 0.7607843, 0.49019608, 0 } + } + } + } + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 1, 1, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 1, 1, 1 } } + } + } + isLocalOrientation: flag = false + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 100, 40, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.6, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.6, 1 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 100, 40, 0 } } + } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 0.4, 0.4, 0.8 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.25, 1 } + values: list[vec3] = { + { 0.8, 3.2, 0 } + { 0.8, 2.4, 0 } + { 0.16, 1.6, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Z_RainbowRay.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 2 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.8 + } + particleLinger: option[f32] = { 0.4 } + emitterName: string = "Cote2" + importance: u8 = 3 + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + FlexShapeDefinition: pointer = VfxFlexShapeDefinitionData { + scaleBirthScaleByBoundObjectSize: f32 = 0.005 + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.919997, 0.7600061, 0.4899977, 0.5000076 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.4, 0.9, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = 5 + alphaRef: u8 = 0 + isUniformScale: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 90, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 50, 200, 1 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.75, 1 } + values: list[vec3] = { + { 0.8, 1, 1 } + { 2, 2, 2 } + { 1, 1, 1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Rell_Base_Alpha_Glow.Zaahen.tex" + uvRotation: embed = ValueFloat { + constantValue: f32 = 90 + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 10 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.5 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 0.9, 1 } + keyValues: list[f32] = { 0.2, 1, 1.1 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 0.5 } + } + } + particleLinger: option[f32] = { 2 } + emitterLinger: option[f32] = { 2 } + fieldCollectionDefinition: pointer = VfxFieldCollectionDefinitionData { + fieldNoiseDefinitions: list[embed] = { + VfxFieldNoiseDefinitionData { + radius: embed = ValueFloat { + constantValue: f32 = 500 + } + frequency: embed = ValueFloat { + constantValue: f32 = 10 + } + velocityDelta: embed = ValueFloat { + constantValue: f32 = 50 + } + axisFraction: vec3 = { 1, 1, 1 } + } + } + } + emitterName: string = "sparks2" + birthOrbitalVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, 2, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 0.5, 0.5001, 1 } + keyValues: list[f32] = { -1, -0.5, 0.5, 1 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 2, 0 } } + } + } + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, -250, 250 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, -250, 250 } } + } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 5, 5, 5 } + } + worldAcceleration: embed = IntegratedValueVector3 { + constantValue: vec3 = { 0, 200, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 200, 0 } } + } + } + IsEmitterSpace: flag = true + bindWeight: embed = ValueFloat { + constantValue: f32 = 0.5 + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 1 } + values: list[f32] = { 0.5, 0 } + } + } + blendMode: u8 = 4 + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.3, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 0, 0.015686275, 1 } + } + } + } + pass: i16 = 20 + censorModulateValue: vec4 = { 0, 1, 1, 1 } + isDirectionOriented: flag = true + isRandomStartFrame: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { -90, 0, 0 } + } + directionVelocityScale: f32 = 0.01 + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 18, 18, 18 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 0.9, 1 } + keyValues: list[f32] = { 0.4, 0.7, 1 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 18, 18, 18 } } + } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 0.5, 0.5, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.2, 0.4, 0.8, 1 } + values: list[vec3] = { + { 0, 0, 0 } + { 0.5, 0.5, 1 } + { 0.5, 0.5, 1 } + { 0.3, 0.3, 0.6 } + { 0, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_R_Sparks.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 200 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.2 + } + emitterName: string = "GOLD_LightTrail5" + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, -500, 500 } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, 0.5 } + } + worldAcceleration: embed = IntegratedValueVector3 { + constantValue: vec3 = { 0, 4000, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 4000, 0 } } + } + } + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + FlexShapeDefinition: pointer = VfxFlexShapeDefinitionData { + scaleBirthScaleByBoundObjectSize: f32 = 0.005 + } + primitive: pointer = VfxPrimitiveCameraTrail { + mTrail: embed = VfxTrailDefinitionData { + mMode: u8 = 1 + mBirthTilingSize: embed = ValueVector3 { + constantValue: vec3 = { 800, 0, 0 } + } + mSmoothingMode: u8 = 1 + } + } + blendMode: u8 = 4 + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.079535216, 0.18529771, 0.37157086, 0.651592, 1 } + values: list[vec4] = { + { 0.9254902, 0.7607843, 0.4745098, 0 } + { 0.9254902, 0.7607843, 0.4745098, 1 } + { 0.57097733, 0.40239567, 0.109300375, 1 } + { 0.44005492, 0.21713588, 0.059967957, 1 } + { 0.29941252, 0.10383765, 0.070756085, 0.34901962 } + { 0.1244831, 0.061081864, 0.069230184, 0 } + } + } + } + pass: i16 = -10 + alphaRef: u8 = 0 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.2864675, 0.64652014, 1 } + values: list[f32] = { 0.190625, 0.571875, 0.8675568, 1 } + } + } + erosionFeatherIn: f32 = 0.15 + erosionFeatherOut: f32 = 0.15 + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Mordekaiser_Skin54_Noise_keka.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 0, 1, 0, 0 } + } + } + useNavmeshMask: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 20, 2, 2 } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 0.8, 0.8, 0.8 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.07960199, 0.14004976, 0.39004976, 0.75, 1 } + values: list[vec3] = { + { 0.32, 0.32, 0.32 } + { 0.72, 0.72, 0.72 } + { 0.7961644, 0.7961644, 0.7961644 } + { 0.7961644, 0.7961644, 0.7961644 } + { 0.4, 0.4, 0.4 } + { 0.24, 0.24, 0.24 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Mordekaiser_R_Smoke_Trail.Zaahen.tex" + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Leona_Base_E_Wisps.Zaahen.tex" + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 200 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.2 + } + emitterName: string = "GOLD_LightTrail6" + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, -500, 500 } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, 0.5 } + } + worldAcceleration: embed = IntegratedValueVector3 { + constantValue: vec3 = { 0, 4000, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 4000, 0 } } + } + } + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + FlexShapeDefinition: pointer = VfxFlexShapeDefinitionData { + scaleBirthScaleByBoundObjectSize: f32 = 0.005 + } + primitive: pointer = VfxPrimitiveCameraTrail { + mTrail: embed = VfxTrailDefinitionData { + mMode: u8 = 1 + mBirthTilingSize: embed = ValueVector3 { + constantValue: vec3 = { 800, 0, 0 } + } + mSmoothingMode: u8 = 1 + } + } + blendMode: u8 = 4 + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.079535216, 0.18529771, 0.37157086, 0.651592, 1 } + values: list[vec4] = { + { 0.9254902, 0.7607843, 0.4745098, 0 } + { 0.9254902, 0.7607843, 0.4745098, 1 } + { 0.57097733, 0.40239567, 0.109300375, 1 } + { 0.44005492, 0.21713588, 0.059967957, 1 } + { 0.29941252, 0.10383765, 0.070756085, 0.34901962 } + { 0.1244831, 0.061081864, 0.069230184, 0 } + } + } + } + pass: i16 = -10 + alphaRef: u8 = 0 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.2864675, 0.64652014, 1 } + values: list[f32] = { 0.190625, 0.571875, 0.8675568, 1 } + } + } + erosionFeatherIn: f32 = 0.15 + erosionFeatherOut: f32 = 0.15 + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Mordekaiser_Skin54_Noise_keka.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 0, 1, 0, 0 } + } + } + uvScrollClamp: flag = true + useNavmeshMask: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 20, 2, 2 } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 0.8, 0.8, 0.8 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.07960199, 0.14004976, 0.39004976, 0.75, 1 } + values: list[vec3] = { + { 0.32, 0.32, 0.32 } + { 0.72, 0.72, 0.72 } + { 0.7961644, 0.7961644, 0.7961644 } + { 0.7961644, 0.7961644, 0.7961644 } + { 0.4, 0.4, 0.4 } + { 0.24, 0.24, 0.24 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Leona_Base_E_Wisps.Zaahen.tex" + birthUVOffset: embed = ValueVector2 { + constantValue: vec2 = { 0.5, 0 } + } + emitterUvScrollRate: vec2 = { -0.3, 0 } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 200 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.2 + } + emitterName: string = "GOLD_LightTrail7" + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, -500, -500 } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, 0.5 } + } + worldAcceleration: embed = IntegratedValueVector3 { + constantValue: vec3 = { 0, 4000, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 4000, 0 } } + } + } + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + FlexShapeDefinition: pointer = VfxFlexShapeDefinitionData { + scaleBirthScaleByBoundObjectSize: f32 = 0.005 + } + primitive: pointer = VfxPrimitiveCameraTrail { + mTrail: embed = VfxTrailDefinitionData { + mMode: u8 = 1 + mBirthTilingSize: embed = ValueVector3 { + constantValue: vec3 = { 800, 0, 0 } + } + mSmoothingMode: u8 = 1 + } + } + blendMode: u8 = 4 + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.079535216, 0.18529771, 0.37157086, 0.651592, 1 } + values: list[vec4] = { + { 0.9254902, 0.7607843, 0.4745098, 0 } + { 0.9254902, 0.7607843, 0.4745098, 1 } + { 0.57097733, 0.40239567, 0.109300375, 1 } + { 0.44005492, 0.21713588, 0.059967957, 1 } + { 0.29941252, 0.10383765, 0.070756085, 0.34901962 } + { 0.1244831, 0.061081864, 0.069230184, 0 } + } + } + } + pass: i16 = -10 + alphaRef: u8 = 0 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.2864675, 0.64652014, 1 } + values: list[f32] = { 0.190625, 0.571875, 0.8675568, 1 } + } + } + erosionFeatherIn: f32 = 0.15 + erosionFeatherOut: f32 = 0.15 + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Mordekaiser_Skin54_Noise_keka.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 0, 1, 0, 0 } + } + } + useNavmeshMask: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 20, 2, 2 } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 0.8, 0.8, 0.8 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.07960199, 0.14004976, 0.39004976, 0.75, 1 } + values: list[vec3] = { + { 0.32, 0.32, 0.32 } + { 0.72, 0.72, 0.72 } + { 0.7961644, 0.7961644, 0.7961644 } + { 0.7961644, 0.7961644, 0.7961644 } + { 0.4, 0.4, 0.4 } + { 0.24, 0.24, 0.24 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Mordekaiser_R_Smoke_Trail.Zaahen.tex" + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Leona_Base_E_Wisps.Zaahen.tex" + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 200 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.2 + } + emitterName: string = "GOLD_LightTrail8" + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, -500, -500 } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, 0.5 } + } + worldAcceleration: embed = IntegratedValueVector3 { + constantValue: vec3 = { 0, 4000, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 4000, 0 } } + } + } + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + FlexShapeDefinition: pointer = VfxFlexShapeDefinitionData { + scaleBirthScaleByBoundObjectSize: f32 = 0.005 + } + primitive: pointer = VfxPrimitiveCameraTrail { + mTrail: embed = VfxTrailDefinitionData { + mMode: u8 = 1 + mBirthTilingSize: embed = ValueVector3 { + constantValue: vec3 = { 800, 0, 0 } + } + mSmoothingMode: u8 = 1 + } + } + blendMode: u8 = 4 + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.079535216, 0.18529771, 0.37157086, 0.651592, 1 } + values: list[vec4] = { + { 0.9254902, 0.7607843, 0.4745098, 0 } + { 0.9254902, 0.7607843, 0.4745098, 1 } + { 0.57097733, 0.40239567, 0.109300375, 1 } + { 0.44005492, 0.21713588, 0.059967957, 1 } + { 0.29941252, 0.10383765, 0.070756085, 0.34901962 } + { 0.1244831, 0.061081864, 0.069230184, 0 } + } + } + } + pass: i16 = -10 + alphaRef: u8 = 0 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.2864675, 0.64652014, 1 } + values: list[f32] = { 0.190625, 0.571875, 0.8675568, 1 } + } + } + erosionFeatherIn: f32 = 0.15 + erosionFeatherOut: f32 = 0.15 + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Mordekaiser_Skin54_Noise_keka.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 0, 1, 0, 0 } + } + } + uvScrollClamp: flag = true + useNavmeshMask: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 20, 2, 2 } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 0.8, 0.8, 0.8 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.07960199, 0.14004976, 0.39004976, 0.75, 1 } + values: list[vec3] = { + { 0.32, 0.32, 0.32 } + { 0.72, 0.72, 0.72 } + { 0.7961644, 0.7961644, 0.7961644 } + { 0.7961644, 0.7961644, 0.7961644 } + { 0.4, 0.4, 0.4 } + { 0.24, 0.24, 0.24 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Leona_Base_E_Wisps.Zaahen.tex" + birthUVOffset: embed = ValueVector2 { + constantValue: vec2 = { 0.25, 0 } + } + emitterUvScrollRate: vec2 = { -0.3, 0 } + } + } + particleName: string = "Zaahen_Base_P_WillRevive_ShoulderR" + particlePath: string = "Characters/Zaahen/Skins/Skin0/Particles/Zaahen_Base_P_WillRevive_ShoulderR" + flags: u16 = 1236 + } + "Characters/Zaahen/Skins/Skin0/Particles/Zaahen_Base_P_WillRevive_ShoulderL" = VfxSystemDefinitionData { + complexEmitterDefinitionData: list[pointer] = { + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 25 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.8 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 0.8 } + } + } + particleLinger: option[f32] = { 1 } + emitterLinger: option[f32] = { 1 } + emitterName: string = "rays1" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + FlexShapeDefinition: pointer = VfxFlexShapeDefinitionData { + scaleBirthScaleByBoundObjectSize: f32 = 0.005 + } + primitive: pointer = VfxPrimitiveRay { } + particleColorTexture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/color-rampdown.Zaahen.tex" + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.92156863, 0.7607843, 0.49019608, 0.8 } + } + Color: embed = ValueColor { + constantValue: vec4 = { 0.92156863, 0.7607843, 0.49019608, 1 } + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 1 } + values: list[vec4] = { + { 0.92156863, 0.7607843, 0.49019608, 0 } + { 0.92156863, 0.7607843, 0.49019608, 1 } + { 0.92156863, 0.7607843, 0.49019608, 0 } + } + } + } + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 1, 1, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 1, 1, 1 } } + } + } + isLocalOrientation: flag = false + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 100, 40, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.6, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.6, 1 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 100, 40, 0 } } + } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 0.4, 0.4, 0.8 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.25, 1 } + values: list[vec3] = { + { 0.8, 3.2, 0 } + { 0.8, 2.4, 0 } + { 0.16, 1.6, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Z_RainbowRay.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 2 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.8 + } + particleLinger: option[f32] = { 0.4 } + emitterName: string = "Cote1" + importance: u8 = 3 + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + FlexShapeDefinition: pointer = VfxFlexShapeDefinitionData { + scaleBirthScaleByBoundObjectSize: f32 = 0.005 + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.919997, 0.7600061, 0.4899977, 0.5000076 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.4, 0.9, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = 5 + alphaRef: u8 = 0 + isUniformScale: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 90, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 50, 200, 1 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.75, 1 } + values: list[vec3] = { + { 0.8, 1, 1 } + { 2, 2, 2 } + { 1, 1, 1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Rell_Base_Alpha_Glow.Zaahen.tex" + uvRotation: embed = ValueFloat { + constantValue: f32 = 90 + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 200 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.2 + } + emitterName: string = "GOLD_LightTrail5" + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, 500, 500 } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, 0.5 } + } + worldAcceleration: embed = IntegratedValueVector3 { + constantValue: vec3 = { 0, 4000, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 4000, 0 } } + } + } + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + FlexShapeDefinition: pointer = VfxFlexShapeDefinitionData { + scaleBirthScaleByBoundObjectSize: f32 = 0.005 + } + primitive: pointer = VfxPrimitiveCameraTrail { + mTrail: embed = VfxTrailDefinitionData { + mMode: u8 = 1 + mBirthTilingSize: embed = ValueVector3 { + constantValue: vec3 = { 800, 0, 0 } + } + mSmoothingMode: u8 = 1 + } + } + blendMode: u8 = 4 + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.079535216, 0.18529771, 0.37157086, 0.651592, 1 } + values: list[vec4] = { + { 0.9254902, 0.7607843, 0.4745098, 0 } + { 0.9254902, 0.7607843, 0.4745098, 1 } + { 0.57097733, 0.40239567, 0.109300375, 1 } + { 0.44005492, 0.21713588, 0.059967957, 1 } + { 0.29941252, 0.10383765, 0.070756085, 0.34901962 } + { 0.1244831, 0.061081864, 0.069230184, 0 } + } + } + } + pass: i16 = -10 + alphaRef: u8 = 0 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.2864675, 0.64652014, 1 } + values: list[f32] = { 0.190625, 0.571875, 0.8675568, 1 } + } + } + erosionFeatherIn: f32 = 0.15 + erosionFeatherOut: f32 = 0.15 + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Mordekaiser_Skin54_Noise_keka.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 0, 1, 0, 0 } + } + } + useNavmeshMask: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 20, 2, 2 } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 0.8, 0.8, 0.8 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.07960199, 0.14004976, 0.39004976, 0.75, 1 } + values: list[vec3] = { + { 0.32, 0.32, 0.32 } + { 0.72, 0.72, 0.72 } + { 0.7961644, 0.7961644, 0.7961644 } + { 0.7961644, 0.7961644, 0.7961644 } + { 0.4, 0.4, 0.4 } + { 0.24, 0.24, 0.24 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Mordekaiser_R_Smoke_Trail.Zaahen.tex" + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Leona_Base_E_Wisps.Zaahen.tex" + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 200 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.2 + } + emitterName: string = "GOLD_LightTrail6" + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, 500, 500 } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, 0.5 } + } + worldAcceleration: embed = IntegratedValueVector3 { + constantValue: vec3 = { 0, 4000, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 4000, 0 } } + } + } + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + FlexShapeDefinition: pointer = VfxFlexShapeDefinitionData { + scaleBirthScaleByBoundObjectSize: f32 = 0.005 + } + primitive: pointer = VfxPrimitiveCameraTrail { + mTrail: embed = VfxTrailDefinitionData { + mMode: u8 = 1 + mBirthTilingSize: embed = ValueVector3 { + constantValue: vec3 = { 800, 0, 0 } + } + mSmoothingMode: u8 = 1 + } + } + blendMode: u8 = 4 + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.079535216, 0.18529771, 0.37157086, 0.651592, 1 } + values: list[vec4] = { + { 0.9254902, 0.7607843, 0.4745098, 0 } + { 0.9254902, 0.7607843, 0.4745098, 1 } + { 0.57097733, 0.40239567, 0.109300375, 1 } + { 0.44005492, 0.21713588, 0.059967957, 1 } + { 0.29941252, 0.10383765, 0.070756085, 0.34901962 } + { 0.1244831, 0.061081864, 0.069230184, 0 } + } + } + } + pass: i16 = -10 + alphaRef: u8 = 0 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.2864675, 0.64652014, 1 } + values: list[f32] = { 0.190625, 0.571875, 0.8675568, 1 } + } + } + erosionFeatherIn: f32 = 0.15 + erosionFeatherOut: f32 = 0.15 + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Mordekaiser_Skin54_Noise_keka.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 0, 1, 0, 0 } + } + } + uvScrollClamp: flag = true + useNavmeshMask: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 20, 2, 2 } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 0.8, 0.8, 0.8 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.07960199, 0.14004976, 0.39004976, 0.75, 1 } + values: list[vec3] = { + { 0.32, 0.32, 0.32 } + { 0.72, 0.72, 0.72 } + { 0.7961644, 0.7961644, 0.7961644 } + { 0.7961644, 0.7961644, 0.7961644 } + { 0.4, 0.4, 0.4 } + { 0.24, 0.24, 0.24 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Leona_Base_E_Wisps.Zaahen.tex" + birthUVOffset: embed = ValueVector2 { + constantValue: vec2 = { 0.25, 0 } + } + emitterUvScrollRate: vec2 = { -0.6, 0 } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 200 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.2 + } + emitterName: string = "GOLD_LightTrail7" + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, 500, -500 } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, 0.5 } + } + worldAcceleration: embed = IntegratedValueVector3 { + constantValue: vec3 = { 0, 4000, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 4000, 0 } } + } + } + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + FlexShapeDefinition: pointer = VfxFlexShapeDefinitionData { + scaleBirthScaleByBoundObjectSize: f32 = 0.005 + } + primitive: pointer = VfxPrimitiveCameraTrail { + mTrail: embed = VfxTrailDefinitionData { + mMode: u8 = 1 + mBirthTilingSize: embed = ValueVector3 { + constantValue: vec3 = { 800, 0, 0 } + } + mSmoothingMode: u8 = 1 + } + } + blendMode: u8 = 4 + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.079535216, 0.18529771, 0.37157086, 0.651592, 1 } + values: list[vec4] = { + { 0.9254902, 0.7607843, 0.4745098, 0 } + { 0.9254902, 0.7607843, 0.4745098, 1 } + { 0.57097733, 0.40239567, 0.109300375, 1 } + { 0.44005492, 0.21713588, 0.059967957, 1 } + { 0.29941252, 0.10383765, 0.070756085, 0.34901962 } + { 0.1244831, 0.061081864, 0.069230184, 0 } + } + } + } + pass: i16 = -10 + alphaRef: u8 = 0 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.2864675, 0.64652014, 1 } + values: list[f32] = { 0.190625, 0.571875, 0.8675568, 1 } + } + } + erosionFeatherIn: f32 = 0.15 + erosionFeatherOut: f32 = 0.15 + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Mordekaiser_Skin54_Noise_keka.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 0, 1, 0, 0 } + } + } + useNavmeshMask: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 20, 2, 2 } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 0.8, 0.8, 0.8 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.07960199, 0.14004976, 0.39004976, 0.75, 1 } + values: list[vec3] = { + { 0.32, 0.32, 0.32 } + { 0.72, 0.72, 0.72 } + { 0.7961644, 0.7961644, 0.7961644 } + { 0.7961644, 0.7961644, 0.7961644 } + { 0.4, 0.4, 0.4 } + { 0.24, 0.24, 0.24 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Mordekaiser_R_Smoke_Trail.Zaahen.tex" + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Leona_Base_E_Wisps.Zaahen.tex" + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 200 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.2 + } + emitterName: string = "GOLD_LightTrail8" + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, 500, -500 } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, 0.5 } + } + worldAcceleration: embed = IntegratedValueVector3 { + constantValue: vec3 = { 0, 4000, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 4000, 0 } } + } + } + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + FlexShapeDefinition: pointer = VfxFlexShapeDefinitionData { + scaleBirthScaleByBoundObjectSize: f32 = 0.005 + } + primitive: pointer = VfxPrimitiveCameraTrail { + mTrail: embed = VfxTrailDefinitionData { + mMode: u8 = 1 + mBirthTilingSize: embed = ValueVector3 { + constantValue: vec3 = { 800, 0, 0 } + } + mSmoothingMode: u8 = 1 + } + } + blendMode: u8 = 4 + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.079535216, 0.18529771, 0.37157086, 0.651592, 1 } + values: list[vec4] = { + { 0.9254902, 0.7607843, 0.4745098, 0 } + { 0.9254902, 0.7607843, 0.4745098, 1 } + { 0.57097733, 0.40239567, 0.109300375, 1 } + { 0.44005492, 0.21713588, 0.059967957, 1 } + { 0.29941252, 0.10383765, 0.070756085, 0.34901962 } + { 0.1244831, 0.061081864, 0.069230184, 0 } + } + } + } + pass: i16 = -10 + alphaRef: u8 = 0 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.2864675, 0.64652014, 1 } + values: list[f32] = { 0.190625, 0.571875, 0.8675568, 1 } + } + } + erosionFeatherIn: f32 = 0.15 + erosionFeatherOut: f32 = 0.15 + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Mordekaiser_Skin54_Noise_keka.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 0, 1, 0, 0 } + } + } + uvScrollClamp: flag = true + useNavmeshMask: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 20, 2, 2 } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 0.8, 0.8, 0.8 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.07960199, 0.14004976, 0.39004976, 0.75, 1 } + values: list[vec3] = { + { 0.32, 0.32, 0.32 } + { 0.72, 0.72, 0.72 } + { 0.7961644, 0.7961644, 0.7961644 } + { 0.7961644, 0.7961644, 0.7961644 } + { 0.4, 0.4, 0.4 } + { 0.24, 0.24, 0.24 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Leona_Base_E_Wisps.Zaahen.tex" + emitterUvScrollRate: vec2 = { -0.6, 0 } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 10 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.5 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 0.9, 1 } + keyValues: list[f32] = { 0.2, 1, 1.1 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 0.5 } + } + } + particleLinger: option[f32] = { 2 } + emitterLinger: option[f32] = { 2 } + fieldCollectionDefinition: pointer = VfxFieldCollectionDefinitionData { + fieldNoiseDefinitions: list[embed] = { + VfxFieldNoiseDefinitionData { + radius: embed = ValueFloat { + constantValue: f32 = 500 + } + frequency: embed = ValueFloat { + constantValue: f32 = 10 + } + velocityDelta: embed = ValueFloat { + constantValue: f32 = 50 + } + axisFraction: vec3 = { 1, 1, 1 } + } + } + } + emitterName: string = "sparks3" + birthOrbitalVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, 2, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 0.5, 0.5001, 1 } + keyValues: list[f32] = { -1, -0.5, 0.5, 1 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 2, 0 } } + } + } + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, 250, 250 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 250, 250 } } + } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 5, 5, 5 } + } + worldAcceleration: embed = IntegratedValueVector3 { + constantValue: vec3 = { 0, 200, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 200, 0 } } + } + } + IsEmitterSpace: flag = true + bindWeight: embed = ValueFloat { + constantValue: f32 = 0.5 + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 1 } + values: list[f32] = { 0.5, 0 } + } + } + blendMode: u8 = 4 + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.3, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 0, 0.015686275, 1 } + } + } + } + pass: i16 = 20 + censorModulateValue: vec4 = { 0, 1, 1, 1 } + isDirectionOriented: flag = true + isRandomStartFrame: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { -90, 0, 0 } + } + directionVelocityScale: f32 = 0.01 + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 18, 18, 18 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 0.9, 1 } + keyValues: list[f32] = { 0.4, 0.7, 1 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 18, 18, 18 } } + } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 0.5, 0.5, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.2, 0.4, 0.8, 1 } + values: list[vec3] = { + { 0, 0, 0 } + { 0.5, 0.5, 1 } + { 0.5, 0.5, 1 } + { 0.3, 0.3, 0.6 } + { 0, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_R_Sparks.Zaahen.tex" + } + } + particleName: string = "Zaahen_Base_P_WillRevive_ShoulderL" + particlePath: string = "Characters/Zaahen/Skins/Skin0/Particles/Zaahen_Base_P_WillRevive_ShoulderL" + flags: u16 = 1236 + } + "Characters/Zaahen/Skins/Skin0/Particles/Zaahen_Base_R_BuffActivate_Glow" = VfxSystemDefinitionData { + complexEmitterDefinitionData: list[pointer] = { + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.12 + rate: embed = ValueFloat { + constantValue: f32 = 20 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.3 + } + lifetime: option[f32] = { 0.15 } + isSingleParticle: flag = true + emitterName: string = "ray_beam" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 450, 0 } + } + FlexShapeDefinition: pointer = VfxFlexShapeDefinitionData { + scaleBirthScaleByBoundObjectSize: f32 = 0.005 + } + primitive: pointer = VfxPrimitiveRay { } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 0.8399939, 0.5400015, 0.14000152 } + } + Color: embed = ValueColor { + constantValue: vec4 = { 0.92156863, 0.7607843, 0.49019608, 1 } + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0.6, 1 } + values: list[vec4] = { + { 0.92156863, 0.7607843, 0.49019608, 1 } + { 0, 0, 0, 0 } + } + } + } + pass: i16 = 50 + alphaRef: u8 = 0 + miscRenderFlags: u8 = 1 + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 1, 1, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 1, 1, 1 } } + } + } + isLocalOrientation: flag = false + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 150, 60, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.6, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.6, 1 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 150, 60, 0 } } + } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 2, 2, 0.8 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.24, 0.99065423 } + values: list[vec3] = { + { 0, 0, 0 } + { 2.0408163, 12.897142, 0 } + { 3.6734693, 14.530612, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Lensflare_Prism.Zaahen.tex" + textureMult: pointer = VfxTextureMultDefinitionData { + birthUvScrollRateMult: embed = ValueVector2 { + constantValue: vec2 = { 0, 1 } + } + birthUVOffsetMult: embed = ValueVector2 { + constantValue: vec2 = { 1, 1 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec2] = { { 1, 1 } } + } + } + } + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.17 + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.3 + } + lifetime: option[f32] = { 2 } + isSingleParticle: flag = true + emitterName: string = "flare" + importance: u8 = 1 + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { -20, 450, 0 } + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 1, 1, 0.6 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 1 } + values: list[vec4] = { + { 1, 1, 1, 0.7400015 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = 50 + alphaRef: u8 = 0 + miscRenderFlags: u8 = 1 + isUniformScale: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 500, 250, 1 } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/solar_tag.Zaahen.tex" + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.25 + rate: embed = ValueFloat { + constantValue: f32 = 2 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.1 + } + lifetime: option[f32] = { 2 } + isSingleParticle: flag = true + emitterName: string = "outer_ring" + importance: u8 = 1 + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { -20, 450, 0 } + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0.07699703, 0.52156866 } + } + Color: embed = ValueColor { + constantValue: vec4 = { 0.92156863, 0.7607843, 0.49019608, 1 } + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 1 } + values: list[vec4] = { + { 0.92156863, 0.7607843, 0.49019608, 1 } + { 0, 0, 0, 0 } + } + } + } + pass: i16 = 22 + softParticleParams: pointer = VfxSoftParticleDefinitionData { + beginIn: f32 = 0.7 + deltaIn: f32 = 0.3 + deltaOut: f32 = 0.3 + } + miscRenderFlags: u8 = 1 + isUniformScale: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 360, 0, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 360, 0, 0 } } + } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 600, 250, 1 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { -0.04105162, 0.16363126, 0.45484108, 0.9949406 } + values: list[vec3] = { + { 0.99927115, 0.9941691, 0.9941691 } + { 1.2824806, 1.2824806, 1.2824806 } + { 1.6177408, 1.6109328, 1.6109328 } + { 1.8837193, 1.8888214, 1.8888214 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_lens-rainbow.Zaahen.tex" + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.12 + rate: embed = ValueFloat { + constantValue: f32 = 12 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.65 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.2, 0.6 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 0.65 } + } + } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "glow" + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 5, 5, 5 } + } + worldAcceleration: embed = IntegratedValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 0, 0 } } + } + } + bindWeight: embed = ValueFloat { + constantValue: f32 = 0.3 + } + SpawnShape: pointer = VfxShapeLegacy { + emitOffset: embed = ValueVector3 { + constantValue: vec3 = { 400, 200, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 400, 200, 0 } } + } + } + emitRotationAngles: list[embed] = { + ValueFloat { + constantValue: f32 = 360 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 360 } + } + } + } + emitRotationAxes: list[vec3] = { { 0, 1, 0 } } + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 600, 0 } + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 0.3709926, 0.22345312, 1 } + } + Color: embed = ValueColor { + constantValue: vec4 = { 1, 1, 1, 0.5000076 } + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0.003937008, 0.023544546, 0.8, 1 } + values: list[vec4] = { + { 1, 1, 1, 0.5000076 } + { 1, 1, 1, 0.5000076 } + { 1, 1, 1, 0.5000076 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = 55 + colorLookUpScales: vec2 = { 1, 0.8 } + colorLookUpOffsets: vec2 = { 0, 0.3 } + miscRenderFlags: u8 = 1 + isUniformScale: flag = true + isRandomStartFrame: flag = true + isLocalOrientation: flag = false + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 15, 120, 1 } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 1, 1.25, 1.25 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.20474903, 1 } + values: list[vec3] = { + { 0, 1.25, 0 } + { 1, 0.9940637, 0 } + { 0, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/BrightGlow.Zaahen.tex" + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.12 + rate: embed = ValueFloat { + constantValue: f32 = 22 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.5 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.1, 1 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 0.5 } + } + } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "sparks" + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 5, 5, 5 } + } + worldAcceleration: embed = IntegratedValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 0, 0 } } + } + } + bindWeight: embed = ValueFloat { + constantValue: f32 = 0.3 + } + SpawnShape: pointer = VfxShapeLegacy { + emitOffset: embed = ValueVector3 { + constantValue: vec3 = { 250, 250, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 250, 250, 0 } } + } + } + emitRotationAngles: list[embed] = { + ValueFloat { + constantValue: f32 = 360 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 360 } + } + } + } + emitRotationAxes: list[vec3] = { { 0, 1, 0 } } + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 400, 0 } + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 0.5604333, 0.28661022, 1 } + } + Color: embed = ValueColor { + constantValue: vec4 = { 1, 1, 1, 0.5000076 } + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0.003937008, 0.023544546, 0.8, 1 } + values: list[vec4] = { + { 1, 1, 1, 0.5000076 } + { 1, 1, 1, 0.5000076 } + { 1, 1, 1, 0.5000076 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = 55 + colorLookUpScales: vec2 = { 1, 0.8 } + colorLookUpOffsets: vec2 = { 0, 0.3 } + miscRenderFlags: u8 = 1 + isUniformScale: flag = true + isRandomStartFrame: flag = true + isLocalOrientation: flag = false + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 20, 60, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.25, 2 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 20, 60, 1 } } + } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 1, 1.25, 1.25 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.20474903, 1 } + values: list[vec3] = { + { 0, 1.25, 0 } + { 1, 0.9940637, 0 } + { 0, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_R_Sparks.Zaahen.tex" + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.17 + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.35 + } + lifetime: option[f32] = { 2 } + isSingleParticle: flag = true + emitterName: string = "Flash_SolidBody" + importance: u8 = 3 + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + primitive: pointer = VfxPrimitiveAttachedMesh { + mMesh: embed = VfxMeshDefinitionData { + mSubmeshesToDraw: list[hash] = { "BODY", "Wings", "weapon" } + mLockMeshToAttachment: bool = true + } + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.9944305, 0.6445716, 0.013977264, 0.50980395 } + } + Color: embed = ValueColor { + constantValue: vec4 = { 1, 0.8003052, 0.5852598, 1 } + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 0.7, 1 } + values: list[vec4] = { + { 1, 0.8003052, 0.5852598, 1 } + { 1, 0.8003052, 0.5852598, 1 } + { 1, 0.8003052, 0.5852598, 0.17999542 } + { 1, 0.8003052, 0.5852598, 0 } + } + } + } + pass: i16 = -500 + censorModulateValue: vec4 = { 1, 1, 1, 0.61960787 } + reflectionDefinition: pointer = VfxReflectionDefinitionData { + reflectionMapTexture: string = "ASSETS/Shared/Particles/Generic_White_Cubemap.TFT_Set15.dds" + reflectionOpacityDirect: f32 = 0.5 + reflectionOpacityGlancing: f32 = 0.1 + reflectionFresnel: f32 = 0.3 + reflectionFresnelColor: vec4 = { 0.90286106, 0.8252079, 0.4269627, 1 } + fresnel: f32 = 0.1 + fresnelColor: vec4 = { 0, 0, 0, 1 } + } + 0xcb13aff1: f32 = -1 + disableBackfaceCull: bool = true + particleIsLocalOrientation: flag = true + isUniformScale: flag = true + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/color-hold.Zaahen.tex" + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_W_Mask_01.Zaahen.tex" + birthUvScrollRateMult: embed = ValueVector2 { + constantValue: vec2 = { 0, 200 } + } + } + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.17 + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.35 + } + lifetime: option[f32] = { 2 } + isSingleParticle: flag = true + emitterName: string = "Flash_Sword" + importance: u8 = 3 + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 0, 0 } } + } + } + primitive: pointer = VfxPrimitiveAttachedMesh { + mMesh: embed = VfxMeshDefinitionData { + mSubmeshesToDraw: list[hash] = { "weapon" } + mLockMeshToAttachment: bool = true + } + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 0.8399939, 0.5400015, 0.10000763 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 0.8, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = -95 + 0xcb13aff1: f32 = -8 + disableBackfaceCull: bool = true + particleIsLocalOrientation: flag = true + isUniformScale: flag = true + isRotationEnabled: flag = true + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Q_Glaive_Mask4.Zaahen.tex" + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/color-hold.Zaahen.tex" + birthUvScrollRateMult: embed = ValueVector2 { + constantValue: vec2 = { 0.5, 0 } + } + } + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.17 + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.35 + } + lifetime: option[f32] = { 2 } + isSingleParticle: flag = true + emitterName: string = "Flash_Gauldrons" + IsEmitterSpace: flag = true + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + primitive: pointer = VfxPrimitiveAttachedMesh { + mMesh: embed = VfxMeshDefinitionData { + mSubmeshesToDraw: list[hash] = { "Wings" } + mLockMeshToAttachment: bool = true + } + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.99806213, 0.4658427, 0.026871137, 0.6901961 } + } + Color: embed = ValueColor { + constantValue: vec4 = { 0.92156863, 0.7607843, 0.49019608, 1 } + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.01, 1 } + values: list[vec4] = { + { 0.92156863, 0.7607843, 0.49019608, 1 } + { 0.92156863, 0.7607843, 0.49019608, 1 } + { 0.92156863, 0.7607843, 0.49019608, 0 } + } + } + } + pass: i16 = -95 + uvParallaxScale: f32 = 0.00075 + 0xcb13aff1: f32 = -4 + disableBackfaceCull: bool = true + particleIsLocalOrientation: flag = true + isUniformScale: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 1.001, 1, 1 } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_P_Wing_Mask.Zaahen.tex" + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.17 + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.35 + } + lifetime: option[f32] = { 2 } + isSingleParticle: flag = true + emitterName: string = "Flash_BodyArmor" + IsEmitterSpace: flag = true + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + primitive: pointer = VfxPrimitiveAttachedMesh { + mMesh: embed = VfxMeshDefinitionData { + mSubmeshesToDraw: list[hash] = { "BODY" } + mLockMeshToAttachment: bool = true + } + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 0.14366369, 0, 0.5019608 } + } + Color: embed = ValueColor { + constantValue: vec4 = { 1, 0.24983597, 0, 1 } + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.01, 1 } + values: list[vec4] = { + { 1, 0.24983597, 0, 0 } + { 1, 0.24983597, 0, 1 } + { 1, 0.24983597, 0, 0 } + } + } + } + pass: i16 = -95 + uvParallaxScale: f32 = 0.00075 + 0xcb13aff1: f32 = -4 + disableBackfaceCull: bool = true + particleIsLocalOrientation: flag = true + isUniformScale: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 1.001, 1, 1 } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_E_Body_Mask.Zaahen.tex" + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.2 + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 1 + } + lifetime: option[f32] = { 2 } + isSingleParticle: flag = true + emitterName: string = "ray_Glow" + importance: u8 = 3 + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, -200, 0 } + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 600, 0 } + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 1, 1, 0.5411765 } + } + Color: embed = ValueColor { + constantValue: vec4 = { 0.8509804, 0.8509804, 0.8509804, 1 } + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.5, 1 } + values: list[vec4] = { + { 0.8509804, 0.08736394, 0, 1 } + { 0.657502, 0.046136163, 0, 1 } + { 0.42980775, 0.02063337, 0, 0 } + } + } + } + pass: i16 = -80 + alphaRef: u8 = 0 + isGroundLayer: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 0, 0 } + } + isLocalOrientation: flag = false + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 1000, 350, 0 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.8, 1 } + values: list[vec3] = { + { 1, 1, 1 } + { 1, 2, 1 } + { 1, 1, 1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Aura_Self.Zaahen.tex" + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.62 + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.2 + } + lifetime: option[f32] = { 2 } + isSingleParticle: flag = true + emitterName: string = "ray_Glow1" + importance: u8 = 3 + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, -200, 0 } + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 600, 0 } + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.38022432, 0, 0.042008087, 1 } + } + Color: embed = ValueColor { + constantValue: vec4 = { 0.8509804, 0.8509804, 0.8509804, 1 } + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.8, 1 } + values: list[vec4] = { + { 0.8509804, 0.8509804, 0.8509804, 1 } + { 0.8509804, 0.8509804, 0.8509804, 0.34999618 } + { 0.05506993, 0, 0, 0 } + } + } + } + pass: i16 = -200 + alphaRef: u8 = 0 + miscRenderFlags: u8 = 1 + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 0, 0 } + } + isLocalOrientation: flag = false + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 1000, 700, 0 } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Aura_Self.Zaahen.tex" + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.62 + rate: embed = ValueFloat { + constantValue: f32 = 100 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.5 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 0.9, 1 } + keyValues: list[f32] = { 0.1, 0.9, 1.1 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 0.5 } + } + } + lifetime: option[f32] = { 0.6 } + emitterName: string = "soulBits" + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { -200, -7000, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 1, -1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 0.8, 1 } + keyValues: list[f32] = { 0.2, 0.6, 1 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { -200, -7000, 0 } } + } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 8, 4, 8 } + } + worldAcceleration: embed = IntegratedValueVector3 { + constantValue: vec3 = { 0, 200, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 200, 0 } } + } + } + SpawnShape: pointer = VfxShapeLegacy { + emitOffset: embed = ValueVector3 { + constantValue: vec3 = { 90, 1, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 90, 1, 0 } } + } + } + emitRotationAngles: list[embed] = { + ValueFloat { + constantValue: f32 = 1 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 1 } + } + } + } + emitRotationAxes: list[vec3] = { { 0, 1, 0 } } + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 800, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.75, 1.25 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 800, 0 } } + } + } + primitive: pointer = VfxPrimitiveArbitraryQuad { } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 0.1481651, 0.110978864, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + colorLookUpTypeY: u8 = 3 + softParticleParams: pointer = VfxSoftParticleDefinitionData { + deltaIn: f32 = 25 + } + isDirectionOriented: flag = true + isRandomStartFrame: flag = true + isGroundLayer: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 90, 0 } + } + directionVelocityScale: f32 = 0.005 + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 100, 20, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.39, 0.42 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 100, 20, 0 } } + } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.1, 0.3, 0.5, 0.7, 0.9, 1 } + values: list[vec3] = { + { 3, 4, 0 } + { 1, 1, 0 } + { 0.5, 0.5, 0 } + { 0.8, 1, 0 } + { 0.3, 0.5, 0 } + { 0.2, 0.2, 0 } + { 0, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/TFT15_Viego_Base_SoulBits.Zaahen.tex" + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.58 + rate: embed = ValueFloat { + constantValue: f32 = 25 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.5 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 0.9, 1 } + keyValues: list[f32] = { 0.1, 0.9, 1.1 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 0.5 } + } + } + lifetime: option[f32] = { 0.55 } + emitterName: string = "soulBits1" + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { -200, -7000, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 1, -1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 0.8, 1 } + keyValues: list[f32] = { 0.2, 0.6, 1 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { -200, -7000, 0 } } + } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 8, 4, 8 } + } + worldAcceleration: embed = IntegratedValueVector3 { + constantValue: vec3 = { 0, 200, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 200, 0 } } + } + } + SpawnShape: pointer = VfxShapeLegacy { + emitOffset: embed = ValueVector3 { + constantValue: vec3 = { 45, 1, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 45, 1, 0 } } + } + } + emitRotationAngles: list[embed] = { + ValueFloat { + constantValue: f32 = 1 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 1 } + } + } + } + emitRotationAxes: list[vec3] = { { 0, 1, 0 } } + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 1000, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.75, 1.25 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 1000, 0 } } + } + } + primitive: pointer = VfxPrimitiveArbitraryQuad { } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.824094, 0.09956512, 0.09956512, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + colorLookUpTypeY: u8 = 3 + softParticleParams: pointer = VfxSoftParticleDefinitionData { + deltaIn: f32 = 25 + } + isDirectionOriented: flag = true + isRandomStartFrame: flag = true + isGroundLayer: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 90, 0 } + } + directionVelocityScale: f32 = 0.005 + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 80, 20, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.39, 0.42 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 80, 20, 0 } } + } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 2, 2, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.1, 0.3, 0.5, 0.7, 0.9, 1 } + values: list[vec3] = { + { 6, 8, 0 } + { 2, 2, 0 } + { 1, 1, 0 } + { 1.6, 2, 0 } + { 0.6, 1, 0 } + { 0.4, 0.4, 0 } + { 0, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/TFT15_Viego_Base_SoulBits.Zaahen.tex" + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.6 + rate: embed = ValueFloat { + constantValue: f32 = 60 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.6 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 0.9, 1 } + keyValues: list[f32] = { 0.1, 0.9, 1.1 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 0.6 } + } + } + lifetime: option[f32] = { 0.55 } + emitterName: string = "soulBits2" + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { -200, -7000, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 1, -1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 0.8, 1 } + keyValues: list[f32] = { 0.2, 0.6, 1 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { -200, -7000, 0 } } + } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 8, 4, 8 } + } + worldAcceleration: embed = IntegratedValueVector3 { + constantValue: vec3 = { 0, 200, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 200, 0 } } + } + } + SpawnShape: pointer = VfxShapeLegacy { + emitOffset: embed = ValueVector3 { + constantValue: vec3 = { 90, 1, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 90, 1, 0 } } + } + } + emitRotationAngles: list[embed] = { + ValueFloat { + constantValue: f32 = 1 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 1 } + } + } + } + emitRotationAxes: list[vec3] = { { 0, 1, 0 } } + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 800, 0 } + } + primitive: pointer = VfxPrimitiveArbitraryQuad { } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.9764706, 0.8039216, 0.45490196, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = 100 + colorLookUpTypeY: u8 = 3 + softParticleParams: pointer = VfxSoftParticleDefinitionData { + deltaIn: f32 = 25 + } + isDirectionOriented: flag = true + isRandomStartFrame: flag = true + isGroundLayer: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 90, 0 } + } + directionVelocityScale: f32 = 0.005 + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 80, 20, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.39, 0.42 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 80, 20, 0 } } + } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.1, 0.3, 0.5, 0.7, 0.9, 1 } + values: list[vec3] = { + { 4, 5, 0 } + { 1, 1, 0 } + { 0.5, 0.5, 0 } + { 0.8, 1, 0 } + { 0.3, 0.5, 0 } + { 0.2, 0.2, 0 } + { 0, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/TFT15_Viego_Base_SoulBits.Zaahen.tex" + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.58 + rate: embed = ValueFloat { + constantValue: f32 = 4 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.175 + } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "flash" + importance: u8 = 3 + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, -4500, 0 } + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, -300, 0 } + } + primitive: pointer = VfxPrimitiveRay { } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.92762643, 0.5182269, 0.43297476, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.3, 0.6, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 0.16470589, 0.10412756, 0.03137255, 0 } + } + } + } + pass: i16 = 910 + alphaRef: u8 = 75 + softParticleParams: pointer = VfxSoftParticleDefinitionData { + beginIn: f32 = 10 + deltaIn: f32 = 100 + } + miscRenderFlags: u8 = 1 + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 270, 0, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 400, 400, 1 } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 1, 6, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.1, 1 } + values: list[vec3] = { + { 1, 6, 0 } + { 1, 6, 1 } + { 1, 6, 1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_R_EyeMask.Zaahen.tex" + texAddressModeBase: u8 = 2 + uvScale: embed = ValueVector2 { + constantValue: vec2 = { 6, 3 } + } + uvRotation: embed = ValueFloat { + constantValue: f32 = 180 + } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Skarner_Rework_Skin04_W_Wave02_01.Zaahen.tex" + uvScaleMult: embed = ValueVector2 { + constantValue: vec2 = { 4, 4 } + } + birthUvScrollRateMult: embed = ValueVector2 { + constantValue: vec2 = { 0, 8 } + } + birthUVOffsetMult: embed = ValueVector2 { + constantValue: vec2 = { 1, 1 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec2] = { { 1, 1 } } + } + } + } + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.54 + rate: embed = ValueFloat { + constantValue: f32 = 4 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.175 + } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "flash1" + importance: u8 = 3 + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, -4500, 0 } + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, -325, 0 } + } + primitive: pointer = VfxPrimitiveRay { } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.9031357, 0.52413213, 0.33955902, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.3, 0.6, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 0.16470589, 0.10412756, 0.03137255, 0 } + } + } + } + pass: i16 = 900 + alphaRef: u8 = 75 + softParticleParams: pointer = VfxSoftParticleDefinitionData { + beginIn: f32 = 10 + deltaIn: f32 = 100 + } + miscRenderFlags: u8 = 1 + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 270, 0, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 400, 400, 1 } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 1, 6, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.7, 0.9, 1 } + values: list[vec3] = { + { 1, 6, 0 } + { 0.9, 6.6, 1 } + { 0.8, 7.8, 1 } + { 1, 6, 1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_R_EyeMask.Zaahen.tex" + texAddressModeBase: u8 = 2 + uvScale: embed = ValueVector2 { + constantValue: vec2 = { 4, 2 } + } + uvRotation: embed = ValueFloat { + constantValue: f32 = 180 + } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Skarner_Rework_Skin04_W_Wave02_01.Zaahen.tex" + uvScaleMult: embed = ValueVector2 { + constantValue: vec2 = { 4, 4 } + } + birthUvScrollRateMult: embed = ValueVector2 { + constantValue: vec2 = { 0, 8 } + } + birthUVOffsetMult: embed = ValueVector2 { + constantValue: vec2 = { 1, 1 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec2] = { { 1, 1 } } + } + } + } + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.55 + rate: embed = ValueFloat { + constantValue: f32 = 5 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.175 + } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "flash2" + importance: u8 = 3 + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, -4500, 0 } + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, -250, 0 } + } + primitive: pointer = VfxPrimitiveRay { } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.9195544, 0.39606318, 0.14648661, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.6, 1 } + values: list[vec4] = { + { 0.919997, 0.8399939, 0.6, 0 } + { 0.9000076, 0.5799954, 0.059998475, 1 } + { 0.2899977, 0.1600061, 0, 1 } + } + } + } + pass: i16 = 2000 + alphaRef: u8 = 0 + softParticleParams: pointer = VfxSoftParticleDefinitionData { + beginIn: f32 = 10 + deltaIn: f32 = 100 + } + miscRenderFlags: u8 = 1 + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 270, 0, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 400, 400, 1 } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 1, 6, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.7, 1 } + values: list[vec3] = { + { 1, 6, 0 } + { 1, 6, 1 } + { 1.2, 6, 1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_R_EyeMask.Zaahen.tex" + texAddressModeBase: u8 = 2 + uvScale: embed = ValueVector2 { + constantValue: vec2 = { 2, 2 } + } + uvRotation: embed = ValueFloat { + constantValue: f32 = 180 + } + textureMult: pointer = VfxTextureMultDefinitionData { + uvScaleMult: embed = ValueVector2 { + constantValue: vec2 = { 1, 2 } + } + birthUvScrollRateMult: embed = ValueVector2 { + constantValue: vec2 = { 0, 8 } + } + birthUVOffsetMult: embed = ValueVector2 { + constantValue: vec2 = { 1, 1 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec2] = { { 1, 1 } } + } + } + } + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.56 + rate: embed = ValueFloat { + constantValue: f32 = 5 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.175 + } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "flash3" + importance: u8 = 3 + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, -4500, 0 } + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 1900, 0 } + } + primitive: pointer = VfxPrimitiveRay { } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.8615549, 0.3450828, 0.28006408, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.6, 1 } + values: list[vec4] = { + { 1, 1, 1, 0.47058824 } + { 1, 0.43967345, 0, 1 } + { 1, 1, 1, 0.47058824 } + } + } + } + pass: i16 = 1500 + alphaRef: u8 = 0 + softParticleParams: pointer = VfxSoftParticleDefinitionData { + beginIn: f32 = 10 + deltaIn: f32 = 100 + } + miscRenderFlags: u8 = 1 + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 0, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 175, 375, 1 } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 1, 4, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.6, 1 } + values: list[vec3] = { + { 1, 4, 0 } + { 0.6, 4, 1 } + { 1, 4, 1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_R_AirBullet.Zaahen.tex" + texAddressModeBase: u8 = 2 + uvScale: embed = ValueVector2 { + constantValue: vec2 = { 2, 2 } + } + uvRotation: embed = ValueFloat { + constantValue: f32 = 180 + } + textureMult: pointer = VfxTextureMultDefinitionData { + uvScaleMult: embed = ValueVector2 { + constantValue: vec2 = { 1, 2 } + } + birthUvScrollRateMult: embed = ValueVector2 { + constantValue: vec2 = { 0, 8 } + } + birthUVOffsetMult: embed = ValueVector2 { + constantValue: vec2 = { 1, 1 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec2] = { { 1, 1 } } + } + } + } + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.58 + rate: embed = ValueFloat { + constantValue: f32 = 3 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.175 + } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "flash4" + importance: u8 = 3 + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, -4500, 0 } + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, -300, 0 } + } + primitive: pointer = VfxPrimitiveRay { } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.33369955, 0.011902037, 0, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.3, 0.6, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = 750 + alphaRef: u8 = 75 + softParticleParams: pointer = VfxSoftParticleDefinitionData { + beginIn: f32 = 10 + deltaIn: f32 = 100 + } + isGroundLayer: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 270, 0, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 400, 400, 1 } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 1, 6, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.1, 1 } + values: list[vec3] = { + { 1, 6, 0 } + { 1, 6, 1 } + { 1, 6, 1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_R_EyeMask.Zaahen.tex" + texAddressModeBase: u8 = 2 + uvRotation: embed = ValueFloat { + constantValue: f32 = 180 + } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Darkin_Shape_Mask_01.Zaahen.tex" + uvScaleMult: embed = ValueVector2 { + constantValue: vec2 = { 3, 4 } + } + birthUvScrollRateMult: embed = ValueVector2 { + constantValue: vec2 = { 0, 8 } + } + birthUVOffsetMult: embed = ValueVector2 { + constantValue: vec2 = { 1, 1 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec2] = { { 1, 1 } } + } + } + } + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.6 + rate: embed = ValueFloat { + constantValue: f32 = 2 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.175 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 1, 1.5 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 0.175 } + } + } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "flash5" + importance: u8 = 3 + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, -4100, 0 } + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 425, 0 } + } + primitive: pointer = VfxPrimitiveRay { } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.75529104, 0, 0.032227054, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.05, 0.95, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = 2700 + alphaRef: u8 = 75 + softParticleParams: pointer = VfxSoftParticleDefinitionData { + beginIn: f32 = 10 + deltaIn: f32 = 100 + } + isGroundLayer: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 270, 0, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 500, 400, 1 } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 1, 2.1, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1.1121495 } + keyValues: list[f32] = { 1, 1.7838137 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0, 0.5, 1 } + values: list[vec3] = { + { 1, 1.68, 0 } + { 1, 2.1, 1 } + { 0.5, 2.9399998, 1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Aura_Self.Zaahen.tex" + texAddressModeBase: u8 = 2 + uvScale: embed = ValueVector2 { + constantValue: vec2 = { 0.75, 0.75 } + } + uvRotation: embed = ValueFloat { + constantValue: f32 = 180 + } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Darkin_Shape_Mask_01.Zaahen.tex" + birthUVOffsetMult: embed = ValueVector2 { + constantValue: vec2 = { 1, 1 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec2] = { { 1, 1 } } + } + } + } + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.6 + rate: embed = ValueFloat { + constantValue: f32 = 2 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.175 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 1, 1.5 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 0.175 } + } + } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "flash6" + importance: u8 = 3 + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, -4100, 0 } + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 425, 0 } + } + primitive: pointer = VfxPrimitiveRay { } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.2415198, 0, 0.01029984, 1 } + } + Color: embed = ValueColor { + constantValue: vec4 = { 0.5069047, 0, 0, 1 } + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.05, 0.95, 1 } + values: list[vec4] = { + { 0.5069047, 0, 0, 1 } + { 0.35930791, 0, 0, 1 } + { 0.24707496, 0, 0, 1 } + { 0.09576543, 0, 0, 0 } + } + } + } + pass: i16 = 5000 + alphaRef: u8 = 75 + softParticleParams: pointer = VfxSoftParticleDefinitionData { + beginIn: f32 = 10 + deltaIn: f32 = 100 + } + isGroundLayer: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 270, 0, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 600, 400, 1 } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 1, 2.1, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 1, 1.5 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0, 0.5, 1 } + values: list[vec3] = { + { 1, 1.6800001, 0 } + { 1, 2.1, 1 } + { 0.5, 2.94, 1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_R_EyeMask.Zaahen.tex" + texAddressModeBase: u8 = 2 + uvScale: embed = ValueVector2 { + constantValue: vec2 = { 0.75, 0.75 } + } + uvRotation: embed = ValueFloat { + constantValue: f32 = 180 + } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Darkin_Shape_Mask_01.Zaahen.tex" + birthUVOffsetMult: embed = ValueVector2 { + constantValue: vec2 = { 1, 1 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec2] = { { 1, 1 } } + } + } + } + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.66 + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.4 + } + lifetime: option[f32] = { 1.8 } + isSingleParticle: flag = true + emitterName: string = "Beam_Core" + importance: u8 = 3 + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + primitive: pointer = VfxPrimitiveRay { } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.5600061, 0.5600061, 0.5600061, 0.7499962 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.12, 0.4, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 0.44600594, 0, 1 } + { 0.5058824, 0.0627451, 0.14509805, 1 } + { 0.37999544, 0.06999313, 0.1600061, 0 } + } + } + } + pass: i16 = 4 + softParticleParams: pointer = VfxSoftParticleDefinitionData { + deltaIn: f32 = 50 + } + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 1 } + values: list[f32] = { 0, 1 } + } + } + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 0, 0, 1, 0 } + } + } + disableBackfaceCull: bool = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { -90, 0, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 65, 1280, 1 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.1, 0.12, 0.18, 0.4, 0.85 } + values: list[vec3] = { + { 0.1, 1, 0 } + { 2, 1, 1 } + { 2, 1, 1 } + { 2.2, 1, 1 } + { 1.5, 1, 2 } + { 0, 1, 0.2 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Viego_Skin30_R_LazurBeam02.Zaahen.tex" + particleUVScrollRate: embed = IntegratedValueVector2 { + constantValue: vec2 = { 0, -2 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 0.1786372, 0.65, 1 } + values: list[vec2] = { + { 0, -12 } + { 0, -4 } + { 0, -2 } + { 0, -0 } + } + } + } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Viego_Skin30_R_mult_02.Zaahen.tex" + texAddressModeMult: u8 = 2 + birthUvScrollRateMult: embed = ValueVector2 { + constantValue: vec2 = { 5, 0 } + } + birthUVOffsetMult: embed = ValueVector2 { + constantValue: vec2 = { 0, 0.01 } + } + } + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.56 + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.55 + } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "Ray" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, -95, 0 } + } + primitive: pointer = VfxPrimitiveRay { } + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.8135195, 0.03227283, 0.009216449, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.05, 0.15, 0.25, 0.4, 0.8, 1 } + values: list[vec4] = { + { 1, 1, 0, 0.3 } + { 1, 1, 1, 0.3 } + { 1, 1, 1, 0.4 } + { 1, 1, 1, 0.3 } + { 1, 1, 0, 0.2 } + { 0.7, 0.2, 0, 0.1 } + { 0.1, 0, 0, 0 } + } + } + } + pass: i16 = 5 + softParticleParams: pointer = VfxSoftParticleDefinitionData { + deltaIn: f32 = 50 + } + stencilMode: u8 = 3 + stencilRef: u8 = 6 + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { -90, 0, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 150, 1600, 0 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.15, 0.3, 0.6, 1 } + values: list[vec3] = { + { 0, 1, 0 } + { 1.3, 1, 0 } + { 0.3, 1, 0 } + { 0.1, 1, 0 } + { 0, 1, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Viego_Skin30_R_SkyBeam.Zaahen.tex" + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.3 + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.75 + } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "Ray1" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, -95, 0 } + } + primitive: pointer = VfxPrimitiveRay { } + particleColorTexture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/color-hold.Zaahen.tex" + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.75193405, 0.048126955, 0, 0.43137255 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.05, 0.15, 0.25, 0.4, 0.8, 1 } + values: list[vec4] = { + { 1, 1, 0, 0.3 } + { 1, 1, 1, 0.3 } + { 1, 1, 1, 0.4 } + { 1, 1, 1, 0.3 } + { 1, 1, 0, 0.2 } + { 0.7, 0.2, 0, 0.1 } + { 0.1, 0, 0, 0 } + } + } + } + pass: i16 = 5 + stencilMode: u8 = 3 + stencilRef: u8 = 1 + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { -90, 0, 0 } + } + isLocalOrientation: flag = false + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 150, 1600, 0 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.24864864, 0.5033543, 0.6, 1 } + values: list[vec3] = { + { 0, 1, 0 } + { 1.2919254, 1, 0 } + { 0.3, 1, 0 } + { 0.1, 1, 0 } + { 0, 1, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Mel_Base_R_SkyBeam.Zaahen.tex" + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.1 + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.8 + } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "ray_Glow3" + importance: u8 = 3 + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 10, 0 } + } + primitive: pointer = VfxPrimitiveArbitraryQuad { } + blendMode: u8 = 5 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 0.26999313, 0.14999619, 0.08000305 } + } + Color: embed = ValueColor { + constantValue: vec4 = { 0.8509804, 0.8509804, 0.8509804, 1 } + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.25, 0.5, 1 } + values: list[vec4] = { + { 0, 0, 0, 0 } + { 0.8509804, 0.8509804, 0.8509804, 1 } + { 0.8509804, 0.8509804, 0.8509804, 1 } + { 0, 0, 0, 0 } + } + } + } + pass: i16 = 3000 + alphaRef: u8 = 0 + miscRenderFlags: u8 = 1 + isUniformScale: flag = true + isGroundLayer: flag = true + useNavmeshMask: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 0, 0 } + } + isLocalOrientation: flag = false + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 250, 500, 0 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 1, 1, 1 } + { 0, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Aura_Self.Zaahen.tex" + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.63 + rate: embed = ValueFloat { + constantValue: f32 = 10 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.2 + } + lifetime: option[f32] = { 0.45 } + emitterName: string = "Comet" + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, -8000, 0 } + } + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 800, 0 } + } + primitive: pointer = VfxPrimitiveRay { } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.8200046, 0.10000763, 0.10000763, 0.4399939 } + } + Color: embed = ValueColor { + constantValue: vec4 = { 0.9254902, 0.9254902, 0.9254902, 1 } + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.2, 1 } + values: list[vec4] = { + { 0.9254902, 0.43497404, 0, 0 } + { 0.9254902, 0.01088812, 0.33027297, 1 } + { 0.193769, 0.035672363, 0.09891102, 0 } + } + } + } + pass: i16 = 700 + softParticleParams: pointer = VfxSoftParticleDefinitionData { + deltaIn: f32 = 50 + } + miscRenderFlags: u8 = 1 + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { -90, 0, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 400, 1200, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.5, 1 } + values: list[vec3] = { + { 400, 1200, 0 } + { 200, 1200, 0 } + { 40, 1200, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_R_AirBullet.Zaahen.tex" + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.1 + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.65 + } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "ray_Glow4" + importance: u8 = 3 + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 10, 0 } + } + primitive: pointer = VfxPrimitiveArbitraryQuad { } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 0.4763409, 0, 1 } + } + Color: embed = ValueColor { + constantValue: vec4 = { 0.8509804, 0.8509804, 0.8509804, 1 } + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.03539906, 0.8, 1 } + values: list[vec4] = { + { 0, 0, 0, 1 } + { 0.8509804, 0.8509804, 0.8509804, 1 } + { 0.8509804, 0.8509804, 0.8509804, 1 } + { 0, 0, 0, 0 } + } + } + } + pass: i16 = 3500 + alphaRef: u8 = 0 + miscRenderFlags: u8 = 1 + isGroundLayer: flag = true + useNavmeshMask: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 0, 0 } + } + isLocalOrientation: flag = false + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 50, 50, 50 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0.0072933836, 0.042328306, 0.44358283, 0.6685208, 0.8768625, 1 } + values: list[vec3] = { + { -0.011810026, -0.007659455, -0.009615128 } + { 1.9145786, 1.9141661, 1.9139786 } + { 1.9017115, 1.8992764, 1.8991908 } + { 2.3024564, 2.3024564, 2.3024564 } + { 0.17333008, 0.2046204, 0.2046204 } + { 0, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Aura_Self.Zaahen.tex" + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.1 + rate: embed = ValueFloat { + constantValue: f32 = 2 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.65 + } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "ray_Glow5" + importance: u8 = 3 + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 10, 0 } + } + primitive: pointer = VfxPrimitiveArbitraryQuad { } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 0.46102083, 0.46102083, 1 } + } + Color: embed = ValueColor { + constantValue: vec4 = { 0.8509804, 0.8509804, 0.8509804, 1 } + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.03539906, 0.8, 1 } + values: list[vec4] = { + { 0, 0, 0, 1 } + { 0.8509804, 0.8509804, 0.8509804, 1 } + { 0.8509804, 0.8509804, 0.8509804, 1 } + { 0, 0, 0, 0 } + } + } + } + pass: i16 = 4000 + alphaRef: u8 = 0 + miscRenderFlags: u8 = 1 + isGroundLayer: flag = true + useNavmeshMask: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 0, 0 } + } + isLocalOrientation: flag = false + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 30, 30, 30 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0.0072933836, 0.042328306, 0.44358283, 0.6685208, 0.8768625, 1 } + values: list[vec3] = { + { -0.011810026, -0.007659455, -0.009615128 } + { 1.9145786, 1.9141661, 1.9139786 } + { 1.9017115, 1.8992764, 1.8991908 } + { 2.3024564, 2.3024564, 2.3024564 } + { 0.17333008, 0.2046204, 0.2046204 } + { 0, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Aura_Self.Zaahen.tex" + } + } + particleName: string = "Zaahen_Base_R_BuffActivate_Glow" + particlePath: string = "Characters/Zaahen/Skins/Skin0/Particles/Zaahen_Base_R_BuffActivate_Glow" + flags: u16 = 196 + } + "Characters/Zaahen/Skins/Skin0/Particles/Zaahen_Base_W_Pull_Tar_Ground" = VfxSystemDefinitionData { + complexEmitterDefinitionData: list[pointer] = { + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLinger: option[f32] = { } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "Avatar2" + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, 100 } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, 5 } + } + SpawnShape: pointer = 0xee39916f { + emitOffset: vec3 = { 0, 0, -30 } + } + primitive: pointer = VfxPrimitiveAttachedMesh { + mMesh: embed = VfxMeshDefinitionData { + mLockMeshToAttachment: bool = true + } + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.26999313, 0.06999313, 0.08000305, 0.5799954 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.15450644, 0.28969958, 0.5450644, 0.67596567, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0.33 } + { 1, 1, 1, 0.15248728 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = 17 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 1 } + values: list[f32] = { 0, 1 } + } + } + erosionFeatherIn: f32 = 0.3 + erosionFeatherOut: f32 = 0.3 + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Senna_Ashe_Base_ground_CrackNoise_mult.Zaahen.tex" + } + disableBackfaceCull: bool = true + particleIsLocalOrientation: flag = true + isUniformScale: flag = true + isRandomStartFrame: flag = true + isRotationEnabled: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 1.01, 1, 1 } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/color-hold.Zaahen.tex" + numFrames: u16 = 4 + birthUvScrollRate: embed = ValueVector2 { + constantValue: vec2 = { 0.4, 0.2 } + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 60 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.2 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 0.2 } + } + } + lifetime: option[f32] = { 0.3 } + emitterName: string = "Trench_Sparks1" + importance: u8 = 1 + birthOrbitalVelocity: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 0, 0 } } + } + } + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, 1000, -2000 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 1000, -2000 } } + } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 10, 1.25, 1.25 } + } + worldAcceleration: embed = IntegratedValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 0, 0 } } + } + } + blendMode: u8 = 5 + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 0.3, 0.6, 1 } + values: list[vec4] = { + { 0.9411765, 0.06666667, 0.07450981, 0 } + { 0.9411765, 0.06666667, 0.07450981, 1 } + { 0.9411765, 0.06666667, 0.07450981, 1 } + { 0.23137255, 0, 0.015686275, 1 } + { 0.23137255, 0, 0.015686275, 0 } + } + } + } + pass: i16 = 10 + miscRenderFlags: u8 = 1 + isDirectionOriented: flag = true + isGroundLayer: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 0, 0 } + } + directionVelocityScale: f32 = 0.005 + directionVelocityMinScale: f32 = 0 + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 15, 15, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 15, 15, 0 } } + } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.1, 0.6, 1 } + values: list[vec3] = { + { 2, 2, 2 } + { 2, 2, 5 } + { 2, 2, 5 } + { 0, 0, 2 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Morgana_Base_P_StardustMoteAlpha.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 100 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.1 + } + lifetime: option[f32] = { 0.2 } + timeActiveDuringPeriod: option[f32] = { 0.5 } + emitterName: string = "flash1" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + FlexShapeDefinition: pointer = VfxFlexShapeDefinitionData { + scaleBirthScaleByBoundObjectSize: f32 = 0.005 + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.92156863, 0.7607843, 0.49019608, 1 } + } + Color: embed = ValueColor { + constantValue: vec4 = { 0.92156863, 0.7607843, 0.49019608, 1 } + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 0.3, 1 } + values: list[vec4] = { + { 0.92156863, 0.7607843, 0.49019608, 0 } + { 0.92156863, 0.7607843, 0.49019608, 1 } + { 0.92156863, 0.7607843, 0.49019608, 0.8509804 } + { 0.35798234, 0.1720544, 0.03781844, 0 } + } + } + } + pass: i16 = 5000 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 1 } + values: list[f32] = { 0.5, 0 } + } + } + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Darius_Skin43_Star_Flash.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + depthBiasFactors: vec2 = { -1, -40 } + miscRenderFlags: u8 = 1 + isRandomStartFrame: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 1, 0, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 1, 0, 0 } } + } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 35, 35, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.75, 2 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.75, 2 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 35, 35, 1 } } + } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.2, 1 } + values: list[vec3] = { + { 0.2, 0.2, 0.2 } + { 1, 1, 1 } + { 1.2, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Darius_Skin43_Star_Flash.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 10 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.75 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.25, 1 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 0.75 } + } + } + lifetime: option[f32] = { 0.3 } + emitterName: string = "Trench_Sparks5" + importance: u8 = 1 + birthOrbitalVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0.5, 0.5, 0.5 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0.5, 0.5, 0.5 } } + } + } + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, 500, -1000 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 500, -1000 } } + } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 10, 1.25, 1.25 } + } + worldAcceleration: embed = IntegratedValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 0, 0 } } + } + } + blendMode: u8 = 5 + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 0.3, 0.6, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 0.8532082, 0.49411765, 1 } + { 0.92156863, 0.7607843, 0.49019608, 1 } + { 0.23137255, 0, 0.015686275, 1 } + { 0.23137255, 0, 0.015686275, 0 } + } + } + } + pass: i16 = 10 + miscRenderFlags: u8 = 1 + isDirectionOriented: flag = true + isGroundLayer: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 0, 0 } + } + directionVelocityScale: f32 = 0.005 + directionVelocityMinScale: f32 = 0 + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 15, 15, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 15, 15, 0 } } + } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.1, 0.6, 1 } + values: list[vec3] = { + { 2, 2, 2 } + { 2, 2, 5 } + { 2, 2, 5 } + { 0, 0, 2 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Morgana_Base_P_StardustMoteAlpha.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 120 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.2 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 0.2 } + } + } + lifetime: option[f32] = { 0.3 } + emitterName: string = "Trench_Sparks6" + importance: u8 = 1 + birthOrbitalVelocity: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 0, 0 } } + } + } + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, 1000, -2000 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 1000, -2000 } } + } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 10, 1.25, 1.25 } + } + worldAcceleration: embed = IntegratedValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 0, 0 } } + } + } + blendMode: u8 = 4 + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 0.3, 0.6, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 0.8532082, 0.49411765, 1 } + { 0.92156863, 0.7607843, 0.49019608, 1 } + { 0.23137255, 0, 0.015686275, 1 } + { 0.23137255, 0, 0.015686275, 0 } + } + } + } + pass: i16 = 15 + miscRenderFlags: u8 = 1 + isDirectionOriented: flag = true + isGroundLayer: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 0, 0 } + } + directionVelocityScale: f32 = 0.005 + directionVelocityMinScale: f32 = 0 + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 15, 15, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 15, 15, 0 } } + } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.1, 0.6, 1 } + values: list[vec3] = { + { 2, 2, 2 } + { 2, 2, 5 } + { 2, 2, 5 } + { 0, 0, 2 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Morgana_Base_P_StardustMoteAlpha.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.5 + } + lifetime: option[f32] = { 3 } + isSingleParticle: flag = true + emitterName: string = "Temp_GroundGlow" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, -150 } + } + primitive: pointer = VfxPrimitiveArbitraryQuad { } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.52106506, 0.01077287, 0, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.15, 0.75, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0.40999466 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = 23 + miscRenderFlags: u8 = 1 + isGroundLayer: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 180, -90 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 300, 160, 180 } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Aura_Self.Zaahen.tex" + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Cape_Nebula.Zaahen.tex" + uvScaleMult: embed = ValueVector2 { + constantValue: vec2 = { 2, 1 } + } + ParticleIntegratedUvScrollMult: embed = IntegratedValueVector2 { + constantValue: vec2 = { 0, -2 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec2] = { + { 0, -2 } + { 0, -0 } + } + } + } + birthUVOffsetMult: embed = ValueVector2 { + constantValue: vec2 = { 0, 4 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec2] = { { 0, 4 } } + } + } + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.3 + } + particleLinger: option[f32] = { } + lifetime: option[f32] = { 0.2 } + isSingleParticle: flag = true + timeActiveDuringPeriod: option[f32] = { 0.5 } + emitterName: string = "Trench_Molten3" + importance: u8 = 3 + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 2, 0 } + } + primitive: pointer = VfxPrimitiveArbitraryQuad { } + blendMode: u8 = 4 + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.8613072, 1 } + values: list[vec4] = { + { 0.9267872, 0.8181887, 0.6353857, 1 } + { 0.8438697, 0.6448615, 0.30988023, 1 } + { 0.772488, 0.5755245, 0.24396124, 0 } + } + } + } + pass: i16 = 990 + colorLookUpScales: vec2 = { 1, 0.1 } + miscRenderFlags: u8 = 1 + isGroundLayer: flag = true + useNavmeshMask: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 0, 1 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 70.5, 70, 1 } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 2, 2, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 2, 2, 1 } + { 0, 2, 1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_W_17.Zaahen.tex" + uvRotation: embed = ValueFloat { + constantValue: f32 = 90 + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 100 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.25 + } + lifetime: option[f32] = { 0.2 } + timeActiveDuringPeriod: option[f32] = { 0.5 } + emitterName: string = "Trench_Molten4" + importance: u8 = 3 + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 2, 0 } + } + FlexShapeDefinition: pointer = VfxFlexShapeDefinitionData { + scaleBirthScaleByBoundObjectSize: f32 = 0.005 + scaleEmitOffsetByBoundObjectHeight: f32 = 0.005 + } + primitive: pointer = VfxPrimitiveArbitraryQuad { } + blendMode: u8 = 1 + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.2438562, 1 } + values: list[vec4] = { + { 0.8901961, 0.09803922, 0.09803922, 1 } + { 0.27681392, 0.056687266, 0.0733196, 1 } + { 0.27450982, 0.06666667, 0.08235294, 0 } + } + } + } + pass: i16 = 900 + colorLookUpScales: vec2 = { 1, 0.1 } + miscRenderFlags: u8 = 1 + isGroundLayer: flag = true + useNavmeshMask: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 0, 1 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 80.5, 60, 1 } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 4, 4, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 4, 4, 1 } + { 0, 4, 1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_W_17.Zaahen.tex" + uvRotation: embed = ValueFloat { + constantValue: f32 = 90 + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 30 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.15 + } + lifetime: option[f32] = { 0.3 } + emitterName: string = "Hotspot_Blend_Brown2" + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 1, 2, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.1, 1 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 1, 2, 1 } } + } + } + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 1, 10 } + } + FlexShapeDefinition: pointer = VfxFlexShapeDefinitionData { + scaleBirthScaleByBoundObjectSize: f32 = 0.005 + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.8899977, 0.2899977, 0.10000763, 0.2 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.05, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = -50 + alphaRef: u8 = 0 + miscRenderFlags: u8 = 1 + isUniformScale: flag = true + isRandomStartFrame: flag = true + isGroundLayer: flag = true + useNavmeshMask: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 0, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 170, 200, 0 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 1, 1, 1 } + { 1, 1, 2 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Aura_Self.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 30 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.2 + } + lifetime: option[f32] = { 0.3 } + emitterName: string = "Hotspot_Blend_Brown3" + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 1, 2, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.1, 1 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 1, 2, 1 } } + } + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 1, 0 } + } + FlexShapeDefinition: pointer = VfxFlexShapeDefinitionData { + scaleBirthScaleByBoundObjectSize: f32 = 0.005 + } + primitive: pointer = VfxPrimitiveArbitraryQuad { } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.26999313, 0.06999313, 0.08000305, 0.8 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.05, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = -1000 + alphaRef: u8 = 0 + miscRenderFlags: u8 = 1 + isUniformScale: flag = true + isRandomStartFrame: flag = true + isGroundLayer: flag = true + useNavmeshMask: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 0, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 250, 200, 0 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 1, 1, 1 } + { 0, 1, 2 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Aura_Self.Zaahen.tex" + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.1 + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.5 + } + lifetime: option[f32] = { 3 } + isSingleParticle: flag = true + emitterName: string = "Temp_GroundGlow6" + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, -500 } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, 4 } + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 1, -50 } + } + primitive: pointer = VfxPrimitiveArbitraryQuad { } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.54985887, 0.043152515, 0.081406884, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.15, 0.75, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0.4599985 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = 23 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0.25, 1 } + values: list[f32] = { 0, 1 } + } + } + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Base_SmokeErode.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + miscRenderFlags: u8 = 1 + isRandomStartFrame: flag = true + isGroundLayer: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 180, -90 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 150, 80, 90 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 1, 1, 0 } + { 1, 2, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/zaahen_dust_cloud.Zaahen.tex" + numFrames: u16 = 4 + texDiv: vec2 = { 2, 2 } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.25 + } + lifetime: option[f32] = { 3 } + isSingleParticle: flag = true + emitterName: string = "Temp_Glow" + EmitterPosition: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 0, 0 } } + } + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.919997, 0.7600061, 0.4899977, 0.5000076 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.15, 0.75, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 0.2, 0.2, 0.2, 1 } + { 0, 0, 0, 0 } + } + } + } + pass: i16 = 24 + alphaRef: u8 = 0 + miscRenderFlags: u8 = 1 + isUniformScale: flag = true + isGroundLayer: flag = true + useNavmeshMask: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 0, -90 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 300, 160, 180 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.13, 1 } + values: list[vec3] = { + { 0, 0, 0 } + { 1, 1, 1 } + { 0, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Aura_Self.Zaahen.tex" + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.1 + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.2 + } + particleLinger: option[f32] = { 0.75 } + lifetime: option[f32] = { 1.3 } + isSingleParticle: flag = true + emitterName: string = "distot_activate1" + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, -300, 0 } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 0, 2, 0 } + } + emissionMeshScale: f32 = 0 + particleColorTexture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Morgana_Base_R_Mark_distort_RGBA.Zaahen.tex" + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 1, 1, 0.37000075 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.2, 0.75, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = 60 + distortionDefinition: pointer = VfxDistortionDefinitionData { + distortion: f32 = 0.07 + normalMapTexture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/DrMundo_Base_R_glow_distort.Zaahen.tex" + } + miscRenderFlags: u8 = 1 + isUniformScale: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 65, 200, 300 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.3, 1 } + values: list[vec3] = { + { 1, 0.2, 0.2 } + { 3, 1.7, 0.5 } + { 4, 2, 0.5 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/color-hold.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.5 + } + lifetime: option[f32] = { 3 } + isSingleParticle: flag = true + emitterName: string = "Temp_GroundGlow7" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + SpawnShape: pointer = 0xee39916f { } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, -200 } + } + primitive: pointer = VfxPrimitiveArbitraryQuad { } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.8901961, 0.09803922, 0.09803922, 1 } + } + Color: embed = ValueColor { + constantValue: vec4 = { 0.96069276, 0.96069276, 0.96069276, 1 } + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.15, 0.75, 1 } + values: list[vec4] = { + { 0.96069276, 0.96069276, 0.96069276, 0 } + { 0.96069276, 0.96069276, 0.96069276, 1 } + { 0.96069276, 0.96069276, 0.96069276, 1 } + { 0.96069276, 0.96069276, 0.96069276, 0 } + } + } + } + pass: i16 = 23 + miscRenderFlags: u8 = 1 + isGroundLayer: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 180, -90 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 300, 160, 180 } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Olaf_Q_Shape.Zaahen.tex" + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Cape_Nebula.Zaahen.tex" + uvScaleMult: embed = ValueVector2 { + constantValue: vec2 = { 2, 1 } + } + birthUvScrollRateMult: embed = ValueVector2 { + constantValue: vec2 = { 0, -1 } + } + birthUVOffsetMult: embed = ValueVector2 { + constantValue: vec2 = { 0, 4 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec2] = { { 0, 4 } } + } + } + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 1 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 1 } + } + } + lifetime: option[f32] = { 0.15 } + isSingleParticle: flag = true + emitterName: string = "MidTone" + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Nami_Skin58_NebulaMesh02.Zaahen.scb" + } + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.27450982, 0.06666667, 0.08235294, 0.45882353 } + dynamics: pointer = VfxAnimatedColorVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.8, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.8, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.8, 1 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec4] = { { 0.27450982, 0.06666667, 0.08235294, 0.45882353 } } + } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.15, 0.32222223, 0.55, 0.8, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0.5576923 } + { 1, 1, 1, 0.25999847 } + { 1, 1, 1, 0.06999313 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = 60 + alphaRef: u8 = 0 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + constantValue: f32 = 1.5 + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.5106554, 1 } + values: list[f32] = { 0.15, 0.34525862, 0.6 } + } + } + erosionFeatherIn: f32 = 0.2 + erosionFeatherOut: f32 = 0.2 + erosionSliceWidth: f32 = 2 + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Emote_Einstein_01_mult.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 0, 0, 1, 0 } + } + } + disableBackfaceCull: bool = true + particleIsLocalOrientation: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 360, 90, -90 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 1, 1 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 360, 90, -90 } } + } + } + directionVelocityMinScale: f32 = 0 + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 2, 3, 2 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 2, 3, 2 } } + } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.3653595, 1 } + values: list[vec3] = { + { 0, 0, 0 } + { 0.7434211, 0.7434211, 0.7434211 } + { 1, 1, 1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Nami_Skin58_R_NebulaMeshText03.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 30 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.15 + } + lifetime: option[f32] = { 0.3 } + emitterName: string = "Hotspot_Blend_Brown5" + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 1, 2, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.1, 1 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 1, 2, 1 } } + } + } + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 1, 0 } + } + FlexShapeDefinition: pointer = VfxFlexShapeDefinitionData { + scaleBirthScaleByBoundObjectSize: f32 = 0.005 + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.92156863, 0.7607843, 0.49019608, 0.2 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.05, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = 950 + alphaRef: u8 = 0 + miscRenderFlags: u8 = 1 + isUniformScale: flag = true + isRandomStartFrame: flag = true + isGroundLayer: flag = true + useNavmeshMask: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 0, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 75, 200, 0 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 1, 1, 1 } + { 1, 1, 2 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Aura_Self.Zaahen.tex" + } + } + particleName: string = "Zaahen_Base_W_Pull_Tar_Ground" + particlePath: string = "Characters/Zaahen/Skins/Skin0/Particles/Zaahen_Base_W_Pull_Tar_Ground" + flags: u16 = 198 + } + "Characters/Zaahen/Skins/Skin0/Particles/Zaahen_Base_BA_Crit_Tar" = VfxSystemDefinitionData { + complexEmitterDefinitionData: list[pointer] = { + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.3 + } + particleLinger: option[f32] = { 10.2 } + lifetime: option[f32] = { 1 } + emitterName: string = "Background" + FlexShapeDefinition: pointer = VfxFlexShapeDefinitionData { + scaleEmitOffsetByBoundObjectSize: f32 = 0.005 + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 1, 1, 0.9799954 } + } + Color: embed = ValueColor { + constantValue: vec4 = { 0.24309148, 0.040939957, 0.07330434, 1 } + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.3, 1 } + values: list[vec4] = { + { 0.24309148, 0.040939957, 0.07330434, 1 } + { 0.24309148, 0.040939957, 0.07330434, 0.8399939 } + { 0.24309148, 0.040939957, 0.07330434, 0 } + } + } + } + pass: i16 = -20 + alphaRef: u8 = 4 + miscRenderFlags: u8 = 1 + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 220, 170, 1 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.2, 1 } + values: list[vec3] = { + { 0.3, 0.3, 11 } + { 1, 1, 1 } + { 1.2, 1.2, 1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Aura_Self.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 2 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.35 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.8, 1.1 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 0.35 } + } + } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "Ray_DARK_BLACK" + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, -100, 0 } + } + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + primitive: pointer = VfxPrimitiveRay { } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.82389563, 0.13794155, 0.13794155, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.0927835, 0.18041237, 0.3530928, 0.5, 1 } + values: list[vec4] = { + { 1, 0.9411765, 0.72156864, 1 } + { 0.85156024, 0.6632029, 0.39346913, 1 } + { 0.82023346, 0.44835585, 0.27548638, 1 } + { 0.76092166, 0.124559395, 0.124559395, 1 } + { 0.33070877, 0.13925384, 0.19575799, 1 } + { 0.20851454, 0.08905165, 0.14770733, 1 } + } + } + } + pass: i16 = 50 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.55 } + values: list[f32] = { 0, 1 } + } + } + erosionSliceWidth: f32 = 1 + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Aatrox_Skin11_Einstein_04_mult.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + erosionMapAddressMode: u8 = 0 + } + miscRenderFlags: u8 = 1 + isDirectionOriented: flag = true + isRandomStartFrame: flag = true + isRotationEnabled: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { -90, 0, 360 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 1, 1 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1.5 } + } + } + times: list[f32] = { 0 } + values: list[vec3] = { { -90, 0, 360 } } + } + } + directionVelocityScale: f32 = 1 + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 100, 120, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1.1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.65, 1.1 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 100, 120, 0 } } + } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 1, 1, 1.2 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.1, 1 } + values: list[vec3] = { + { 0, 0, 0 } + { 1, 2, 0 } + { 1, 3, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Aatrox_Skin11_Particles_2_78.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.1 + } + particleLinger: option[f32] = { 0.6 } + lifetime: option[f32] = { 0.7 } + isSingleParticle: flag = true + emitterName: string = "DarkSwipe" + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, -200, 0 } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 3, 3, 3 } + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.90559244, 0.10394446, 0.10394446, 0.7019608 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 1 } + values: list[vec4] = { + { 0.939971, 0.8281071, 0.589868, 1 } + { 0.90952927, 0.6944381, 0.40538645, 1 } + { 0.3040818, 0.14012359, 0.14717327, 0 } + } + } + } + pass: i16 = 5 + alphaRef: u8 = 0 + miscRenderFlags: u8 = 1 + particleIsLocalOrientation: flag = true + isDirectionOriented: flag = true + isRotationEnabled: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 0, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 120, 150, 0 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.1, 1 } + values: list[vec3] = { + { 0, 0, 0 } + { 1, 1, 1 } + { 0, 1, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Aura_Self.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 4 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.1 + } + lifetime: option[f32] = { 0.2 } + isSingleParticle: flag = true + emitterName: string = "circleflare_blend" + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 0, 1, 0 } + } + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + particleColorTexture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/common_color-bellcurve.Zaahen.tex" + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.9077897, 0.13917755, 0.12216373, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.06652807, 0.1964657, 0.38253638, 0.6486486, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0.47272727 } + { 1, 1, 1, 0.21212122 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = 50 + meshRenderFlags: u8 = 0 + alphaRef: u8 = 0 + miscRenderFlags: u8 = 1 + isRandomStartFrame: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 40, 100, 200 } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Thresh_Skin28_Q_Impact_04.Zaahen.tex" + numFrames: u16 = 4 + texDiv: vec2 = { 2, 2 } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 2 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.2 + } + lifetime: option[f32] = { 0.2 } + isSingleParticle: flag = true + emitterName: string = "circleflare_blend2" + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 0, 1, 0 } + } + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + particleColorTexture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/common_color-bellcurve.Zaahen.tex" + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.92841995, 0.46456093, 0.4678874, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 0.5, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 0.85265887, 0.27139696, 0.27139696, 1 } + { 0.7837034, 0.09224079, 0.09224079, 0 } + } + } + } + pass: i16 = -25 + meshRenderFlags: u8 = 0 + alphaRef: u8 = 0 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + constantValue: f32 = 0 + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0.4, 1 } + values: list[f32] = { 0, 0 } + } + } + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Nebula_Streak_Mult_Vertical.Zaahen.tex" + } + miscRenderFlags: u8 = 1 + isRandomStartFrame: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 20, 100, 200 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.25, 1 } + values: list[vec3] = { + { 1, 1, 0 } + { 1, 1, 1 } + { 1, 1, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Thresh_Skin28_Q_Impact_04.Zaahen.tex" + numFrames: u16 = 4 + texDiv: vec2 = { 2, 2 } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 4 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.4 + } + lifetime: option[f32] = { 0.2 } + isSingleParticle: flag = true + emitterName: string = "circleflare_blend3" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + particleColorTexture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/common_color-bellcurve.Zaahen.tex" + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.17181659, 0.07031357, 0.067200735, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.06652807, 0.1964657, 0.38253638, 0.6486486, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0.47272727 } + { 1, 1, 1, 0.21212122 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = -50 + meshRenderFlags: u8 = 0 + alphaRef: u8 = 0 + isUniformScale: flag = true + isRandomStartFrame: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 1, 360, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 1, 0, 0 } } + } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 40, 200, 200 } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 1.5, 1, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.08212058, 0.17525057, 1 } + values: list[vec3] = { + { 0, 1, 1 } + { 2.4626865, 0.9178794, 0.9178794 } + { 3.1791046, 0.8247494, 0.8247494 } + { 4.5, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Thresh_Skin28_Q_Impact_04.Zaahen.tex" + numFrames: u16 = 4 + texDiv: vec2 = { 2, 2 } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 2 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.3 + } + particleLinger: option[f32] = { 10.2 } + lifetime: option[f32] = { 1.05 } + isSingleParticle: flag = true + emitterName: string = "flash_Mult" + importance: u8 = 3 + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 1, 1, 0.51999694 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.0927835, 0.18041237, 0.3530928, 0.5, 1 } + values: list[vec4] = { + { 0.9491264, 0.5418326, 0.4489662, 0 } + { 0.88844126, 0.2568704, 0.23878844, 0.14901961 } + { 0.88485545, 0.083054855, 0.08879225, 1 } + { 0.76092166, 0.124559395, 0.124559395, 1 } + { 0.33070877, 0.13925384, 0.19575799, 1 } + { 0.20999466, 0.08999771, 0.14999619, 0 } + } + } + } + pass: i16 = -1 + miscRenderFlags: u8 = 1 + isUniformScale: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 1, 0, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 1, 0, 0 } } + } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 100, 2, 2 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 1, 1, 1 } + { 0.3, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Aura_Self.Zaahen.tex" + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.05 + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.3 + } + particleLinger: option[f32] = { 10.2 } + lifetime: option[f32] = { 1.05 } + isSingleParticle: flag = true + emitterName: string = "flash_Mult1" + importance: u8 = 3 + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.9125353, 0.054703593, 0.08545052, 1 } + } + Color: embed = ValueColor { + constantValue: vec4 = { 1, 1, 1, 0.7000076 } + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.5, 1 } + values: list[vec4] = { + { 1, 1, 1, 0.7000076 } + { 1, 1, 1, 0.7000076 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = -1 + miscRenderFlags: u8 = 1 + isUniformScale: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 1, 0, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 1, 0, 0 } } + } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 230, 2, 2 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 1, 1, 1 } + { 0.3, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/JarvanIV_Skin35_R_glow.Zaahen.tex" + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.1 + rate: embed = ValueFloat { + constantValue: f32 = 10 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.35 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.2, 1.5 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 0.35 } + } + } + particleLinger: option[f32] = { 1 } + lifetime: option[f32] = { 0.3 } + isSingleParticle: flag = true + emitterName: string = "Embers" + birthOrbitalVelocity: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 0, 0 } } + } + } + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 1000, 1000, 1000 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.2, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 1000, 1000, 1000 } } + } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 5, 5, 5 } + } + worldAcceleration: embed = IntegratedValueVector3 { + constantValue: vec3 = { 0, 300, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.75, 1.25 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 300, 0 } } + } + } + bindWeight: embed = ValueFloat { + constantValue: f32 = 0.1 + } + SpawnShape: pointer = VfxShapeBox { + flags: u8 = 1 + Size: vec3 = { 10, 10, 10 } + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, -25, 0 } + } + blendMode: u8 = 5 + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 0.3, 0.6, 1 } + values: list[vec4] = { + { 0.9411765, 0.06666667, 0.07450981, 0 } + { 0.9411765, 0.06666667, 0.07450981, 1 } + { 0.9411765, 0.06666667, 0.07450981, 1 } + { 0.23137255, 0, 0.015686275, 1 } + { 0.23137255, 0, 0.015686275, 0 } + } + } + } + pass: i16 = 10 + miscRenderFlags: u8 = 1 + isDirectionOriented: flag = true + isUniformScale: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 1, 0, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 1, 0, 0 } } + } + } + birthRotationalVelocity0: embed = ValueVector3 { + constantValue: vec3 = { 300, 0, 0 } + } + directionVelocityScale: f32 = 0.004 + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 30, 60, 50 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.2, 1 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 30, 60, 50 } } + } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.1, 0.13, 0.4, 0.5, 1 } + values: list[vec3] = { + { 0, 0, 0 } + { 1.2, 1, 1 } + { 1, 1, 1 } + { 1, 0.5, 1 } + { 1, 0.5, 1 } + { 0, 0, 1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Morgana_Base_P_StardustMoteAlpha.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 8 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.4 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.65, 1 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 0.4 } + } + } + particleLinger: option[f32] = { } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "Smoke_Burst" + importance: u8 = 3 + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 1200, 1000, 1200 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.3, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 1200, 1000, 1200 } } + } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 8, 8, 8 } + } + worldAcceleration: embed = IntegratedValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 0, 0 } } + } + } + SpawnShape: pointer = VfxShapeBox { + flags: u8 = 1 + Size: vec3 = { 10, 10, 10 } + } + primitive: pointer = VfxPrimitiveArbitraryQuad { } + blendMode: u8 = 1 + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.2, 0.5, 1 } + values: list[vec4] = { + { 0.9520409, 0.5544671, 0.5569238, 0 } + { 0.77254903, 0.13725491, 0.14117648, 1 } + { 0.22000457, 0, 0.05070573, 0.43137255 } + { 0.13698024, 0.0508278, 0.073121235, 0 } + } + } + } + pass: i16 = 10 + alphaRef: u8 = 0 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.25633293, 0.6982072, 1 } + values: list[f32] = { 0, 0, 0.2, 0.5 } + } + } + erosionFeatherOut: f32 = 0.2 + erosionSliceWidth: f32 = 2 + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Emote_Flames_02.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + depthBiasFactors: vec2 = { -1, -15 } + disableBackfaceCull: bool = true + miscRenderFlags: u8 = 1 + isDirectionOriented: flag = true + isRandomStartFrame: flag = true + isGroundLayer: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, -90, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 90, -90, 0 } } + } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 160, 120, 100 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.8, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.8, 1 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 160, 120, 100 } } + } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 0.5, 0.5, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.2, 0.5, 1 } + values: list[vec3] = { + { 0.25, 0.3, 0.8 } + { 0.325, 0.375, 0.75 } + { 0.5, 0.55, 1 } + { 0.45, 0.65, 1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Shapes02.Zaahen.tex" + numFrames: u16 = 4 + texDiv: vec2 = { 2, 2 } + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.05 + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.1 + } + particleLinger: option[f32] = { 10.55 } + lifetime: option[f32] = { 0.2 } + isSingleParticle: flag = true + emitterName: string = "VerticalBlack" + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 100, 1000, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.2, 1 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 100, 1000, 0 } } + } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 6, 6, 6 } + } + worldAcceleration: embed = IntegratedValueVector3 { + constantValue: vec3 = { 0, -10, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0 } + values: list[vec3] = { { 0, -10, 0 } } + } + } + SpawnShape: pointer = VfxShapeCylinder { + radius: f32 = 10 + } + FlexShapeDefinition: pointer = VfxFlexShapeDefinitionData { + scaleBirthScaleByBoundObjectSize: f32 = 0.005 + } + primitive: pointer = VfxPrimitiveRay { } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 1, 1, 0.5019608 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.2, 0.5, 1 } + values: list[vec4] = { + { 0.9520409, 0.5544671, 0.5569238, 0 } + { 0.77254903, 0.13725491, 0.14117648, 1 } + { 0.22000457, 0, 0.05070573, 0.43137255 } + { 0.13698024, 0.0508278, 0.073121235, 0 } + } + } + } + pass: i16 = 6 + colorLookUpTypeY: u8 = 3 + alphaRef: u8 = 15 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.3, 1 } + values: list[f32] = { 0, 0, 1 } + } + } + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Garen_Skin24_BA_ErosionShapes01.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + miscRenderFlags: u8 = 1 + isDirectionOriented: flag = true + isRandomStartFrame: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { -90, 0, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 180, 750, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.6, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 180, 750, 1 } } + } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 0.75, 0.75, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 0.75, 0.75, 1 } + { 0.6, 0.75, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Shapes02.Zaahen.tex" + numFrames: u16 = 4 + texDiv: vec2 = { 2, 2 } + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.05 + rate: embed = ValueFloat { + constantValue: f32 = 2 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.3 + } + particleLinger: option[f32] = { 10.55 } + lifetime: option[f32] = { 0.2 } + isSingleParticle: flag = true + emitterName: string = "VerticalColumn" + importance: u8 = 3 + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 100, 1000, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.2, 1 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 100, 1000, 0 } } + } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 6, 6, 6 } + } + worldAcceleration: embed = IntegratedValueVector3 { + constantValue: vec3 = { 0, -10, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0 } + values: list[vec3] = { { 0, -10, 0 } } + } + } + SpawnShape: pointer = VfxShapeCylinder { + radius: f32 = 10 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, -150, 0 } + } + FlexShapeDefinition: pointer = VfxFlexShapeDefinitionData { + scaleBirthScaleByBoundObjectSize: f32 = 0.005 + } + primitive: pointer = VfxPrimitiveRay { } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.77000076, 0.14000152, 0.14000152, 0.8299992 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.2, 0.75, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 0.8697795, 0.13975738, 0.13975738, 1 } + { 0.22000457, 0, 0.05070573, 0.43137255 } + { 0.13698024, 0.0508278, 0.073121235, 0 } + } + } + } + pass: i16 = 1 + colorLookUpTypeY: u8 = 3 + alphaRef: u8 = 15 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.3, 1 } + values: list[f32] = { 0, 0, 1 } + } + } + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Garen_Skin24_BA_ErosionShapes01.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + miscRenderFlags: u8 = 1 + isDirectionOriented: flag = true + isRandomStartFrame: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { -90, 0, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 250, 650, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 250, 650, 1 } } + } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 1, 1, 1 } + { 0.8, 1, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Shapes02.Zaahen.tex" + numFrames: u16 = 4 + texDiv: vec2 = { 2, 2 } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.85 + } + particleLinger: option[f32] = { } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "StrokeDissolve_primary" + importance: u8 = 3 + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.88000304, 0.2, 0.2, 0.2899977 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.2, 0.8, 1 } + values: list[vec4] = { + { 0.80784315, 0.5137255, 0.42352942, 1 } + { 0.78431374, 0.101960786, 0, 1 } + { 0.78431374, 0.101960786, 0, 1 } + { 0.13725491, 0.007843138, 0.05882353, 1 } + } + } + } + pass: i16 = 5 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.55 } + values: list[f32] = { 0.15, 1 } + } + } + erosionSliceWidth: f32 = 1 + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Aatrox_Skin11_AA_Wall_Erosion.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + erosionMapAddressMode: u8 = 0 + } + disableBackfaceCull: bool = true + isUniformScale: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 360, 1, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 360, 1, 0 } } + } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 100, 120, 120 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.2, 1 } + values: list[vec3] = { + { 0.5, 0.25, 0.1 } + { 0.75, 0.75, 0.5 } + { 1, 1.2, 1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Aatrox_Skin11_AA_Flares_03.Zaahen.tex" + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.05 + rate: embed = ValueFloat { + constantValue: f32 = 2 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.3 + } + particleLinger: option[f32] = { 10.55 } + lifetime: option[f32] = { 0.2 } + isSingleParticle: flag = true + emitterName: string = "VerticalColumn1" + importance: u8 = 3 + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 100, 1000, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.2, 1 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 100, 1000, 0 } } + } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 6, 6, 6 } + } + worldAcceleration: embed = IntegratedValueVector3 { + constantValue: vec3 = { 0, -10, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0 } + values: list[vec3] = { { 0, -10, 0 } } + } + } + SpawnShape: pointer = VfxShapeCylinder { + radius: f32 = 10 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, -150, 0 } + } + FlexShapeDefinition: pointer = VfxFlexShapeDefinitionData { + scaleBirthScaleByBoundObjectSize: f32 = 0.005 + } + primitive: pointer = VfxPrimitiveRay { } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.40999466, 0.050003815, 0.050003815, 0.77000076 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.2, 0.5, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 0.22000457, 0, 0.05070573, 0.43137255 } + { 0.13698024, 0.0508278, 0.073121235, 0 } + } + } + } + pass: i16 = -50 + colorLookUpTypeY: u8 = 3 + alphaRef: u8 = 15 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.3, 1 } + values: list[f32] = { 0, 0, 1 } + } + } + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Garen_Skin24_BA_ErosionShapes01.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + miscRenderFlags: u8 = 1 + isDirectionOriented: flag = true + isRandomStartFrame: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { -90, 0, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 250, 650, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.75, 1 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 250, 650, 1 } } + } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 1.25, 1.25, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 1.25, 1.25, 1 } + { 1, 1.25, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Shapes02.Zaahen.tex" + numFrames: u16 = 4 + texDiv: vec2 = { 2, 2 } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 4 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.4 + } + lifetime: option[f32] = { 0.2 } + isSingleParticle: flag = true + emitterName: string = "circleflare_blend4" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + primitive: pointer = VfxPrimitiveArbitraryQuad { } + particleColorTexture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/common_color-bellcurve.Zaahen.tex" + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.17181659, 0.07031357, 0.067200735, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.06652807, 0.1964657, 0.38253638, 0.6486486, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0.47272727 } + { 1, 1, 1, 0.21212122 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = -50 + meshRenderFlags: u8 = 0 + alphaRef: u8 = 0 + isUniformScale: flag = true + isRandomStartFrame: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 0, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0 } + values: list[vec3] = { { 90, 0, 0 } } + } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 40, 200, 200 } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 2, 1, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.08212058, 0.17525057, 1 } + values: list[vec3] = { + { 0, 1, 1 } + { 3.283582, 0.9178794, 0.9178794 } + { 4.238806, 0.8247494, 0.8247494 } + { 6, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Thresh_Skin28_Q_Impact_04.Zaahen.tex" + numFrames: u16 = 4 + texDiv: vec2 = { 2, 2 } + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.05 + rate: embed = ValueFloat { + constantValue: f32 = 200 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.5 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 0.9, 1 } + keyValues: list[f32] = { 0.2, 1, 1.5 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 0.5 } + } + } + particleLinger: option[f32] = { 1 } + lifetime: option[f32] = { 0.1 } + emitterName: string = "Sparkles1" + birthOrbitalVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, 3, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 3, 0 } } + } + } + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 1000, 500, 1000 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1.1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 1000, 500, 1000 } } + } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 8, 2, 8 } + } + worldAcceleration: embed = IntegratedValueVector3 { + constantValue: vec3 = { 0, 200, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 200, 0 } } + } + } + SpawnShape: pointer = VfxShapeBox { + flags: u8 = 1 + Size: vec3 = { 50, 50, 50 } + } + blendMode: u8 = 4 + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 0.3, 0.6, 1 } + values: list[vec4] = { + { 0.928069, 0.8185092, 0.6716716, 0 } + { 0.91024643, 0.65159076, 0.65392536, 1 } + { 0.93354696, 0.4036927, 0.4084535, 1 } + { 0.9411765, 0.06666667, 0.07450981, 1 } + { 0.23137255, 0, 0.015686275, 0 } + } + } + } + pass: i16 = 10 + miscRenderFlags: u8 = 1 + isDirectionOriented: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 1, 0, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 1, 0, 0 } } + } + } + birthRotationalVelocity0: embed = ValueVector3 { + constantValue: vec3 = { -300, 0, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 25, 50, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.3, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 1, 2 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 25, 50, 0 } } + } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.1, 0.19223854, 0.37142858, 1 } + values: list[vec3] = { + { 0, 0, 0 } + { 1, 1, 1 } + { 0.21186441, 0.5, 0.5 } + { 0.56271183, 0.33380866, 0.33380866 } + { 0, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_R_Sparks.Zaahen.tex" + } + } + particleName: string = "Zaahen_Base_BA_Crit_Tar" + particlePath: string = "Characters/Zaahen/Skins/Skin0/Particles/Zaahen_Base_BA_Crit_Tar" + } + "Characters/Zaahen/Skins/Skin0/Particles/Zaahen_Base_BA_Tar_Child" = VfxSystemDefinitionData { + complexEmitterDefinitionData: list[pointer] = { + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.3 + } + particleLinger: option[f32] = { 10.3 } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "flash3" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + FlexShapeDefinition: pointer = VfxFlexShapeDefinitionData { + scaleBirthScaleByBoundObjectSize: f32 = 0.005 + scaleEmitOffsetByBoundObjectSize: f32 = 0.005 + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.8096742, 0.19507134, 0.1309224, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 0.50980395, 0.011764706, 0.101960786, 1 } + } + } + } + pass: i16 = 50 + alphaRef: u8 = 0 + miscRenderFlags: u8 = 1 + isUniformScale: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 1, 0, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 1, 0, 0 } } + } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 100, 100, 1 } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 3, 1.5, 2 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.3, 0.6, 1 } + values: list[vec3] = { + { 0, 0, 0 } + { 3, 1.5, 2 } + { 0.6, 0.3, 0.4 } + { 0, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Naafiri_Base_R_Flash_sharp.Zaahen.tex" + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.05 + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.3 + } + particleLinger: option[f32] = { 10.2 } + lifetime: option[f32] = { 1.05 } + isSingleParticle: flag = true + emitterName: string = "flash_Mult1" + importance: u8 = 3 + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.31302357, 0.013519494, 0.11020066, 1 } + } + Color: embed = ValueColor { + constantValue: vec4 = { 1, 1, 1, 0.7000076 } + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.5, 1 } + values: list[vec4] = { + { 1, 1, 1, 0.7000076 } + { 1, 1, 1, 0.7000076 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = -1 + miscRenderFlags: u8 = 1 + isUniformScale: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 1, 0, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 1, 0, 0 } } + } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 230, 2, 2 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 1, 1, 1 } + { 0.3, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/JarvanIV_Skin35_R_glow.Zaahen.tex" + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.1 + rate: embed = ValueFloat { + constantValue: f32 = 10 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.25 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.2, 1.5 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 0.25 } + } + } + particleLinger: option[f32] = { 1 } + lifetime: option[f32] = { 0.3 } + isSingleParticle: flag = true + emitterName: string = "Embers" + birthOrbitalVelocity: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 0, 0 } } + } + } + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { -2000, 0, -1000 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.2, 1 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.2, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec3] = { { -2000, 0, -1000 } } + } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 2.5, 1, 2.5 } + } + birthAcceleration: embed = ValueVector3 { + constantValue: vec3 = { 0, -100, 0 } + } + worldAcceleration: embed = IntegratedValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.75, 1.25 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 0, 0 } } + } + } + bindWeight: embed = ValueFloat { + constantValue: f32 = 0.1 + } + SpawnShape: pointer = VfxShapeBox { + flags: u8 = 1 + Size: vec3 = { 10, 10, 10 } + } + blendMode: u8 = 5 + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 0.3, 0.6, 1 } + values: list[vec4] = { + { 0.9411765, 0.06666667, 0.07450981, 0 } + { 0.9411765, 0.06666667, 0.07450981, 1 } + { 0.9411765, 0.06666667, 0.07450981, 1 } + { 0.23137255, 0, 0.015686275, 1 } + { 0.23137255, 0, 0.015686275, 0 } + } + } + } + pass: i16 = 10 + miscRenderFlags: u8 = 1 + isDirectionOriented: flag = true + isUniformScale: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 1, 0, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 1, 0, 0 } } + } + } + birthRotationalVelocity0: embed = ValueVector3 { + constantValue: vec3 = { 300, 0, 0 } + } + directionVelocityScale: f32 = 0.004 + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 30, 60, 50 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.2, 1 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 30, 60, 50 } } + } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.1, 0.13, 0.4, 0.5, 1 } + values: list[vec3] = { + { 0, 0, 0 } + { 1.2, 1, 1 } + { 1, 1, 1 } + { 1, 0.5, 1 } + { 1, 0.5, 1 } + { 0, 0, 1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Morgana_Base_P_StardustMoteAlpha.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 5 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.25 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.4, 0.75 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 0.25 } + } + } + lifetime: option[f32] = { 0.98 } + isSingleParticle: flag = true + emitterName: string = "SolidBeams2" + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { -2000, 0, -1000 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.2, 1 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.2, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec3] = { { -2000, 0, -1000 } } + } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 5, 1, 5 } + } + birthAcceleration: embed = ValueVector3 { + constantValue: vec3 = { 0, -100, 0 } + } + worldAcceleration: embed = IntegratedValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.75, 1.25 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 0, 0 } } + } + } + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + SpawnShape: pointer = VfxShapeBox { + flags: u8 = 1 + Size: vec3 = { 10, 10, 10 } + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.9034714, 0.38281834, 0.38281834, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.3, 1 } + values: list[vec4] = { + { 1, 0.84705883, 0.5411765, 0 } + { 0.9019608, 0.74509805, 0.5411765, 1 } + { 0.8715038, 0.16140993, 0.08235294, 0.45882353 } + } + } + } + pass: i16 = 55 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + constantValue: f32 = 0 + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 1 } + values: list[f32] = { 0, 0 } + } + } + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/AlphaSlice_bubbles_02.Zaahen.tex" + } + miscRenderFlags: u8 = 1 + isDirectionOriented: flag = true + isRandomStartFrame: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 1, 1, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 1, 1, 0 } } + } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 13, 18, 38 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1.5 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 13, 18, 38 } } + } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.2, 0.75, 1 } + values: list[vec3] = { + { 0, 0, 0 } + { 5, 3, 0 } + { 4, 5, 1 } + { 0, 7, 1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/JarvanIV_Skin35_bolts_HitEffect_Physical_S_01.Zaahen.tex" + numFrames: u16 = 4 + texDiv: vec2 = { 4, 1 } + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.05 + rate: embed = ValueFloat { + constantValue: f32 = 5 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 1 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 0.85, 1 } + keyValues: list[f32] = { 0.4, 0.6, 0.9 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 1 } + } + } + particleLinger: option[f32] = { 2 } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "DustSpikes2" + SpawnShape: pointer = VfxShapeCylinder { + radius: f32 = 10 + height: f32 = 10 + } + primitive: pointer = VfxPrimitiveRay { } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.57019913, 0.09764248, 0.18066682, 0.47058824 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.2, 0.5, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 0.22000457, 0, 0.05070573, 0.43137255 } + { 0.13698024, 0.0508278, 0.073121235, 0 } + } + } + } + alphaRef: u8 = 50 + censorModulateValue: vec4 = { 0.3, 1, 1, 0.988 } + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.25633293, 0.6982072, 1 } + values: list[f32] = { 0, 0, 0.2, 0.5 } + } + } + erosionFeatherOut: f32 = 0.2 + erosionSliceWidth: f32 = 2 + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Emote_Flames_02.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + isRandomStartFrame: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 1, 1, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -10, 0 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -160, -100 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 1, 1, 1 } } + } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 15, 50, 70 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.75, 1.4 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 0.2, 0.8, 1 } + keyValues: list[f32] = { 0.3, 0.6, 1, 1 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 15, 50, 70 } } + } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 0.5, 0.5, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.2, 0.85, 1 } + values: list[vec3] = { + { 1, 0, 0 } + { 2.5, 2.75, 0 } + { 3, 2.875, 1 } + { 3.25, 3, 1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Shapes02.Zaahen.tex" + birthFrameRate: embed = ValueFloat { + constantValue: f32 = 0 + } + numFrames: u16 = 4 + texDiv: vec2 = { 4, 2 } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.3 + } + particleLinger: option[f32] = { 10.2 } + lifetime: option[f32] = { 1 } + emitterName: string = "Background" + FlexShapeDefinition: pointer = VfxFlexShapeDefinitionData { + scaleEmitOffsetByBoundObjectSize: f32 = 0.005 + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 1, 1, 0.9799954 } + } + Color: embed = ValueColor { + constantValue: vec4 = { 0.24309148, 0.040939957, 0.07330434, 1 } + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.3, 1 } + values: list[vec4] = { + { 0.24309148, 0.040939957, 0.07330434, 1 } + { 0.24309148, 0.040939957, 0.07330434, 0.8399939 } + { 0.24309148, 0.040939957, 0.07330434, 0 } + } + } + } + pass: i16 = -20 + alphaRef: u8 = 4 + miscRenderFlags: u8 = 1 + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 220, 170, 1 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.2, 1 } + values: list[vec3] = { + { 0.3, 0.3, 11 } + { 1, 1, 1 } + { 1.2, 1.2, 1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Aura_Self.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.85 + } + particleLinger: option[f32] = { } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "StrokeDissolve_primary" + importance: u8 = 3 + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.88000304, 0.2, 0.2, 0.2899977 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.2, 0.8, 1 } + values: list[vec4] = { + { 0.80784315, 0.5137255, 0.42352942, 1 } + { 0.78431374, 0.101960786, 0, 1 } + { 0.78431374, 0.101960786, 0, 1 } + { 0.13725491, 0.007843138, 0.05882353, 1 } + } + } + } + pass: i16 = 5 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.55 } + values: list[f32] = { 0.15, 1 } + } + } + erosionSliceWidth: f32 = 1 + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Aatrox_Skin11_AA_Wall_Erosion.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + erosionMapAddressMode: u8 = 0 + } + disableBackfaceCull: bool = true + isUniformScale: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 360, 1, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 360, 1, 0 } } + } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 100, 120, 120 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.2, 1 } + values: list[vec3] = { + { 0.5, 0.25, 0.1 } + { 0.75, 0.75, 0.5 } + { 1, 1.2, 1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Aatrox_Skin11_AA_Flares_03.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 2 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.5 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.8, 1.1 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 0.5 } + } + } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "Ray_DARK_BLACK" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + primitive: pointer = VfxPrimitiveRay { } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.9034714, 0.38281834, 0.38281834, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.0927835, 0.18041237, 0.3530928, 0.5, 1 } + values: list[vec4] = { + { 1, 0.7792477, 0.72156864, 1 } + { 0.85156024, 0.48874646, 0.39346913, 1 } + { 0.82023346, 0.3443961, 0.27548638, 1 } + { 0.76092166, 0.124559395, 0.124559395, 1 } + { 0.33070877, 0.13925384, 0.19575799, 1 } + { 0.20851454, 0.08905165, 0.14770733, 1 } + } + } + } + pass: i16 = 50 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + } + times: list[f32] = { 0, 0.55 } + values: list[f32] = { 0, 1 } + } + } + erosionSliceWidth: f32 = 1 + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Aatrox_Skin11_Einstein_04_mult.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + erosionMapAddressMode: u8 = 0 + } + miscRenderFlags: u8 = 1 + isDirectionOriented: flag = true + isRandomStartFrame: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 0, -115, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 1.5, 0.8 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, -115, 0 } } + } + } + directionVelocityScale: f32 = 1 + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 100, 120, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1.1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.65, 1.1 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 100, 120, 0 } } + } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 0.75, 0.75, 1.2 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.1, 1 } + values: list[vec3] = { + { 0, 0, 0 } + { 0.75, 1.5, 0 } + { 0.75, 2.25, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Aatrox_Skin11_Particles_2_78.Zaahen.tex" + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.1 + rate: embed = ValueFloat { + constantValue: f32 = 7 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.5 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 0.9, 1 } + keyValues: list[f32] = { 0.2, 1, 1.5 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 0.5 } + } + } + particleLinger: option[f32] = { 1 } + lifetime: option[f32] = { 0.3 } + isSingleParticle: flag = true + emitterName: string = "Sparkles" + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 555, 1, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 0.85 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.75, 1.1 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 555, 1, 0 } } + } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 8, 8, 8 } + } + worldAcceleration: embed = IntegratedValueVector3 { + constantValue: vec3 = { 0, 200, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 200, 0 } } + } + } + SpawnShape: pointer = VfxShapeLegacy { + emitOffset: embed = ValueVector3 { + constantValue: vec3 = { 100, 0, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.2, 1 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 100, 0, 0 } } + } + } + emitRotationAngles: list[embed] = { + ValueFloat { + constantValue: f32 = 1 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 1 } + } + } + ValueFloat { + constantValue: f32 = 1 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 1 } + } + } + } + emitRotationAxes: list[vec3] = { + { 0, 1.0000001, 0 } + { 0, 0, 1.0000001 } + } + } + blendMode: u8 = 5 + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 0.3, 0.6, 1 } + values: list[vec4] = { + { 0.9411765, 0.06666667, 0.07450981, 0 } + { 0.9411765, 0.06666667, 0.07450981, 1 } + { 0.9411765, 0.06666667, 0.07450981, 1 } + { 0.23137255, 0, 0.015686275, 1 } + { 0.23137255, 0, 0.015686275, 0 } + } + } + } + pass: i16 = 10 + miscRenderFlags: u8 = 1 + isUniformScale: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 1, 0, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 1, 0, 0 } } + } + } + birthRotationalVelocity0: embed = ValueVector3 { + constantValue: vec3 = { -300, 0, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 50, 65, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 0.9, 1 } + keyValues: list[f32] = { 0.3, 1, 2 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 50, 65, 0 } } + } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.1, 0.19223854, 0.37142858, 1 } + values: list[vec3] = { + { 0, 0, 0 } + { 1, 1, 1 } + { 0.21186441, 0.5, 0.5 } + { 0.56271183, 0.33380866, 0.33380866 } + { 0, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Morgana_Base_P_StardustMoteAlpha.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 2 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.2 + } + particleLinger: option[f32] = { 0.6 } + lifetime: option[f32] = { 0.7 } + isSingleParticle: flag = true + emitterName: string = "DarkSwipe2" + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { -1200, 0, -800 } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 3, 4, 4 } + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 30, 0, 20 } + } + blendMode: u8 = 5 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 1, 1, 0.7019608 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 1 } + values: list[vec4] = { + { 0.939971, 0.8281071, 0.589868, 1 } + { 0.90952927, 0.55536735, 0.40538645, 1 } + { 0.25177386, 0.0944686, 0.10122835, 0 } + } + } + } + pass: i16 = 5 + alphaRef: u8 = 0 + miscRenderFlags: u8 = 1 + particleIsLocalOrientation: flag = true + isDirectionOriented: flag = true + isRotationEnabled: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 0, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 80, 150, 0 } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 0.5, 0.5, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.1, 1 } + values: list[vec3] = { + { 0, 0, 0 } + { 0.5, 0.5, 1 } + { 0, 0.5, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Skin_06_Spark_Vertical.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.1 + } + particleLinger: option[f32] = { 0.6 } + lifetime: option[f32] = { 0.7 } + isSingleParticle: flag = true + emitterName: string = "DarkSwipe4" + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { -1200, 0, -400 } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 3, 4, 4 } + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 30, 0, 20 } + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 1, 1, 0.7019608 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 1 } + values: list[vec4] = { + { 0.939971, 0.8281071, 0.589868, 1 } + { 0.90952927, 0.6944381, 0.40538645, 1 } + { 0.3040818, 0.14012359, 0.14717327, 0 } + } + } + } + pass: i16 = 5 + alphaRef: u8 = 0 + miscRenderFlags: u8 = 1 + particleIsLocalOrientation: flag = true + isDirectionOriented: flag = true + isRotationEnabled: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 0, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 120, 150, 0 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.1, 1 } + values: list[vec3] = { + { 0, 0, 0 } + { 1, 1, 1 } + { 0, 1, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Aura_Self.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.3 + } + particleLinger: option[f32] = { 10.3 } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "flash14" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + FlexShapeDefinition: pointer = VfxFlexShapeDefinitionData { + scaleBirthScaleByBoundObjectSize: f32 = 0.005 + scaleEmitOffsetByBoundObjectSize: f32 = 0.005 + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.9061265, 0.9061265, 0.9061265, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 1 } + values: list[vec4] = { + { 0.8844129, 0.7690547, 0.5053635, 1 } + { 0.50980395, 0.011764706, 0.101960786, 1 } + } + } + } + pass: i16 = 55 + alphaRef: u8 = 0 + miscRenderFlags: u8 = 1 + isUniformScale: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 1, 0, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 1, 0, 0 } } + } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 75, 100, 1 } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 1, 1.5, 2 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.3, 0.6, 1 } + values: list[vec3] = { + { 0, 0, 0 } + { 1, 1.5, 2 } + { 0.2, 0.3, 0.4 } + { 0, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Naafiri_Base_R_Flash_sharp.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 2 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.4 + } + lifetime: option[f32] = { 0.2 } + isSingleParticle: flag = true + emitterName: string = "circleflare_blend" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 12.815607, 0 } + } + particleColorTexture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/common_color-bellcurve.Zaahen.tex" + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.17181659, 0.07031357, 0.067200735, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.06652807, 0.1964657, 0.38253638, 0.6486486, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0.47272727 } + { 1, 1, 1, 0.21212122 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = -50 + meshRenderFlags: u8 = 0 + alphaRef: u8 = 0 + isUniformScale: flag = true + isRandomStartFrame: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 1, 0, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 1, 0, 0 } } + } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 40, 200, 200 } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 1.5, 1, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.08212058, 0.17525057, 1 } + values: list[vec3] = { + { 0, 1, 1 } + { 2.4626865, 0.9178794, 0.9178794 } + { 3.1791046, 0.8247494, 0.8247494 } + { 4.5, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Thresh_Skin28_Q_Impact_04.Zaahen.tex" + numFrames: u16 = 4 + texDiv: vec2 = { 2, 2 } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 2 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.1 + } + lifetime: option[f32] = { 0.2 } + isSingleParticle: flag = true + emitterName: string = "circleflare_blend1" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 12.815607, 0 } + } + particleColorTexture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/common_color-bellcurve.Zaahen.tex" + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.91340506, 0.8514229, 0.64872205, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.06652807, 0.1964657, 0.38253638, 0.6486486, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0.47272727 } + { 1, 1, 1, 0.21212122 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = -50 + meshRenderFlags: u8 = 0 + alphaRef: u8 = 0 + isUniformScale: flag = true + isRandomStartFrame: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 1, 0, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 1, 0, 0 } } + } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 40, 200, 200 } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 1.5, 1, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.08212058, 0.17525057, 1 } + values: list[vec3] = { + { 0, 1, 1 } + { 2.4626865, 0.9178794, 0.9178794 } + { 3.1791046, 0.8247494, 0.8247494 } + { 4.5, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Thresh_Skin28_Q_Impact_04.Zaahen.tex" + numFrames: u16 = 4 + texDiv: vec2 = { 2, 2 } + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.05 + rate: embed = ValueFloat { + constantValue: f32 = 5 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 1 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 0.85, 1 } + keyValues: list[f32] = { 0.4, 0.6, 0.9 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 1 } + } + } + particleLinger: option[f32] = { 2 } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "DustSpikes4" + SpawnShape: pointer = VfxShapeCylinder { + radius: f32 = 10 + height: f32 = 10 + } + primitive: pointer = VfxPrimitiveRay { } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.77254903, 0.13725491, 0.1419089, 0.47058824 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.2, 0.5, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 0.22000457, 0, 0.05070573, 0.43137255 } + { 0.13698024, 0.0508278, 0.073121235, 0 } + } + } + } + alphaRef: u8 = 50 + censorModulateValue: vec4 = { 0.3, 1, 1, 0.988 } + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.25633293, 0.6982072, 1 } + values: list[f32] = { 0, 0, 0.2, 0.5 } + } + } + erosionFeatherOut: f32 = 0.2 + erosionSliceWidth: f32 = 2 + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Emote_Flames_02.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + isRandomStartFrame: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 0, -125, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 15, 85, 70 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.75, 1.4 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 0.2, 0.8, 1 } + keyValues: list[f32] = { 0.3, 0.6, 1, 1.2 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 15, 85, 70 } } + } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 0.5, 0.5, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.2, 0.85, 1 } + values: list[vec3] = { + { 1, 0, 0 } + { 2.5, 2.75, 0 } + { 3, 2.875, 1 } + { 3.25, 3, 1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Shapes02.Zaahen.tex" + birthFrameRate: embed = ValueFloat { + constantValue: f32 = 0 + } + numFrames: u16 = 4 + texDiv: vec2 = { 4, 2 } + } + } + particleName: string = "Zaahen_Base_BA_Tar_Child" + particlePath: string = "Characters/Zaahen/Skins/Skin0/Particles/Zaahen_Base_BA_Tar_Child" + } + "Characters/Zaahen/Skins/Skin0/Particles/Zaahen_Base_Q_2_Warning" = VfxSystemDefinitionData { + complexEmitterDefinitionData: list[pointer] = { + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 20 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.5 + } + emitterName: string = "Basic" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + FlexShapeDefinition: pointer = VfxFlexShapeDefinitionData { + scaleBirthScaleByBoundObjectSize: f32 = 0.01 + scaleEmitOffsetByBoundObjectSize: f32 = 0.01 + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.6, 0.4899977, 0.22999924, 0.19000535 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.4, 0.7, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = 20 + alphaRef: u8 = 0 + 0xcb13aff1: f32 = -40 + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 360, 0, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 360, 0, 0 } } + } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 20, 20, 0 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 1, 1, 0 } + { 4, 1, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/BrightGlow.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 10 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 1 + } + emitterName: string = "Basic1" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + FlexShapeDefinition: pointer = VfxFlexShapeDefinitionData { + scaleBirthScaleByBoundObjectSize: f32 = 0.01 + scaleEmitOffsetByBoundObjectSize: f32 = 0.01 + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0, 0.1600061, 0.59000534, 0.10000763 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.4682324, 0.5354759, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 0.99019605 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = 10 + alphaRef: u8 = 0 + softParticleParams: pointer = VfxSoftParticleDefinitionData { + beginOut: f32 = 0.1 + deltaIn: f32 = 0.5 + deltaOut: f32 = 1 + } + 0xcb13aff1: f32 = -40 + isUniformScale: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 100, 10, 0 } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Aura_Self.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 5 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 1 + } + emitterName: string = "Basic4" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + FlexShapeDefinition: pointer = VfxFlexShapeDefinitionData { + scaleBirthScaleByBoundObjectSize: f32 = 0.01 + scaleEmitOffsetByBoundObjectSize: f32 = 0.01 + } + blendMode: u8 = 2 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.23137255, 0.6, 0.6, 0.1882353 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 0.8, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = -100 + alphaRef: u8 = 0 + 0xcb13aff1: f32 = -40 + isUniformScale: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 50, 10, 0 } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Aura_Self.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 150 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.15 + } + emitterName: string = "GOLD_LightGlow" + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, 125 } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, 0.5 } + } + primitive: pointer = VfxPrimitiveCameraTrail { + mTrail: embed = VfxTrailDefinitionData { + mMode: u8 = 1 + mBirthTilingSize: embed = ValueVector3 { + constantValue: vec3 = { 800, 0, 0 } + } + mSmoothingMode: u8 = 1 + } + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 1, 1, 0.34901962 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 0.8, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 0.9254902, 0.7607843, 0.4745098, 1 } + { 0.5600061, 0.41855496, 0.17264058, 0.53333336 } + { 0.16159303, 0.10722515, 0.12523079, 0 } + } + } + } + pass: i16 = -15 + alphaRef: u8 = 0 + useNavmeshMask: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 55, 2, 2 } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 0.8, 0.8, 0.8 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.07960199, 0.14004976, 0.39546493, 0.77527076, 1 } + values: list[vec3] = { + { 0.32000002, 0.32000002, 0.32000002 } + { 0.71999997, 0.71999997, 0.71999997 } + { 0.7961644, 0.7961644, 0.7961644 } + { 0.72706515, 0.7961644, 0.7961644 } + { 0.3814612, 0.4, 0.4 } + { 0.24000001, 0.24000001, 0.24000001 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/common_color-bellcurve32.Zaahen.tex" + uvRotation: embed = ValueFloat { + constantValue: f32 = 90 + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 2 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = -1 + } + isSingleParticle: flag = true + emitterName: string = "blackOrb_main1" + importance: u8 = 3 + IsEmitterSpace: flag = true + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { -5, 0, 0 } + } + primitive: pointer = VfxPrimitiveArbitraryQuad { } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.9254902, 0.7607843, 0.4745098, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.44, 0.50064516 } + values: list[vec4] = { + { 0.59607846, 0.59607846, 0.59607846, 1 } + { 0.8509804, 0.8509804, 0.8509804, 1 } + { 1, 1, 1, 1 } + } + } + } + pass: i16 = 100 + alphaRef: u8 = 0 + 0xcb13aff1: f32 = -40 + particleIsLocalOrientation: flag = true + isUniformScale: flag = true + isRotationEnabled: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 0, 90, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 7, 1, 1 } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Udyr_Base_VGU_GlowMask_Thicc.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 5 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.5 + } + emitterName: string = "Basic7" + importance: u8 = 3 + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { -5, 0, 0 } + } + FlexShapeDefinition: pointer = VfxFlexShapeDefinitionData { + scaleBirthScaleByBoundObjectSize: f32 = 0.01 + scaleEmitOffsetByBoundObjectSize: f32 = 0.01 + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.5499962, 0.42000458, 0.11999695, 0.4500038 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 1 } + values: list[vec4] = { + { 0.9292134, 0.8355535, 0.61007094, 0 } + { 0.88000304, 0.7499962, 0.4500038, 1 } + { 0.20909438, 0.15808347, 0.03527886, 0 } + } + } + } + pass: i16 = 10 + alphaRef: u8 = 0 + 0xcb13aff1: f32 = -40 + isUniformScale: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 360, 0, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 360, 0, 0 } } + } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 50, 10, 0 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 0, 1, 1 } + { 1, 1, 1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Tryndamere_Skin18_Impact_Burst.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 5 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.4 + } + emitterName: string = "flash" + importance: u8 = 3 + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { -5, 0, 0 } + } + FlexShapeDefinition: pointer = VfxFlexShapeDefinitionData { + scaleBirthScaleByBoundObjectSize: f32 = 0.005 + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 1, 1, 0.5000076 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 0.3, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 0.79681087, 0.6157626, 0.2843824, 0.8509804 } + { 0.38844892, 0.077149615, 0.077149615, 0 } + } + } + } + pass: i16 = 5000 + alphaRef: u8 = 0 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + constantValue: f32 = 0 + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 1 } + values: list[f32] = { 0, 0 } + } + } + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Darius_Skin43_Star_Flash.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + 0xcb13aff1: f32 = -40 + isRandomStartFrame: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 1, 0, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 1, 0, 0 } } + } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 35, 35, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.75, 2 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.75, 2 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 35, 35, 1 } } + } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 0.5, 0.5, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.2, 1 } + values: list[vec3] = { + { 0.1, 0.1, 0.2 } + { 0.5, 0.5, 1 } + { 1.5, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Darius_Skin43_Star_Flash.Zaahen.tex" + } + } + particleName: string = "Zaahen_Base_Q_2_Warning" + particlePath: string = "Characters/Zaahen/Skins/Skin0/Particles/Zaahen_Base_Q_2_Warning" + soundPersistentDefault: string = "Play_sfx_Zaahen_ZaahenQ2_warning_buffactivate" + flags: u16 = 1236 + } + "Characters/Zaahen/Skins/Skin0/Particles/Zaahen_Base_Emote_Taunt_Trail" = VfxSystemDefinitionData { + complexEmitterDefinitionData: list[pointer] = { + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 100 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.25 + } + particleLinger: option[f32] = { 0.2 } + lifetime: option[f32] = { 1 } + rateByVelocityFunction: embed = ValueVector2 { + constantValue: vec2 = { 1, 0 } + } + emitterName: string = "Pantheon2" + importance: u8 = 3 + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 20, 0, 0 } + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, 10 } + } + primitive: pointer = VfxPrimitiveCameraTrail { + mTrail: embed = VfxTrailDefinitionData { + mMode: u8 = 1 + mBirthTilingSize: embed = ValueVector3 { + constantValue: vec3 = { 800, 0, 0 } + } + mSmoothingMode: u8 = 1 + } + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.47058824, 0.101960786, 0.10980392, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.4, 0.6, 1 } + values: list[vec4] = { + { 0.92941177, 0.08627451, 0.02745098, 0 } + { 0.6666667, 0, 0, 1 } + { 0.39215687, 0, 0, 0.38039216 } + { 0, 0, 0, 0 } + } + } + } + pass: i16 = 100 + alphaRef: u8 = 0 + particleIsLocalOrientation: flag = true + isUniformScale: flag = true + isGroundLayer: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 80, 100, 0 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.5, 1 } + values: list[vec3] = { + { 1.3, 0, 0 } + { 0.5, 0, 0 } + { 0.2, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_WispTrail_BW.Zaahen.tex" + birthUvScrollRate: embed = ValueVector2 { + constantValue: vec2 = { 0.5, 0 } + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 100 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.11 + } + particleLinger: option[f32] = { 0.1 } + lifetime: option[f32] = { 1 } + rateByVelocityFunction: embed = ValueVector2 { + constantValue: vec2 = { 1, 0 } + } + emitterName: string = "Pantheon3" + importance: u8 = 3 + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 20, 0, 0 } + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, 5 } + } + primitive: pointer = VfxPrimitiveCameraTrail { + mTrail: embed = VfxTrailDefinitionData { + mMode: u8 = 1 + mBirthTilingSize: embed = ValueVector3 { + constantValue: vec3 = { 500, 0, 0 } + } + mSmoothingMode: u8 = 1 + } + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.8666667, 0.7137255, 0.3254902, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.4, 0.5, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0.51999694 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = 101 + alphaRef: u8 = 0 + isUniformScale: flag = true + isRotationEnabled: flag = true + isGroundLayer: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 50, 10, 0 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.5, 1 } + values: list[vec3] = { + { 1, 0, 0 } + { 0.5, 0, 0 } + { 0.2, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Tape_trail_small.Zaahen.tex" + birthUvScrollRate: embed = ValueVector2 { + constantValue: vec2 = { 1, 0 } + } + birthUVOffset: embed = ValueVector2 { + constantValue: vec2 = { 0, -0.25 } + } + } + } + particleName: string = "Zaahen_Base_Emote_Taunt_Trail" + particlePath: string = "Characters/Zaahen/Skins/Skin0/Particles/Zaahen_Base_Emote_Taunt_Trail" + } + "Characters/Zaahen/Skins/Skin0/Particles/Zaahen_Base_R_AngelPose_EyeGlint" = VfxSystemDefinitionData { + complexEmitterDefinitionData: list[pointer] = { + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 2 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.2 + } + lifetime: option[f32] = { 2 } + isSingleParticle: flag = true + emitterName: string = "ray_Glow2" + importance: u8 = 3 + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 0.68000305, 0.25999847, 0.2399939 } + } + Color: embed = ValueColor { + constantValue: vec4 = { 0.8509804, 0.8509804, 0.8509804, 1 } + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.747549, 1 } + values: list[vec4] = { + { 0.8509804, 0.8509804, 0.8509804, 1 } + { 0.8509804, 0.83819693, 0.8498183, 0.86427313 } + { 0.8509804, 0, 0, 0 } + } + } + } + pass: i16 = 200 + alphaRef: u8 = 0 + miscRenderFlags: u8 = 1 + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 0, 0 } + } + isLocalOrientation: flag = false + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 750, 250, 0 } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Aura_Self.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 2 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.2 + } + lifetime: option[f32] = { 2 } + isSingleParticle: flag = true + emitterName: string = "ray_Glow4" + importance: u8 = 3 + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.61132216, 0.017929351, 0, 0.4 } + } + Color: embed = ValueColor { + constantValue: vec4 = { 0.8509804, 0.8509804, 0.8509804, 1 } + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.4822549, 0.8186275, 1 } + values: list[vec4] = { + { 0.8509804, 0.8509804, 0.8509804, 0 } + { 0.8509804, 0.84344965, 0.8502957, 0.030837005 } + { 0.8509804, 0.83819693, 0.8498182, 0.9062555 } + { 0.8509804, 0, 0, 0.72246695 } + } + } + } + pass: i16 = 500 + alphaRef: u8 = 0 + miscRenderFlags: u8 = 1 + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 0, 0 } + } + isLocalOrientation: flag = false + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 750, 250, 0 } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Aura_Self.Zaahen.tex" + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.1 + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.2 + } + particleLinger: option[f32] = { 1 } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "Horiz_glow_2" + importance: u8 = 3 + IsEmitterSpace: flag = true + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 5, -10 } + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 0.00999466, 0.02418555, 0.7882353 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + } + } + } + pass: i16 = 500 + alphaRef: u8 = 0 + 0xcb13aff1: f32 = -5 + miscRenderFlags: u8 = 1 + isRandomStartFrame: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 150, 450, 1 } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 3, 1, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.12268603, 1 } + values: list[vec3] = { + { 1.5, 0.1, 0 } + { 6, 0.11088825, 0 } + { 1.5, 0.1, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Aura_Self.Zaahen.tex" + uvRotation: embed = ValueFloat { + constantValue: f32 = 90 + } + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.1 + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.15 + } + particleLinger: option[f32] = { 1 } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "Horiz_halo_1" + importance: u8 = 3 + IsEmitterSpace: flag = true + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 5, -10 } + } + blendMode: u8 = 4 + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + } + } + } + pass: i16 = 2000 + alphaRef: u8 = 0 + 0xcb13aff1: f32 = -5 + miscRenderFlags: u8 = 1 + isRandomStartFrame: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 25, 100, 0 } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 3, 1, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.08914701, 1 } + values: list[vec3] = { + { 1.5, 0.1, 0 } + { 6, 0.11088825, 0 } + { 0.33094555, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Pantheon_Base_Q_Streaks.Zaahen.tex" + uvRotation: embed = ValueFloat { + constantValue: f32 = 90 + } + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.1 + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.15 + } + particleLinger: option[f32] = { 1 } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "Vert_halo_1" + importance: u8 = 3 + IsEmitterSpace: flag = true + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 5, -10 } + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.98965436, 0.8582742, 0.62146944, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + } + } + } + pass: i16 = 2000 + alphaRef: u8 = 0 + 0xcb13aff1: f32 = -5 + miscRenderFlags: u8 = 1 + isRandomStartFrame: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 0, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 30, 30, 30 } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Pantheon_Base_Idle_Glow_04.Zaahen.tex" + uvRotation: embed = ValueFloat { + constantValue: f32 = 90 + } + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.1 + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.2 + } + particleLinger: option[f32] = { 1 } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "Horiz_glow_3" + importance: u8 = 3 + IsEmitterSpace: flag = true + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 5, -10 } + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 0.4399939, 0.42000458, 0.7199969 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + } + } + } + pass: i16 = 1000 + alphaRef: u8 = 0 + 0xcb13aff1: f32 = -5 + miscRenderFlags: u8 = 1 + isRandomStartFrame: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 50, 250, 1 } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 3, 1, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.12268603, 1 } + values: list[vec3] = { + { 1.5, 0.1, 0 } + { 6, 0.11088825, 0 } + { 1.5, 0.1, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Pantheon_Base_Q_Streaks.Zaahen.tex" + uvRotation: embed = ValueFloat { + constantValue: f32 = 90 + } + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.1 + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.2 + } + particleLinger: option[f32] = { 1 } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "Horiz_glow_4" + importance: u8 = 3 + IsEmitterSpace: flag = true + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 5, -10 } + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.36478218, 0.014923324, 0.050492104, 0.4117647 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + } + } + } + pass: i16 = 250 + alphaRef: u8 = 0 + 0xcb13aff1: f32 = -5 + miscRenderFlags: u8 = 1 + isRandomStartFrame: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 250, 550, 1 } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 3, 1, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.12268603, 1 } + values: list[vec3] = { + { 1.5, 0.1, 0 } + { 6, 0.11088825, 0 } + { 1.5, 0.1, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Aura_Self.Zaahen.tex" + uvRotation: embed = ValueFloat { + constantValue: f32 = 90 + } + } + } + particleName: string = "Zaahen_Base_R_AngelPose_EyeGlint" + particlePath: string = "Characters/Zaahen/Skins/Skin0/Particles/Zaahen_Base_R_AngelPose_EyeGlint" + } + "Characters/Zaahen/Skins/Skin0/Particles/Zaahen_Base_BA_Swipe_child" = VfxSystemDefinitionData { + complexEmitterDefinitionData: list[pointer] = { + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 2 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.2 + } + particleLinger: option[f32] = { } + lifetime: option[f32] = { 0.5 } + isSingleParticle: flag = true + emitterLinger: option[f32] = { 0.5 } + emitterName: string = "CrossElement_drk1" + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, -20, 0 } + } + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/SwipeCrossElement.Zaahen.scb" + } + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.8666667, 0.7607843, 0.44705883, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.043626808, 0.2, 0.4 } + values: list[vec4] = { + { 0, 0, 0, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = 30 + alphaRef: u8 = 0 + disableBackfaceCull: bool = true + isUniformScale: flag = true + TextureFlipU: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 1.3, 1, 1 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 1, 1, 1 } + { 1.2, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Aura_Self.Zaahen.tex" + birthUvScrollRate: embed = ValueVector2 { + constantValue: vec2 = { 6, 1 } + } + texAddressModeBase: u8 = 2 + uvScale: embed = ValueVector2 { + constantValue: vec2 = { 2, 3 } + } + uvRotation: embed = ValueFloat { + constantValue: f32 = 90 + } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Udyr_Base_VGU_GlowMask_Thicc.Zaahen.tex" + texAddressModeMult: u8 = 2 + uvScaleMult: embed = ValueVector2 { + constantValue: vec2 = { 3, 1 } + } + ParticleIntegratedUvScrollMult: embed = IntegratedValueVector2 { + constantValue: vec2 = { 0.5, 0 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0 } + values: list[vec2] = { { 0.5, 0 } } + } + } + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.2 + } + particleLinger: option[f32] = { } + lifetime: option[f32] = { 0.5 } + isSingleParticle: flag = true + emitterLinger: option[f32] = { 0.5 } + emitterName: string = "CrossElement_drk2" + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, -20, 0 } + } + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/SwipeCrossElement.Zaahen.scb" + } + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.37261006, 0.08313115, 0.08728161, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.043626808, 0.2, 0.4 } + values: list[vec4] = { + { 0, 0, 0, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = 27 + alphaRef: u8 = 0 + disableBackfaceCull: bool = true + isUniformScale: flag = true + TextureFlipU: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 1.25, 1, 1 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 1, 1, 1 } + { 1.2, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Chogath_Skin14_R_Ribbon_01.Zaahen.tex" + paletteDefinition: pointer = VfxPaletteDefinitionData { + paletteTexture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_W_Gradient_RGB.Zaahen.tex" + paletteCount: i32 = 50 + } + birthUvScrollRate: embed = ValueVector2 { + constantValue: vec2 = { 4, 0 } + } + uvScale: embed = ValueVector2 { + constantValue: vec2 = { 2, 1 } + } + uvRotation: embed = ValueFloat { + constantValue: f32 = 90 + } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Udyr_Base_VGU_GlowMask_Thicc.Zaahen.tex" + texAddressModeMult: u8 = 2 + ParticleIntegratedUvScrollMult: embed = IntegratedValueVector2 { + constantValue: vec2 = { 0.5, 1 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0 } + values: list[vec2] = { { 0.5, 1 } } + } + } + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.2 + } + particleLinger: option[f32] = { 0.2 } + lifetime: option[f32] = { 0.5 } + isSingleParticle: flag = true + emitterLinger: option[f32] = { 0.5 } + emitterName: string = "Trail_Red7" + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_BA_SwipeMesh1.Zaahen.scb" + } + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 1, 1, 0.2500038 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.75, 1 } + values: list[vec4] = { + { 0.5411765, 0.40784314, 0.29411766, 1 } + { 0.5411765, 0.40784314, 0.29411766, 1 } + { 0.5411765, 0.40784314, 0.29411766, 0 } + } + } + } + pass: i16 = 15 + alphaRef: u8 = 0 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.85 } + values: list[f32] = { 0.3, 1 } + } + } + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Mordekaiser_Skin54_Noise_keka.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + disableBackfaceCull: bool = true + isUniformScale: flag = true + TextureFlipU: flag = true + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 1, 1, 1 } + { 1.2, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/color-hold.Zaahen.tex" + uvRotation: embed = ValueFloat { + constantValue: f32 = 90 + } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Ambessa_Base_P_SpecialAttack_Swipe_shape1.Zaahen.tex" + texAddressModeMult: u8 = 2 + uvScaleMult: embed = ValueVector2 { + constantValue: vec2 = { 0.5, 1 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec2] = { + { 0.5, 1 } + { 1, 1 } + } + } + } + ParticleIntegratedUvScrollMult: embed = IntegratedValueVector2 { + constantValue: vec2 = { 0, 1 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec2] = { + { 0, 1 } + { 0, 0 } + } + } + } + birthUVOffsetMult: embed = ValueVector2 { + constantValue: vec2 = { 0.1, -0.25 } + } + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.2 + } + particleLinger: option[f32] = { 0.2 } + lifetime: option[f32] = { 0.5 } + isSingleParticle: flag = true + emitterLinger: option[f32] = { 0.5 } + emitterName: string = "Trail_Gold12" + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_BA_SwipeMesh1.Zaahen.scb" + } + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 1, 1, 0.5000076 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.2, 0.4 } + values: list[vec4] = { + { 0.62352943, 0.5058824, 0.34117648, 1 } + { 0.62352943, 0.5058824, 0.34117648, 1 } + { 0.62352943, 0.5058824, 0.34117648, 0 } + } + } + } + pass: i16 = 28 + alphaRef: u8 = 15 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0.5, 1 } + values: list[f32] = { 0, 0.9907834 } + } + } + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Mordekaiser_Skin54_Noise_keka.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + disableBackfaceCull: bool = true + isUniformScale: flag = true + TextureFlipU: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 1.1, 1, 1 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 1, 1, 1 } + { 1.2, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/common_color-bellcurve.Zaahen.tex" + birthUVOffset: embed = ValueVector2 { + constantValue: vec2 = { -0.6, 0 } + } + texAddressModeBase: u8 = 2 + uvScale: embed = ValueVector2 { + constantValue: vec2 = { 2, 1 } + } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Udyr_Base_VGU_GlowMask_Thicc.Zaahen.tex" + texAddressModeMult: u8 = 2 + uvScaleMult: embed = ValueVector2 { + constantValue: vec2 = { 2, 1 } + } + ParticleIntegratedUvScrollMult: embed = IntegratedValueVector2 { + constantValue: vec2 = { 0.5, 1 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0 } + values: list[vec2] = { { 0.5, 1 } } + } + } + birthUVOffsetMult: embed = ValueVector2 { + constantValue: vec2 = { -0.5, 0 } + } + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.2 + } + particleLinger: option[f32] = { 0.2 } + lifetime: option[f32] = { 0.5 } + isSingleParticle: flag = true + emitterLinger: option[f32] = { 0.5 } + emitterName: string = "Trail_Red8" + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_BA_SwipeMesh1.Zaahen.scb" + } + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 1, 1, 0.2500038 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.75, 1 } + values: list[vec4] = { + { 0.5411765, 0.40784314, 0.29411766, 1 } + { 0.5411765, 0.40784314, 0.29411766, 1 } + { 0.5411765, 0.40784314, 0.29411766, 0 } + } + } + } + pass: i16 = 10 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + constantValue: f32 = 0.5 + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.85 } + values: list[f32] = { 0, 0.5 } + } + } + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Mordekaiser_Skin54_Noise_keka.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + disableBackfaceCull: bool = true + isUniformScale: flag = true + TextureFlipU: flag = true + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 1, 1, 1 } + { 1.2, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_R_Screen_Flames_Soft.Zaahen.tex" + birthUVOffset: embed = ValueVector2 { + constantValue: vec2 = { 0.5, 0 } + } + particleUVScrollRate: embed = IntegratedValueVector2 { + constantValue: vec2 = { 1, 0 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec2] = { + { 1, 0 } + { 0, 0 } + } + } + } + uvRotation: embed = ValueFloat { + constantValue: f32 = 90 + } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Ambessa_Base_P_SpecialAttack_Swipe_shape1.Zaahen.tex" + texAddressModeMult: u8 = 2 + uvScaleMult: embed = ValueVector2 { + constantValue: vec2 = { 0.5, 1 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec2] = { + { 0.5, 1 } + { 1, 1 } + } + } + } + ParticleIntegratedUvScrollMult: embed = IntegratedValueVector2 { + constantValue: vec2 = { 0, 1 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec2] = { + { 0, 1 } + { 0, 0 } + } + } + } + birthUVOffsetMult: embed = ValueVector2 { + constantValue: vec2 = { 0.1, -0.25 } + } + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 2 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.2 + } + particleLinger: option[f32] = { 0.2 } + lifetime: option[f32] = { 0.5 } + isSingleParticle: flag = true + emitterLinger: option[f32] = { 0.5 } + emitterName: string = "Trail_Gold13" + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_BA_SwipeMesh1.Zaahen.scb" + } + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.9714351, 0.9714351, 0.9714351, 0.5019608 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.2, 0.4 } + values: list[vec4] = { + { 0.62352943, 0.14901961, 0.08235294, 1 } + { 0.62352943, 0.14901961, 0.08235294, 1 } + { 0.62352943, 0.14901961, 0.08235294, 0 } + } + } + } + pass: i16 = 30 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.5 } + values: list[f32] = { 0.25, 1 } + } + } + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Mordekaiser_Skin54_Noise_keka.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + disableBackfaceCull: bool = true + isUniformScale: flag = true + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 1, 1, 1 } + { 1.2, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Wave_Texture.Zaahen.tex" + texAddressModeBase: u8 = 2 + uvScale: embed = ValueVector2 { + constantValue: vec2 = { 2, 1 } + } + uvRotation: embed = ValueFloat { + constantValue: f32 = 180 + } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Udyr_Base_VGU_GlowMask_Thicc.Zaahen.tex" + texAddressModeMult: u8 = 2 + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 2 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.2 + } + particleLinger: option[f32] = { 0.2 } + lifetime: option[f32] = { 0.5 } + isSingleParticle: flag = true + emitterLinger: option[f32] = { 0.5 } + emitterName: string = "Trail_Gold14" + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_BA_SwipeMesh1.Zaahen.scb" + } + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 1, 1, 0.5000076 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.2, 0.4 } + values: list[vec4] = { + { 0.62352943, 0.5058824, 0.34117648, 1 } + { 0.62352943, 0.5058824, 0.34117648, 1 } + { 0.62352943, 0.5058824, 0.34117648, 0 } + } + } + } + pass: i16 = 29 + alphaRef: u8 = 15 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0.5, 1 } + values: list[f32] = { 0, 0.9907834 } + } + } + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Mordekaiser_Skin54_Noise_keka.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + disableBackfaceCull: bool = true + isUniformScale: flag = true + TextureFlipU: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 1.1, 1, 1 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 1, 1, 1 } + { 1.2, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/common_color-bellcurve.Zaahen.tex" + birthUVOffset: embed = ValueVector2 { + constantValue: vec2 = { -0.75, 0 } + } + texAddressModeBase: u8 = 2 + uvScale: embed = ValueVector2 { + constantValue: vec2 = { 2, 1 } + } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Udyr_Base_VGU_GlowMask_Thicc.Zaahen.tex" + texAddressModeMult: u8 = 2 + uvScaleMult: embed = ValueVector2 { + constantValue: vec2 = { 2, 1 } + } + ParticleIntegratedUvScrollMult: embed = IntegratedValueVector2 { + constantValue: vec2 = { 0.5, 1 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0 } + values: list[vec2] = { { 0.5, 1 } } + } + } + birthUVOffsetMult: embed = ValueVector2 { + constantValue: vec2 = { -0.5, 0 } + } + } + } + } + particleName: string = "Zaahen_Base_BA_Swipe_child" + particlePath: string = "Characters/Zaahen/Skins/Skin0/Particles/Zaahen_Base_BA_Swipe_child" + } + "Characters/Zaahen/Skins/Skin0/Particles/Zaahen_Base_R_cas" = VfxSystemDefinitionData { + complexEmitterDefinitionData: list[pointer] = { + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 10 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.25 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.9, 2 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 0.25 } + } + } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "backing_burst" + importance: u8 = 1 + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, 500, 500 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.3, 0.9 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 500, 500 } } + } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 5, 5, 5 } + } + worldAcceleration: embed = IntegratedValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 0, 0 } } + } + } + SpawnShape: pointer = VfxShapeBox { + flags: u8 = 1 + Size: vec3 = { 50, 0, 50 } + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.7100023, 0.57000077, 0.48000306, 0.2399939 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.3, 0.54073596, 0.7483273, 0.85743695, 1 } + values: list[vec4] = { + { 1, 0.9372549, 0.78039217, 0 } + { 1, 0.9490196, 0.7921569, 0.9607843 } + { 0.78039217, 0.64705884, 0.48235294, 1 } + { 0.6745098, 0.47058824, 0.3019608, 0.22745098 } + { 0.4862745, 0.42745098, 0.38431373, 0.09019608 } + { 0.105882354, 0.09019608, 0.08235294, 0 } + } + } + } + pass: i16 = -50 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + constantValue: f32 = 2 + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.14760914, 1 } + values: list[f32] = { 0, 0.10557377, 0.6 } + } + } + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Base_SmokeErode.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + miscRenderFlags: u8 = 1 + isDirectionOriented: flag = true + isRandomStartFrame: flag = true + directionVelocityScale: f32 = 0.002 + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 150, 150, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 0.5, 0.51, 1 } + keyValues: list[f32] = { -1, -0.7, 0.7, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 0.8, 1 } + keyValues: list[f32] = { 0.6, 0.9, 1.1 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 150, 150, 0 } } + } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.163214, 0.5527579, 0.996912 } + values: list[vec3] = { + { 0.9, 0.5, 1 } + { 1.0672269, 1.2, 1 } + { 1.1389356, 2.011753, 1 } + { 1.4, 2.7, 1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Shapes02.Zaahen.tex" + numFrames: u16 = 4 + texDiv: vec2 = { 2, 2 } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 5 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.25 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.9, 1 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 0.25 } + } + } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "backing_burst3" + importance: u8 = 1 + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 500, 1000, 2000 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.3, 0.9 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 500, 1000, 2000 } } + } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 1, 1, 1 } + } + worldAcceleration: embed = IntegratedValueVector3 { + constantValue: vec3 = { 0, -1000, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0 } + values: list[vec3] = { { 0, -1000, 0 } } + } + } + SpawnShape: pointer = VfxShapeBox { + flags: u8 = 1 + Size: vec3 = { 50, 0, 50 } + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.28801402, 0.23308156, 0.19777219, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.3, 0.54073596, 0.7483273, 0.85743695, 1 } + values: list[vec4] = { + { 1, 0.9372549, 0.78039217, 0 } + { 1, 0.9490196, 0.7921569, 0.9607843 } + { 0.78039217, 0.64705884, 0.48235294, 1 } + { 0.6745098, 0.47058824, 0.3019608, 0.22745098 } + { 0.4862745, 0.42745098, 0.38431373, 0.09019608 } + { 0.105882354, 0.09019608, 0.08235294, 0 } + } + } + } + pass: i16 = -50 + miscRenderFlags: u8 = 1 + isDirectionOriented: flag = true + isRandomStartFrame: flag = true + directionVelocityScale: f32 = 0.002 + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 35, 35, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 0.5, 0.51, 1 } + keyValues: list[f32] = { -1, -0.7, 0.7, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 0.8, 1 } + keyValues: list[f32] = { 0.6, 0.9, 1.1 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 35, 35, 0 } } + } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.2, 1 } + values: list[vec3] = { + { 0, 0, 1 } + { 1.0672269, 1.2, 1 } + { 0, 0, 1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Skarner_Rework_Base_W_Rocks_2x2.Zaahen.tex" + numFrames: u16 = 4 + texDiv: vec2 = { 2, 2 } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.25 + } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "Ground_glow" + primitive: pointer = VfxPrimitiveArbitraryQuad { } + particleColorTexture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/color-hold.Zaahen.tex" + blendMode: u8 = 4 + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 0.3, 1 } + values: list[vec4] = { + { 0.99215686, 1, 0.76862746, 0 } + { 0.92156863, 0.7607843, 0.49019608, 1 } + { 0.92156863, 0.7607843, 0.49019608, 0.2 } + { 0, 0, 0, 0 } + } + } + } + pass: i16 = 500 + meshRenderFlags: u8 = 0 + alphaRef: u8 = 0 + miscRenderFlags: u8 = 1 + isUniformScale: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { -90, 0, 0 } + } + isLocalOrientation: flag = false + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 200, 350, 350 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 1, 1, 0.5 } + { 0, 0, 1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Aura_Self.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.5 + } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "orb" + SpawnShape: pointer = 0xee39916f { + emitOffset: vec3 = { 0, 30, 0 } + } + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Shyvana_Skin17_q_Wind_Swipe_01.Zaahen.scb" + } + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 1, 1, 0.7199969 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1740413, 0.45359883, 1 } + values: list[vec4] = { + { 0.8973373, 0.11221485, 0.11221485, 0.47058824 } + { 0.4, 0.09019608, 0.09019608, 1 } + { 0.21898222, 0.122560464, 0.122560464, 0.23137255 } + { 0.13968109, 0.08734264, 0.08734264, 0 } + } + } + } + pass: i16 = 202 + softParticleParams: pointer = VfxSoftParticleDefinitionData { + deltaIn: f32 = 70 + } + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + constantValue: f32 = 0.5 + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 1 } + values: list[f32] = { 0, 0.5 } + } + } + erosionFeatherOut: f32 = 0.3 + erosionSliceWidth: f32 = 1.8 + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Shyvana_Skin17_Q_Swipe_Mult_01.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + erosionMapAddressMode: u8 = 0 + } + disableBackfaceCull: bool = true + isRandomStartFrame: flag = true + isRotationEnabled: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 0, 360, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 360, 0 } } + } + } + rotation0: embed = IntegratedValueVector3 { + constantValue: vec3 = { 0, -1, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.3558997, 1 } + values: list[vec3] = { + { 0, -5, 0 } + { 0, -0.44444445, 0 } + { 0, -0, 0 } + } + } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 1.1, 3, 1.1 } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 3, 2, 3 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 0, 0, 0 } + { 3.3000002, 2, 3.3000002 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Leona_Base_E_Wisps.Zaahen.tex" + birthUvScrollRate: embed = ValueVector2 { + constantValue: vec2 = { -1, 0 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0.5 } + keyValues: list[f32] = { 0.5 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -0.2, 0.5 } + } + } + times: list[f32] = { 0 } + values: list[vec2] = { { -1, 0 } } + } + } + birthUVOffset: embed = ValueVector2 { + constantValue: vec2 = { 1, 0 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 1, -1 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec2] = { { 1, 0 } } + } + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 1 + } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "Ground_glow1" + primitive: pointer = VfxPrimitiveArbitraryQuad { } + particleColorTexture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/color-hold.Zaahen.tex" + blendMode: u8 = 1 + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 0.5, 1 } + values: list[vec4] = { + { 0.5261616, 0.23964293, 0.0845655, 0 } + { 0.45087358, 0.14877546, 0.077286944, 1 } + { 0.20671397, 0.038513772, 0.048859388, 0.2 } + { 0, 0, 0, 0 } + } + } + } + pass: i16 = -200 + meshRenderFlags: u8 = 0 + alphaRef: u8 = 0 + miscRenderFlags: u8 = 1 + isUniformScale: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { -90, 0, 0 } + } + isLocalOrientation: flag = false + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 400, 350, 350 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.3, 1 } + values: list[vec3] = { + { 0.5, 0.5, 0.5 } + { 0.7, 0.7, 0.7 } + { 1, 1, 1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Aura_Self.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 20 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 20 } + } + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.15 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 0.9 } + keyValues: list[f32] = { 0.8, 2 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 0.15 } + } + } + particleLinger: option[f32] = { 0.2 } + lifetime: option[f32] = { 0.2 } + isSingleParticle: flag = true + emitterName: string = "motes" + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 750, 0, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.45, 1 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 750, 0, 0 } } + } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 3, 3, 3 } + } + velocity: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, 1100 } + } + SpawnShape: pointer = VfxShapeSphere { + flags: u8 = 1 + radius: f32 = 100 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 50, 25 } + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 0.97000074, 0.93000686, 0.8299992 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0.0013315579, 0.19973369, 0.9960053 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 0.32252994, 0.10489052, 0.10489052, 0 } + } + } + } + pass: i16 = 10 + isDirectionOriented: flag = true + isUniformScale: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.9, 1.1 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 0, 1 } } + } + } + directionVelocityScale: f32 = 0.004 + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 40, 1, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.25, 1.2 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 40, 1, 1 } } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Morgana_Base_P_StardustMoteAlpha.Zaahen.tex" + paletteDefinition: pointer = VfxPaletteDefinitionData { + paletteTexture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_W_Gradient_RGB.Zaahen.tex" + paletteSelector: embed = ValueVector3 { + constantValue: vec3 = { 3, 0, 0 } + } + paletteCount: i32 = 8 + } + } + } + particleName: string = "Zaahen_Base_R_cas" + particlePath: string = "Characters/Zaahen/Skins/Skin0/Particles/Zaahen_Base_R_cas" + } + "Characters/Zaahen/Skins/Skin0/Particles/Zaahen_Base_Emote_Homeguard" = VfxSystemDefinitionData { + particleName: string = "Zaahen_Base_Emote_Homeguard" + particlePath: string = "Characters/Zaahen/Skins/Skin0/Particles/Zaahen_Base_Emote_Homeguard" + } + "Characters/Zaahen/Skins/Skin0/Particles/Zaahen_Base_Q_1_Tar" = VfxSystemDefinitionData { + complexEmitterDefinitionData: list[pointer] = { + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.35 + } + particleLinger: option[f32] = { } + lifetime: option[f32] = { 0.2 } + isSingleParticle: flag = true + emitterName: string = "flash6" + importance: u8 = 3 + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + blendMode: u8 = 4 + Color: embed = ValueColor { + constantValue: vec4 = { 0.85490197, 0.13725491, 0.13725491, 0.84313726 } + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.2, 1 } + values: list[vec4] = { + { 0.85490197, 0.13725491, 0.13725491, 0.84313726 } + { 0.85490197, 0.13725491, 0.13725491, 0.84313726 } + { 0.85490197, 0.13725491, 0.13725491, 0.84313726 } + } + } + } + pass: i16 = 600 + alphaRef: u8 = 0 + miscRenderFlags: u8 = 1 + isUniformScale: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 45, 0, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 50, 79.25, 0.84 } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 5, 1.5, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.3, 1 } + values: list[vec3] = { + { 5, 0, 0 } + { 3, 1.5, 0 } + { 0, 2.25, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Darius_Skin43_Star_Flash.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.2 + } + particleLinger: option[f32] = { 0.5 } + lifetime: option[f32] = { 0.2 } + isSingleParticle: flag = true + emitterName: string = "Activate12" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.3 } + values: list[f32] = { 1, 0 } + } + } + SpawnShape: pointer = VfxShapeBox { + flags: u8 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 15, 0 } + } + blendMode: u8 = 1 + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.2, 1 } + values: list[vec4] = { + { 0.28235295, 0.07450981, 0.20784314, 1 } + { 0.10980392, 0, 0.03137255, 1 } + { 0.23529412, 0, 0.09019608, 0 } + } + } + } + pass: i16 = -15 + alphaRef: u8 = 0 + depthBiasFactors: vec2 = { -1, -45 } + particleIsLocalOrientation: flag = true + isUniformScale: flag = true + isRandomStartFrame: flag = true + isRotationEnabled: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 35, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 50, 1, 1 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.2, 0.5, 1 } + values: list[vec3] = { + { 0.2, 0, 0 } + { 3, 1, 1 } + { 2, 1, 1 } + { 2, 1, 1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Naafiri_Base_Foundation_Glow01.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.2 + } + particleLinger: option[f32] = { 10.4 } + lifetime: option[f32] = { 0.5 } + isSingleParticle: flag = true + emitterName: string = "Mid_" + importance: u8 = 3 + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 100, -100, 0 } + } + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { -10, 10, 0 } + } + FlexShapeDefinition: pointer = VfxFlexShapeDefinitionData { + scaleBirthScaleByBoundObjectSize: f32 = 0.005 + scaleEmitOffsetByBoundObjectSize: f32 = 0.005 + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.8693828, 0.7724117, 0.4815137, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.08252427, 0.79126215, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0.94690263 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = 799 + miscRenderFlags: u8 = 1 + particleIsLocalOrientation: flag = true + isDirectionOriented: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 0, -90, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 125, 100, 100 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.7, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.7, 1.2 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 125, 100, 100 } } + } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.3, 1 } + values: list[vec3] = { + { 0, 0.3, 0 } + { 0.5, 1.5, 1 } + { 0.1, 1.25, 1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Skin_06_Spark_Vertical.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.25 + } + particleLinger: option[f32] = { 10.4 } + lifetime: option[f32] = { 0.5 } + isSingleParticle: flag = true + emitterName: string = "BG_" + importance: u8 = 3 + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 100, -100, 0 } + } + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + SpawnShape: pointer = VfxShapeLegacy { + emitOffset: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -15, 15 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 0, 0 } } + } + } + } + FlexShapeDefinition: pointer = VfxFlexShapeDefinitionData { + scaleBirthScaleByBoundObjectSize: f32 = 0.005 + scaleEmitOffsetByBoundObjectSize: f32 = 0.005 + } + blendMode: u8 = 1 + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.08252427, 0.79126215, 1 } + values: list[vec4] = { + { 0.91961545, 0.44303045, 0.44303045, 0 } + { 0.8817426, 0.08007935, 0.08007935, 1 } + { 0.3764706, 0.08235294, 0.08235294, 1 } + { 0.18707561, 0.09283589, 0.11288624, 0 } + } + } + } + pass: i16 = 599 + miscRenderFlags: u8 = 1 + particleIsLocalOrientation: flag = true + isDirectionOriented: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 0, -90, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 150, 120, 100 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.3, 1 } + values: list[vec3] = { + { 0, 0.3, 0 } + { 1, 1.5, 1 } + { 0, 1.25, 1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Skin_06_Spark_Vertical.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.2 + } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterLinger: option[f32] = { 10 } + emitterName: string = "Sheen_" + importance: u8 = 3 + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 2000, -2000, 0 } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 4, 4, 0 } + } + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { -150, 150, 0 } + } + blendMode: u8 = 4 + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 0.6, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = 820 + depthBiasFactors: vec2 = { -1, -4 } + disableBackfaceCull: bool = true + miscRenderFlags: u8 = 1 + isDirectionOriented: flag = true + isRandomStartFrame: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 30, 90, 1 } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 1.4, 1.4, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.2, 0.6, 1 } + values: list[vec3] = { + { 0.7, 0.7, 0.5 } + { 1.8199999, 2.8, 1.1 } + { 0.7, 1.4, 0 } + { 0, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/XinZhaoRework_Base_LensFlare.Zaahen.tex" + numFrames: u16 = 4 + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.12 + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.2 + } + particleLinger: option[f32] = { 10.4 } + lifetime: option[f32] = { 0.5 } + isSingleParticle: flag = true + emitterName: string = "Mid_1" + importance: u8 = 3 + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { -100, -100, 0 } + } + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 10, 10, 0 } + } + FlexShapeDefinition: pointer = VfxFlexShapeDefinitionData { + scaleBirthScaleByBoundObjectSize: f32 = 0.005 + scaleEmitOffsetByBoundObjectSize: f32 = 0.005 + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.8693828, 0.7724117, 0.4815137, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.08252427, 0.79126215, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 0.8510109, 0.5459831, 0.17114519, 0.94509804 } + { 0.38263524, 0.2017548, 0.054062713, 0 } + } + } + } + pass: i16 = 799 + miscRenderFlags: u8 = 1 + particleIsLocalOrientation: flag = true + isDirectionOriented: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 0, -90, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 125, 100, 100 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.7, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.7, 1.2 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 125, 100, 100 } } + } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.3, 1 } + values: list[vec3] = { + { 0, 0.3, 0 } + { 0.5, 1.5, 1 } + { 0.1, 1.25, 1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Skin_06_Spark_Vertical.Zaahen.tex" + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.12 + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.2 + } + particleLinger: option[f32] = { 10.4 } + lifetime: option[f32] = { 0.5 } + isSingleParticle: flag = true + emitterName: string = "BG_1" + importance: u8 = 3 + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { -100, -100, 0 } + } + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + SpawnShape: pointer = VfxShapeLegacy { + emitOffset: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -15, 15 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 0, 0 } } + } + } + } + FlexShapeDefinition: pointer = VfxFlexShapeDefinitionData { + scaleBirthScaleByBoundObjectSize: f32 = 0.005 + scaleEmitOffsetByBoundObjectSize: f32 = 0.005 + } + blendMode: u8 = 1 + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.08252427, 0.79126215, 1 } + values: list[vec4] = { + { 0.91961545, 0.44303045, 0.44303045, 0 } + { 0.8817426, 0.08007935, 0.08007935, 1 } + { 0.3764706, 0.08235294, 0.08235294, 1 } + { 0.18707561, 0.09283589, 0.11288624, 0 } + } + } + } + pass: i16 = 599 + miscRenderFlags: u8 = 1 + particleIsLocalOrientation: flag = true + isDirectionOriented: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 0, -90, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 300, 120, 100 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.7, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.7, 1.2 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 300, 120, 100 } } + } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.3, 1 } + values: list[vec3] = { + { 0, 0.3, 0 } + { 0.5, 1.5, 1 } + { 0.1, 1.25, 1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Skin_06_Spark_Vertical.Zaahen.tex" + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.12 + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.2 + } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterLinger: option[f32] = { 10 } + emitterName: string = "Sheen_1" + importance: u8 = 3 + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { -4000, -4000, 0 } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 16, 16, 0 } + } + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 150, 150, 0 } + } + blendMode: u8 = 4 + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 0.6, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = 810 + depthBiasFactors: vec2 = { -1, -4 } + disableBackfaceCull: bool = true + miscRenderFlags: u8 = 1 + isDirectionOriented: flag = true + isRandomStartFrame: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 30, 120, 1 } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 1.4, 1.4, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.2, 0.6, 1 } + values: list[vec3] = { + { 0.7, 0.7, 0.5 } + { 1.8199999, 2.8, 1.1 } + { 0.7, 1.4, 0 } + { 0, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/XinZhaoRework_Base_LensFlare.Zaahen.tex" + numFrames: u16 = 4 + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.1 + } + lifetime: option[f32] = { 0.4 } + isSingleParticle: flag = true + emitterName: string = "bloom_glow" + importance: u8 = 1 + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.93015945, 0.36343938, 0.17013809, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0.20149253, 0.9835821 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 0.467689, 0.1392691, 0.16298161, 0 } + } + } + } + pass: i16 = 802 + alphaRef: u8 = 0 + miscRenderFlags: u8 = 1 + isUniformScale: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 120, 1, 1 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { -0.0035587188, 0.19928825, 0.5960854, 1.0017793 } + values: list[vec3] = { + { 0.60573477, 0, 0 } + { 0.98207885, 0, 0 } + { 1.2222222, 0, 0 } + { 1.3512545, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Aura_Self.Zaahen.tex" + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.12 + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.1 + } + lifetime: option[f32] = { 0.4 } + isSingleParticle: flag = true + emitterName: string = "bloom_glow1" + importance: u8 = 1 + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.93015945, 0.36343938, 0.17013809, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0.20149253, 0.9835821 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 0.467689, 0.1392691, 0.16298161, 0 } + } + } + } + pass: i16 = 802 + alphaRef: u8 = 0 + miscRenderFlags: u8 = 1 + isUniformScale: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 120, 1, 1 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { -0.0035587188, 0.19928825, 0.5960854, 1.0017793 } + values: list[vec3] = { + { 0.60573477, 0, 0 } + { 0.98207885, 0, 0 } + { 1.2222222, 0, 0 } + { 1.3512545, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Aura_Self.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 1 + } + isSingleParticle: flag = true + childParticleSetDefinition: pointer = VfxChildParticleSetDefinitionData { + childrenIdentifiers: list[embed] = { + VfxChildIdentifier { + effectKey: hash = "Zaahen_Q_1_Trail" + } + } + } + emitterName: string = "Gimbal_Left" + importance: u8 = 3 + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { -100, -75, -250 } + } + primitive: pointer = VfxPrimitiveArbitraryQuad { } + blendMode: u8 = 1 + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 0, 180, 45 } + } + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.12 + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 1 + } + isSingleParticle: flag = true + childParticleSetDefinition: pointer = VfxChildParticleSetDefinitionData { + childrenIdentifiers: list[embed] = { + VfxChildIdentifier { + effectKey: hash = "Zaahen_Q_1_Trail" + } + } + } + emitterName: string = "Gimbal_Right" + importance: u8 = 3 + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { -100, 75, -250 } + } + primitive: pointer = VfxPrimitiveArbitraryQuad { } + blendMode: u8 = 1 + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 0, 180, 135 } + } + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.12 + rate: embed = ValueFloat { + constantValue: f32 = 2 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.5 + } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterLinger: option[f32] = { 10 } + emitterName: string = "Sheen_2" + importance: u8 = 3 + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { -2, -2, 0 } + } + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 20, 20, 0 } + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.22000457, 0.050003815, 0.050003815, 0.3600061 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = -1000 + depthBiasFactors: vec2 = { -1, -4 } + disableBackfaceCull: bool = true + miscRenderFlags: u8 = 1 + isDirectionOriented: flag = true + isRandomStartFrame: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 30, 120, 1 } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 1.4, 1.4, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.2, 0.6, 1 } + values: list[vec3] = { + { 1.8199999, 2.8, 0.5 } + { 1.8199999, 2.8, 1.1 } + { 1.4, 2.8, 0 } + { 0, 5.6, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/XinZhaoRework_Base_LensFlare.Zaahen.tex" + numFrames: u16 = 4 + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 2 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.5 + } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterLinger: option[f32] = { 10 } + emitterName: string = "Sheen_3" + importance: u8 = 3 + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 2, -2, 0 } + } + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { -20, 20, 0 } + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.22000457, 0.050003815, 0.050003815, 0.3600061 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = -1000 + depthBiasFactors: vec2 = { -1, -4 } + disableBackfaceCull: bool = true + miscRenderFlags: u8 = 1 + isDirectionOriented: flag = true + isRandomStartFrame: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 30, 90, 1 } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 1.4, 1.4, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.2, 0.6, 1 } + values: list[vec3] = { + { 1.8199999, 2.8, 0.5 } + { 1.8199999, 2.8, 1.1 } + { 1.8199999, 2.8, 0 } + { 1.8199999, 2.8, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/XinZhaoRework_Base_LensFlare.Zaahen.tex" + numFrames: u16 = 4 + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.12 + rate: embed = ValueFloat { + constantValue: f32 = 4 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.3 + } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterLinger: option[f32] = { 10 } + emitterName: string = "Sheen_4" + importance: u8 = 3 + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { -2, -2, 0 } + } + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 20, 20, 0 } + } + blendMode: u8 = 4 + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 0.8912642, 0.62404823, 0.62404823, 1 } + { 0.20021363, 0.076081485, 0.09929045, 0 } + } + } + } + pass: i16 = -990 + depthBiasFactors: vec2 = { -1, -4 } + disableBackfaceCull: bool = true + miscRenderFlags: u8 = 1 + isDirectionOriented: flag = true + isRandomStartFrame: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 30, 120, 1 } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 1.2, 1.4, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.2, 0.4, 1 } + values: list[vec3] = { + { 1.5600001, 2.8, 0.5 } + { 1.5600001, 2.8, 1.1 } + { 0.72, 2.8, 0 } + { 0, 5.6, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/XinZhaoRework_Base_LensFlare.Zaahen.tex" + numFrames: u16 = 4 + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.4 + } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterLinger: option[f32] = { 10 } + emitterName: string = "Sheen_5" + importance: u8 = 3 + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 2, -2, 0 } + } + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { -20, 20, 0 } + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.8901961, 0.09803922, 0.09803922, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 1 } + values: list[vec4] = { + { 0.94479287, 0.34148166, 0.34148166, 0 } + { 0.8901961, 0.09803922, 0.09803922, 1 } + { 0.20021363, 0.076081485, 0.09929045, 0 } + } + } + } + pass: i16 = -990 + depthBiasFactors: vec2 = { -1, -4 } + disableBackfaceCull: bool = true + miscRenderFlags: u8 = 1 + isDirectionOriented: flag = true + isRandomStartFrame: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 30, 90, 1 } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 1.4, 1.4, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.2, 0.6, 1 } + values: list[vec3] = { + { 1.8199999, 2.8, 0.5 } + { 1.8199999, 2.8, 1.1 } + { 0.84, 2.8, 0 } + { 0, 2.8, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/XinZhaoRework_Base_LensFlare.Zaahen.tex" + numFrames: u16 = 4 + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.4 + } + lifetime: option[f32] = { 0.2 } + isSingleParticle: flag = true + emitterName: string = "circleflare_blend1" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 12.815607, 0 } + } + particleColorTexture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/common_color-bellcurve.Zaahen.tex" + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.17181659, 0.07031357, 0.067200735, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.06652807, 0.1964657, 0.38253638, 0.6486486, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0.47272727 } + { 1, 1, 1, 0.21212122 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = -50 + meshRenderFlags: u8 = 0 + alphaRef: u8 = 0 + isUniformScale: flag = true + isRandomStartFrame: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 1, 0, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 1, 0, 0 } } + } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 40, 200, 200 } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 1.5, 1, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.08212058, 0.17525057, 1 } + values: list[vec3] = { + { 0, 1, 1 } + { 2.4626865, 0.9178794, 0.9178794 } + { 3.1791043, 0.8247494, 0.8247494 } + { 4.5, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Thresh_Skin28_Q_Impact_04.Zaahen.tex" + numFrames: u16 = 4 + texDiv: vec2 = { 2, 2 } + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.12 + rate: embed = ValueFloat { + constantValue: f32 = 10 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.75 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 0.9, 1 } + keyValues: list[f32] = { 0.2, 1, 1.5 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 0.75 } + } + } + particleLinger: option[f32] = { 1 } + lifetime: option[f32] = { 0.2 } + isSingleParticle: flag = true + emitterName: string = "Sparkles4" + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { -2000, -2000, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1.2 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1.2 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { -2000, -2000, 0 } } + } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 12, 12, 8 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 12, 12, 8 } } + } + } + worldAcceleration: embed = IntegratedValueVector3 { + constantValue: vec3 = { 0, 400, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 400, 0 } } + } + } + SpawnShape: pointer = VfxShapeBox { + flags: u8 = 1 + Size: vec3 = { 30, 30, 30 } + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 40, 40, 0 } + } + blendMode: u8 = 5 + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 0.3, 0.6, 1 } + values: list[vec4] = { + { 0.9411765, 0.06666667, 0.07450981, 0 } + { 0.9411765, 0.06666667, 0.07450981, 1 } + { 0.9411765, 0.06666667, 0.07450981, 1 } + { 0.23137255, 0, 0.015686275, 1 } + { 0.23137255, 0, 0.015686275, 0 } + } + } + } + pass: i16 = 10 + miscRenderFlags: u8 = 1 + isDirectionOriented: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 1, 0, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 1, 0, 0 } } + } + } + birthRotationalVelocity0: embed = ValueVector3 { + constantValue: vec3 = { -300, 0, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 75, 200, 0 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.1, 0.19223854, 0.37142858, 1 } + values: list[vec3] = { + { 0, 0, 0 } + { 1, 1, 1 } + { 0.21186441, 0.5, 0.5 } + { 0.56271183, 0.33380866, 0.33380866 } + { 0, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Morgana_Base_P_StardustMoteAlpha.Zaahen.tex" + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.12 + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.85 + } + particleLinger: option[f32] = { } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "StrokeDissolve_primary1" + importance: u8 = 3 + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.88000304, 0.2, 0.2, 0.2899977 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.2, 0.8, 1 } + values: list[vec4] = { + { 0.80784315, 0.5137255, 0.42352942, 1 } + { 0.78431374, 0.101960786, 0, 1 } + { 0.78431374, 0.101960786, 0, 1 } + { 0.13725491, 0.007843138, 0.05882353, 1 } + } + } + } + pass: i16 = 5 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.55 } + values: list[f32] = { 0.15, 1 } + } + } + erosionSliceWidth: f32 = 1 + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Aatrox_Skin11_AA_Wall_Erosion.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + erosionMapAddressMode: u8 = 0 + } + disableBackfaceCull: bool = true + isUniformScale: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 360, 1, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 360, 1, 0 } } + } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 200, 120, 120 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.2, 1 } + values: list[vec3] = { + { 0.5, 0.25, 0.1 } + { 0.75, 0.75, 0.5 } + { 1, 1.2, 1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Aatrox_Skin11_AA_Flares_03.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 10 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.75 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 0.9, 1 } + keyValues: list[f32] = { 0.2, 1, 1.5 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 0.75 } + } + } + particleLinger: option[f32] = { 1 } + lifetime: option[f32] = { 0.2 } + isSingleParticle: flag = true + emitterName: string = "Sparkles6" + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 2000, -2000, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1.2 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1.2 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 2000, -2000, 0 } } + } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 12, 12, 8 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 12, 12, 8 } } + } + } + worldAcceleration: embed = IntegratedValueVector3 { + constantValue: vec3 = { 0, 400, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 400, 0 } } + } + } + SpawnShape: pointer = VfxShapeBox { + flags: u8 = 1 + Size: vec3 = { 30, 30, 30 } + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { -40, 40, 0 } + } + blendMode: u8 = 5 + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 0.3, 0.6, 1 } + values: list[vec4] = { + { 0.9411765, 0.06666667, 0.07450981, 0 } + { 0.9411765, 0.06666667, 0.07450981, 1 } + { 0.9411765, 0.06666667, 0.07450981, 1 } + { 0.23137255, 0, 0.015686275, 1 } + { 0.23137255, 0, 0.015686275, 0 } + } + } + } + pass: i16 = 10 + miscRenderFlags: u8 = 1 + isDirectionOriented: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 1, 0, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 1, 0, 0 } } + } + } + birthRotationalVelocity0: embed = ValueVector3 { + constantValue: vec3 = { -300, 0, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 75, 200, 0 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.1, 0.19223854, 0.37142858, 1 } + values: list[vec3] = { + { 0, 0, 0 } + { 1, 1, 1 } + { 0.21186441, 0.5, 0.5 } + { 0.56271183, 0.33380866, 0.33380866 } + { 0, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Morgana_Base_P_StardustMoteAlpha.Zaahen.tex" + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.12 + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.2 + } + particleLinger: option[f32] = { 0.5 } + lifetime: option[f32] = { 0.2 } + isSingleParticle: flag = true + emitterName: string = "Activate13" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.3 } + values: list[f32] = { 1, 0 } + } + } + SpawnShape: pointer = VfxShapeBox { + flags: u8 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 15, 0 } + } + blendMode: u8 = 1 + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.2, 1 } + values: list[vec4] = { + { 0.28235295, 0.07450981, 0.20784314, 1 } + { 0.10980392, 0, 0.03137255, 1 } + { 0.23529412, 0, 0.09019608, 0 } + } + } + } + pass: i16 = -15 + alphaRef: u8 = 0 + depthBiasFactors: vec2 = { -1, -45 } + particleIsLocalOrientation: flag = true + isUniformScale: flag = true + isRandomStartFrame: flag = true + isRotationEnabled: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 35, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 50, 1, 1 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.2, 0.5, 1 } + values: list[vec3] = { + { 0.2, 0, 0 } + { 3, 1, 1 } + { 2, 1, 1 } + { 2, 1, 1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Naafiri_Base_Foundation_Glow01.Zaahen.tex" + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.12 + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.17 + } + particleLinger: option[f32] = { } + lifetime: option[f32] = { 0.2 } + isSingleParticle: flag = true + emitterName: string = "flash14" + importance: u8 = 3 + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + blendMode: u8 = 4 + Color: embed = ValueColor { + constantValue: vec4 = { 0.85490197, 0.13725491, 0.13725491, 0.84313726 } + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.2, 1 } + values: list[vec4] = { + { 0.85490197, 0.13725491, 0.13725491, 0.84313726 } + { 0.85490197, 0.13725491, 0.13725491, 0.84313726 } + { 0.85490197, 0.13725491, 0.13725491, 0.84313726 } + } + } + } + pass: i16 = 600 + alphaRef: u8 = 0 + miscRenderFlags: u8 = 1 + isUniformScale: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 45, 0, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 50, 79.25, 0.84 } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 5, 1.5, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.3, 1 } + values: list[vec3] = { + { 5, 0, 0 } + { 3, 1.5, 0 } + { 0, 2.25, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Darius_Skin43_Star_Flash.Zaahen.tex" + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.12 + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.4 + } + lifetime: option[f32] = { 0.2 } + isSingleParticle: flag = true + emitterName: string = "circleflare_blend2" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 12.815607, 0 } + } + particleColorTexture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/common_color-bellcurve.Zaahen.tex" + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.17181659, 0.07031357, 0.067200735, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.06652807, 0.1964657, 0.38253638, 0.6486486, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0.47272727 } + { 1, 1, 1, 0.21212122 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = -50 + meshRenderFlags: u8 = 0 + alphaRef: u8 = 0 + isUniformScale: flag = true + isRandomStartFrame: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 1, 0, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 1, 0, 0 } } + } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 40, 200, 200 } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 1.5, 1, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.08212058, 0.17525057, 1 } + values: list[vec3] = { + { 0, 1, 1 } + { 2.4626865, 0.9178794, 0.9178794 } + { 3.1791043, 0.8247494, 0.8247494 } + { 4.5, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Thresh_Skin28_Q_Impact_04.Zaahen.tex" + numFrames: u16 = 4 + texDiv: vec2 = { 2, 2 } + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.12 + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.5 + } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterLinger: option[f32] = { 10 } + emitterName: string = "Sheen_6" + importance: u8 = 3 + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { -2, -2, 0 } + } + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 20, 20, 0 } + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.8901961, 0.09803922, 0.09803922, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 1 } + values: list[vec4] = { + { 0.94479287, 0.34148166, 0.34148166, 0 } + { 0.8901961, 0.09803922, 0.09803922, 1 } + { 0.20021363, 0.076081485, 0.09929045, 0 } + } + } + } + pass: i16 = -995 + depthBiasFactors: vec2 = { -1, -4 } + disableBackfaceCull: bool = true + miscRenderFlags: u8 = 1 + isDirectionOriented: flag = true + isRandomStartFrame: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 30, 120, 1 } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 1.2, 1.4, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.2, 0.6, 1 } + values: list[vec3] = { + { 1.5600001, 2.8, 0.5 } + { 1.5600001, 2.8, 1.1 } + { 0.72, 2.8, 0 } + { 0, 5.6, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/XinZhaoRework_Base_LensFlare.Zaahen.tex" + numFrames: u16 = 4 + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.12 + rate: embed = ValueFloat { + constantValue: f32 = 4 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.3 + } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterLinger: option[f32] = { 10 } + emitterName: string = "Sheen_7" + importance: u8 = 3 + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { -2, -2, 0 } + } + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 20, 20, 0 } + } + blendMode: u8 = 4 + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 0.8912642, 0.62404823, 0.62404823, 1 } + { 0.20021363, 0.076081485, 0.09929045, 0 } + } + } + } + pass: i16 = -990 + depthBiasFactors: vec2 = { -1, -4 } + disableBackfaceCull: bool = true + miscRenderFlags: u8 = 1 + isDirectionOriented: flag = true + isRandomStartFrame: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 30, 120, 1 } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 1.2, 1.4, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.2, 0.4, 1 } + values: list[vec3] = { + { 1.5600001, 2.8, 0.5 } + { 1.5600001, 2.8, 1.1 } + { 0.72, 2.8, 0 } + { 0, 4.2, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/XinZhaoRework_Base_LensFlare.Zaahen.tex" + numFrames: u16 = 4 + } + } + particleName: string = "Zaahen_Base_Q_1_Tar" + particlePath: string = "Characters/Zaahen/Skins/Skin0/Particles/Zaahen_Base_Q_1_Tar" + } + "Characters/Zaahen/Skins/Skin0/Particles/Zaahen_Base_Q_Knockup_Tar" = VfxSystemDefinitionData { + complexEmitterDefinitionData: list[pointer] = { + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 4 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.8 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 0.8 } + } + } + lifetime: option[f32] = { 0.2 } + emitterName: string = "BottomSwirl1" + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/CylinderSwirl.Zaahen.scb" + } + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.3453727, 0.3453727, 0.3453727, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.17276995, 0.81784034, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0.26999313 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = -2 + depthBiasFactors: vec2 = { -1, -100 } + disableBackfaceCull: bool = true + isRotationEnabled: flag = true + birthRotationalVelocity0: embed = ValueVector3 { + constantValue: vec3 = { 0, -600, 0 } + } + isLocalOrientation: flag = false + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 15, 6, 15 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 1, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.8, 1.25 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 1, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 15, 6, 15 } } + } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.3, 1 } + values: list[vec3] = { + { 0.65, 0.8, 0.65 } + { 0.8, 0.8, 0.8 } + { 0.8, 0.8, 0.8 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/XinZhaoRework_Base_Typhoon.Zaahen.tex" + birthUvScrollRate: embed = ValueVector2 { + constantValue: vec2 = { -0.5, 0.7 } + } + birthUVOffset: embed = ValueVector2 { + constantValue: vec2 = { 1, 0 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec2] = { { 1, 0 } } + } + } + uvScale: embed = ValueVector2 { + constantValue: vec2 = { 1, 0.5 } + } + particleUVRotateRate: embed = IntegratedValueFloat { + constantValue: f32 = 0.6 + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0 } + values: list[f32] = { 0.6 } + } + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 3 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 1 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 1 } + } + } + particleLinger: option[f32] = { 0.2 } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "SlowSmoke1" + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, 2000, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 0 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 1, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 2000, 0 } } + } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 6, 6, 6 } + } + SpawnShape: pointer = VfxShapeBox { + flags: u8 = 1 + Size: vec3 = { 20, 20, 20 } + } + EmitterPosition: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 0, 0 } } + } + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.48287174, 0.1501793, 0.11985961, 0.41960785 } + dynamics: pointer = VfxAnimatedColorVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.8, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec4] = { { 0.48287174, 0.1501793, 0.11985961, 0.41960785 } } + } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0.3, 0.5, 1 } + values: list[vec4] = { + { 0.55976194, 0.4688487, 0.4688487, 1 } + { 0.27919433, 0.13868925, 0.13868925, 0.47843137 } + { 0.14116122, 0.06677348, 0.06677348, 1 } + } + } + } + pass: i16 = 5 + meshRenderFlags: u8 = 0 + colorLookUpScales: vec2 = { 0.5, 1 } + colorLookUpOffsets: vec2 = { 0.5, 0 } + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0.3, 0.4, 1 } + values: list[f32] = { 0, 0.3, 1 } + } + } + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Base_SmokeErode.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + 0xcb13aff1: f32 = 10 + miscRenderFlags: u8 = 1 + isDirectionOriented: flag = true + isRandomStartFrame: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 1, 0, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 1, 0, 0 } } + } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 70, 100, 100 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.7, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.7, 1.2 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 70, 100, 100 } } + } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 1, 1.4, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.2, 1 } + values: list[vec3] = { + { 1, 0.7, 0.5 } + { 1, 2.1, 1.5 } + { 1.5, 2.38, 1.5 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Emote_Smoke01.Zaahen.tex" + numFrames: u16 = 4 + texDiv: vec2 = { 2, 2 } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 3 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.8 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.4, 1.5 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 0.8 } + } + } + lifetime: option[f32] = { 0.2 } + isSingleParticle: flag = true + emitterName: string = "Smoke1" + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, 1000, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.4, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 1, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 1000, 0 } } + } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 5, 5, 5 } + } + SpawnShape: pointer = VfxShapeLegacy { + emitOffset: embed = ValueVector3 { + constantValue: vec3 = { 20, 0, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 20, 0, 0 } } + } + } + emitRotationAngles: list[embed] = { + ValueFloat { } + ValueFloat { } + } + emitRotationAxes: list[vec3] = { + { 0, 0, 0 } + { 0, 0, 0 } + } + } + EmitterPosition: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 0, 0 } } + } + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.92156863, 0.7607843, 0.49019608, 0.5019608 } + } + Color: embed = ValueColor { + constantValue: vec4 = { 0.8352941, 0.8352941, 0.8352941, 1 } + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.15, 0.5, 1 } + values: list[vec4] = { + { 0.8352941, 0.76322955, 0.64203, 1 } + { 0.46514422, 0.37014994, 0.2587774, 1 } + { 0.53458315, 0.31740794, 0.25059462, 0.66999316 } + { 0.12529093, 0.075174555, 0.025058188, 0.4500038 } + } + } + } + pass: i16 = 4 + colorLookUpTypeY: u8 = 3 + alphaRef: u8 = 2 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.1, 1 } + values: list[f32] = { 0, 0, 1 } + } + } + erosionFeatherIn: f32 = 0.2 + erosionFeatherOut: f32 = 0.2 + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Base_SmokeErode.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + miscRenderFlags: u8 = 1 + isDirectionOriented: flag = true + isRandomStartFrame: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { -135, 0, 0 } + } + directionVelocityScale: f32 = 0.002 + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 60, 125, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.6, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 60, 125, 1 } } + } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.034759358, 0.080213904, 0.14438502, 0.24919786, 0.3657754, 1 } + values: list[vec3] = { + { 0, 0, 0 } + { 0.2682927, 0.2682927, 0.2682927 } + { 0.5, 0.5027579, 0.5027579 } + { 0.6585366, 0.6535755, 0.6535755 } + { 0.76829267, 0.76648456, 0.76648456 } + { 0.80487806, 0.8275755, 0.8275755 } + { 1, 1, 1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Emote_Smoke01.Zaahen.tex" + numFrames: u16 = 4 + texDiv: vec2 = { 2, 2 } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.5 + } + particleLinger: option[f32] = { 0.5 } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "ground_shadow1" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 0, 0 } } + } + } + primitive: pointer = VfxPrimitiveArbitraryQuad { } + blendMode: u8 = 1 + Color: embed = ValueColor { + constantValue: vec4 = { 0.1254902, 0.08235294, 0.0627451, 0.7607843 } + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.2, 1 } + values: list[vec4] = { + { 0.1254902, 0.08235294, 0.0627451, 0.7607843 } + { 0.1254902, 0.08235294, 0.0627451, 0.7607843 } + { 0.1254902, 0.08235294, 0.0627451, 0 } + } + } + } + pass: i16 = -50 + disableBackfaceCull: bool = true + miscRenderFlags: u8 = 1 + particleIsLocalOrientation: flag = true + isUniformScale: flag = true + isGroundLayer: flag = true + useNavmeshMask: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 360, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 90, 360, 0 } } + } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 140, 200, 1 } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/XinZhaoRework_Base_Q_Mound_Shadow.Zaahen.tex" + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.1 + rate: embed = ValueFloat { + constantValue: f32 = 8 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 1 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 1 } + } + } + particleLinger: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "impactStones1" + importance: u8 = 1 + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 100, 1000, -500 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.2, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -0.2, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 100, 1000, -500 } } + } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 0, 3, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 3, 0 } } + } + } + worldAcceleration: embed = IntegratedValueVector3 { + constantValue: vec3 = { 0, -1500, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0 } + values: list[vec3] = { { 0, -1500, 0 } } + } + } + SpawnShape: pointer = VfxShapeLegacy { + emitOffset: embed = ValueVector3 { + constantValue: vec3 = { 100, 0, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 100, 0, 0 } } + } + } + emitRotationAngles: list[embed] = { + ValueFloat { + constantValue: f32 = 1 + } + ValueFloat { } + } + emitRotationAxes: list[vec3] = { + { 0, 1, 0 } + { 0, 0, 0 } + } + } + EmitterPosition: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 0, 0 } } + } + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.61960787, 0.49411765, 0.30588236, 1 } + dynamics: pointer = VfxAnimatedColorVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 1, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.8, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.9, 1 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec4] = { { 0.61960787, 0.49411765, 0.30588236, 1 } } + } + } + pass: i16 = 1 + miscRenderFlags: u8 = 1 + isUniformScale: flag = true + isRandomStartFrame: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 15, 15, 15 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 15, 15, 15 } } + } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.5, 1 } + values: list[vec3] = { + { 0, 0, 0 } + { 1, 1, 1 } + { 0, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Emote_Pebbles.Zaahen.tex" + numFrames: u16 = 16 + texDiv: vec2 = { 4, 4 } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 3 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 1 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 1 } + } + } + particleLinger: option[f32] = { 0.2 } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "SlowSmoke2" + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, 2000, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 0 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 1, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 2000, 0 } } + } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 6, 6, 6 } + } + SpawnShape: pointer = VfxShapeBox { + flags: u8 = 1 + Size: vec3 = { 20, 20, 20 } + } + EmitterPosition: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 0, 0 } } + } + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.92156863, 0.7607843, 0.49019608, 0.11372549 } + dynamics: pointer = VfxAnimatedColorVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.8, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec4] = { { 0.92156863, 0.7607843, 0.49019608, 0.11372549 } } + } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0.3, 0.5, 1 } + values: list[vec4] = { + { 1, 1, 1, 0.30000764 } + { 0.27919433, 0.13868925, 0.13868925, 0.47843137 } + { 0.14116122, 0.06677348, 0.06677348, 1 } + } + } + } + pass: i16 = 5 + meshRenderFlags: u8 = 0 + colorLookUpScales: vec2 = { 0.5, 1 } + colorLookUpOffsets: vec2 = { 0.5, 0 } + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0.3, 0.4, 1 } + values: list[f32] = { 0, 0.3, 1 } + } + } + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Base_SmokeErode.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + miscRenderFlags: u8 = 1 + isDirectionOriented: flag = true + isRandomStartFrame: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 1, 0, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 1, 0, 0 } } + } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 70, 100, 100 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.7, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.7, 1.2 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 70, 100, 100 } } + } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 1, 1.4, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.2, 1 } + values: list[vec3] = { + { 1, 0.7, 0.5 } + { 1, 2.1, 1.5 } + { 1.5, 2.38, 1.5 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Emote_Smoke01.Zaahen.tex" + numFrames: u16 = 4 + texDiv: vec2 = { 2, 2 } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 4 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.1 + } + lifetime: option[f32] = { 0.2 } + isSingleParticle: flag = true + emitterName: string = "circleflare_blend" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 12.815607, 0 } + } + particleColorTexture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/common_color-bellcurve.Zaahen.tex" + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.8769818, 0.71776915, 0.5003128, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.06652807, 0.1964657, 0.38253638, 0.6486486, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0.47272727 } + { 1, 1, 1, 0.21212122 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = 50 + meshRenderFlags: u8 = 0 + alphaRef: u8 = 0 + miscRenderFlags: u8 = 1 + isRandomStartFrame: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 40, 200, 200 } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Thresh_Skin28_Q_Impact_04.Zaahen.tex" + numFrames: u16 = 4 + texDiv: vec2 = { 2, 2 } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 2 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.2 + } + lifetime: option[f32] = { 0.2 } + isSingleParticle: flag = true + emitterName: string = "circleflare_blend1" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 12.815607, 0 } + } + particleColorTexture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/common_color-bellcurve.Zaahen.tex" + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.8627451, 0.49019608, 0.3764706, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 0.1964657, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 0.85265887, 0.27139696, 0.27139696, 1 } + { 0.7837034, 0.09224079, 0.09224079, 0 } + } + } + } + pass: i16 = 50 + meshRenderFlags: u8 = 0 + alphaRef: u8 = 0 + miscRenderFlags: u8 = 1 + isRandomStartFrame: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 40, 200, 200 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.25, 1 } + values: list[vec3] = { + { 1, 1, 0 } + { 1, 1, 1 } + { 0, 0.5, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Thresh_Skin28_Q_Impact_04.Zaahen.tex" + numFrames: u16 = 4 + texDiv: vec2 = { 2, 2 } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 2 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.4 + } + lifetime: option[f32] = { 0.2 } + isSingleParticle: flag = true + emitterName: string = "circleflare_blend2" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 12.815607, 0 } + } + particleColorTexture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/common_color-bellcurve.Zaahen.tex" + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.17181659, 0.07031357, 0.067200735, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.06652807, 0.1964657, 0.38253638, 0.6486486, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0.47272727 } + { 1, 1, 1, 0.21212122 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = -50 + meshRenderFlags: u8 = 0 + alphaRef: u8 = 0 + miscRenderFlags: u8 = 1 + isUniformScale: flag = true + isRandomStartFrame: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 1, 0, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 1, 0, 0 } } + } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 40, 200, 200 } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 1.5, 1, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.08212058, 0.17525057, 1 } + values: list[vec3] = { + { 0, 1, 1 } + { 2.4626865, 0.9178794, 0.9178794 } + { 3.1791046, 0.8247494, 0.8247494 } + { 4.5, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Thresh_Skin28_Q_Impact_04.Zaahen.tex" + numFrames: u16 = 4 + texDiv: vec2 = { 2, 2 } + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.05 + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.3 + } + particleLinger: option[f32] = { 10.2 } + lifetime: option[f32] = { 1.05 } + isSingleParticle: flag = true + emitterName: string = "flash_Mult" + importance: u8 = 3 + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.92156863, 0.7607843, 0.49019608, 0.5019608 } + } + Color: embed = ValueColor { + constantValue: vec4 = { 1, 1, 1, 0.7000076 } + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.5, 1 } + values: list[vec4] = { + { 1, 1, 1, 0.7000076 } + { 1, 1, 1, 0.7000076 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = -1 + miscRenderFlags: u8 = 1 + isUniformScale: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 1, 0, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 1, 0, 0 } } + } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 230, 2, 2 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 1, 1, 1 } + { 0.3, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/JarvanIV_Skin35_R_glow.Zaahen.tex" + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.1 + rate: embed = ValueFloat { + constantValue: f32 = 7 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.5 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 0.9, 1 } + keyValues: list[f32] = { 0.2, 1, 1.5 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 0.5 } + } + } + particleLinger: option[f32] = { 1 } + lifetime: option[f32] = { 0.3 } + isSingleParticle: flag = true + emitterName: string = "Sparkles" + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 555, 1, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 0.85 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.75, 1.1 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 555, 1, 0 } } + } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 8, 8, 8 } + } + worldAcceleration: embed = IntegratedValueVector3 { + constantValue: vec3 = { 0, 200, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 200, 0 } } + } + } + SpawnShape: pointer = VfxShapeLegacy { + emitOffset: embed = ValueVector3 { + constantValue: vec3 = { 100, 0, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.2, 1 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 100, 0, 0 } } + } + } + emitRotationAngles: list[embed] = { + ValueFloat { + constantValue: f32 = 1 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 1 } + } + } + ValueFloat { + constantValue: f32 = 1 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 1 } + } + } + } + emitRotationAxes: list[vec3] = { + { 0, 1.0000001, 0 } + { 0, 0, 1.0000001 } + } + } + blendMode: u8 = 5 + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 0.3, 0.6, 1 } + values: list[vec4] = { + { 0.9411765, 0.06666667, 0.07450981, 0 } + { 0.9411765, 0.06666667, 0.07450981, 1 } + { 0.9411765, 0.06666667, 0.07450981, 1 } + { 0.23137255, 0, 0.015686275, 1 } + { 0.23137255, 0, 0.015686275, 0 } + } + } + } + pass: i16 = 10 + miscRenderFlags: u8 = 1 + isUniformScale: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 1, 0, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 1, 0, 0 } } + } + } + birthRotationalVelocity0: embed = ValueVector3 { + constantValue: vec3 = { -300, 0, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 50, 65, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 0.9, 1 } + keyValues: list[f32] = { 0.3, 1, 2 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 50, 65, 0 } } + } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.1, 0.19223854, 0.37142858, 1 } + values: list[vec3] = { + { 0, 0, 0 } + { 1, 1, 1 } + { 0.21186441, 0.5, 0.5 } + { 0.56271183, 0.33380866, 0.33380866 } + { 0, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Morgana_Base_P_StardustMoteAlpha.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 2 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.85 + } + particleLinger: option[f32] = { } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "StrokeDissolve_primary" + importance: u8 = 3 + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 1, 0 } + } + primitive: pointer = VfxPrimitiveArbitraryQuad { } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.919997, 0.7600061, 0.4899977, 0.20999466 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.2, 0.8, 1 } + values: list[vec4] = { + { 0.80784315, 0.5137255, 0.42352942, 1 } + { 1, 1, 1, 1 } + { 0.92156863, 0.7607843, 0.49019608, 0.5019608 } + { 0.13725491, 0.007843138, 0.05882353, 1 } + } + } + } + pass: i16 = 5 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.55 } + values: list[f32] = { 0.15, 1 } + } + } + erosionSliceWidth: f32 = 1 + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Aatrox_Skin11_AA_Wall_Erosion.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + erosionMapAddressMode: u8 = 0 + } + disableBackfaceCull: bool = true + isUniformScale: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 360, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 90, 360, 0 } } + } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 150, 120, 120 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.2, 1 } + values: list[vec3] = { + { 0.5, 0.25, 0.1 } + { 0.75, 0.75, 0.5 } + { 1, 1.2, 1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Aatrox_Skin11_AA_Flares_03.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 2 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.35 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.8, 1.1 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 0.35 } + } + } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "Ray_DARK_BLACK" + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, -100, 0 } + } + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + primitive: pointer = VfxPrimitiveRay { } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.9848325, 0.8168002, 0.8168002, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.0927835, 0.3530928, 0.5, 1 } + values: list[vec4] = { + { 1, 0.9411765, 0.72156864, 1 } + { 0.85156024, 0.6632029, 0.39346913, 1 } + { 0.92156863, 0.7607843, 0.49019608, 1 } + { 0.92156863, 0.7607843, 0.49019608, 0.5019608 } + { 0.20851454, 0.08905165, 0.14770733, 1 } + } + } + } + pass: i16 = 50 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.55 } + values: list[f32] = { 0, 1 } + } + } + erosionSliceWidth: f32 = 1 + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Aatrox_Skin11_Einstein_04_mult.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + erosionMapAddressMode: u8 = 0 + } + miscRenderFlags: u8 = 1 + isDirectionOriented: flag = true + isRandomStartFrame: flag = true + isRotationEnabled: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { -90, 0, 360 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 1, 1 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1.5 } + } + } + times: list[f32] = { 0 } + values: list[vec3] = { { -90, 0, 360 } } + } + } + directionVelocityScale: f32 = 1 + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 100, 120, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1.1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.65, 1.1 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 100, 120, 0 } } + } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 1, 1, 1.2 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.1, 1 } + values: list[vec3] = { + { 0, 0, 0 } + { 1, 2, 0 } + { 1, 3, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Aatrox_Skin11_Particles_2_78.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 2 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.3 + } + particleLinger: option[f32] = { 10.2 } + lifetime: option[f32] = { 1.05 } + isSingleParticle: flag = true + emitterName: string = "flash_Mult1" + importance: u8 = 3 + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.8901961, 0.2901961, 0.09803922, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = -1 + miscRenderFlags: u8 = 1 + isUniformScale: flag = true + isGroundLayer: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 1, 0, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 1, 0, 0 } } + } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 100, 2, 2 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 1, 1, 1 } + { 1.5, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Aura_Self.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 8 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.4 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.65, 1 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 0.4 } + } + } + particleLinger: option[f32] = { } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "Smoke_Burst" + importance: u8 = 3 + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 1200, 1000, 1200 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.3, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 1200, 1000, 1200 } } + } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 8, 8, 8 } + } + worldAcceleration: embed = IntegratedValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 0, 0 } } + } + } + SpawnShape: pointer = VfxShapeBox { + flags: u8 = 1 + Size: vec3 = { 5, 5, 5 } + } + primitive: pointer = VfxPrimitiveArbitraryQuad { } + blendMode: u8 = 4 + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.2, 0.5, 1 } + values: list[vec4] = { + { 0.9370413, 0.8512093, 0.70670635, 0 } + { 0.92156863, 0.7607843, 0.49019608, 1 } + { 0.6374914, 0.50202185, 0.273991, 0.5019608 } + { 0.13698024, 0.0508278, 0.073121235, 0 } + } + } + } + pass: i16 = 10 + alphaRef: u8 = 0 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.25633293, 0.6982072, 1 } + values: list[f32] = { 0, 0, 0.2, 0.5 } + } + } + erosionFeatherOut: f32 = 0.2 + erosionSliceWidth: f32 = 2 + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Emote_Flames_02.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + depthBiasFactors: vec2 = { -1, -15 } + disableBackfaceCull: bool = true + miscRenderFlags: u8 = 1 + isDirectionOriented: flag = true + isRandomStartFrame: flag = true + isGroundLayer: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, -90, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 90, -90, 0 } } + } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 160, 120, 100 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.8, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.8, 1 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 160, 120, 100 } } + } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 0.5, 0.5, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.2, 0.5, 1 } + values: list[vec3] = { + { 0.25, 0.3, 0.8 } + { 0.325, 0.375, 0.75 } + { 0.5, 0.55, 1 } + { 0.45, 0.65, 1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Shapes02.Zaahen.tex" + numFrames: u16 = 4 + texDiv: vec2 = { 2, 2 } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 2 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.2 + } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterLinger: option[f32] = { 10 } + emitterName: string = "Sheen3" + importance: u8 = 3 + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, 450, 0 } + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, -50, 0 } + } + primitive: pointer = VfxPrimitiveRay { } + blendMode: u8 = 4 + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 0.6, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 0.92156863, 0.7607843, 0.49019608, 1 } + { 0.16292058, 0.059235524, 0.09861906, 0 } + } + } + } + pass: i16 = 810 + disableBackfaceCull: bool = true + miscRenderFlags: u8 = 1 + isDirectionOriented: flag = true + isRandomStartFrame: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { -90, 0, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 30, 120, 1 } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 3, 3, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.2, 1 } + values: list[vec3] = { + { 1.5, 1.5, 0.5 } + { 3.8999999, 3.8999999, 1.3 } + { 0, 3, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/XinZhaoRework_Base_LensFlare.Zaahen.tex" + numFrames: u16 = 4 + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.3 + } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "Temp_GroundGlow" + EmitterPosition: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 0, 0 } } + } + } + primitive: pointer = VfxPrimitiveArbitraryQuad { } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.8, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec4] = { { 1, 1, 1, 1 } } + } + } + Color: embed = ValueColor { + constantValue: vec4 = { 0.39000535, 0.020004578, 0.12607004, 1 } + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 0.75, 1 } + values: list[vec4] = { + { 0.39000535, 0.020004578, 0.12607004, 0 } + { 0.39000535, 0.020004578, 0.12607004, 1 } + { 0.39000535, 0.020004578, 0.12607004, 1 } + { 0.39000535, 0.020004578, 0.12607004, 0 } + } + } + } + pass: i16 = -5 + miscRenderFlags: u8 = 1 + particleIsLocalOrientation: flag = true + isUniformScale: flag = true + isGroundLayer: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 0, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 100, 40, 50 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.13, 1 } + values: list[vec3] = { + { 0.5, 0.5, 0 } + { 1.5, 5, 1 } + { 2, 5, 1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Rell_Base_Alpha_Glow.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.1 + } + particleLinger: option[f32] = { 12 } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "Temp_GroundGlow1" + EmitterPosition: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 0, 0 } } + } + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.8, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec4] = { { 1, 1, 1, 1 } } + } + } + Color: embed = ValueColor { + constantValue: vec4 = { 0.8901961, 0.2901961, 0.09803922, 0.61960787 } + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 0.75, 1 } + values: list[vec4] = { + { 0.8901961, 0.2901961, 0.09803922, 0 } + { 0.8901961, 0.2901961, 0.09803922, 0.61960787 } + { 0.8901961, 0.2901961, 0.09803922, 0.61960787 } + { 0.8901961, 0.2901961, 0.09803922, 0 } + } + } + } + miscRenderFlags: u8 = 1 + particleIsLocalOrientation: flag = true + isUniformScale: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 0, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 110, 40, 50 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.13, 1 } + values: list[vec3] = { + { 2, 0.5, 0 } + { 0.5, 5, 1 } + { 3, 5, 1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Rell_Base_Alpha_Glow.Zaahen.tex" + } + } + particleName: string = "Zaahen_Base_Q_Knockup_Tar" + particlePath: string = "Characters/Zaahen/Skins/Skin0/Particles/Zaahen_Base_Q_Knockup_Tar" + } + "Characters/Zaahen/Skins/Skin0/Particles/Zaahen_Base_E_AoE_Tar" = VfxSystemDefinitionData { + complexEmitterDefinitionData: list[pointer] = { + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.05 + rate: embed = ValueFloat { + constantValue: f32 = 200 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.5 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 0.9, 1 } + keyValues: list[f32] = { 0.2, 1, 1.5 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 0.5 } + } + } + particleLinger: option[f32] = { 1 } + lifetime: option[f32] = { 0.1 } + emitterName: string = "Sparkles" + birthOrbitalVelocity: embed = ValueVector3 { + constantValue: vec3 = { 1, 1, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 1, 1, 1 } } + } + } + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 1000, 500, 1000 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1.1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 1000, 500, 1000 } } + } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 8, 2, 8 } + } + worldAcceleration: embed = IntegratedValueVector3 { + constantValue: vec3 = { 0, 200, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 200, 0 } } + } + } + SpawnShape: pointer = VfxShapeBox { + flags: u8 = 1 + Size: vec3 = { 50, 50, 50 } + } + blendMode: u8 = 4 + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 0.3, 0.6, 1 } + values: list[vec4] = { + { 0.928069, 0.8185092, 0.6716716, 0 } + { 0.91024643, 0.65159076, 0.65392536, 1 } + { 0.93354696, 0.4036927, 0.4084535, 1 } + { 0.9411765, 0.06666667, 0.07450981, 1 } + { 0.23137255, 0, 0.015686275, 0 } + } + } + } + pass: i16 = 10 + miscRenderFlags: u8 = 1 + isDirectionOriented: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 1, 0, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 1, 0, 0 } } + } + } + birthRotationalVelocity0: embed = ValueVector3 { + constantValue: vec3 = { -300, 0, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 25, 50, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.3, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 1, 2 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 25, 50, 0 } } + } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.1, 0.19223854, 0.37142858, 1 } + values: list[vec3] = { + { 0, 0, 0 } + { 1, 1, 1 } + { 0.21186441, 0.5, 0.5 } + { 0.56271183, 0.33380866, 0.33380866 } + { 0, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_R_Sparks.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.3 + } + particleLinger: option[f32] = { 10.2 } + lifetime: option[f32] = { 1 } + emitterName: string = "Background" + FlexShapeDefinition: pointer = VfxFlexShapeDefinitionData { + scaleEmitOffsetByBoundObjectSize: f32 = 0.005 + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 1, 1, 0.9799954 } + } + Color: embed = ValueColor { + constantValue: vec4 = { 0.24309148, 0.040939957, 0.07330434, 1 } + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.3, 1 } + values: list[vec4] = { + { 0.24309148, 0.040939957, 0.07330434, 1 } + { 0.24309148, 0.040939957, 0.07330434, 0.8399939 } + { 0.24309148, 0.040939957, 0.07330434, 0 } + } + } + } + pass: i16 = -20 + alphaRef: u8 = 4 + miscRenderFlags: u8 = 1 + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 220, 170, 1 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.2, 1 } + values: list[vec3] = { + { 0.3, 0.3, 11 } + { 1, 1, 1 } + { 1.2, 1.2, 1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Aura_Self.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 2 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.1 + } + lifetime: option[f32] = { 0.2 } + isSingleParticle: flag = true + emitterName: string = "circleflare_blend" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 12.815607, 0 } + } + particleColorTexture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/common_color-bellcurve.Zaahen.tex" + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.91340506, 0.8514229, 0.64872205, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.06652807, 0.1964657, 0.38253638, 0.6486486, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0.47272727 } + { 1, 1, 1, 0.21212122 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = -50 + meshRenderFlags: u8 = 0 + alphaRef: u8 = 0 + isUniformScale: flag = true + isRandomStartFrame: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 1, 0, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 1, 0, 0 } } + } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 40, 200, 200 } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 1.5, 1, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.08212058, 0.17525057, 1 } + values: list[vec3] = { + { 0, 1, 1 } + { 2.4626865, 0.9178794, 0.9178794 } + { 3.1791046, 0.8247494, 0.8247494 } + { 4.5, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Thresh_Skin28_Q_Impact_04.Zaahen.tex" + numFrames: u16 = 4 + texDiv: vec2 = { 2, 2 } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 2 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.4 + } + lifetime: option[f32] = { 0.2 } + isSingleParticle: flag = true + emitterName: string = "circleflare_blend1" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 12.815607, 0 } + } + particleColorTexture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/common_color-bellcurve.Zaahen.tex" + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.17181659, 0.07031357, 0.067200735, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.06652807, 0.1964657, 0.38253638, 0.6486486, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0.47272727 } + { 1, 1, 1, 0.21212122 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = -50 + meshRenderFlags: u8 = 0 + alphaRef: u8 = 0 + isUniformScale: flag = true + isRandomStartFrame: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 1, 0, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 1, 0, 0 } } + } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 40, 200, 200 } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 1.5, 1, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.08212058, 0.17525057, 1 } + values: list[vec3] = { + { 0, 1, 1 } + { 2.4626865, 0.9178794, 0.9178794 } + { 3.1791046, 0.8247494, 0.8247494 } + { 4.5, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Thresh_Skin28_Q_Impact_04.Zaahen.tex" + numFrames: u16 = 4 + texDiv: vec2 = { 2, 2 } + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.05 + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.3 + } + particleLinger: option[f32] = { 10.2 } + lifetime: option[f32] = { 1.05 } + isSingleParticle: flag = true + emitterName: string = "flash_Mult" + importance: u8 = 3 + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.31302357, 0.013519494, 0.11020066, 1 } + } + Color: embed = ValueColor { + constantValue: vec4 = { 1, 1, 1, 0.7000076 } + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.5, 1 } + values: list[vec4] = { + { 1, 1, 1, 0.7000076 } + { 1, 1, 1, 0.7000076 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = -1 + miscRenderFlags: u8 = 1 + isUniformScale: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 1, 0, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 1, 0, 0 } } + } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 230, 2, 2 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 1, 1, 1 } + { 0.3, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/JarvanIV_Skin35_R_glow.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.85 + } + particleLinger: option[f32] = { } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "StrokeDissolve_primary1" + importance: u8 = 3 + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 1, 1, 0.7600061 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.2, 6, 1 } + values: list[vec4] = { + { 0.919997, 0.11999695, 0.11000229, 0.14000152 } + { 0.6156863, 0.12941177, 0.12156863, 1 } + { 0.23921569, 0.09019608, 0.12941177, 1 } + { 0.14000152, 0.00999466, 0.059998475, 0 } + } + } + } + pass: i16 = 5 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.55 } + values: list[f32] = { 0.15, 1 } + } + } + erosionSliceWidth: f32 = 1 + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Aatrox_Skin11_AA_Wall_Erosion.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + erosionMapAddressMode: u8 = 0 + } + 0xcb13aff1: f32 = -10 + disableBackfaceCull: bool = true + miscRenderFlags: u8 = 1 + isUniformScale: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 360, 1, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 360, 1, 0 } } + } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 100, 120, 120 } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 1.5, 1.5, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.2, 1 } + values: list[vec3] = { + { 0.75, 0.375, 0.1 } + { 1.125, 1.125, 0.5 } + { 1.5, 1.8000001, 1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Aatrox_Skin11_AA_Flares_03.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.3 + } + particleLinger: option[f32] = { 10.3 } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "flash6" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + FlexShapeDefinition: pointer = VfxFlexShapeDefinitionData { + scaleBirthScaleByBoundObjectSize: f32 = 0.005 + scaleEmitOffsetByBoundObjectSize: f32 = 0.005 + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.9061265, 0.9061265, 0.9061265, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 1 } + values: list[vec4] = { + { 0.8844129, 0.7690547, 0.5053635, 1 } + { 0.50980395, 0.011764706, 0.101960786, 1 } + } + } + } + pass: i16 = 55 + alphaRef: u8 = 0 + miscRenderFlags: u8 = 1 + isUniformScale: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 1, 0, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 1, 0, 0 } } + } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 75, 100, 1 } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 1, 1.5, 2 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.3, 0.6, 1 } + values: list[vec3] = { + { 0, 0, 0 } + { 1, 1.5, 2 } + { 0.2, 0.3, 0.4 } + { 0, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Naafiri_Base_R_Flash_sharp.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.3 + } + particleLinger: option[f32] = { 10.3 } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "flash7" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + FlexShapeDefinition: pointer = VfxFlexShapeDefinitionData { + scaleBirthScaleByBoundObjectSize: f32 = 0.005 + scaleEmitOffsetByBoundObjectSize: f32 = 0.005 + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.92156863, 0.7607843, 0.49019608, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 0.50980395, 0.011764706, 0.101960786, 1 } + } + } + } + pass: i16 = 50 + alphaRef: u8 = 0 + miscRenderFlags: u8 = 1 + isUniformScale: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 1, 0, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 1, 0, 0 } } + } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 100, 100, 1 } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 3, 1.5, 2 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.3, 0.6, 1 } + values: list[vec3] = { + { 0, 0, 0 } + { 3, 1.5, 2 } + { 0.6, 0.3, 0.4 } + { 0, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Naafiri_Base_R_Flash_sharp.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 2 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.2 + } + particleLinger: option[f32] = { 1 } + lifetime: option[f32] = { 0.25 } + isSingleParticle: flag = true + emitterName: string = "Flash9" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.92156863, 0.7607843, 0.49019608, 1 } + } + Color: embed = ValueColor { + constantValue: vec4 = { 1, 1, 1, 0.972549 } + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 1 } + values: list[vec4] = { + { 1, 1, 1, 0.972549 } + { 1, 1, 1, 0.972549 } + } + } + } + pass: i16 = 500 + meshRenderFlags: u8 = 0 + alphaRef: u8 = 0 + depthBiasFactors: vec2 = { -1, -20 } + miscRenderFlags: u8 = 1 + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 150, 50, 300 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.5, 1 } + values: list[vec3] = { + { 0.5, 0.5, 0.5 } + { 1, 1, 1 } + { 0.25, 0.25, 0.25 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/TahmKench_Skin30_bigglow023.Zaahen.tex" + } + } + particleName: string = "Zaahen_Base_E_AoE_Tar" + particlePath: string = "Characters/Zaahen/Skins/Skin0/Particles/Zaahen_Base_E_AoE_Tar" + soundPersistentDefault: string = "Play_sfx_Zaahen_ZaahenEAttack_hit_inner" + flags: u16 = 214 + } + "Characters/Zaahen/Skins/Skin0/Particles/Zaahen_Base_w_mis" = VfxSystemDefinitionData { + complexEmitterDefinitionData: list[pointer] = { + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.3 + } + lifetime: option[f32] = { 3 } + isSingleParticle: flag = true + childParticleSetDefinition: pointer = VfxChildParticleSetDefinitionData { + childrenIdentifiers: list[embed] = { + VfxChildIdentifier { + effectKey: hash = "Zaahen_W_Mis_Death" + } + } + childEmitOnDeath: bool = true + } + emitterName: string = "Child_Death" + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, 800, 0 } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 0, 3, 0 } + } + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, -300, 0 } + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.5 + } + lifetime: option[f32] = { 3 } + isSingleParticle: flag = true + childParticleSetDefinition: pointer = VfxChildParticleSetDefinitionData { + childrenIdentifiers: list[embed] = { + VfxChildIdentifier { + effectKey: hash = "Zaahen_W_Mis_Child" + } + } + } + emitterName: string = "Child_Missile" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + } + } + particleName: string = "Zaahen_Base_w_mis" + particlePath: string = "Characters/Zaahen/Skins/Skin0/Particles/Zaahen_Base_w_mis" + } + "Characters/Zaahen/Skins/Skin0/Particles/Zaahen_Base_P_Revive" = VfxSystemDefinitionData { + complexEmitterDefinitionData: list[pointer] = { + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.2 + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 1 + } + lifetime: option[f32] = { 4 } + emitterName: string = "Dlack_avatar3" + importance: u8 = 3 + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + primitive: pointer = VfxPrimitiveAttachedMesh { + mMesh: embed = VfxMeshDefinitionData { + mSubmeshesToDraw: list[hash] = { "BODY", "Wings", "weapon" } + mLockMeshToAttachment: bool = true + } + } + blendMode: u8 = 2 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.4899977, 0.8200046, 0.919997, 0.2500038 } + } + pass: i16 = -5000 + 0xcb13aff1: f32 = -1 + disableBackfaceCull: bool = true + particleIsLocalOrientation: flag = true + isUniformScale: flag = true + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/color-hold.Zaahen.tex" + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 4 + rate: embed = ValueFloat { + constantValue: f32 = 2 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 1 + } + lifetime: option[f32] = { 5 } + isSingleParticle: flag = true + emitterName: string = "Fresnel" + importance: u8 = 5 + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 10, 0, 10 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 10, 0, 10 } } + } + } + Linger: pointer = VfxLingerDefinitionData { + UseSeparateLingerColor: flag = true + SeparateLingerColor: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0.5, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + } + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + primitive: pointer = VfxPrimitiveAttachedMesh { + mMesh: embed = VfxMeshDefinitionData { + mLockMeshToAttachment: bool = true + } + } + blendMode: u8 = 2 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.4899977, 0.8200046, 0.919997, 0.93000686 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.3, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + } + } + } + pass: i16 = -4990 + reflectionDefinition: pointer = VfxReflectionDefinitionData { + reflectionMapTexture: string = "ASSETS/Shared/Particles/Generic_White_Cubemap.TFT_Set15.dds" + reflectionOpacityDirect: f32 = -1 + reflectionOpacityGlancing: f32 = 0.1 + reflectionFresnel: f32 = 0.3 + reflectionFresnelColor: vec4 = { 0.4269627, 0.82949567, 0.90286106, 1 } + fresnel: f32 = 0.1 + fresnelColor: vec4 = { 0, 0, 0, 1 } + } + 0xcb13aff1: f32 = -2 + particleIsLocalOrientation: flag = true + isUniformScale: flag = true + hasPostRotateOrientation: flag = true + isRandomStartFrame: flag = true + isRotationEnabled: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 0, 180, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 1.002, 1, 1 } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Base_SmokeErode.Zaahen.tex" + numFrames: u16 = 4 + birthUvScrollRate: embed = ValueVector2 { + constantValue: vec2 = { 0.4, 0.2 } + } + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.2 + rate: embed = ValueFloat { + constantValue: f32 = 2 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 1.5 + } + lifetime: option[f32] = { 4 } + emitterName: string = "DarkGlow3" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + SpawnShape: pointer = 0xee39916f { + emitOffset: vec3 = { 0, 120, 0 } + } + FlexShapeDefinition: pointer = VfxFlexShapeDefinitionData { + scaleBirthScaleByBoundObjectSize: f32 = 0.005 + scaleEmitOffsetByBoundObjectSize: f32 = 0.005 + } + blendMode: u8 = 2 + Color: embed = ValueColor { + constantValue: vec4 = { 0.666667, 1, 0.952941, 0.8 } + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.3, 1 } + values: list[vec4] = { + { 0.666667, 1, 0.952941, 0 } + { 0.666667, 1, 0.952941, 0.8 } + { 0.666667, 1, 0.952941, 0 } + } + } + } + pass: i16 = -5000 + softParticleParams: pointer = VfxSoftParticleDefinitionData { + beginIn: f32 = 100 + deltaIn: f32 = 20 + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 160, 145, 125 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 0.7, 0.7, 0.7 } + { 1, 1, 1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Naafiri_Base_Foundation_Glow01.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 4 + } + lifetime: option[f32] = { 5 } + isSingleParticle: flag = true + emitterName: string = "AVATAR9" + importance: u8 = 3 + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + primitive: pointer = VfxPrimitiveAttachedMesh { + mMesh: embed = VfxMeshDefinitionData { + mSubmeshesToDraw: list[hash] = { "Wings", "BODY" } + mLockMeshToAttachment: bool = true + } + } + blendMode: u8 = 1 + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.2, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + } + } + } + pass: i16 = -10 + censorModulateValue: vec4 = { 0.7893797, 0.85181963, 0.30569926, 1 } + modulationFactor: vec4 = { 0.8202487, 0.046143282, 0.046143282, 1 } + 0xcb13aff1: f32 = 50 + particleIsLocalOrientation: flag = true + isUniformScale: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 1.02, 1, 1 } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/color-hold.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 2 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 4 + } + isSingleParticle: flag = true + emitterName: string = "HologramAdd1" + IsEmitterSpace: flag = true + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + primitive: pointer = VfxPrimitiveAttachedMesh { + mMesh: embed = VfxMeshDefinitionData { + mSubmeshesToDraw: list[hash] = { "BODY" } + mLockMeshToAttachment: bool = true + } + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.919997, 0.7600061, 0.4899977, 0.5000076 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = -95 + uvParallaxScale: f32 = 0.00075 + 0xcb13aff1: f32 = -4 + disableBackfaceCull: bool = true + particleIsLocalOrientation: flag = true + isUniformScale: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 1.001, 1, 1 } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_E_Body_Mask.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 30 + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.3, 1 } + values: list[f32] = { 0, 30, 0 } + } + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.4 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 0.4 } + } + } + lifetime: option[f32] = { 3 } + fieldCollectionDefinition: pointer = VfxFieldCollectionDefinitionData { + fieldNoiseDefinitions: list[embed] = { + VfxFieldNoiseDefinitionData { + radius: embed = ValueFloat { + constantValue: f32 = 500 + } + frequency: embed = ValueFloat { + constantValue: f32 = 10 + } + velocityDelta: embed = ValueFloat { + constantValue: f32 = 50 + } + axisFraction: vec3 = { 1, 1, 1 } + } + } + } + emitterName: string = "Sparks2" + birthOrbitalVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, 1.2, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 1.2, 0 } } + } + } + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 50, 200, -100 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.4, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 50, 200, -100 } } + } + } + velocity: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, -10 } + } + SpawnShape: pointer = VfxShapeBox { + flags: u8 = 1 + Size: vec3 = { 60, 60, 30 } + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 150, 0 } + } + Color: embed = ValueColor { + constantValue: vec4 = { 0.97087055, 0.7678035, 0.64429694, 1 } + } + pass: i16 = 900 + miscRenderFlags: u8 = 1 + isDirectionOriented: flag = true + isUniformScale: flag = true + isRandomStartFrame: flag = true + directionVelocityScale: f32 = 0.004 + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 35, 10, 40 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.15, 0.7 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 35, 10, 40 } } + } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.1, 0.3, 0.6, 1 } + values: list[vec3] = { + { 0.1, 0.1, 0.1 } + { 0.3, 0.3, 0.3 } + { 1.4, 1.4, 1.4 } + { 0.3, 0.3, 0.3 } + { 0.1, 0.1, 0.1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zyra_Skin36_Add_Gold.Zaahen.tex" + numFrames: u16 = 4 + texDiv: vec2 = { 2, 2 } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 2 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.2 + } + lifetime: option[f32] = { 2 } + isSingleParticle: flag = true + emitterName: string = "flareRing" + importance: u8 = 1 + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 150, 0 } + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 1, 1, 1, 0.2500038 } + } + Color: embed = ValueColor { + constantValue: vec4 = { 0.92156863, 0.7607843, 0.49019608, 1 } + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 1 } + values: list[vec4] = { + { 0.92156863, 0.7607843, 0.49019608, 1 } + { 0, 0, 0, 0 } + } + } + } + pass: i16 = 22 + softParticleParams: pointer = VfxSoftParticleDefinitionData { + beginIn: f32 = 0.7 + deltaIn: f32 = 0.3 + deltaOut: f32 = 0.3 + } + miscRenderFlags: u8 = 1 + isUniformScale: flag = true + isGroundLayer: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 360, 0, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 360, 0, 0 } } + } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 300, 250, 1 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 1, 1, 1 } + { 1.2, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_lens-rainbow.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 2 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.2 + } + lifetime: option[f32] = { 2 } + isSingleParticle: flag = true + emitterName: string = "Crown" + importance: u8 = 3 + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 150, 0 } + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.919997, 0.7600061, 0.4899977, 0.2500038 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = -5 + alphaRef: u8 = 0 + miscRenderFlags: u8 = 1 + isUniformScale: flag = true + isGroundLayer: flag = true + useNavmeshMask: flag = true + isLocalOrientation: flag = false + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 700, 250, 1 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 1, 1, 1 } + { 1.2, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/AurelionSol_Skin31_E_Comet_Flare.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.125 + } + particleLinger: option[f32] = { 0.2 } + lifetime: option[f32] = { 2 } + isSingleParticle: flag = true + emitterName: string = "CAS_STAR" + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, 50, 0 } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 0, 3, 0 } + } + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 150, 0 } + } + blendMode: u8 = 4 + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0.4, 0.5 } + values: list[vec4] = { + { 0, 0, 0, 1 } + { 1, 1, 1, 1 } + } + } + } + pass: i16 = 320 + miscRenderFlags: u8 = 1 + isUniformScale: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 120, 230, 0 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.3, 1 } + values: list[vec3] = { + { 3, 1.5, 1.5 } + { 0.8, 0.8, 0.8 } + { 0.2, 0.2, 0.2 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Ahri_Skin89_Sparkle.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.2 + } + particleLinger: option[f32] = { 0.2 } + lifetime: option[f32] = { 2 } + isSingleParticle: flag = true + emitterName: string = "CAS_STAR1" + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, 50, 0 } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 0, 3, 0 } + } + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 150, 0 } + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.919997, 0.7600061, 0.4899977, 1 } + } + pass: i16 = 310 + miscRenderFlags: u8 = 1 + isUniformScale: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 150, 230, 0 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.3, 1 } + values: list[vec3] = { + { 3, 1.5, 1.5 } + { 0.8, 0.8, 0.8 } + { 0.2, 0.2, 0.2 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Ahri_Skin89_Sparkle.Zaahen.tex" + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.1 + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.35 + } + particleLinger: option[f32] = { 1 } + lifetime: option[f32] = { 9 } + isSingleParticle: flag = true + emitterName: string = "avatar11" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + primitive: pointer = VfxPrimitiveAttachedMesh { + mMesh: embed = VfxMeshDefinitionData { + mLockMeshToAttachment: bool = true + } + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.919997, 0.7600061, 0.4899977, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1790235, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 0.3783784 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = 1 + 0xcb13aff1: f32 = -1 + particleIsLocalOrientation: flag = true + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/color-hold.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.1 + } + particleLinger: option[f32] = { 1 } + lifetime: option[f32] = { 9 } + isSingleParticle: flag = true + emitterName: string = "Dark_flash_Avatar1" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + primitive: pointer = VfxPrimitiveAttachedMesh { + mMesh: embed = VfxMeshDefinitionData { + mLockMeshToAttachment: bool = true + } + } + blendMode: u8 = 1 + Color: embed = ValueColor { + constantValue: vec4 = { 0.14901961, 0.043076217, 0.02745098, 1 } + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.646895, 1 } + values: list[vec4] = { + { 0.14901961, 0.043076217, 0.02745098, 1 } + { 0.14901961, 0.043076217, 0.02745098, 1 } + { 0.14901961, 0.043076217, 0.02745098, 0 } + } + } + } + 0xcb13aff1: f32 = -2 + particleIsLocalOrientation: flag = true + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/color-hold.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 20 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 2 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 2 } + } + } + lifetime: option[f32] = { 3 } + isSingleParticle: flag = true + emitterName: string = "Sparks4" + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 500, 500, 500 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 500, 500, 500 } } + } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 10, 10, 10 } + } + velocity: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, -10 } + } + worldAcceleration: embed = IntegratedValueVector3 { + constantValue: vec3 = { 0, 20, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 20, 0 } } + } + } + SpawnShape: pointer = VfxShapeBox { + flags: u8 = 1 + Size: vec3 = { 60, 60, 30 } + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 150, 0 } + } + Color: embed = ValueColor { + constantValue: vec4 = { 0.9795529, 0.80729383, 0.7025254, 1 } + } + pass: i16 = 900 + miscRenderFlags: u8 = 1 + particleIsLocalOrientation: flag = true + isUniformScale: flag = true + isRandomStartFrame: flag = true + isRotationEnabled: flag = true + birthRotationalVelocity0: embed = ValueVector3 { + constantValue: vec3 = { 2, 0, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 2, 0, 0 } } + } + } + directionVelocityScale: f32 = 0.004 + rotation0: embed = IntegratedValueVector3 { + constantValue: vec3 = { 2, 0, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 2, 0, 0 } + { 0, 0, 0 } + } + } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 50, 10, 40 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.15, 0.7 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 50, 10, 40 } } + } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0.5, 1 } + values: list[vec3] = { + { 1, 1, 1 } + { 0, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zyra_Skin36_Add_Gold.Zaahen.tex" + numFrames: u16 = 4 + texDiv: vec2 = { 2, 2 } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.3 + } + lifetime: option[f32] = { 0.1 } + isSingleParticle: flag = true + emitterName: string = "Flash_Big" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + SpawnShape: pointer = VfxShapeLegacy { + emitOffset: embed = ValueVector3 { + constantValue: vec3 = { 15, 15, 15 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 15, 15, 15 } } + } + } + emitRotationAngles: list[embed] = { + ValueFloat { } + ValueFloat { } + } + emitRotationAxes: list[vec3] = { + { 0, 0, 0 } + { 0, 0, 0 } + } + } + EmitterPosition: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 0, 0 } } + } + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.67058825, 0.18579385, 0.105882354, 0.47058824 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = 100 + meshRenderFlags: u8 = 0 + colorLookUpTypeX: u8 = 3 + colorLookUpTypeY: u8 = 1 + depthBiasFactors: vec2 = { 0, -100 } + disableBackfaceCull: bool = true + miscRenderFlags: u8 = 1 + isUniformScale: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 500, 1, 1 } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Aura_Self.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.6 + } + lifetime: option[f32] = { 0.3 } + isSingleParticle: flag = true + emitterName: string = "Ground_Blend" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 0, 0 } } + } + } + primitive: pointer = VfxPrimitiveArbitraryQuad { } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.297261, 0.056839857, 0.05502403, 0.5019608 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.16867469, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = -200 + meshRenderFlags: u8 = 0 + colorLookUpTypeX: u8 = 3 + colorLookUpTypeY: u8 = 1 + depthBiasFactors: vec2 = { 0, -100 } + disableBackfaceCull: bool = true + miscRenderFlags: u8 = 1 + isUniformScale: flag = true + isGroundLayer: flag = true + useNavmeshMask: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 0, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 300, 1, 1 } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Aura_Self.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 4 + } + particleLinger: option[f32] = { } + lifetime: option[f32] = { 0.3 } + isSingleParticle: flag = true + emitterName: string = "glow" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + SpawnShape: pointer = 0xee39916f { + emitOffset: vec3 = { 0, -300, -50 } + } + primitive: pointer = VfxPrimitiveRay { } + blendMode: u8 = 4 + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.3, 0.9, 1 } + values: list[vec4] = { + { 0.84138244, 0.6256962, 0.39574274, 0.36862746 } + { 0.69460595, 0.45542076, 0.1890898, 1 } + { 0.4865339, 0.10403601, 0.039093614, 0.36862746 } + { 0.12156863, 0.03137255, 0.07450981, 0 } + } + } + } + alphaRef: u8 = 0 + depthBiasFactors: vec2 = { -1, -200 } + miscRenderFlags: u8 = 1 + particleIsLocalOrientation: flag = true + isRotationEnabled: flag = true + isGroundLayer: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 0, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 420, -500, 1 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.1, 1 } + values: list[vec3] = { + { 0, 1, 0 } + { 1, 1.5, 0 } + { 2, 2, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Aura_Self.Zaahen.tex" + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.4 + rate: embed = ValueFloat { + constantValue: f32 = 55 + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 1 } + values: list[f32] = { 55, 55 } + } + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.5 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 0.9, 1 } + keyValues: list[f32] = { 0.5, 1.5, 4 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 0.5 } + } + } + particleLinger: option[f32] = { } + lifetime: option[f32] = { 4 } + fieldCollectionDefinition: pointer = VfxFieldCollectionDefinitionData { + fieldAttractionDefinitions: list[embed] = { + VfxFieldAttractionDefinitionData { + Position: embed = ValueVector3 { + constantValue: vec3 = { 0, 700, -100 } + } + radius: embed = ValueFloat { + constantValue: f32 = 2000 + } + acceleration: embed = ValueFloat { + constantValue: f32 = 1000 + } + } + } + fieldNoiseDefinitions: list[embed] = { + VfxFieldNoiseDefinitionData { + radius: embed = ValueFloat { + constantValue: f32 = 1000 + } + frequency: embed = ValueFloat { + constantValue: f32 = 10 + } + velocityDelta: embed = ValueFloat { + constantValue: f32 = 5 + } + axisFraction: vec3 = { 1, 1, 1 } + } + } + } + emitterName: string = "burst_end" + birthOrbitalVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, -4, 0 } + } + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 500, 0, 0 } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 4, 4, 4 } + } + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + SpawnShape: pointer = VfxShapeCylinder { + radius: f32 = 50 + } + primitive: pointer = VfxPrimitiveArbitraryQuad { } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 0.15, 1 } + keyValues: list[f32] = { 0, 0.5, 1 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec4] = { { 1, 1, 1, 1 } } + } + } + Color: embed = ValueColor { + constantValue: vec4 = { 0.6117647, 0, 0, 1 } + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.3, 1 } + values: list[vec4] = { + { 0.6117647, 0, 0, 0 } + { 0.6117647, 0, 0, 1 } + { 0.12955017, 0, 0, 1 } + } + } + } + disableBackfaceCull: bool = true + particleIsLocalOrientation: flag = true + isUniformScale: flag = true + isRandomStartFrame: flag = true + isRotationEnabled: flag = true + useEmissionMeshNormalForBirth: flag = false + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 1, 0, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 1, 0, 0 } } + } + } + birthRotationalVelocity0: embed = ValueVector3 { + constantValue: vec3 = { 200, 200, 200 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 200, 200, 200 } } + } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 40, 2, 2 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 0.9, 1 } + keyValues: list[f32] = { 0.4, 0.6, 1.2 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 40, 0, 0 } + { 24, 0, 0 } + } + } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.15, 0.7, 1 } + values: list[vec3] = { + { 0.7, 0.7, 3 } + { 0.8, 0.8, 0.8 } + { 0.2, 0.2, 0.2 } + { 0.1, 0.1, 0.1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Aatrox_Base_R_Petal_Amber.Zaahen.tex" + numFrames: u16 = 4 + texDiv: vec2 = { 2, 2 } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 2 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 4 + } + particleLinger: option[f32] = { } + lifetime: option[f32] = { 0.1 } + isSingleParticle: flag = true + emitterName: string = "DarkBackground" + importance: u8 = 3 + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 5, 0 } + } + primitive: pointer = VfxPrimitiveArbitraryQuad { } + blendMode: u8 = 1 + Color: embed = ValueColor { + constantValue: vec4 = { 0.101960786, 0, 0, 0.6862745 } + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.5, 0.8, 1 } + values: list[vec4] = { + { 0.101960786, 0, 0, 0 } + { 0.101960786, 0, 0, 0.6862745 } + { 0.101960786, 0, 0, 0.6862745 } + { 0.101960786, 0, 0, 0 } + } + } + } + pass: i16 = -100 + alphaRef: u8 = 0 + isUniformScale: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 90, 0, 0 } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 200, 1, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.9, 1.1 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 200, 1, 1 } } + } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.5, 1 } + values: list[vec3] = { + { 1, 1, 1 } + { 1.4, 1, 1 } + { 2, 2, 2 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Aura_Self.Zaahen.tex" + startFrame: u16 = 1 + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 3 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 1 + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 1 } + values: list[f32] = { 4, 0 } + } + } + particleLinger: option[f32] = { } + lifetime: option[f32] = { 3 } + emitterName: string = "noodles" + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 0, 5, 0 } + } + birthAcceleration: embed = ValueVector3 { + constantValue: vec3 = { 0, 800, 0 } + } + worldAcceleration: embed = IntegratedValueVector3 { + constantValue: vec3 = { 0, -100, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0 } + values: list[vec3] = { { 0, -100, 0 } } + } + } + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + SpawnShape: pointer = VfxShapeLegacy { + emitOffset: embed = ValueVector3 { + constantValue: vec3 = { 1, 1, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 0, 30, 1 } + { 0, 300, -40 } + } + } + } + } + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Aatrox_Base_Death_Revivenoodles.Zaahen.scb" + } + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 1 } + values: list[vec4] = { + { 0.19607843, 0.015686275, 0.015686275, 1 } + { 1, 0, 0, 1 } + } + } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.5, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.5, 1 } + values: list[f32] = { 1, 0.6, 1 } + } + } + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Emote_Einstein_01_mult.Zaahen.tex" + } + disableBackfaceCull: bool = true + isRotationEnabled: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 0, 1, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 1, 0 } } + } + } + birthRotationalVelocity0: embed = ValueVector3 { + constantValue: vec3 = { 0, 1, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 0, 1, 0 } + { 0, 200, 0 } + } + } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 1, 0.3, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 1.4, 0.3, 1.4 } + { 0, 0.060000002, 0 } + } + } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.1, 1 } + values: list[vec3] = { + { 1, 1, 1 } + { 1, 1, 1 } + { 0.5, 0.3, 0.5 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Tape_trail_small.Zaahen.tex" + uvMode: u8 = 2 + birthUvScrollRate: embed = ValueVector2 { + constantValue: vec2 = { 1, 0 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec2] = { + { -0.2, 0 } + { -1, 0 } + } + } + } + birthUVOffset: embed = ValueVector2 { + constantValue: vec2 = { 1, 0 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec2] = { + { 0, 0 } + { 1, 0 } + } + } + } + particleUVScrollRate: embed = IntegratedValueVector2 { + constantValue: vec2 = { 1, 0 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec2] = { + { -0.3, 0 } + { -1.5, 0 } + } + } + } + textureMult: pointer = VfxTextureMultDefinitionData { } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 2 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.4 + } + lifetime: option[f32] = { 1.1 } + isSingleParticle: flag = true + emitterName: string = "CenterOrb_Out" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + SpawnShape: pointer = 0xee39916f { + emitOffset: vec3 = { 0, 150, 0 } + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.919997, 0.7600061, 0.4899977, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1790235, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 0.3783784 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = 102 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0.1, 1 } + values: list[f32] = { 0, 2 } + } + } + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/frost_cloud_01.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + isUniformScale: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 1, 0, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 1, 0, 0 } } + } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 70, 100, 100 } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 1, 2.3, 2 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.088958204, 0.15710996, 0.22298162, 0.25910434, 0.41496012, 0.93728137 } + values: list[vec3] = { + { 0, 0, 0 } + { 2.790961, 6.4192104, 5.581922 } + { 1.8930335, 4.3520436, 3.784386 } + { 2.866931, 6.5812807, 5.7228527 } + { 2.9170752, 6.6532974, 5.785476 } + { 2.960181, 6.7721047, 5.888787 } + { 2.9795203, 6.8528967, 5.9590406 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Swain_Base_Z_HollowOrb.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 2 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.4 + } + lifetime: option[f32] = { 1.1 } + isSingleParticle: flag = true + emitterName: string = "CenterOrb_Out1" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + SpawnShape: pointer = 0xee39916f { + emitOffset: vec3 = { 0, 150, 0 } + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.919997, 0.7600061, 0.4899977, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1790235, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 0.3783784 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = 103 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0.1, 1 } + values: list[f32] = { 0, 2 } + } + } + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/frost_cloud_01.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + isUniformScale: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 1, 0, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 1, 0, 0 } } + } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 70, 100, 100 } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 1, 2.3, 2 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.088958204, 0.15710996, 0.22298162, 0.25910434, 0.41496012, 0.93728137 } + values: list[vec3] = { + { 0, 0, 0 } + { 2.790961, 6.4192104, 5.581922 } + { 1.8930335, 4.3520436, 3.784386 } + { 2.866931, 6.5812807, 5.7228527 } + { 2.9170752, 6.6532974, 5.785476 } + { 2.960181, 6.7721047, 5.888787 } + { 2.9795203, 6.8528967, 5.9590406 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Swain_Base_Z_HollowOrb.Zaahen.tex" + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 2.35 + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 1.4 + } + lifetime: option[f32] = { 9 } + isSingleParticle: flag = true + emitterName: string = "WeaponFlash" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + primitive: pointer = VfxPrimitiveAttachedMesh { + mMesh: embed = VfxMeshDefinitionData { + mSubmeshesToDraw: list[hash] = { "weapon" } + mLockMeshToAttachment: bool = true + } + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.8899977, 0.10000763, 0.10000763, 0.5000076 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 0.75, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + } + } + } + pass: i16 = 100 + alphaRef: u8 = 0 + reflectionDefinition: pointer = VfxReflectionDefinitionData { + reflectionMapTexture: string = "ASSETS/Shared/Particles/Generic_White_Cubemap.TFT_Set15.dds" + reflectionOpacityDirect: f32 = -1 + reflectionOpacityGlancing: f32 = 0.1 + reflectionFresnel: f32 = 0.3 + reflectionFresnelColor: vec4 = { 0.8901961, 0.09803922, 0.09803922, 1 } + fresnel: f32 = 0.1 + fresnelColor: vec4 = { 0, 0, 0, 1 } + } + 0xcb13aff1: f32 = -4 + particleIsLocalOrientation: flag = true + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/color-hold.Zaahen.tex" + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 2.35 + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 1.4 + } + lifetime: option[f32] = { 9 } + isSingleParticle: flag = true + emitterName: string = "WeaponFlash1" + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + primitive: pointer = VfxPrimitiveAttachedMesh { + mMesh: embed = VfxMeshDefinitionData { + mSubmeshesToDraw: list[hash] = { "weapon" } + mLockMeshToAttachment: bool = true + } + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.17999542, 0.08999771, 0.08999771, 0.7499962 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 0.75, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + } + } + } + pass: i16 = 95 + 0xcb13aff1: f32 = -3 + particleIsLocalOrientation: flag = true + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/color-hold.Zaahen.tex" + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 2.35 + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 1.4 + } + lifetime: option[f32] = { 9 } + isSingleParticle: flag = true + emitterName: string = "ADD_EdgeGlow1" + importance: u8 = 3 + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 0, 0 } } + } + } + primitive: pointer = VfxPrimitiveAttachedMesh { + mMesh: embed = VfxMeshDefinitionData { + mSubmeshesToDraw: list[hash] = { "weapon" } + mSubmeshesToDrawAlways: list[hash] = { "weapon" } + mLockMeshToAttachment: bool = true + } + UseAvatarSpecificSubmeshMask: bool = true + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.8899977, 0.10000763, 0.10000763, 0.5000076 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 0.75, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + } + } + } + pass: i16 = 9 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + constantValue: f32 = 0 + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.5, 1 } + values: list[f32] = { 0, 0, 0 } + } + } + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Emote_Einstein_01_mult.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + 0xcb13aff1: f32 = -4 + particleIsLocalOrientation: flag = true + isRotationEnabled: flag = true + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Q_Glaive_Mask2.Zaahen.tex" + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/color-hold.Zaahen.tex" + birthUvScrollRateMult: embed = ValueVector2 { + constantValue: vec2 = { 0.5, 0 } + } + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 30 + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 1 } + values: list[f32] = { 0, 30 } + } + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 1 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 1 } + } + } + particleLinger: option[f32] = { 2 } + emitterName: string = "ShadowWisps1" + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, 250, 0 } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 4, 2, 4 } + } + worldAcceleration: embed = IntegratedValueVector3 { + constantValue: vec3 = { 0, -100, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0 } + values: list[vec3] = { { 0, -100, 0 } } + } + } + bindWeight: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 1 } + values: list[f32] = { 0, 0 } + } + } + SpawnShape: pointer = VfxShapeBox { + flags: u8 = 1 + Size: vec3 = { 40, 60, 30 } + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { 0, 50, 0 } + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.54985887, 0.043152515, 0.081406884, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.15, 0.75, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0.4599985 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = 23 + alphaRef: u8 = 0 + softParticleParams: pointer = VfxSoftParticleDefinitionData { + beginIn: f32 = 10 + deltaOut: f32 = 50 + } + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 1 } + values: list[f32] = { 0, 1 } + } + } + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Emote_Einstein_01_mult.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + isUniformScale: flag = true + isRandomStartFrame: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 0, 360, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 1 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 360, 0 } } + } + } + birthRotationalVelocity0: embed = ValueVector3 { + constantValue: vec3 = { 20, 0, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 20, 0, 0 } } + } + } + isLocalOrientation: flag = false + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 60, 60, 30 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.15189302, 0.2885187, 0.4379786, 0.67653877, 1.0122888 } + values: list[vec3] = { + { 0.49325153, 0.49325153, 0.49325153 } + { 0.5917946, 0.59913427, 0.59913427 } + { 0.81314945, 0.81817883, 0.81817883 } + { 0.9906985, 0.9850261, 0.9850261 } + { 1.12698, 1.1474447, 1.1244107 } + { 1.3109593, 1.3109593, 1.3109593 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/zaahen_dust_cloud.Zaahen.tex" + numFrames: u16 = 4 + texDiv: vec2 = { 2, 2 } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 3 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 1 + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 1 } + values: list[f32] = { 4, 0 } + } + } + particleLinger: option[f32] = { } + lifetime: option[f32] = { 3 } + emitterName: string = "noodles1" + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 0, 5, 0 } + } + birthAcceleration: embed = ValueVector3 { + constantValue: vec3 = { 0, 800, 0 } + } + worldAcceleration: embed = IntegratedValueVector3 { + constantValue: vec3 = { 0, -100, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0 } + values: list[vec3] = { { 0, -100, 0 } } + } + } + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + SpawnShape: pointer = VfxShapeLegacy { + emitOffset: embed = ValueVector3 { + constantValue: vec3 = { 1, 1, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 0, 30, 1 } + { 0, 300, -40 } + } + } + } + } + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Aatrox_Base_Death_Revivenoodles.Zaahen.scb" + } + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 1 } + values: list[vec4] = { + { 0.19607843, 0.015686275, 0.015686275, 1 } + { 1, 0, 0, 1 } + } + } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.5, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.5, 1 } + values: list[f32] = { 1, 0.6, 1 } + } + } + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Emote_Einstein_01_mult.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + disableBackfaceCull: bool = true + isRotationEnabled: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 0, 1, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 1, 0 } } + } + } + birthRotationalVelocity0: embed = ValueVector3 { + constantValue: vec3 = { 0, 1, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 0, 1, 0 } + { 0, 200, 0 } + } + } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 1, 0.3, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 1.4, 0.3, 1.4 } + { 0, 0.060000002, 0 } + } + } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.1, 1 } + values: list[vec3] = { + { 1, 1, 1 } + { 1, 1, 1 } + { 0.5, 0.3, 0.5 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_E_Swipe_DarkinTrail_Add.Zaahen.tex" + uvMode: u8 = 2 + birthUvScrollRate: embed = ValueVector2 { + constantValue: vec2 = { 1, 0 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec2] = { + { -0.2, 0 } + { -1, 0 } + } + } + } + birthUVOffset: embed = ValueVector2 { + constantValue: vec2 = { 1, 0 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec2] = { + { 0, 0 } + { 1, 0 } + } + } + } + particleUVScrollRate: embed = IntegratedValueVector2 { + constantValue: vec2 = { 1, 0 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec2] = { + { -0.3, 0 } + { -1.5, 0 } + } + } + } + uvScale: embed = ValueVector2 { + constantValue: vec2 = { 0.5, 1 } + } + textureMult: pointer = VfxTextureMultDefinitionData { } + } + } + particleName: string = "Zaahen_Base_P_Revive" + particlePath: string = "Characters/Zaahen/Skins/Skin0/Particles/Zaahen_Base_P_Revive" + } + "Characters/Zaahen/Skins/Skin0/Particles/Zaahen_Base_W_Pull_Flourish_Hand" = VfxSystemDefinitionData { + complexEmitterDefinitionData: list[pointer] = { + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 200 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.4 + } + particleLinger: option[f32] = { 0.2 } + lifetime: option[f32] = { 0.25 } + emitterName: string = "Trail" + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, 125 } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 0, 0, 0.5 } + } + Linger: pointer = VfxLingerDefinitionData { + UseLingerScale: flag = true + LingerScale: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 1, 1, 1 } + { 0, 0, 0 } + } + } + } + UseKeyedLingerVelocity: flag = true + SeparateLingerColor: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.13009709, 0.6097087, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 1, 1, 1, 0.6814815 } + { 1, 1, 1, 0.16296296 } + { 1, 1, 1, 0 } + } + } + } + } + FlexShapeDefinition: pointer = VfxFlexShapeDefinitionData { + scaleBirthScaleByBoundObjectSize: f32 = 0.004 + scaleEmitOffsetByBoundObjectSize: f32 = 0.004 + } + primitive: pointer = VfxPrimitiveCameraTrail { + mTrail: embed = VfxTrailDefinitionData { + mMode: u8 = 1 + mBirthTilingSize: embed = ValueVector3 { + constantValue: vec3 = { 800, 0, 0 } + } + mSmoothingMode: u8 = 1 + } + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.919997, 0.7600061, 0.4899977, 0.68000305 } + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 0.8, 1 } + values: list[vec4] = { + { 0.919997, 0.7600061, 0.4899977, 0 } + { 0.919997, 0.7600061, 0.4899977, 0.68000305 } + { 0.919997, 0.7600061, 0.4899977, 0.68000305 } + { 0.919997, 0.7600061, 0.4899977, 0 } + } + } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.1, 0.7, 1 } + values: list[vec4] = { + { 0.92156863, 0.7607843, 0.49019608, 0 } + { 0.92156863, 0.7607843, 0.49019608, 1 } + { 0.92156863, 0.7607843, 0.49019608, 0.36078432 } + { 0.2871748, 0.15510796, 0.14795148, 0 } + } + } + } + pass: i16 = 80 + alphaRef: u8 = 0 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.07158352, 0.19088937, 0.37744033, 1 } + values: list[f32] = { 1, 0.5869565, 0.23188406, 0, 0 } + } + } + UseLingerErosionDriveCurve: bool = true + LingerErosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 1 } + values: list[f32] = { 1, 0 } + } + } + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Base_SmokeErode.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0, 0 } + } + } + miscRenderFlags: u8 = 1 + isGroundLayer: flag = true + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 100, 2, 2 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.5, 1 } + values: list[vec3] = { + { 0, 0, 0 } + { 1, 1, 1 } + { 0, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Leona_Base_E_Wisps.Zaahen.tex" + emitterUvScrollRate: vec2 = { -0.5, 0 } + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.25 + rate: embed = ValueFloat { + constantValue: f32 = 3 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.5 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1.5 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 0.5 } + } + } + particleLinger: option[f32] = { 1 } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "mesh_ground" + worldAcceleration: embed = IntegratedValueVector3 { + constantValue: vec3 = { 0, -400, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0 } + values: list[vec3] = { { 0, -400, 0 } } + } + } + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0, 0.2 } + values: list[f32] = { 1, 0 } + } + } + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Cassiopeia_Skin20_Q_weaponswipe6.Zaahen.scb" + } + } + blendMode: u8 = 1 + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.2, 0.8, 1 } + values: list[vec4] = { + { 0.92156863, 0.7607843, 0.49019608, 0 } + { 0.92156863, 0.7607843, 0.49019608, 1 } + { 0.10980392, 0, 0.03137255, 1 } + { 0.10980392, 0, 0.03137255, 0 } + } + } + } + pass: i16 = 5 + softParticleParams: pointer = VfxSoftParticleDefinitionData { + deltaIn: f32 = 10 + } + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0.2, 1 } + values: list[f32] = { 0.06, 1 } + } + } + erosionSliceWidth: f32 = 1 + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Udyr_Base_VGU_Awaken_Ribbonmask01.Zaahen.tex" + } + disableBackfaceCull: bool = true + isUniformScale: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 360, 1, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 1, 360 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 360, 1, 0 } } + } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 0.2, 0.63, 0.63 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.8, 1.1 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0.2, 0.63, 0.63 } } + } + } + scale0: embed = ValueVector3 { + constantValue: vec3 = { 0.7, 1.5, 1 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0.1, 0.3, 1 } + values: list[vec3] = { + { 0.525, 1.3499999, 0.9 } + { 1.05, 1.9499999, 1.3 } + { 1.4, 2.25, 1.6 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Naafiri_Base_Foundation_Missile02.Zaahen.tex" + texAddressModeBase: u8 = 2 + particleUVScrollRate: embed = IntegratedValueVector2 { + constantValue: vec2 = { 1, 0 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec2] = { + { 0.4, 0 } + { 0.1, 0 } + } + } + } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Udyr_Base_VGU_Q_Ele_Flat_Energy.Zaahen.tex" + birthUvScrollRateMult: embed = ValueVector2 { + constantValue: vec2 = { 1, 0 } + } + } + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.25 + rate: embed = ValueFloat { + constantValue: f32 = 20 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.35 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.7, 2.6 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 0.35 } + } + } + particleLinger: option[f32] = { } + lifetime: option[f32] = { 1 } + isSingleParticle: flag = true + emitterName: string = "healspark" + birthVelocity: embed = ValueVector3 { + constantValue: vec3 = { 600, 0, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 600, 0, 0 } } + } + } + birthDrag: embed = ValueVector3 { + constantValue: vec3 = { 5, 5, 5 } + } + worldAcceleration: embed = IntegratedValueVector3 { + constantValue: vec3 = { 0, -100, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0 } + values: list[vec3] = { { 0, -100, 0 } } + } + } + SpawnShape: pointer = VfxShapeSphere { + radius: f32 = 10 + } + particleColorTexture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/common_color-bellcurve.Zaahen.tex" + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.92156863, 0.7607843, 0.49019608, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.5, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0 } + } + } + } + isUniformScale: flag = true + isLocalOrientation: flag = false + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 25, 105, 105 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.2, 1 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 25, 105, 105 } } + } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.1, 0.3, 0.6, 1 } + values: list[vec3] = { + { 0.1, 0, 0 } + { 5, 0, 0 } + { 0.5, 0, 0 } + { 0.5, 0, 0 } + { 0.1, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Warwick_Skin30_BightSpark.Zaahen.tex" + } + VfxEmitterDefinitionData { + timeBeforeFirstEmission: f32 = 0.25 + rate: embed = ValueFloat { + constantValue: f32 = 10 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.3 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1 } + } + } + times: list[f32] = { 0 } + values: list[f32] = { 0.3 } + } + } + lifetime: option[f32] = { 0.3 } + isSingleParticle: flag = true + emitterName: string = "Yellow_Flash1" + importance: u8 = 3 + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + FlexShapeDefinition: pointer = VfxFlexShapeDefinitionData { + scaleBirthScaleByBoundObjectSize: f32 = 0.005 + scaleEmitOffsetByBoundObjectSize: f32 = 0.005 + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.92156863, 0.7607843, 0.49019608, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 1 } + values: list[vec4] = { + { 1, 1, 1, 1 } + { 0.23244068, 0.06208896, 0.07193103, 0 } + } + } + } + pass: i16 = 500 + miscRenderFlags: u8 = 1 + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 360, 1, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0 } + keyValues: list[f32] = { 0 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 360, 1, 0 } } + } + } + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 40, 200, 350 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.6, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0, 0.7057055, 1 } + values: list[vec3] = { + { 40, 200, 350 } + { 40, 200, 350 } + { 40, 200, 350 } + } + } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.2, 1 } + values: list[vec3] = { + { 0.2, 0.2, 0.2 } + { 2, 1, 1 } + { 0.2, 0.3, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Cassiopeia_Skin38_Assets_1_369.Zaahen.tex" + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 35 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.5 + dynamics: pointer = VfxAnimatedFloatVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.3, 0.8 } + } + } + times: list[f32] = { 0, 1 } + values: list[f32] = { 0.5, 0.25 } + } + } + lifetime: option[f32] = { 0.25 } + emitterName: string = "ChargeIn" + importance: u8 = 3 + birthOrbitalVelocity: embed = ValueVector3 { + constantValue: vec3 = { -0.5, 0, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 0.7, 1 } + keyValues: list[f32] = { 0.2, 1, 5 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { -0.5, 0, 0 } } + } + } + birthAcceleration: embed = ValueVector3 { + constantValue: vec3 = { -100, 500, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { -5502, 0, 0 } + { -10000, 500, 0 } + } + } + } + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + SpawnShape: pointer = VfxShapeSphere { + radius: f32 = 130 + } + FlexShapeDefinition: pointer = VfxFlexShapeDefinitionData { + scaleEmitOffsetByBoundObjectSize: f32 = 0.006 + } + blendMode: u8 = 4 + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.2, 0.4, 0.6, 0.8, 1 } + values: list[vec4] = { + { 1, 1, 1, 0 } + { 0.9137255, 0.827451, 0.42352942, 0.47058824 } + { 0.9137255, 0.827451, 0.42352942, 1 } + { 1, 0.6555886, 0.34168002, 1 } + { 1, 0.8957351, 0.45882353, 1 } + { 1, 0.95564204, 0.6278172, 1 } + } + } + } + colorLookUpTypeY: u8 = 3 + isDirectionOriented: flag = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 1, 0, 0 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0, 360 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 1, 0, 0 } } + } + } + birthRotationalVelocity0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + VfxProbabilityTableData { } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 0, 0, 0 } } + } + } + directionVelocityScale: f32 = 0.002 + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 12, 10, 10 } + dynamics: pointer = VfxAnimatedVector3fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 1 } + } + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { 0.5, 2 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec3] = { { 12, 10, 10 } } + } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.23743455, 1 } + values: list[vec3] = { + { 0, 0, 0 } + { 1, 1, 1 } + { 0, 0, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Warwick_Skin30_BightSpark.Zaahen.tex" + paletteDefinition: pointer = VfxPaletteDefinitionData { + paletteTexture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_W_Gradient_RGB.Zaahen.tex" + paletteSelector: embed = ValueVector3 { + constantValue: vec3 = { 6, 0, 0 } + } + paletteCount: i32 = 8 + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.8 + } + lifetime: option[f32] = { 0.1 } + isSingleParticle: flag = true + emitterName: string = "Purple Ring" + importance: u8 = 3 + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { -10, 10, -10 } + } + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Chogath_R_yuan_di_02.Zaahen.scb" + } + } + blendMode: u8 = 4 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.92156863, 0.7607843, 0.49019608, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.06198327, 0.21481246, 0.3710934, 0.5, 0.9999 } + values: list[vec4] = { + { 0, 0, 0, 0 } + { 1, 1, 1, 0.6666667 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0.7058824 } + { 1, 1, 1, 0.06999313 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = 80 + 0xcb13aff1: f32 = -10 + disableBackfaceCull: bool = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 135, 0, 0 } + } + isLocalOrientation: flag = false + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 2, 0.2, 2 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 0.6 } + values: list[vec3] = { + { 1, 1, 1 } + { 0.1, 0.3, 0.1 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Seraphine_Skin14_BA_03.Zaahen.tex" + birthUVOffset: embed = ValueVector2 { + constantValue: vec2 = { 1, 0 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + probabilityTables: list[pointer] = { + VfxProbabilityTableData { + keyTimes: list[f32] = { 0, 1 } + keyValues: list[f32] = { -1, 1 } + } + VfxProbabilityTableData { } + } + times: list[f32] = { 0 } + values: list[vec2] = { { 1, 0 } } + } + } + particleUVScrollRate: embed = IntegratedValueVector2 { + constantValue: vec2 = { 0.2, 0.2 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec2] = { + { 0.2, 0.2 } + { 0.060000002, 0.060000002 } + } + } + } + uvScale: embed = ValueVector2 { + constantValue: vec2 = { 0.5, 0.5 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec2] = { + { 0.5, 0.5 } + { 0.65, 1 } + } + } + } + particleUVRotateRate: embed = IntegratedValueFloat { + constantValue: f32 = -300 + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0.5, 1 } + values: list[f32] = { -300, -150 } + } + } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Naafiri_Base_Foundation_Glow01.Zaahen.tex" + texAddressModeMult: u8 = 3 + uvScaleMult: embed = ValueVector2 { + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 0.5, 1 } + values: list[vec2] = { + { 1, 1 } + { 1, 1 } + { 1.8, 1.8 } + } + } + } + ParticleIntegratedUvRotateMult: embed = IntegratedValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0 } + values: list[f32] = { 0 } + } + } + } + } + VfxEmitterDefinitionData { + rate: embed = ValueFloat { + constantValue: f32 = 1 + } + particleLifetime: embed = ValueFloat { + constantValue: f32 = 0.8 + } + lifetime: option[f32] = { 0.1 } + isSingleParticle: flag = true + emitterName: string = "Purple Ring1" + importance: u8 = 3 + bindWeight: embed = ValueFloat { + constantValue: f32 = 1 + } + EmitterPosition: embed = ValueVector3 { + constantValue: vec3 = { -10, 10, -10 } + } + primitive: pointer = VfxPrimitiveMesh { + mMesh: embed = VfxMeshDefinitionData { + mSimpleMeshName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Chogath_R_yuan_di_02.Zaahen.scb" + } + } + blendMode: u8 = 1 + birthColor: embed = ValueColor { + constantValue: vec4 = { 0.545388, 0.072312504, 0.109300375, 1 } + } + Color: embed = ValueColor { + dynamics: pointer = VfxAnimatedColorVariableData { + times: list[f32] = { 0, 0.06198327, 0.21481246, 0.3710934, 0.5, 0.9999 } + values: list[vec4] = { + { 0, 0, 0, 0 } + { 1, 1, 1, 0.6666667 } + { 1, 1, 1, 1 } + { 1, 1, 1, 0.7058824 } + { 1, 1, 1, 0.06999313 } + { 1, 1, 1, 0 } + } + } + } + pass: i16 = 60 + alphaErosionDefinition: pointer = VfxAlphaErosionDefinitionData { + erosionDriveCurve: embed = ValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0.3, 0.8 } + values: list[f32] = { 0, 1.3 } + } + } + erosionFeatherOut: f32 = 0.5 + erosionMapName: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Base_SmokeErode.Zaahen.tex" + erosionMapChannelMixer: embed = ValueColor { + constantValue: vec4 = { 1, 0, 0.020004578, 0 } + } + } + 0xcb13aff1: f32 = -10 + disableBackfaceCull: bool = true + birthRotation0: embed = ValueVector3 { + constantValue: vec3 = { 135, 0, 0 } + } + isLocalOrientation: flag = false + birthScale0: embed = ValueVector3 { + constantValue: vec3 = { 2, 0.2, 2 } + } + scale0: embed = ValueVector3 { + dynamics: pointer = VfxAnimatedVector3fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec3] = { + { 1, 1, 1 } + { 0, 0.3, 0 } + } + } + } + texture: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_Emote_Einstein_01_mult.Zaahen.tex" + particleUVScrollRate: embed = IntegratedValueVector2 { + constantValue: vec2 = { 0.2, 0.2 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec2] = { + { 0.2, 0.2 } + { 0.060000002, 0.060000002 } + } + } + } + uvScale: embed = ValueVector2 { + constantValue: vec2 = { 0.5, 0.5 } + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 1 } + values: list[vec2] = { + { 0.5, 0.5 } + { 0.65, 1 } + } + } + } + particleUVRotateRate: embed = IntegratedValueFloat { + constantValue: f32 = -300 + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0.5, 1 } + values: list[f32] = { -300, -150 } + } + } + textureMult: pointer = VfxTextureMultDefinitionData { + textureMult: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Naafiri_Base_Foundation_Glow01.Zaahen.tex" + texAddressModeMult: u8 = 3 + uvScaleMult: embed = ValueVector2 { + dynamics: pointer = VfxAnimatedVector2fVariableData { + times: list[f32] = { 0, 0.5, 1 } + values: list[vec2] = { + { 1, 1 } + { 1, 1 } + { 1.8, 1.8 } + } + } + } + ParticleIntegratedUvRotateMult: embed = IntegratedValueFloat { + dynamics: pointer = VfxAnimatedFloatVariableData { + times: list[f32] = { 0 } + values: list[f32] = { 0 } + } + } + } + } + } + particleName: string = "Zaahen_Base_W_Pull_Flourish_Hand" + particlePath: string = "Characters/Zaahen/Skins/Skin0/Particles/Zaahen_Base_W_Pull_Flourish_Hand" + flags: u16 = 214 + } + "Characters/Zaahen/Skins/Skin0/Resources" = ResourceResolver { + resourceMap: map[hash, link] = { + "Zaahen_BA_Crit_Tar" = 0xa6188ed7 + "Zaahen_BA_Tar" = 0x4b910d2e + "Zaahen_E_Cas" = 0x9e6c0380 + "Zaahen_R_Tar" = 0x7bbcc857 + "Zaahen_Z_RecallSwipe1VFX" = 0xa8d028cc + "Zaahen_E_AoE" = 0x7da0b0ca + "Zaahen_E_AoE_Tar" = 0xe25cc536 + "Zaahen_P_buf" = 0x6ed7c7e7 + "Zaahen_R_buf" = 0x4c7942a5 + "Zaahen_W_Cas" = 0x1f422ace + "Zaahen_BA_Tar_Child" = 0xaf6f4b1b + "Zaahen_BA_Tar2" = 0x1157a314 + "Zaahen_Q_1_Buff" = 0x2131d62 + "Zaahen_Q_2_Buff" = 0x24577629 + "Zaahen_R_cas" = 0xc618c2a9 + 0xf02dd3bd = 0x77d8fc3b + 0xed2dcf04 = 0x78d8fdce + "Zaahen_Q_Swipe_02" = 0x547cf66 + "Zaahen_Q_Knockup_Tar" = 0xdd0e3c40 + "Zaahen_R_AoE" = 0xcfec1bb + 0xee2dd097 = 0x79d8ff61 + "Zaahen_P_Revive" = 0xee11b8b3 + "Zaahen_E_AoE_Slow" = 0x74c69916 + "Zaahen_Q_1_Tar" = 0xca23d326 + "Zaahen_Q_1_Trail" = 0x46b4734d + "Zaahen_P_MaxStacks_Avatar" = 0x840db03 + "Zaahen_P_MaxStacks_Will_Revive" = 0xb7fa80e + "Zaahen_W_Tell" = 0xb1bea22 + "Zaahen_w_mis" = 0xe85d1d90 + "Zaahen_Q_2_Warning" = 0xb2c0f3f4 + "Zaahen_R_Trail" = 0x7f4e0354 + "Zaahen_W_Mis_Child" = 0x402f2b35 + "Zaahen_P_WillRevive_ShoulderR" = 0x9e872fea + "Zaahen_P_WillRevive_ShoulderL" = 0xa0873310 + "Zaahen_BA_Tar3" = 0x1257a4a7 + "Zaahen_P_WillRevive_Screenbound" = 0xf9592b0 + "Zaahen_R_AngelPose_EyeGlint" = 0xba7c3a5a + "Zaahen_W_Pull_Flourish" = 0x80d47b67 + "Zaahen_W_Mis_Death" = 0x841953c5 + "Zaahen_W_Pull" = 0xc63102fe + "Zaahen_W_Pull_Tar_Chest" = 0x9a6d26ac + "Zaahen_W_Pull_Flourish_Hand" = 0xfeefa3f9 + "Zaahen_W_Mis_Tar" = 0x4a279ec4 + "Zaahen_R_BuffActivate_Glow" = 0xa2b80c88 + "Zaahen_Emote_Death" = 0x84dd857c + "Zaahen_W_Pull_Tar_Ground" = 0xa5ba7fd0 + 0x5d63b4f5 = 0x4b8f48dc + "Zaahen_Emote_Joke" = 0x3f347369 + "Zaahen_Emote_Taunt" = 0x7c3df4a2 + "Zaahen_Emote_Homeguard" = 0xca02e09a + "Zaahen_Z_Recall" = 0x80e31f0d + 0x2b3f334 = 0x5bacc2cc + "Zaahen_BA_Swipe_child" = 0xc47c46fe + "Zaahen_R_DR" = 0x39b12612 + "Zaahen_Z_Winddown" = 0xdfbd9566 + "Zaahen_Emote_Taunt_Trail" = 0xb9c163e5 + "Zaahen_Z_Glow_Weapon" = 0xd6723a9a + "Zaahen_P_Revive_End" = 0x6675f5b9 + "Zaahen_Base_Z_Back" = 0x9e2a6db + "Zaahen_R_AOE_Indicator_Enemy" = 0x40bbeef2 + } + } + "Characters/Zaahen/Skins/Skin0/Materials/Zaahen_VFXBase_inst" = StaticMaterialDef { + name: string = "Characters/Zaahen/Skins/Skin0/Materials/Zaahen_VFXBase_inst" + samplerValues: list2[embed] = { + StaticMaterialShaderSamplerDef { + TextureName: string = "Diffuse_Texture" + texturePath: string = "ASSETS/Characters/Zaahen/Skins/Base/Zaahen_Base_TX_CM.Zaahen.tex" + addressU: u32 = 1 + addressV: u32 = 1 + addressW: u32 = 1 + } + StaticMaterialShaderSamplerDef { + TextureName: string = "Mask_Texture" + texturePath: string = "ASSETS/Characters/Aatrox/Skins/Base/Particles/Aatrox_Base_R_body_mask.tex" + addressU: u32 = 1 + addressV: u32 = 1 + addressW: u32 = 1 + } + StaticMaterialShaderSamplerDef { + TextureName: string = "Gradient_Texture" + texturePath: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_DissolveGradient1.Zaahen.tex" + addressU: u32 = 1 + addressV: u32 = 1 + addressW: u32 = 1 + } + } + paramValues: list2[embed] = { + StaticMaterialShaderParamDef { + name: string = "Dissolve_SmoothStep" + value: vec4 = { 0, 0.15, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Dissolve_Bias" + value: vec4 = { -0.2, 0, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Pulse_Rate" + value: vec4 = { 3, 0, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Pulse_Max" + value: vec4 = { 0.4, 0, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Gradient_Sharpness" + value: vec4 = { 0.5, 0, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Alpha_Sharpness" + value: vec4 = { 0.001, 0, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Bloom_Intensity" + value: vec4 = { 1, 0, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Pulse_Offset" + value: vec4 = { 0.3, 0, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Alpha" + value: vec4 = { 1, 0, 0, 0 } + } + } + shaderMacros: map[string, string] = { + "NUM_BLEND_WEIGHTS" = "4" + } + techniques: list[embed] = { + StaticMaterialTechniqueDef { + name: string = "normal" + passes: list[embed] = { + StaticMaterialPassDef { + shader: link = 0x5377f3e9 + blendEnable: bool = true + srcColorBlendFactor: u32 = 6 + srcAlphaBlendFactor: u32 = 6 + dstColorBlendFactor: u32 = 7 + dstAlphaBlendFactor: u32 = 7 + } + } + } + } + childTechniques: list[embed] = { + StaticMaterialChildTechniqueDef { + name: string = "transition" + parentName: string = "normal" + shaderMacros: map[string, string] = { + "TRANSITION" = "1" + } + } + } + dynamicMaterial: pointer = DynamicMaterialDef { + parameters: list[embed] = { + DynamicMaterialParameterDef { + name: string = "Dissolve_Bias" + driver: pointer = MaxMaterialDriver { + mDrivers: list[pointer] = { + FloatGraphMaterialDriver { + driver: pointer = LerpMaterialDriver { + mBoolDriver: pointer = IsDeadDynamicMaterialBoolDriver { } + mTurnOnTimeSec: f32 = 2.5 + mTurnOffTimeSec: f32 = 0 + } + graph: embed = VfxAnimatedFloatVariableData { + times: list[f32] = { 0.0017193094, 0.21673875, 0.7667682, 1.0048844 } + values: list[f32] = { -0.22144419, 0.26013866, 0.7522475, 0.86541003 } + } + } + FloatGraphMaterialDriver { + driver: pointer = LerpMaterialDriver { + mBoolDriver: pointer = IsAnimationPlayingDynamicMaterialBoolDriver { + mAnimationNames: list[hash] = { "Passive_Death" } + } + mTurnOnTimeSec: f32 = 3 + } + graph: embed = VfxAnimatedFloatVariableData { + times: list[f32] = { 0.0032178767, 0.3814774, 0.9977753 } + values: list[f32] = { -0.22578026, 0.58381504, 0.99421966 } + } + } + } + } + } + DynamicMaterialParameterDef { + name: string = "Pulse_Rate" + driver: pointer = LerpMaterialDriver { + mBoolDriver: pointer = HasBuffDynamicMaterialBoolDriver { + mScriptName: string = "AatroxR" + } + mOnValue: f32 = 5 + mTurnOnTimeSec: f32 = 0 + mTurnOffTimeSec: f32 = 0 + } + } + } + } + } + "Characters/Zaahen/Skins/Skin0/Materials/Zaahen_VFXBase_Wings_inst" = StaticMaterialDef { + name: string = "Characters/Zaahen/Skins/Skin0/Materials/Zaahen_VFXBase_Wings_inst" + samplerValues: list2[embed] = { + StaticMaterialShaderSamplerDef { + TextureName: string = "Diffuse_Texture" + texturePath: string = "ASSETS/Characters/Zaahen/Skins/Base/Zaahen_Base_Weapon_TX_CM.Zaahen.tex" + addressU: u32 = 1 + addressV: u32 = 1 + addressW: u32 = 1 + } + StaticMaterialShaderSamplerDef { + TextureName: string = "Mask_Texture" + texturePath: string = "ASSETS/Characters/Aatrox/Skins/Base/Particles/Aatrox_Base_R_body_mask.tex" + addressU: u32 = 1 + addressV: u32 = 1 + addressW: u32 = 1 + } + StaticMaterialShaderSamplerDef { + TextureName: string = "Gradient_Texture" + texturePath: string = "ASSETS/Characters/Zaahen/Skins/Base/Particles/Zaahen_Base_DissolveGradient1.Zaahen.tex" + addressU: u32 = 1 + addressV: u32 = 1 + addressW: u32 = 1 + } + } + paramValues: list2[embed] = { + StaticMaterialShaderParamDef { + name: string = "Dissolve_SmoothStep" + value: vec4 = { 0, 0.15, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Dissolve_Bias" + value: vec4 = { -0.2, 0, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Pulse_Rate" + value: vec4 = { 3, 0, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Pulse_Max" + value: vec4 = { 0.4, 0, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Gradient_Sharpness" + value: vec4 = { 0.5, 0, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Alpha_Sharpness" + value: vec4 = { 0.001, 0, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Bloom_Intensity" + value: vec4 = { 1, 0, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Pulse_Offset" + value: vec4 = { 0.3, 0, 0, 0 } + } + StaticMaterialShaderParamDef { + name: string = "Alpha" + value: vec4 = { 1, 0, 0, 0 } + } + } + shaderMacros: map[string, string] = { + "NUM_BLEND_WEIGHTS" = "4" + } + techniques: list[embed] = { + StaticMaterialTechniqueDef { + name: string = "normal" + passes: list[embed] = { + StaticMaterialPassDef { + shader: link = 0x5377f3e9 + blendEnable: bool = true + srcColorBlendFactor: u32 = 6 + srcAlphaBlendFactor: u32 = 6 + dstColorBlendFactor: u32 = 7 + dstAlphaBlendFactor: u32 = 7 + } + } + } + } + childTechniques: list[embed] = { + StaticMaterialChildTechniqueDef { + name: string = "transition" + parentName: string = "normal" + shaderMacros: map[string, string] = { + "TRANSITION" = "1" + } + } + } + dynamicMaterial: pointer = DynamicMaterialDef { + parameters: list[embed] = { + DynamicMaterialParameterDef { + name: string = "Dissolve_Bias" + driver: pointer = MaxMaterialDriver { + mDrivers: list[pointer] = { + FloatGraphMaterialDriver { + driver: pointer = LerpMaterialDriver { + mBoolDriver: pointer = IsDeadDynamicMaterialBoolDriver { } + mTurnOnTimeSec: f32 = 2.5 + mTurnOffTimeSec: f32 = 0 + } + graph: embed = VfxAnimatedFloatVariableData { + times: list[f32] = { 0.0017193094, 0.21673875, 0.7667682, 1.0048844 } + values: list[f32] = { -0.22144419, 0.26013866, 0.7522475, 0.86541003 } + } + } + FloatGraphMaterialDriver { + driver: pointer = LerpMaterialDriver { + mBoolDriver: pointer = IsAnimationPlayingDynamicMaterialBoolDriver { + mAnimationNames: list[hash] = { "Passive_Death" } + } + mTurnOnTimeSec: f32 = 3 + } + graph: embed = VfxAnimatedFloatVariableData { + times: list[f32] = { 0.0032178767, 0.3814774, 0.9977753 } + values: list[f32] = { -0.22578026, 0.58381504, 0.99421966 } + } + } + } + } + } + DynamicMaterialParameterDef { + name: string = "Pulse_Rate" + driver: pointer = LerpMaterialDriver { + mBoolDriver: pointer = HasBuffDynamicMaterialBoolDriver { + mScriptName: string = "AatroxR" + } + mOnValue: f32 = 5 + mTurnOnTimeSec: f32 = 0 + mTurnOffTimeSec: f32 = 0 + } + } + } + } + } +} \ No newline at end of file diff --git a/crates/ltk_ritobin/src/cst/builder.rs b/crates/ltk_ritobin/src/cst/builder.rs index 1f7830ba..5ef6155b 100644 --- a/crates/ltk_ritobin/src/cst/builder.rs +++ b/crates/ltk_ritobin/src/cst/builder.rs @@ -310,7 +310,7 @@ impl Builder { } fn bin_to_cst(&mut self, bin: &Bin) -> Cst { - let mut entries = Vec::new(); + let mut entries = vec![]; for obj in bin.objects.values() { entries.push(self.bin_object_to_cst(obj)); @@ -318,7 +318,7 @@ impl Builder { let entries_key = self.spanned_token(Tok::Name, "entries"); let entries_type = self.rito_type(RitoType { - base: ltk_meta::PropertyKind::Map, + base: PropertyKind::Map, subtypes: [Some(PropertyKind::Hash), Some(PropertyKind::Embedded)], }); let entries = self.entry( @@ -327,10 +327,32 @@ impl Builder { tree(Kind::EntryValue, vec![self.block(entries)]), ); + let linked_key = self.spanned_token(Tok::Name, "linked"); + let linked_type = self.rito_type(RitoType { + base: PropertyKind::Container, + subtypes: [Some(PropertyKind::String), None], + }); + let linked = bin + .dependencies + .iter() + .map(|dep| { + tree( + Kind::ListItem, + vec![tree(Kind::Literal, vec![self.string(format!("\"{dep}\""))])], + ) + }) + .collect(); + + let linked = self.entry( + tree(Kind::EntryKey, vec![linked_key]), + Some(linked_type), + tree(Kind::EntryValue, vec![self.block(linked)]), + ); + Cst { kind: Kind::File, span: Span::default(), - children: vec![entries], + children: vec![linked, entries], errors: vec![], } } diff --git a/crates/ltk_ritobin/src/typecheck/visitor.rs b/crates/ltk_ritobin/src/typecheck/visitor.rs index a65cb6d7..59e1be68 100644 --- a/crates/ltk_ritobin/src/typecheck/visitor.rs +++ b/crates/ltk_ritobin/src/typecheck/visitor.rs @@ -158,6 +158,10 @@ pub enum Diagnostic { span: Span, got: RitoType, }, + InvalidDependenciesEntry { + span: Span, + got: RitoType, + }, TypeMismatch { span: Span, @@ -222,6 +226,7 @@ impl Diagnostic { | AmbiguousNumeric(span) | NotEnoughItems { span, .. } | TooManyItems { span, .. } + | InvalidDependenciesEntry { span, .. } | InvalidEntriesMap { span, .. } => Some(span), } } @@ -796,6 +801,41 @@ pub fn resolve_entry( impl<'a> TypeChecker<'a> { pub fn collect_to_bin(mut self) -> (Bin, Vec) { + let dependencies = self.root.swap_remove("linked").and_then(|v| { + let PropertyValueEnum::Container(list) = v else { + self.ctx.diagnostics.push( + InvalidDependenciesEntry { + span: *v.meta(), + got: RitoType::simple(v.kind()), + } + .unwrap(), + ); + return None; + }; + + Some( + list.into_items() + .filter_map(|value| { + let span = *value.meta(); + let PropertyValueEnum::String(dependency) = + coerce_type(value, PropertyKind::String)? + else { + self.ctx.diagnostics.push( + UnexpectedContainerItem { + span, + expected: RitoType::simple(PropertyKind::String), + expected_span: None, + } + .unwrap(), + ); + return None; + }; + Some(dependency.value) + }) + .collect::>(), + ) + }); + let objects = self .root .swap_remove("entries") @@ -838,7 +878,7 @@ impl<'a> TypeChecker<'a> { }) .unwrap_or_default(); - let tree = Bin::new(objects, Vec::::new()); + let tree = Bin::new(objects, dependencies.unwrap_or_default()); (tree, self.ctx.diagnostics) } From 854de220f419110370f14d3a0d216fb92439ddfd Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Sat, 28 Mar 2026 23:30:30 +0000 Subject: [PATCH 184/187] fix(print): propagate all fmt errors instead of unwrapping --- crates/ltk_ritobin/src/print/visitor.rs | 145 +++++++++++++----------- 1 file changed, 80 insertions(+), 65 deletions(-) diff --git a/crates/ltk_ritobin/src/print/visitor.rs b/crates/ltk_ritobin/src/print/visitor.rs index 4a6928b8..8c40349c 100644 --- a/crates/ltk_ritobin/src/print/visitor.rs +++ b/crates/ltk_ritobin/src/print/visitor.rs @@ -95,87 +95,96 @@ impl<'a, W: Write> CstVisitor<'a, W> { } } - fn push(&mut self, cmd: Cmd<'a>) { + fn push(&mut self, cmd: Cmd<'a>) -> fmt::Result { // eprintln!("+ {cmd:?}"); self.queue.push_back(cmd); self.queue_size_max = self.queue_size_max.max(self.queue.len()); if self.queue.len() > MAX_QUEUE { eprintln!("[!!] hit hard queue limit - force breaking to save memory"); - self.break_first_group(); + self.break_first_group()?; } + Ok(()) } - pub fn text(&mut self, txt: &'a str) { + pub fn text(&mut self, txt: &'a str) -> fmt::Result { for size in &mut self.size_stack { *size += txt.len(); } - self.check_running_size(); - self.push(Cmd::Text(txt)); + self.check_running_size()?; + self.push(Cmd::Text(txt))?; + Ok(()) } - pub fn text_if(&mut self, txt: &'a str, mode: Mode) { - self.push(Cmd::TextIf(txt, mode)); + pub fn text_if(&mut self, txt: &'a str, mode: Mode) -> fmt::Result { + self.push(Cmd::TextIf(txt, mode))?; + Ok(()) } - pub fn space(&mut self) { + pub fn space(&mut self) -> fmt::Result { if self.queue.back().is_some_and(|c| c.is_whitespace()) { // eprintln!("# skipping Space! ({:?})", self.queue.back()); - return; + return Ok(()); } - self.push(Cmd::Space); + self.push(Cmd::Space)?; + Ok(()) } - pub fn line(&mut self) { + pub fn line(&mut self) -> fmt::Result { if self.queue.is_empty() && self.printed_commands == 0 { - return; + return Ok(()); } if self.queue.back().is_some_and(|c| c.is_whitespace()) { // eprintln!("# replacing ({:?}) w/ Line", self.queue.back()); self.queue.pop_back(); } - self.push(Cmd::Line); + self.push(Cmd::Line)?; + Ok(()) } - pub fn softline(&mut self) { + pub fn softline(&mut self) -> fmt::Result { if self.queue.is_empty() && self.printed_commands == 0 { - return; + return Ok(()); } if self.queue.back().is_some_and(|c| c.is_whitespace()) { // eprintln!("# replacing ({:?}) w/ SoftLine", self.queue.back()); self.queue.pop_back(); } - self.push(Cmd::SoftLine); + self.push(Cmd::SoftLine)?; + Ok(()) } - pub fn begin_group(&mut self, mode: Option) -> GroupId { + pub fn begin_group(&mut self, mode: Option) -> Result { let idx = self.queue.len() + self.printed_commands; - self.push(Cmd::Begin(mode)); + self.push(Cmd::Begin(mode))?; self.group_stack.push(idx); self.size_stack.push(0); - GroupId(idx) + Ok(GroupId(idx)) } - pub fn end_group(&mut self) { - self.push(Cmd::End); + pub fn end_group(&mut self) -> fmt::Result { + self.push(Cmd::End)?; self.group_stack.pop(); self.size_stack.pop(); - self.print_safe().unwrap(); + self.print_safe()?; + Ok(()) } - pub fn indent(&mut self, n: usize) { - self.push(Cmd::Indent(n)); + pub fn indent(&mut self, n: usize) -> fmt::Result { + self.push(Cmd::Indent(n))?; + Ok(()) } - pub fn dedent(&mut self, n: usize) { - self.push(Cmd::Dedent(n)); + pub fn dedent(&mut self, n: usize) -> fmt::Result { + self.push(Cmd::Dedent(n))?; + Ok(()) } /// break the first/oldest group if running size is too big (bottom of the stack) - pub fn break_first_group(&mut self) { + pub fn break_first_group(&mut self) -> fmt::Result { if let Some(&idx) = self.group_stack.first() { // eprintln!("[printer] breaking first group"); self.force_group(GroupId(idx), Mode::Break); @@ -183,16 +192,18 @@ impl<'a, W: Write> CstVisitor<'a, W> { self.group_stack.remove(0); self.size_stack.remove(0); } - self.print_safe().unwrap(); + self.print_safe()?; + Ok(()) } /// break the first/oldest group if running size is too big (bottom of the stack) - pub fn check_running_size(&mut self) { + pub fn check_running_size(&mut self) -> fmt::Result { if let Some(size) = self.size_stack.last() { if self.col + size > self.config.wrap.line_width { - self.break_first_group(); + self.break_first_group()?; } } + Ok(()) } fn fits(&self) -> bool { @@ -240,6 +251,10 @@ impl<'a, W: Write> CstVisitor<'a, W> { grp_mode.replace(mode); } + fn last_mode(&self) -> &Mode { + self.modes.last().unwrap(/* Safety: we start with one mode, and don't pop them */) + } + fn print(&mut self, cmd: Cmd) -> fmt::Result { match cmd { Cmd::Text(s) => { @@ -250,7 +265,7 @@ impl<'a, W: Write> CstVisitor<'a, W> { self.block_line = false; } Cmd::TextIf(s, mode) => { - if *self.modes.last().unwrap() == mode { + if *self.last_mode() == mode { self.out.write_str(s)?; self.printed_bytes += s.len(); self.col += s.len(); @@ -282,7 +297,7 @@ impl<'a, W: Write> CstVisitor<'a, W> { } } - Cmd::SoftLine => match self.modes.last().unwrap() { + Cmd::SoftLine => match self.last_mode() { Mode::Flat => { if !self.block_space { // eprintln!(" - not skipping -> space!"); @@ -376,7 +391,7 @@ impl<'a, W: Write> CstVisitor<'a, W> { fn enter_tree_inner(&mut self, tree: &Cst) -> Result<(), PrintError> { match tree.kind { Kind::TypeArgList => { - let grp = self.begin_group(Some(Mode::Flat)); + let grp = self.begin_group(Some(Mode::Flat))?; // eprintln!("{:#?}", tree.children); self.list_stack.push(ListContext { len: tree @@ -391,8 +406,8 @@ impl<'a, W: Write> CstVisitor<'a, W> { }); } Kind::ListItemBlock => { - self.softline(); - let grp = self.begin_group(None); + self.softline()?; + let grp = self.begin_group(None)?; let len = tree .children @@ -414,7 +429,7 @@ impl<'a, W: Write> CstVisitor<'a, W> { } Kind::Block => { // eprintln!("BLOCK: {:#?}", tree.children); - let grp = self.begin_group(None); + let grp = self.begin_group(None)?; let list_len = tree .children .iter() @@ -462,12 +477,12 @@ impl<'a, W: Write> CstVisitor<'a, W> { self.force_group(list.grp, Mode::Break); } } - self.softline(); + self.softline()?; } Kind::Entry => { match self.config.wrap.inline_structs { - true => self.softline(), - false => self.line(), + true => self.softline()?, + false => self.line()?, }; // self.flush().unwrap(); } @@ -480,7 +495,7 @@ impl<'a, W: Write> CstVisitor<'a, W> { match tree.kind { Kind::TypeArgList => { self.list_stack.pop(); - self.end_group(); + self.end_group()?; } Kind::ListItemBlock | Kind::Block => { self.list_stack.pop(); @@ -491,13 +506,13 @@ impl<'a, W: Write> CstVisitor<'a, W> { // self.softline(); } } - self.end_group(); + self.end_group()?; } Kind::Entry if self.config.wrap.inline_structs => { if let Some(list) = self.list_stack.last() { if list.len > 1 { self.force_group(list.grp, Mode::Break); - self.text_if(";", Mode::Flat); + self.text_if(";", Mode::Flat)?; // self.softline(); } } else { @@ -510,14 +525,14 @@ impl<'a, W: Write> CstVisitor<'a, W> { let last_item = ctx.idx + 1 == ctx.len; if !last_item { - self.text_if(",", Mode::Flat); - self.space(); + self.text_if(",", Mode::Flat)?; + self.space()?; if tree.kind == Kind::ListItem { - self.softline(); + self.softline()?; } } - self.list_stack.last_mut().unwrap(/* guaranteed by if let */).idx += 1; + self.list_stack.last_mut().unwrap(/* Safety: guaranteed by if let */).idx += 1; } } _ => {} @@ -540,17 +555,17 @@ impl<'a, W: Write> CstVisitor<'a, W> { // eprintln!("->{:?}", token.kind); match token.kind { TokenKind::LCurly => { - self.space(); - self.text("{"); - self.indent(4); - self.space(); + self.space()?; + self.text("{")?; + self.indent(4)?; + self.space()?; // self.softline(); } TokenKind::RCurly => { - self.dedent(4); - self.softline(); - self.text("}"); + self.dedent(4)?; + self.softline()?; + self.text("}")?; } TokenKind::Comma => { @@ -558,37 +573,37 @@ impl<'a, W: Write> CstVisitor<'a, W> { // self.softline(); } TokenKind::Colon => { - self.text(":"); - self.space(); + self.text(":")?; + self.space()?; } TokenKind::Eq => { - self.space(); - self.text("="); - self.space(); + self.space()?; + self.text("=")?; + self.space()?; } TokenKind::LBrack => { - self.text("["); + self.text("[")?; } TokenKind::RBrack => { - self.text("]"); + self.text("]")?; } TokenKind::Quote => { - self.text("\""); + self.text("\"")?; } TokenKind::False => { - self.text("false"); + self.text("false")?; } TokenKind::True => { - self.text("true"); + self.text("true")?; } _ => { if let Some(print) = print_value { - self.text(print); + self.text(print)?; } else { - self.text(txt); + self.text(txt)?; } } } From e09c0b9fb6307314ebf8793a929959fad18c0917 Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Sat, 28 Mar 2026 23:32:12 +0000 Subject: [PATCH 185/187] fix(typecheck): remove useless ObjectLink arm in merge_ir --- crates/ltk_ritobin/src/typecheck/visitor.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/crates/ltk_ritobin/src/typecheck/visitor.rs b/crates/ltk_ritobin/src/typecheck/visitor.rs index 59e1be68..5d8bc9fe 100644 --- a/crates/ltk_ritobin/src/typecheck/visitor.rs +++ b/crates/ltk_ritobin/src/typecheck/visitor.rs @@ -931,7 +931,6 @@ impl<'a> TypeChecker<'a> { struct_val.properties.insert(*key, value); } - PropertyValueEnum::ObjectLink(_object_link_value) => todo!(), PropertyValueEnum::Map(map_value) => { let IrItem::Entry(IrEntry { key, value }) = child else { eprintln!("map item must be entry"); From 0d51ed2ad3a1200714de7f86840ab0fa249f9736 Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Sat, 28 Mar 2026 23:34:38 +0000 Subject: [PATCH 186/187] fix(typecheck): default span in populate_vec_or_color --- crates/ltk_ritobin/src/typecheck/visitor.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/ltk_ritobin/src/typecheck/visitor.rs b/crates/ltk_ritobin/src/typecheck/visitor.rs index 5d8bc9fe..71f96487 100644 --- a/crates/ltk_ritobin/src/typecheck/visitor.rs +++ b/crates/ltk_ritobin/src/typecheck/visitor.rs @@ -1045,7 +1045,7 @@ fn populate_vec_or_color( }; use PropertyValueEnum as V; - let mut span = Span::new(0, 0); // FIXME: get a span in here stat + let mut span = *target.value().meta(); // TODO: is this the right span to start with? let expected; match target.value_mut() { V::Vector2(values::Vector2 { value: vec, .. }) => { From 8795aca2349c544d49d0fa1a271f81afc176e9e2 Mon Sep 17 00:00:00 2001 From: Alan Panayotov Date: Sat, 28 Mar 2026 23:42:32 +0000 Subject: [PATCH 187/187] doc: lib.rs --- crates/ltk_ritobin/src/lib.rs | 58 +++++++++++++++++++++-------------- 1 file changed, 35 insertions(+), 23 deletions(-) diff --git a/crates/ltk_ritobin/src/lib.rs b/crates/ltk_ritobin/src/lib.rs index d5535f7f..87528e40 100644 --- a/crates/ltk_ritobin/src/lib.rs +++ b/crates/ltk_ritobin/src/lib.rs @@ -5,44 +5,55 @@ //! //! # Example //! -//! ```rust,ignore -//! use ltk_ritobin::{parse, write}; +//! ```rust +//! use ltk_ritobin::{Cst, Print as _}; //! //! // Parse ritobin text //! let text = r#" //! #PROP_text -//! type: string = "PROP" +//! type: string = "my_str" //! version: u32 = 3 +//! linked: list[string] = [ ] +//! entries: map[hash, embed] = { } //! "#; //! -//! let file = parse(text).unwrap(); -//! let tree = file.to_bin_tree(); +//! let cst = Cst::parse(text); +//! assert!(cst.errors.is_empty()); +//! +//! let (bin, bin_errors) = cst.build_bin(text); +//! assert!(bin_errors.is_empty()); //! //! // Write back to text -//! let output = write(&tree).unwrap(); +//! let output = bin.print().unwrap(); +//! +//! assert_eq!(text, output); //! ``` //! //! # Error Reporting //! -//! Parse errors include span information compatible with [`miette`] for rich -//! error reporting with source highlighting: -//! -//! ```rust,ignore -//! use ltk_ritobin::parse; -//! use miette::Report; -//! -//! let text = "test: badtype = 42"; -//! match parse(text) { -//! Ok(file) => { /* ... */ } -//! Err(e) => { -//! // Print with miette formatting -//! eprintln!("{:?}", Report::new(e)); -//! } -//! } +//! For resilient parsing, errors can appear embedded as nodes into the concrete syntax tree (cst), or as a list in the [`Cst`] struct. This +//! allows for more versatile behaviour for things like pretty-printing technically invalid trees, +//! since parsing will always result in a cst. +//! +//! The same handling of errors is done in the type-checker (when building a [`ltk_meta::Bin`]), to +//! always provide a best effort construction. +//! +//! ```rust +//! use ltk_ritobin::{Cst, cst::FlatErrors}; +//! +//! let text = "test: u32 = 4!!2"; +//! let cst = Cst::parse(text); +//! assert_eq!(cst.errors.len(), 0); // no 'top level' errors in the CST +//! +//! // helper that walks the CST, and returns all error +//! // nodes as a list +//! let flat_errors = FlatErrors::walk(&cst); +//! assert_eq!(flat_errors.len(), 1); // the unexpected "!!!" in the value +//! //! ``` -// Nom-style parsers use elided lifetimes extensively -#![allow(mismatched_lifetime_syntaxes)] +#[allow(unused)] // for doc link above +use ltk_meta::Bin; pub mod cst; pub mod hashes; @@ -55,3 +66,4 @@ pub use hashes::*; pub use types::*; pub use cst::Cst; +pub use print::Print;