skeleton attack

This commit is contained in:
artem 2024-02-01 10:41:26 +03:00
parent 9596969d3d
commit 29b3f57986
3 changed files with 745 additions and 523 deletions

View File

@ -1,13 +1,30 @@
use fyrox::{
core::{
algebra::{Vector3, Vector2}, impl_component_provider, pool::Handle, reflect::prelude::*, uuid_provider, visitor::prelude::*
algebra::{Point2, Vector2, Vector3},
impl_component_provider,
pool::Handle,
reflect::prelude::*,
uuid_provider,
visitor::prelude::*,
},
scene::{
animation::spritesheet::SpriteSheetAnimation,
base::BaseBuilder,
collider::{BitMask, Collider, InteractionGroups},
dim2::{
physics::{Intersection, RayCastOptions},
rectangle::{Rectangle, RectangleBuilder},
rigidbody::RigidBody,
},
graph::Graph,
node::Node,
transform::TransformBuilder,
},
scene::animation::spritesheet::SpriteSheetAnimation,
scene::dim2::{collider::Collider, rectangle::Rectangle, rigidbody::RigidBody},
scene::node::Node,
script::{ScriptContext, ScriptTrait},
};
use crate::Player;
impl_component_provider!(Enemy,);
uuid_provider!(Enemy = "a5671d19-9f1a-4286-8486-add4ebaadaec");
@ -40,30 +57,98 @@ pub struct Enemy {
handle: Handle<Node>,
player_handle: Handle<Node>,
player_collider: Handle<Node>,
attack_damage: f32,
attack_timer: f32,
attack_speed: f32,
}
impl Enemy {
// pub fn build(&self) {
// let mut material = Material::standard_2d();
// material
// .set_property(
// &ImmutableString::new("diffuseTexture"),
// PropertyValue::Sampler {
// value: Some(resource_manager.request::<Texture>(path)),
// fallback: SamplerFallback::Normal,
// },
// )
// .unwrap();
// material_resource = MaterialResource::new_ok(Default::default(), material);
// }
// let mut material = Material::standard_2d();
// material
// .set_property(
// &ImmutableString::new("diffuseTexture"),
// PropertyValue::Sampler {
// value: Some(resource_manager.request::<Texture>(path)),
// fallback: SamplerFallback::Normal,
// },
// )
// .unwrap();
// material_resource = MaterialResource::new_ok(Default::default(), material);
// }
fn init(&mut self) {
self.attack_damage = 2.0;
self.attack_speed = 0.5;
}
fn attack_player(&mut self, graph: &mut Graph) {
// Get *this* node instance
let self_node = match graph.try_get(self.handle) {
Some(node) => node,
None => return,
};
// Get the player node
let player_node = match graph.try_get(self.player_handle) {
Some(node) => node,
None => return,
};
// Get the current position of *this* node and the player node
let self_position = self_node.global_position();
let player_position = player_node.global_position();
// Calculate the direction vector from *this* node to the player node
let direction = player_position - self_position;
// Cast a ray from *this* node in the direction of the player node
let mut buffer = Vec::<Intersection>::new();
graph.physics2d.cast_ray(
RayCastOptions {
ray_origin: Point2::new(self_position.x, self_position.y),
ray_direction: Vector2::new(direction.x, direction.y),
max_len: 1.,
groups: InteractionGroups::new(
// Only collide with the player
BitMask(0b1000_0000_0000_0000_0000_0000_0000_0000),
BitMask(0b0111_1111_1111_1111_1111_1111_1111_1111),
),
// Sort the results by distance
sort_results: true,
},
// Store the collisions in the vector
&mut buffer,
);
// If the ray hit the player, damage the player
for i in 0..buffer.len() {
if buffer[i].collider != self.player_collider {
continue;
}
match graph.try_get_script_of_mut::<Player>(self.player_handle) {
Some(script) => {
script.take_damage(&self.attack_damage);
}
None => {}
};
break;
}
}
fn distance_to_player(&self, context: &mut ScriptContext) -> f32 {
let mut graph_ctx = context.scene.graph.begin_multi_borrow::<2>();
let enemy_rigid_body = graph_ctx.try_get(context.handle).unwrap().cast_mut::<RigidBody>();
let enemy_rigid_body = graph_ctx
.try_get(context.handle)
.unwrap()
.cast_mut::<RigidBody>();
let enemy_rigid_data = match enemy_rigid_body {
Some(rigid_data) => rigid_data,
None => return 0.0,
};
let player_rigid_body = graph_ctx.try_get(self.player_handle).unwrap().cast_mut::<RigidBody>();
let player_rigid_body = graph_ctx
.try_get(self.player_handle)
.unwrap()
.cast_mut::<RigidBody>();
let player_rigid_data = match player_rigid_body {
Some(rigid_body) => rigid_body,
None => return 0.0,
@ -71,12 +156,12 @@ impl Enemy {
let player_position = player_rigid_data.local_transform().position();
// TODO: if player is places abroad maps - stop activity
if player_position.x <= END_MAP_LEFT || player_position.x >= END_MAP_RIGHT{
return 100.0
if player_position.x <= END_MAP_LEFT || player_position.x >= END_MAP_RIGHT {
return 100.0;
}
let enemy_position = enemy_rigid_data.local_transform().position();
return player_position.x - enemy_position.x;
return player_position.x - enemy_position.x;
}
fn get_speed(&self, context: &mut ScriptContext) -> f32 {
@ -84,17 +169,17 @@ impl Enemy {
if distance > DISTANCE_TO_VIEW {
return 0.0;
}
if distance < DISTANCE_TO_VIEW * -1.0 {
if distance < DISTANCE_TO_VIEW * -1.0 {
return 0.0;
}
if distance > DISTANCE_TO_FIGHT{
return 2.0
if distance > DISTANCE_TO_FIGHT {
return 2.0;
}
if distance < DISTANCE_TO_FIGHT * -1.0 {
return -2.0
return -2.0;
}
return 0.0;
return 0.0;
}
fn change_orientation(&self, context: &mut ScriptContext) {
@ -138,16 +223,23 @@ impl Enemy {
if self.fight {
self.current_animation = Animations::Fight;
}
}
fn set_figh(&mut self, context: &mut ScriptContext) {
let distance = self.distance_to_player(context);
self.fight = distance < DISTANCE_TO_FIGHT && distance > -1.0 * DISTANCE_TO_FIGHT
fn set_fight(&mut self, context: &mut ScriptContext) {
let distance = self.distance_to_player(context);
self.fight = distance < DISTANCE_TO_FIGHT && distance > -1.0 * DISTANCE_TO_FIGHT;
if !self.fight {
self.attack_timer = 0.0;
return;
}
self.attack_timer += context.dt;
if self.attack_timer >= self.attack_speed {
self.attack_player(&mut context.scene.graph);
self.attack_timer = 0.0;
}
}
pub fn animation_do(&mut self, context: &mut ScriptContext) {
self.animate_choose(context);
let cur_anim = self.current_animation as usize;
let current_animation = self.animations.get_mut(cur_anim);
@ -175,6 +267,7 @@ impl Enemy {
}
impl ScriptTrait for Enemy {
fn on_init(&mut self, context: &mut ScriptContext) {
self.init();
// Store reference to *this* instance of the enemy node
self.handle = context.handle;
@ -187,9 +280,14 @@ impl ScriptTrait for Enemy {
// Find and store the Player's collider node handle
for child in handle.1.children().iter() {
if let Some(_) = context.scene.graph[*child].cast::<Collider>() {
self.player_collider = *child;
}
// TODO:
self.player_collider = *child;
break;
// println!("1!!!!!!!!!!!!!Collider{:?}", context.scene.graph[*child]);
// if let Some(_) = context.scene.graph[*child].cast::<Collider>() {
// println!("2!!!!!!!!!!!!!Collider{:?}", *child);
// self.player_collider = *child;
// }
}
}
None => {}
@ -200,6 +298,6 @@ impl ScriptTrait for Enemy {
self.change_orientation(context);
self.animation_do(context);
self.move_do(context);
self.set_figh(context);
self.set_fight(context);
}
}

View File

@ -3,6 +3,7 @@ use std::collections::VecDeque;
use fyrox::{
core::{
algebra::{Vector2, Vector3},
color::Color,
impl_component_provider,
log::Log,
pool::Handle,
@ -10,13 +11,20 @@ use fyrox::{
uuid_provider,
visitor::prelude::*,
},
event::{ElementState, Event, WindowEvent, TouchPhase},
engine::GraphicsContext,
event::{ElementState, Event, TouchPhase, WindowEvent},
keyboard::{KeyCode, PhysicalKey},
scene::animation::spritesheet::SpriteSheetAnimation,
scene::dim2::{rectangle::Rectangle, rigidbody::RigidBody},
scene::node::Node,
script::{ScriptContext, ScriptTrait}
scene::{
animation::spritesheet::SpriteSheetAnimation,
base::BaseBuilder,
dim2::{
rectangle::{Rectangle, RectangleBuilder},
rigidbody::RigidBody,
},
node::Node,
transform::TransformBuilder,
},
script::{ScriptContext, ScriptTrait},
};
#[derive(Visit, Reflect, Debug, Clone, Default)]
@ -38,6 +46,12 @@ pub struct Player {
pub window_height: u32, // TODO: need change place
pub window_width: u32,
// Health Bar
max_health: f32,
health: f32,
health_bar_background: Handle<Node>,
health_bar_progress: Handle<Node>,
}
#[derive(Clone, Copy, PartialEq)]
@ -51,6 +65,9 @@ enum Animations {
uuid_provider!(Player = "c5671d19-9f1a-4286-8486-add4ebaadaec");
impl Player {
const PLAYER_STARTING_HEALTH: f32 = 100.0;
const MAX_HEALTH_BAR_WIDTH: f32 = 0.5;
pub fn init(&mut self, context: &mut ScriptContext) {
let rigid_body = context.scene.graph[context.handle].cast_mut::<RigidBody>();
match rigid_body {
@ -59,6 +76,84 @@ impl Player {
}
None => {}
}
self.health_bar(context);
}
fn health_bar(&mut self, context: &mut ScriptContext) {
// Create the healthbar background
let health_bar_background = RectangleBuilder::new(
BaseBuilder::new()
.with_name("HealthBarBackground")
.with_local_transform(
TransformBuilder::new()
// Resize the healthbar so it is wide and short
.with_local_scale(Vector3::new(
Self::MAX_HEALTH_BAR_WIDTH,
Self::MAX_HEALTH_BAR_WIDTH / 4.,
1.,
))
// Move the pivot center to the top left of the healthbar
// This is so it can be scaled from the left to the right
.with_scaling_pivot(Vector3::new(
Self::MAX_HEALTH_BAR_WIDTH / 2.,
Self::MAX_HEALTH_BAR_WIDTH / 4.,
1.,
))
// Position the healthbar just above the player
.with_local_position(Vector3::new(-0.1, 0.25, 0.01))
.build(),
),
)
// Gray color
.with_color(Color::opaque(50, 50, 50))
.build(&mut context.scene.graph);
// Create the healthbar progress
let health_bar_progress = RectangleBuilder::new(
BaseBuilder::new()
.with_name("HealthBarProgress")
.with_local_transform(
TransformBuilder::new()
// Resize the healthbar so it is wide and short
.with_local_scale(Vector3::new(
Self::MAX_HEALTH_BAR_WIDTH,
Self::MAX_HEALTH_BAR_WIDTH / 4.,
1.,
))
// Move the pivot center to the top left of the healthbar
// This is so it can be scaled from the left to the right
.with_scaling_pivot(Vector3::new(
Self::MAX_HEALTH_BAR_WIDTH / 2.,
Self::MAX_HEALTH_BAR_WIDTH / 4.,
1.,
))
// Position the healthbar just above the player, and just in front of the background
.with_local_position(Vector3::new(-0.1, 0.35, 0.0))
.build(),
),
)
.with_color(Color::GREEN)
.build(&mut context.scene.graph);
// Make the healthbar background and progress child nodes of the player
context
.scene
.graph
.link_nodes(health_bar_background, context.handle);
context
.scene
.graph
.link_nodes(health_bar_progress, context.handle);
// Set the Player struct properties
self.max_health = Self::PLAYER_STARTING_HEALTH;
self.health = Self::PLAYER_STARTING_HEALTH;
self.health_bar_background = health_bar_background;
self.health_bar_progress = health_bar_progress;
}
pub fn take_damage(&mut self, damage: &f32) {
self.health -= damage;
}
pub fn loop_over(&mut self, context: &mut ScriptContext) {
@ -196,7 +291,7 @@ impl Player {
None => {}
}
}
fn add_animation_to_stack(&mut self, animation: Animations) {
if self.current_animation.len() > 2 {
return;
@ -248,6 +343,34 @@ impl Player {
}
}
fn update_health(&mut self, context: &mut ScriptContext) {
// Grab the healthbar progess node
let health_bar_progress = context.scene.graph[self.health_bar_progress].as_rectangle_mut();
// Grab the healthbar progess node's transform
let health_bar_transform = health_bar_progress.local_transform_mut();
// Grab the current scale of the healthbar progess node
let health_bar_scale = health_bar_transform.scale();
// Calculate the new scale of the healthbar progess node
// Don't let it go below 0 HP
let new_health = f32::max(
(self.health / self.max_health) * Self::MAX_HEALTH_BAR_WIDTH,
0.0,
);
// If the new scale is different from the current scale, update the scale
if health_bar_scale.x != new_health {
health_bar_transform.set_scale(Vector3::new(
new_health,
// Don't change the y or z scale
health_bar_scale.y,
health_bar_scale.z,
));
}
}
pub fn animation_do(&mut self, context: &mut ScriptContext) {
self.animate_choose(context);
//let can_update_frame = self.is_need_update_anim_frame(context);
@ -368,6 +491,7 @@ impl ScriptTrait for Player {
self.move_do(context);
self.change_orientation(context);
self.animation_do(context);
self.update_health(context);
self.loop_over(context);
}

View File

@ -321,138 +321,6 @@
pitch: 0.0,
),
node_infos: {
(
index: 8,
generation: 1,
): (
is_expanded: false,
),
(
index: 37,
generation: 1,
): (
is_expanded: false,
),
(
index: 90,
generation: 1,
): (
is_expanded: false,
),
(
index: 40,
generation: 1,
): (
is_expanded: true,
),
(
index: 18,
generation: 1,
): (
is_expanded: true,
),
(
index: 32,
generation: 1,
): (
is_expanded: true,
),
(
index: 17,
generation: 1,
): (
is_expanded: false,
),
(
index: 7,
generation: 1,
): (
is_expanded: true,
),
(
index: 23,
generation: 1,
): (
is_expanded: true,
),
(
index: 41,
generation: 1,
): (
is_expanded: true,
),
(
index: 20,
generation: 1,
): (
is_expanded: true,
),
(
index: 87,
generation: 1,
): (
is_expanded: false,
),
(
index: 36,
generation: 1,
): (
is_expanded: false,
),
(
index: 30,
generation: 1,
): (
is_expanded: true,
),
(
index: 6,
generation: 1,
): (
is_expanded: true,
),
(
index: 62,
generation: 1,
): (
is_expanded: true,
),
(
index: 53,
generation: 1,
): (
is_expanded: true,
),
(
index: 4,
generation: 1,
): (
is_expanded: true,
),
(
index: 65,
generation: 1,
): (
is_expanded: true,
),
(
index: 58,
generation: 1,
): (
is_expanded: true,
),
(
index: 60,
generation: 1,
): (
is_expanded: false,
),
(
index: 93,
generation: 1,
): (
is_expanded: false,
),
(
index: 38,
generation: 1,
@ -460,37 +328,7 @@
is_expanded: true,
),
(
index: 16,
generation: 1,
): (
is_expanded: true,
),
(
index: 13,
generation: 1,
): (
is_expanded: true,
),
(
index: 33,
generation: 1,
): (
is_expanded: true,
),
(
index: 92,
generation: 1,
): (
is_expanded: true,
),
(
index: 47,
generation: 1,
): (
is_expanded: true,
),
(
index: 12,
index: 8,
generation: 1,
): (
is_expanded: false,
@ -501,324 +339,6 @@
): (
is_expanded: true,
),
(
index: 78,
generation: 1,
): (
is_expanded: false,
),
(
index: 35,
generation: 1,
): (
is_expanded: true,
),
(
index: 50,
generation: 1,
): (
is_expanded: true,
),
(
index: 86,
generation: 1,
): (
is_expanded: true,
),
(
index: 59,
generation: 1,
): (
is_expanded: true,
),
(
index: 75,
generation: 1,
): (
is_expanded: false,
),
(
index: 66,
generation: 1,
): (
is_expanded: false,
),
(
index: 46,
generation: 1,
): (
is_expanded: false,
),
(
index: 48,
generation: 1,
): (
is_expanded: true,
),
(
index: 31,
generation: 1,
): (
is_expanded: true,
),
(
index: 89,
generation: 1,
): (
is_expanded: true,
),
(
index: 74,
generation: 1,
): (
is_expanded: true,
),
(
index: 56,
generation: 1,
): (
is_expanded: true,
),
(
index: 57,
generation: 1,
): (
is_expanded: false,
),
(
index: 28,
generation: 1,
): (
is_expanded: false,
),
(
index: 94,
generation: 1,
): (
is_expanded: true,
),
(
index: 5,
generation: 1,
): (
is_expanded: true,
),
(
index: 52,
generation: 1,
): (
is_expanded: true,
),
(
index: 54,
generation: 1,
): (
is_expanded: true,
),
(
index: 51,
generation: 1,
): (
is_expanded: true,
),
(
index: 82,
generation: 1,
): (
is_expanded: true,
),
(
index: 91,
generation: 1,
): (
is_expanded: true,
),
(
index: 81,
generation: 1,
): (
is_expanded: false,
),
(
index: 21,
generation: 1,
): (
is_expanded: false,
),
(
index: 27,
generation: 1,
): (
is_expanded: false,
),
(
index: 11,
generation: 1,
): (
is_expanded: false,
),
(
index: 95,
generation: 1,
): (
is_expanded: true,
),
(
index: 29,
generation: 1,
): (
is_expanded: true,
),
(
index: 0,
generation: 1,
): (
is_expanded: true,
),
(
index: 25,
generation: 1,
): (
is_expanded: false,
),
(
index: 49,
generation: 1,
): (
is_expanded: false,
),
(
index: 72,
generation: 1,
): (
is_expanded: false,
),
(
index: 69,
generation: 1,
): (
is_expanded: false,
),
(
index: 63,
generation: 1,
): (
is_expanded: false,
),
(
index: 2,
generation: 1,
): (
is_expanded: true,
),
(
index: 84,
generation: 1,
): (
is_expanded: false,
),
(
index: 1,
generation: 1,
): (
is_expanded: true,
),
(
index: 77,
generation: 1,
): (
is_expanded: true,
),
(
index: 42,
generation: 1,
): (
is_expanded: false,
),
(
index: 39,
generation: 1,
): (
is_expanded: false,
),
(
index: 24,
generation: 1,
): (
is_expanded: false,
),
(
index: 26,
generation: 1,
): (
is_expanded: true,
),
(
index: 34,
generation: 1,
): (
is_expanded: true,
),
(
index: 9,
generation: 1,
): (
is_expanded: false,
),
(
index: 44,
generation: 1,
): (
is_expanded: true,
),
(
index: 55,
generation: 1,
): (
is_expanded: true,
),
(
index: 19,
generation: 1,
): (
is_expanded: false,
),
(
index: 15,
generation: 1,
): (
is_expanded: true,
),
(
index: 43,
generation: 1,
): (
is_expanded: false,
),
(
index: 3,
generation: 1,
): (
is_expanded: true,
),
(
index: 45,
generation: 1,
): (
is_expanded: true,
),
(
index: 80,
generation: 1,
): (
is_expanded: true,
),
(
index: 14,
generation: 1,
): (
is_expanded: true,
),
(
index: 10,
generation: 1,
@ -831,12 +351,492 @@
): (
is_expanded: false,
),
(
index: 27,
generation: 1,
): (
is_expanded: false,
),
(
index: 54,
generation: 1,
): (
is_expanded: true,
),
(
index: 34,
generation: 1,
): (
is_expanded: true,
),
(
index: 63,
generation: 1,
): (
is_expanded: false,
),
(
index: 89,
generation: 1,
): (
is_expanded: true,
),
(
index: 18,
generation: 1,
): (
is_expanded: true,
),
(
index: 47,
generation: 1,
): (
is_expanded: true,
),
(
index: 33,
generation: 1,
): (
is_expanded: true,
),
(
index: 87,
generation: 1,
): (
is_expanded: false,
),
(
index: 49,
generation: 1,
): (
is_expanded: false,
),
(
index: 2,
generation: 1,
): (
is_expanded: true,
),
(
index: 55,
generation: 1,
): (
is_expanded: true,
),
(
index: 90,
generation: 1,
): (
is_expanded: false,
),
(
index: 40,
generation: 1,
): (
is_expanded: true,
),
(
index: 62,
generation: 1,
): (
is_expanded: true,
),
(
index: 92,
generation: 1,
): (
is_expanded: true,
),
(
index: 44,
generation: 1,
): (
is_expanded: true,
),
(
index: 58,
generation: 1,
): (
is_expanded: true,
),
(
index: 83,
generation: 1,
): (
is_expanded: true,
),
(
index: 45,
generation: 1,
): (
is_expanded: true,
),
(
index: 35,
generation: 1,
): (
is_expanded: true,
),
(
index: 65,
generation: 1,
): (
is_expanded: true,
),
(
index: 28,
generation: 1,
): (
is_expanded: false,
),
(
index: 11,
generation: 1,
): (
is_expanded: false,
),
(
index: 84,
generation: 1,
): (
is_expanded: false,
),
(
index: 29,
generation: 1,
): (
is_expanded: true,
),
(
index: 51,
generation: 1,
): (
is_expanded: true,
),
(
index: 81,
generation: 1,
): (
is_expanded: false,
),
(
index: 13,
generation: 1,
): (
is_expanded: true,
),
(
index: 52,
generation: 1,
): (
is_expanded: true,
),
(
index: 0,
generation: 1,
): (
is_expanded: true,
),
(
index: 77,
generation: 1,
): (
is_expanded: true,
),
(
index: 16,
generation: 1,
): (
is_expanded: true,
),
(
index: 93,
generation: 1,
): (
is_expanded: false,
),
(
index: 56,
generation: 1,
): (
is_expanded: true,
),
(
index: 69,
generation: 1,
): (
is_expanded: false,
),
(
index: 3,
generation: 1,
): (
is_expanded: true,
),
(
index: 32,
generation: 1,
): (
is_expanded: true,
),
(
index: 14,
generation: 1,
): (
is_expanded: true,
),
(
index: 94,
generation: 1,
): (
is_expanded: true,
),
(
index: 9,
generation: 1,
): (
is_expanded: false,
),
(
index: 39,
generation: 1,
): (
is_expanded: false,
),
(
index: 17,
generation: 1,
): (
is_expanded: false,
),
(
index: 31,
generation: 1,
): (
is_expanded: true,
),
(
index: 4,
generation: 1,
): (
is_expanded: true,
),
(
index: 91,
generation: 1,
): (
is_expanded: true,
),
(
index: 6,
generation: 1,
): (
is_expanded: true,
),
(
index: 24,
generation: 1,
): (
is_expanded: false,
),
(
index: 15,
generation: 1,
): (
is_expanded: true,
),
(
index: 50,
generation: 1,
): (
is_expanded: true,
),
(
index: 95,
generation: 1,
): (
is_expanded: true,
),
(
index: 72,
generation: 1,
): (
is_expanded: false,
),
(
index: 5,
generation: 1,
): (
is_expanded: true,
),
(
index: 60,
generation: 1,
): (
is_expanded: false,
),
(
index: 48,
generation: 1,
): (
is_expanded: true,
),
(
index: 78,
generation: 1,
): (
is_expanded: false,
),
(
index: 7,
generation: 1,
): (
is_expanded: true,
),
(
index: 46,
generation: 1,
): (
is_expanded: false,
),
(
index: 86,
generation: 1,
): (
is_expanded: true,
),
(
index: 21,
generation: 1,
): (
is_expanded: false,
),
(
index: 37,
generation: 1,
): (
is_expanded: false,
),
(
index: 25,
generation: 1,
): (
is_expanded: false,
),
(
index: 12,
generation: 1,
): (
is_expanded: false,
),
(
index: 82,
generation: 1,
): (
is_expanded: true,
),
(
index: 26,
generation: 1,
): (
is_expanded: true,
),
(
index: 59,
generation: 1,
): (
is_expanded: true,
),
(
index: 23,
generation: 1,
): (
is_expanded: true,
),
(
index: 74,
generation: 1,
): (
is_expanded: true,
),
(
index: 1,
generation: 1,
): (
is_expanded: true,
),
(
index: 66,
generation: 1,
): (
is_expanded: false,
),
(
index: 43,
generation: 1,
): (
is_expanded: false,
),
(
index: 41,
generation: 1,
): (
is_expanded: true,
),
(
index: 80,
generation: 1,
): (
is_expanded: true,
),
(
index: 57,
generation: 1,
): (
is_expanded: false,
),
(
index: 36,
generation: 1,
): (
is_expanded: false,
),
(
index: 53,
generation: 1,
): (
is_expanded: true,
),
(
index: 42,
generation: 1,
): (
is_expanded: false,
),
(
index: 19,
generation: 1,
): (
is_expanded: false,
),
(
index: 30,
generation: 1,
): (
is_expanded: true,
),
(
index: 75,
generation: 1,
): (
is_expanded: false,
),
(
index: 20,
generation: 1,
): (
is_expanded: true,
),
},
),
},