Fixed guns reloading all animation players when reload anim is triggered on the same gun

This commit is contained in:
Franklin 2023-11-12 16:38:23 -04:00
parent 01bd24bf19
commit 865070ed90
22 changed files with 190 additions and 85 deletions

View File

@ -0,0 +1,37 @@
use bevy::prelude::*;
use crate::{comps::core::{items::item::{Item, ItemType}, grid::UGrid, markers::holdable::HoldableObjectType}, logic::core::guns::firearm::Firearm};
#[derive(Component)]
pub struct Glock17GunItem;
impl Item for Glock17GunItem {
fn get_type(&self) -> ItemType {
ItemType::Holdable(HoldableObjectType::Firearm(Firearm::Glock17))
}
fn asset_path(&self) -> &str {
"weapons/glock_17_pistol.glb"
}
#[doc = " Optional Stackable. If value is Some(x) x is the max quantity per stack"]
fn stackable(&self) -> Option<u32> {
None
}
fn inventory_size(&self) -> UGrid {
UGrid { width: 2, height: 1 }
}
fn inventory_rotatable(&self) -> bool {
true
}
fn inventory_title(&self) -> String {
String::from("Glock17 Firearm")
}
fn inventory_description(&self) -> String {
String::from("Glock17 Firearm chambered in 9x19mm.")
}
}

View File

@ -1 +1,2 @@
pub mod m4a1;
pub mod glock17;

View File

@ -67,6 +67,7 @@ pub trait Item {
)),
))
.id();
let firearm_size = firearm.get_size();
commands
.spawn((
firearm.holdable_object_data(),
@ -80,7 +81,7 @@ pub trait Item {
..Default::default()
},
RigidBody::Dynamic,
Collider::cuboid(5.0, 5.0, 5.0),
Collider::cuboid(firearm_size.x, firearm_size.y, firearm_size.z),
Interactable::Item,
))
.push_children(&[firearm_asset_entity]);

View File

@ -4,3 +4,4 @@ pub mod grid;
pub mod inventory;
pub mod items;
pub mod markers;
pub mod spawners;

View File

@ -0,0 +1,18 @@
use bevy::prelude::*;
use crate::comps::core::{items::{guns::glock17::Glock17GunItem, item::Item}, spawners::item::ItemSpawnPoint};
#[derive(Component)]
pub struct Glock17SpawnPoint {
pub transform: Transform,
}
impl ItemSpawnPoint for Glock17SpawnPoint {
fn get_transform(&self) -> Transform {
self.transform
}
fn get_item(&self) -> Box<dyn Item> {
Box::new(Glock17GunItem)
}
}

View File

@ -1,6 +1,6 @@
use bevy::prelude::*;
use crate::{setup::spawners::item::ItemSpawnPoint, comps::core::items::{guns::m4a1::M4a1GunItem, item::Item}};
use crate::comps::core::{items::{guns::m4a1::M4a1GunItem, item::Item}, spawners::item::ItemSpawnPoint};
#[derive(Component)]
pub struct M4a1SpawnPoint {

View File

@ -0,0 +1,2 @@
pub mod m4a1_spawner;
pub mod glock17_spawner;

View File

@ -1,6 +1,6 @@
use bevy::{prelude::*, gltf::Gltf};
use crate::{setup::{load_state::GameLoadState, assets::GltfAssets, spawners::guns::m4a1_spawner::M4a1SpawnPoint}, comps::core::items::item::Item};
use crate::{setup::{load_state::GameLoadState, assets::GltfAssets}, comps::core::{items::item::Item, spawners::guns::{m4a1_spawner::M4a1SpawnPoint, glock17_spawner::Glock17SpawnPoint}}};
#[bevy_trait_query::queryable]
pub trait ItemSpawnPoint {
@ -32,6 +32,7 @@ impl Plugin for ItemSpawnPointPlugin {
fn build(&self, app: &mut App) {
use bevy_trait_query::RegisterExt;
app
.register_component_as::<dyn ItemSpawnPoint, M4a1SpawnPoint>();
.register_component_as::<dyn ItemSpawnPoint, M4a1SpawnPoint>()
.register_component_as::<dyn ItemSpawnPoint, Glock17SpawnPoint>();
}
}

View File

@ -1,4 +1,5 @@
pub mod item;
pub mod player;
pub mod spawn_point;
pub mod guns;
pub mod guns;
pub mod spawn;

View File

@ -0,0 +1,15 @@
use bevy::prelude::*;
use super::{player::player_spawner, item::{item_spawner, ItemSpawnPointPlugin}, spawn_point::SpawnPointPlugin};
pub struct SpawnerPlugin;
impl Plugin for SpawnerPlugin {
fn build(&self, app: &mut App) {
app.add_plugins((SpawnPointPlugin, ItemSpawnPointPlugin));
app.add_systems(
Update,
(player_spawner, item_spawner),
);
}
}

View File

@ -1,6 +1,6 @@
use bevy::prelude::*;
use crate::setup::spawners::player::PlayerSpawnPoint;
use crate::comps::core::spawners::player::PlayerSpawnPoint;
#[bevy_trait_query::queryable]

View File

@ -111,4 +111,10 @@ impl Firearm {
},
}
}
pub fn get_size(&self) -> Vec3 {
match self {
Firearm::M4A1 => Vec3 { x: 0.3, y: 0.7, z: 2.5 },
Firearm::Glock17 => Vec3::ZERO,
}
}
}

View File

@ -1,4 +1,4 @@
use bevy::prelude::*;
use bevy::{prelude::*, ecs::system::SystemParam};
use bevy_rapier3d::prelude::*;
use crate::{
@ -19,34 +19,40 @@ use crate::{
load_state::GameLoadState,
},
ui::game::{hud::hud::HudState, settings::SettingsScreenUIConfiguration},
utils::rad_deg::radians_from_degrees,
utils::{rad_deg::radians_from_degrees, self},
};
pub fn capture_hand_usage(
mut commands: Commands,
mouse_buttons: Res<Input<MouseButton>>,
keyboard_input: Res<Input<KeyCode>>,
mut hand_query: Query<&mut Transform, With<PlayerHand>>,
time: Res<Time>,
#[derive(SystemParam)]
pub struct CaptureHandUsageResourcesParams<'w> {
mouse_buttons: Res<'w, Input<MouseButton>>,
keyboard_input: Res<'w, Input<KeyCode>>,
game_load_state: Res<'w, GameLoadState>,
settings_screen_config: Res<'w, SettingsScreenUIConfiguration>,
meshes: ResMut<'w, Assets<Mesh>>,
materials: ResMut<'w, Assets<StandardMaterial>>,
animation_clips: Res<'w, Assets<AnimationClip>>,
all_firearm_animations: Res<'w, AllFirearmAnimations>,
time: Res<'w, Time>,
}
pub fn capture_hand_usage(
mut resources: CaptureHandUsageResourcesParams,
mut commands: Commands,
mut hand_query: Query<&mut Transform, With<PlayerHand>>,
mut firearm_query: Query<
(&GlobalTransform, &'static FirearmData, &mut MagazineData),
(Entity, &GlobalTransform, &'static FirearmData, &mut MagazineData),
(With<InPlayerHands>, Without<PlayerHand>),
>,
player_query: Query<&Player>,
mut player_firing_info_query: Query<&mut PlayerFiringInfo, With<Player>>,
all_firearm_animations: Res<AllFirearmAnimations>,
mut animation_players: Query<&mut AnimationPlayer>,
animation_clips: Res<Assets<AnimationClip>>,
mut animation_players: Query<(Entity, &mut AnimationPlayer)>,
game_load_state: Res<GameLoadState>,
#[allow(unused)] mut equipment_change_event_writer: EventWriter<EquipmentChangeEvent>,
settings_screen_config: Res<SettingsScreenUIConfiguration>,
mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<StandardMaterial>>,
children: Query<&Children>,
mut equipment_change_event_writer: EventWriter<EquipmentChangeEvent>,
) {
if !game_load_state.player_loaded {
if !resources.game_load_state.player_loaded {
return;
}
if player_query.iter().len() == 0 {
@ -56,14 +62,14 @@ pub fn capture_hand_usage(
// Equipping stuff
// Equipping gun
if !settings_screen_config.settings_menu_shown {
if keyboard_input.just_pressed(KeyCode::Key1) {
if !resources.settings_screen_config.settings_menu_shown {
if resources.keyboard_input.just_pressed(KeyCode::Key1) {
equipment_change_event_writer
.send(EquipmentChangeEvent(Equipment::Firearm(Firearm::M4A1)));
} else if keyboard_input.just_pressed(KeyCode::Key2) {
} else if resources.keyboard_input.just_pressed(KeyCode::Key2) {
equipment_change_event_writer
.send(EquipmentChangeEvent(Equipment::Firearm(Firearm::Glock17)));
} else if keyboard_input.just_pressed(KeyCode::Key3) {
} else if resources.keyboard_input.just_pressed(KeyCode::Key3) {
equipment_change_event_writer.send(EquipmentChangeEvent(Equipment::Nothing));
}
}
@ -71,19 +77,22 @@ pub fn capture_hand_usage(
// Firearm stuff
if let Equipment::Firearm(player_firearm) = player_query.single().0.equipment.clone() {
for mut player_firing_info in player_firing_info_query.iter_mut() {
player_firing_info.full_auto_timer.tick(time.delta());
player_firing_info.full_auto_timer.tick(resources.time.delta());
for (firearm_transform, firearm_data, mut magazine_data) in firearm_query.iter_mut() {
for (firearm_entity, firearm_transform, firearm_data, mut magazine_data) in firearm_query.iter_mut() {
for mut hand_transform in hand_query.iter_mut() {
if player_firing_info.is_reloading {
for animation_player in &mut animation_players {
if let Some(firearm_animations) = all_firearm_animations
for (animation_player_entity, animation_player) in &mut animation_players {
//children.get_component(entity)
// Only reload if this animation_player_entity is a child of the firearm_entity
if utils::hierarchy::find_child_in_parent_children(&mut commands, firearm_entity, animation_player_entity, &children) {
if let Some(firearm_animations) = resources.all_firearm_animations
.animations
.iter()
.find(|animation| &animation.firearm == &player_firearm)
{
if let Some(animation_clip) =
animation_clips.get(&firearm_animations.reload_magazine)
resources.animation_clips.get(&firearm_animations.reload_magazine)
{
if animation_player.elapsed() >= animation_clip.duration() {
magazine_data.rounds_shot = 0;
@ -91,39 +100,45 @@ pub fn capture_hand_usage(
}
}
}
}
}
} else {
// Player is not in a reload animation
if keyboard_input.just_pressed(KeyCode::R)
&& !settings_screen_config.settings_menu_shown
if resources.keyboard_input.just_pressed(KeyCode::R)
&& !resources.settings_screen_config.settings_menu_shown
{
// Start reload animation
for mut animation_player in &mut animation_players {
if let Some(firearm_animations) = all_firearm_animations
for (animation_player_entity, mut animation_player) in &mut animation_players {
// Only reload if this animation_player_entity is a child of the firearm_entity
if utils::hierarchy::find_child_in_parent_children(&mut commands, firearm_entity, animation_player_entity, &children) {
if let Some(firearm_animations) = resources.all_firearm_animations
.animations
.iter()
.find(|animation| &animation.firearm == &player_firearm)
{
animation_player
.start(firearm_animations.reload_magazine.clone_weak());
player_firing_info.is_reloading = true;
{
animation_player
.start(firearm_animations.reload_magazine.clone_weak());
player_firing_info.is_reloading = true;
}
}
}
// Set is_reloading = true
// At the end of reload animation, set magazine data to capacity = 0
}
// AIMING IN/OUT
if mouse_buttons.pressed(MouseButton::Right)
&& !settings_screen_config.settings_menu_shown
if resources.mouse_buttons.pressed(MouseButton::Right)
&& !resources.settings_screen_config.settings_menu_shown
{
let rotation_lerp_quat = hand_transform.rotation.lerp(
firearm_data.final_aimed_rotation,
(time.delta_seconds() / firearm_data.rebound_time_seconds)
(resources.time.delta_seconds() / firearm_data.rebound_time_seconds)
.clamp(0.0, 1.0),
);
let position_lerp_vec3 = hand_transform.translation.lerp(
firearm_data.final_aimed_position,
(time.delta_seconds() / firearm_data.rebound_time_seconds)
(resources.time.delta_seconds() / firearm_data.rebound_time_seconds)
.clamp(0.0, 1.0),
);
hand_transform.rotation = rotation_lerp_quat;
@ -131,19 +146,19 @@ pub fn capture_hand_usage(
} else {
hand_transform.rotation = hand_transform.rotation.lerp(
firearm_data.final_rotation,
(time.delta_seconds() / firearm_data.rebound_time_seconds)
(resources.time.delta_seconds() / firearm_data.rebound_time_seconds)
.clamp(0.0, 1.0),
);
hand_transform.translation = hand_transform.translation.lerp(
firearm_data.final_position,
(time.delta_seconds() / firearm_data.rebound_time_seconds)
(resources.time.delta_seconds() / firearm_data.rebound_time_seconds)
.clamp(0.0, 1.0),
);
}
// SHOOTING & RECOIL
if mouse_buttons.pressed(MouseButton::Left)
&& !settings_screen_config.settings_menu_shown
if resources.mouse_buttons.pressed(MouseButton::Left)
&& !resources.settings_screen_config.settings_menu_shown
{
if player_firing_info.full_auto_timer.finished() {
if magazine_data.rounds_shot < magazine_data.max_capacity {
@ -177,8 +192,8 @@ pub fn capture_hand_usage(
let up = firearm_transform.up();
shoot_bullet(
&mut commands,
&mut meshes,
&mut materials,
&mut resources.meshes,
&mut resources.materials,
Transform::from_translation(firing_point),
forward,
up,
@ -186,7 +201,7 @@ pub fn capture_hand_usage(
);
// Increment indexes and timers
player_firing_info.current_round_index += 1;
player_firing_info.last_shot_timestamp = time.elapsed_seconds();
player_firing_info.last_shot_timestamp = resources.time.elapsed_seconds();
player_firing_info.full_auto_timer.reset();
magazine_data.rounds_shot += 1;

View File

@ -4,7 +4,6 @@
use bevy::prelude::*;
use bevy_rapier3d::prelude::*;
use scenes::scene1;
use setup::spawners::{spawn_point::SpawnPointPlugin, item::ItemSpawnPointPlugin};
use ui::{editor::plugin::MainEditorUiPlugin, game::plugin::MainGameUIPlugin};
mod comps;
@ -34,7 +33,7 @@ fn setup_plugins(application: &mut App) {
//.add_plugins(WorldInspectorPlugin::new())
.add_plugins(MainGameUIPlugin)
.add_plugins(MainEditorUiPlugin)
.add_plugins((SpawnPointPlugin, ItemSpawnPointPlugin));
.add_plugins(RapierDebugRenderPlugin::default());
}
fn load(application: &mut App) {

View File

@ -1,7 +1,7 @@
use bevy::prelude::*;
use crate::{
comps::core::controller::capture_input,
comps::core::{controller::capture_input, spawners::{player::player_spawner, spawn::SpawnerPlugin}},
logic::core::{
guns::despawn_shots::{despawn_muzzle_flashes, despawn_stray_bullets},
player::{
@ -18,8 +18,6 @@ use crate::{
assets::load_all_assets,
equipment::{change_equipment, EquipmentChangeEvent},
load_state::GameLoadState,
spawn::add_all_spawners,
spawners::player::player_spawner,
},
};
@ -33,6 +31,8 @@ pub fn load_scene(application: &mut App) {
application.insert_resource(MouseMovementSettings::default());
application.insert_resource(AllFirearmAnimations::default());
application.insert_resource(PlayerValuesState::default());
application.add_plugins(SpawnerPlugin);
// Startup
application.add_systems(PreStartup, load_all_assets);
application.add_systems(Startup, spawn_ground);
@ -43,7 +43,7 @@ pub fn load_scene(application: &mut App) {
application.add_systems(Startup, setup_lighting);
application.add_systems(Startup, set_spawn_points);
// Update
add_all_spawners(application);
application.add_systems(Update, capture_input);
application.add_systems(Update, sync_player_y_state);
application.add_systems(Update, follow_cursor_with_camera);
@ -51,11 +51,12 @@ pub fn load_scene(application: &mut App) {
application.add_systems(Update, set_skybox_if_loaded);
application.add_systems(Update, update_camera_vertical_position);
application.add_systems(Update, (capture_hand_usage, interact_action));
application.add_systems(Update, capture_hand_usage);
application.add_systems(Update, interact_action);
application.add_systems(Update, change_equipment.before(player_spawner));
application.add_systems(Update, (despawn_muzzle_flashes, despawn_stray_bullets));
//application.add_systems(Update, register_bullet_hits);
application.add_event::<EquipmentChangeEvent>();
}
}

View File

@ -1,9 +1,6 @@
use bevy::prelude::*;
use crate::{
comps::core::markers::player::{Player, PlayerData},
setup::spawners::{player::PlayerSpawnPoint, guns::m4a1_spawner::M4a1SpawnPoint},
};
use crate::{comps::core::{markers::player::{Player, PlayerData}, spawners::{player::PlayerSpawnPoint, guns::{m4a1_spawner::M4a1SpawnPoint, glock17_spawner::Glock17SpawnPoint}}}, utils};
pub fn set_spawn_points(mut commands: Commands) {
commands.spawn(PlayerSpawnPoint {
@ -11,6 +8,17 @@ pub fn set_spawn_points(mut commands: Commands) {
player: Player(PlayerData::default()),
});
commands.spawn(M4a1SpawnPoint {
transform: Transform::from_xyz(20.0, 10.0, 10.0),
transform: {
let mut transform = Transform::from_xyz(18.0, 10.0, 10.0);
transform.rotate_z(utils::rad_deg::radians_from_degrees(-90.0));
transform
},
});
commands.spawn(Glock17SpawnPoint {
transform: {
let mut transform = Transform::from_xyz(20.0, 10.0, 10.0);
transform.rotate_z(utils::rad_deg::radians_from_degrees(-90.0));
transform
},
});
}

View File

@ -2,5 +2,3 @@ pub mod animations;
pub mod assets;
pub mod equipment;
pub mod load_state;
pub mod spawn;
pub mod spawners;

View File

@ -1,16 +0,0 @@
use bevy::prelude::*;
use super::spawners::{item::item_spawner, player::player_spawner};
/// Where some Bundle T will replace this.
#[derive(Component, Reflect)]
pub struct SpawnPoint {
pub at: Transform,
}
pub fn add_all_spawners(application: &mut App) {
application.add_systems(
Update,
(player_spawner, item_spawner),
);
}

View File

@ -1 +0,0 @@
pub mod m4a1_spawner;

17
src/utils/hierarchy.rs Normal file
View File

@ -0,0 +1,17 @@
use bevy::prelude::*;
pub fn find_child_in_parent_children(commands: &mut Commands, parent_entity: Entity, descendant_entity: Entity, children: &Query<&Children>) -> bool {
let all_children = flatten_if_possible_inf_levels(commands, parent_entity, children);
all_children.contains(&descendant_entity)
}
fn flatten_if_possible_inf_levels(commands: &mut Commands, parent_entity: Entity, children: &Query<&Children>) -> Vec<Entity> {
let mut all_descendant_entities: Vec<Entity> = Vec::new();
let descendants = children.iter_descendants(parent_entity);
for descendant in descendants {
all_descendant_entities.push(descendant);
all_descendant_entities.append(&mut flatten_if_possible_inf_levels(commands, descendant, children));
}
all_descendant_entities
}

View File

@ -1 +1,2 @@
pub mod rad_deg;
pub mod hierarchy;