use bevy::prelude::*; use bevy_asset_loader::asset_collection::AssetCollection; use ron_asset_manager::prelude::RonAsset; use serde::{Deserialize, Serialize}; use crate::{math::int::FGi32, menus::style::FGUiStyle}; #[derive(Reflect, Serialize, Deserialize, Clone)] #[reflect(opaque)] pub struct FighterSettingsCommon { pub walk_speed_ease: FGi32, /// Maximum allowed horizontal velocity pub ground_max_horizontal_velocity: FGi32, /// Ground friction applied when the fighter is above the walk speed pub ground_friction_over_walk_speed_multiplier: FGi32, pub knockback_stacking_window: u32, pub knockback_decay_per_frame: FGi32, /// Multiplier that translates knockback -> game unit velocity pub knockback_launch_velocity_multiplier: FGi32, pub hitstun_frames_per_unit_knockback: FGi32, /// If an attack's hitstop > this value it will cause a grounded fighter to either bounce (if a meteor/spike) /// or to become airborne pub tumble_bounce_hitstop_threshold: u32, /// Angle diff from straight down under which the attack will count as a meteor pub meteor_angle_threshold: FGi32, /// Angle diff from straight up under which the attack will force an airborne state pub attack_ground_to_airborne_transition_vertical_angle_threshold: FGi32, pub visual_shake_frames_per_hitstop_frame: FGi32, // offsets applied when the fighter is in hitstop pub visual_shake_table: Vec, /// The attacker will always get less hitstop pub attacker_visual_shake_multiplier: f32, /// Maximum angle changed caused by directional influence pub di_max_angle: FGi32, pub leave_ground_ecb_frame_lock_duration: u32, pub platform_pass_platform_ignore_duration_frames: u32, pub platform_pass_initial_downwards_velocity: FGi32, pub intangible_color: Color, pub intangible_pulse_duration: u32, pub angel_platform_invulnerability_duration: u32, /// When hit while the receiver is in the air, use this angle pub sakurai_angle_aerial_angle: FGi32, /// When hit while the receiver is in the ground and at low knockback, use this angle pub sakurai_angle_low_knockback_angle: FGi32, /// When hit while the receiver is in the ground and at high knockback, use this angle pub sakurai_angle_high_knockback_angle: FGi32, /// past this threshold, the knockback is considered high, so it will use [sakurai_angle_high_knockback_angle] pub sakurai_angle_knockback_threshold: FGi32, } #[derive(Reflect, Serialize, Deserialize, Clone)] #[reflect(opaque)] pub struct InputSettingsCommon { pub stick_deadzone: FGi32, pub trigger_deadzone: FGi32, pub smash_input_reset_axis_threshold: FGi32, pub smash_input_axis_threshold: FGi32, pub run_stick_threshold: FGi32, pub smash_input_frame_threshold: u8, pub input_buffer_size: u8, pub turn_into_dashback_window: u8, } #[derive(Reflect, Serialize, Deserialize, Resource, Asset, Clone, RonAsset)] pub struct GameSettings { pub fighter_common: FighterSettingsCommon, pub input_common: InputSettingsCommon, pub fighter_manifest_paths: Vec, pub stage_manifest_paths: Vec, } #[derive(AssetCollection, Resource)] pub struct CommonAssets { #[asset(path = "game_settings.ron")] pub game_settings: Handle, #[asset(path = "game.stylesheet.ron")] pub ui_style: Handle, } impl FromWorld for GameSettings { fn from_world(world: &mut World) -> Self { let game_settings_handle = world.resource::().game_settings.clone(); world .resource::>() .get(&game_settings_handle) .expect("GameSettings should already be loaded! Bug?") .clone() } }