Interactable hud bug fixes

This commit is contained in:
Franklin 2023-11-12 11:05:37 -04:00
parent bc90efbbc4
commit 8afa56d306
74 changed files with 1097 additions and 561 deletions

View File

@ -1,9 +1,15 @@
use bevy::prelude::*; use bevy::prelude::*;
use bevy_rapier3d::prelude::*; use bevy_rapier3d::prelude::*;
use crate::{logic::core::player::{player_movement::{ use crate::{
move_player, PlayerLinearXZState, PlayerLinearYState, PlayerMovementInput, logic::core::player::{
}, player_values_state::PlayerValuesState}, ui::game::settings::SettingsScreenUIConfiguration}; player_movement::{
move_player, PlayerLinearXZState, PlayerLinearYState, PlayerMovementInput,
},
player_values_state::PlayerValuesState,
},
ui::game::settings::SettingsScreenUIConfiguration,
};
use super::markers::player::Player; use super::markers::player::Player;
@ -23,7 +29,7 @@ pub fn capture_input(
>, >,
time: Res<Time>, time: Res<Time>,
settings_screen_config: Res<SettingsScreenUIConfiguration>, settings_screen_config: Res<SettingsScreenUIConfiguration>,
player_values_state: Res<PlayerValuesState> player_values_state: Res<PlayerValuesState>,
) { ) {
// Don't allocate on each frame. Instead Check if any of the inputs are being pressed and then allocate. // Don't allocate on each frame. Instead Check if any of the inputs are being pressed and then allocate.
if keyboard_input.any_pressed([ if keyboard_input.any_pressed([
@ -51,9 +57,19 @@ pub fn capture_input(
sprint: keyboard_input.pressed(KeyCode::ShiftLeft), sprint: keyboard_input.pressed(KeyCode::ShiftLeft),
}; };
if settings_screen_config.settings_menu_shown { if settings_screen_config.settings_menu_shown {
move_player(PlayerMovementInput::default(), player_query, time, player_values_state); move_player(
PlayerMovementInput::default(),
player_query,
time,
player_values_state,
);
} else { } else {
move_player(player_movement_input, player_query, time, player_values_state); move_player(
player_movement_input,
player_query,
time,
player_values_state,
);
} }
} }
} }

View File

@ -3,4 +3,4 @@ use bevy::prelude::*;
use crate::comps::core::inventory::any_inventory::AnyInventory; use crate::comps::core::inventory::any_inventory::AnyInventory;
#[derive(Event)] #[derive(Event)]
pub struct LootContainerEvent(pub AnyInventory); pub struct LootContainerEvent(pub AnyInventory);

View File

@ -1,2 +1,2 @@
pub mod loot_container; pub mod loot_container;
pub mod pickup_item; pub mod pickup_item;

View File

@ -1,4 +1,4 @@
use bevy::prelude::*; use bevy::prelude::*;
#[derive(Event)] #[derive(Event)]
pub struct PickupItemEvent(); pub struct PickupItemEvent();

View File

@ -1,4 +1,3 @@
#[derive(Copy, Clone, Default, Debug, PartialEq, Eq, PartialOrd, Ord)] #[derive(Copy, Clone, Default, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub struct UGrid { pub struct UGrid {
pub width: u32, pub width: u32,
@ -8,7 +7,10 @@ pub struct UGrid {
impl UGrid { impl UGrid {
/// Creates a ugrid with width = size and height = size /// Creates a ugrid with width = size and height = size
pub fn new_square(size: u32) -> Self { pub fn new_square(size: u32) -> Self {
Self { width: size, height: size } Self {
width: size,
height: size,
}
} }
} }
@ -16,7 +18,10 @@ impl std::ops::Add for UGrid {
type Output = UGrid; type Output = UGrid;
fn add(self, rhs: Self) -> Self::Output { fn add(self, rhs: Self) -> Self::Output {
Self { width: self.width + rhs.width, height: self.height + rhs.height } Self {
width: self.width + rhs.width,
height: self.height + rhs.height,
}
} }
} }
@ -24,6 +29,9 @@ impl std::ops::Sub for UGrid {
type Output = UGrid; type Output = UGrid;
fn sub(self, rhs: Self) -> Self::Output { fn sub(self, rhs: Self) -> Self::Output {
Self { width: self.width - rhs.width, height: self.height - rhs.height } Self {
width: self.width - rhs.width,
height: self.height - rhs.height,
}
} }
} }

View File

@ -1,6 +1,6 @@
use bevy::ecs::component::SparseStorage; use bevy::ecs::component::SparseStorage;
use crate::comps::core::{items::item::Item, grid::UGrid}; use crate::comps::core::{grid::UGrid, items::item::Item};
use super::inventory_item::InventoryItem; use super::inventory_item::InventoryItem;
@ -8,19 +8,18 @@ use super::inventory_item::InventoryItem;
#[derive(Clone)] #[derive(Clone)]
pub struct AnyInventory { pub struct AnyInventory {
size: UGrid, size: UGrid,
items: Vec<InventoryItem> items: Vec<InventoryItem>,
} }
#[allow(unused)] #[allow(unused)]
impl AnyInventory { impl AnyInventory {
pub fn new(size: UGrid) -> Self { pub fn new(size: UGrid) -> Self {
Self { size, items: Vec::new() } Self {
size,
items: Vec::new(),
}
} }
pub fn add_item_at( pub fn add_item_at(&mut self, position: UGrid, item: impl Item<Storage = SparseStorage>) {
&mut self,
position: UGrid,
item: impl Item<Storage = SparseStorage>,
) {
// Is Item bigger than inventory? // Is Item bigger than inventory?
// Does position + item size exceed bounds? // Does position + item size exceed bounds?
if !self.valid_item_and_size_for_inventory(position, &item) { if !self.valid_item_and_size_for_inventory(position, &item) {
@ -38,17 +37,23 @@ impl AnyInventory {
let spots_to_occupy = Self::get_spots_from_item_at_pos(position, item); let spots_to_occupy = Self::get_spots_from_item_at_pos(position, item);
for inventory_item in self.items.iter() { for inventory_item in self.items.iter() {
if inventory_item.is_in_range(&spots_to_occupy) { if inventory_item.is_in_range(&spots_to_occupy) {
return false return false;
} }
} }
true true
} }
pub fn get_spots_from_item_at_pos(position: UGrid, item: &impl Item<Storage = SparseStorage>) -> Vec<UGrid> { pub fn get_spots_from_item_at_pos(
position: UGrid,
item: &impl Item<Storage = SparseStorage>,
) -> Vec<UGrid> {
let end_position = position + item.inventory_size(); let end_position = position + item.inventory_size();
let mut spots = Vec::new(); let mut spots = Vec::new();
for pos_width in position.width..end_position.width { for pos_width in position.width..end_position.width {
for pos_height in position.height..end_position.height { for pos_height in position.height..end_position.height {
spots.push(UGrid { width: pos_width, height: pos_height }); spots.push(UGrid {
width: pos_width,
height: pos_height,
});
} }
} }
spots spots
@ -61,4 +66,4 @@ impl AnyInventory {
let item_bounds = position + item.inventory_size(); let item_bounds = position + item.inventory_size();
!(item_bounds.width > self.size.width || item_bounds.height > self.size.height) !(item_bounds.width > self.size.width || item_bounds.height > self.size.height)
} }
} }

View File

@ -4,7 +4,6 @@ use bevy::ecs::component::SparseStorage;
use crate::comps::core::{grid::UGrid, items::item::Item}; use crate::comps::core::{grid::UGrid, items::item::Item};
#[derive(Clone)] #[derive(Clone)]
pub struct InventoryItem { pub struct InventoryItem {
item: Arc<dyn Item<Storage = SparseStorage>>, item: Arc<dyn Item<Storage = SparseStorage>>,
@ -21,21 +20,22 @@ impl InventoryItem {
pub fn rotated(&self) -> Option<bool> { pub fn rotated(&self) -> Option<bool> {
self.rotated self.rotated
} }
pub fn new( pub fn new(item: impl Item<Storage = SparseStorage>, occupied_spots: Vec<UGrid>) -> Self {
item: impl Item<Storage = SparseStorage>,
occupied_spots: Vec<UGrid>,
) -> Self {
let size = item.inventory_size(); let size = item.inventory_size();
let rotated = item.inventory_rotatable().then(|| false); let rotated = item.inventory_rotatable().then(|| false);
Self { item: Arc::new(item), occupied_spots, rotated } Self {
item: Arc::new(item),
occupied_spots,
rotated,
}
} }
/// Returns true if there is overlap between both /// Returns true if there is overlap between both
pub fn is_in_range(&self, spots_to_occupy: &Vec<UGrid>) -> bool { pub fn is_in_range(&self, spots_to_occupy: &Vec<UGrid>) -> bool {
for occupied_spot in self.occupied_spots.iter() { for occupied_spot in self.occupied_spots.iter() {
if spots_to_occupy.contains(occupied_spot) { if spots_to_occupy.contains(occupied_spot) {
return true return true;
} }
} }
false false
} }
} }

View File

@ -1,6 +1,6 @@
use std::sync::Arc; use std::sync::Arc;
use bevy::{prelude::*, ecs::component::SparseStorage}; use bevy::{ecs::component::SparseStorage, prelude::*};
use crate::comps::core::items::item::Item; use crate::comps::core::items::item::Item;
@ -9,4 +9,4 @@ use crate::comps::core::items::item::Item;
#[derive(Component, Clone, Default)] #[derive(Component, Clone, Default)]
pub struct ItemInventory { pub struct ItemInventory {
pub item: Option<Arc<dyn Item<Storage = SparseStorage>>>, pub item: Option<Arc<dyn Item<Storage = SparseStorage>>>,
} }

View File

@ -1,4 +1,4 @@
pub mod any_inventory; pub mod any_inventory;
pub mod inventory_item; pub mod inventory_item;
pub mod item_inventory; pub mod item_inventory;
pub mod player_inventory; pub mod player_inventory;

View File

@ -2,7 +2,7 @@ use bevy::prelude::*;
use crate::comps::core::grid::UGrid; use crate::comps::core::grid::UGrid;
use super::{item_inventory::ItemInventory, any_inventory::AnyInventory}; use super::{any_inventory::AnyInventory, item_inventory::ItemInventory};
#[derive(Component)] #[derive(Component)]
pub struct PlayerInventory { pub struct PlayerInventory {
@ -13,6 +13,10 @@ pub struct PlayerInventory {
impl Default for PlayerInventory { impl Default for PlayerInventory {
fn default() -> Self { fn default() -> Self {
Self { primary: Default::default(), secondary: Default::default(), backpack: AnyInventory::new(UGrid::new_square(10)) } Self {
primary: Default::default(),
secondary: Default::default(),
backpack: AnyInventory::new(UGrid::new_square(10)),
}
} }
} }

View File

@ -0,0 +1,46 @@
use bevy::prelude::*;
use crate::{
comps::core::{
grid::UGrid,
items::item::{Item, ItemType},
markers::holdable::HoldableObjectType,
},
logic::core::guns::firearm::Firearm,
};
#[derive(Component)]
pub struct M4a1GunItem;
impl Item for M4a1GunItem {
fn get_type(&self) -> ItemType {
ItemType::Holdable(HoldableObjectType::Firearm(Firearm::M4A1))
}
fn asset_path(&self) -> &str {
"weapons/m4a1_rifle.glb"
}
fn stackable(&self) -> Option<u32> {
None
}
fn inventory_size(&self) -> crate::comps::core::grid::UGrid {
UGrid {
width: 4,
height: 2,
}
}
fn inventory_rotatable(&self) -> bool {
true
}
fn inventory_title(&self) -> String {
String::from("M4A1 Rifle")
}
fn inventory_description(&self) -> String {
String::from("Rifle chambered in 5.56x45mm NATO, shoots 800 rounds per minute.")
}
}

View File

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

View File

@ -1,16 +1,22 @@
use bevy::prelude::*; use crate::{
comps::core::{
use crate::comps::core::grid::UGrid; grid::UGrid,
markers::{firearm::FirearmData, holdable::HoldableObjectType, interactable::Interactable},
},
setup::assets::{GltfAssetType, GltfAssets},
utils,
};
use bevy::{gltf::Gltf, prelude::*};
use bevy_rapier3d::prelude::*;
#[allow(unused)] #[allow(unused)]
pub enum ItemType { pub enum ItemType {
Holdable, Holdable(HoldableObjectType),
Equippable, Equippable,
Consumable, Consumable,
} }
pub trait Item: Component { pub trait Item: Component {
fn get_type(&self) -> ItemType; fn get_type(&self) -> ItemType;
fn asset_path(&self) -> &str; fn asset_path(&self) -> &str;
/// Optional Stackable. If value is Some(x) x is the max quantity per stack /// Optional Stackable. If value is Some(x) x is the max quantity per stack
@ -18,4 +24,72 @@ pub trait Item: Component {
fn inventory_size(&self) -> UGrid; fn inventory_size(&self) -> UGrid;
fn inventory_rotatable(&self) -> bool; fn inventory_rotatable(&self) -> bool;
fn inventory_title(&self) -> String; fn inventory_title(&self) -> String;
} fn inventory_description(&self) -> String;
fn spawn(
&self,
commands: &mut Commands,
transform: Transform,
assets_gltf: &GltfAssets,
loaded_gltf_assets: &Assets<Gltf>,
) {
match self.get_type() {
ItemType::Holdable(object_type) => {
match object_type {
HoldableObjectType::Firearm(firearm) => {
if let Some(asset_handle) = assets_gltf.assets.iter().find(|asset| {
asset.asset_type == GltfAssetType::Firearm(firearm.clone())
}) {
if let Some(gltf) = loaded_gltf_assets.get(&asset_handle.asset) {
let firearm_data: FirearmData = firearm.firearm_data();
let mut firearm_transform = Transform::from_xyz(0.0, 0.0, 0.0);
firearm_transform.rotate_local_y(
utils::rad_deg::radians_from_degrees(
firearm.holdable_object_data().y_rot,
),
);
firearm_transform.scale =
firearm_transform.scale * firearm_data.scale_factor;
let scene = gltf.scenes[0].clone();
let firearm_asset_entity = commands
.spawn((
SceneBundle {
scene,
visibility: Visibility::Inherited,
transform: firearm_transform,
..default()
},
Name::new(format!(
"{} Item Gltf Asset",
self.inventory_title()
)),
))
.id();
commands
.spawn((
firearm.holdable_object_data(),
Name::new(format!("{} Item", self.inventory_title())),
TransformBundle {
local: transform,
..Default::default()
},
VisibilityBundle {
visibility: Visibility::Visible,
..Default::default()
},
RigidBody::Dynamic,
Collider::cuboid(5.0, 5.0, 5.0),
Interactable::Item,
))
.push_children(&[firearm_asset_entity]);
}
}
}
};
}
ItemType::Equippable => todo!(),
ItemType::Consumable => todo!(),
};
}
}

View File

@ -1 +1,2 @@
pub mod item; pub mod guns;
pub mod item;

View File

@ -1,11 +1,14 @@
use bevy::{prelude::{Component, Vec3}, reflect::Reflect, time::Timer}; use bevy::{
prelude::{Component, Vec3},
reflect::Reflect,
time::Timer,
};
use crate::logic::core::guns::caliber::Caliber; use crate::logic::core::guns::caliber::Caliber;
#[derive(Component, Reflect)] #[derive(Component, Reflect)]
pub struct BulletMarker { pub struct BulletMarker {
pub caliber: Caliber, pub caliber: Caliber,
pub starting_point: Vec3, pub starting_point: Vec3,
pub timer: Timer, pub timer: Timer,
} }

View File

@ -1,4 +1,7 @@
use bevy::{prelude::{Component, Quat, Vec3}, reflect::Reflect}; use bevy::{
prelude::{Component, Quat, Vec3},
reflect::Reflect,
};
use crate::logic::core::guns::{caliber::Caliber, spray_pattern::FirearmSprayPattern}; use crate::logic::core::guns::{caliber::Caliber, spray_pattern::FirearmSprayPattern};
@ -46,4 +49,4 @@ pub struct FirearmData {
pub struct MagazineData { pub struct MagazineData {
pub rounds_shot: usize, pub rounds_shot: usize,
pub max_capacity: usize, pub max_capacity: usize,
} }

View File

@ -1,5 +1,7 @@
use bevy::prelude::*; use bevy::prelude::*;
use crate::logic::core::guns::firearm::Firearm;
/// Anything that can go in the player's hands. /// Anything that can go in the player's hands.
#[derive(Component, Default, Debug, Reflect)] #[derive(Component, Default, Debug, Reflect)]
pub struct HoldableObjectData { pub struct HoldableObjectData {
@ -11,3 +13,8 @@ pub struct HoldableObjectData {
#[derive(Component, Reflect)] #[derive(Component, Reflect)]
pub struct InPlayerHands; pub struct InPlayerHands;
#[derive(Reflect)]
pub enum HoldableObjectType {
Firearm(Firearm),
}

View File

@ -20,4 +20,4 @@ impl Display for Interactable {
Interactable::Item => write!(f, "Item"), Interactable::Item => write!(f, "Item"),
} }
} }
} }

View File

@ -1,7 +1,7 @@
pub mod bullet;
pub mod camera; pub mod camera;
pub mod firearm; pub mod firearm;
pub mod holdable; pub mod holdable;
pub mod player; pub mod interactable;
pub mod muzzle_flash; pub mod muzzle_flash;
pub mod bullet; pub mod player;
pub mod interactable;

View File

@ -1,4 +1,4 @@
use bevy::{prelude::Component, time::Timer}; use bevy::{prelude::Component, time::Timer};
#[derive(Component)] #[derive(Component)]
pub struct MuzzleFlashMarker(pub Timer); pub struct MuzzleFlashMarker(pub Timer);

View File

@ -10,4 +10,4 @@ pub struct PlayerData {
pub struct Player(pub PlayerData); pub struct Player(pub PlayerData);
#[derive(Component, Reflect)] #[derive(Component, Reflect)]
pub struct PlayerHand; pub struct PlayerHand;

View File

@ -1,6 +1,6 @@
pub mod controller; pub mod controller;
pub mod markers;
pub mod grid;
pub mod events; pub mod events;
pub mod grid;
pub mod inventory; pub mod inventory;
pub mod items; pub mod items;
pub mod markers;

View File

@ -0,0 +1 @@

View File

@ -0,0 +1 @@

View File

@ -49,4 +49,4 @@ impl Caliber {
Caliber::Parabellum9mm => 0.05, Caliber::Parabellum9mm => 0.05,
} }
} }
} }

View File

@ -1,8 +1,12 @@
use crate::comps::core::markers::{bullet::BulletMarker, muzzle_flash::MuzzleFlashMarker};
use bevy::prelude::*; use bevy::prelude::*;
use bevy_rapier3d::prelude::*; use bevy_rapier3d::prelude::*;
use crate::comps::core::markers::{muzzle_flash::MuzzleFlashMarker, bullet::BulletMarker};
pub fn despawn_muzzle_flashes(mut commands: Commands, mut query: Query<(&mut MuzzleFlashMarker, Entity)>, time: Res<Time>) { pub fn despawn_muzzle_flashes(
mut commands: Commands,
mut query: Query<(&mut MuzzleFlashMarker, Entity)>,
time: Res<Time>,
) {
for (mut muzzle_flash, entity) in query.iter_mut() { for (mut muzzle_flash, entity) in query.iter_mut() {
muzzle_flash.0.tick(time.delta()); muzzle_flash.0.tick(time.delta());
if muzzle_flash.0.finished() { if muzzle_flash.0.finished() {
@ -26,28 +30,41 @@ pub fn despawn_stray_bullets(
for event in collisions_read.iter() { for event in collisions_read.iter() {
match event { match event {
CollisionEvent::Started(entity_a, entity_b, _) => { CollisionEvent::Started(entity_a, entity_b, _) => {
if entity_a == entity_b { // Avoid inner collisions if entity_a == entity_b {
// Avoid inner collisions
continue; continue;
} }
if entity_a == &bullet_entity || entity_b == &bullet_entity{ if entity_a == &bullet_entity || entity_b == &bullet_entity {
commands.entity(bullet_entity).remove::<Collider>(); commands.entity(bullet_entity).remove::<Collider>();
//commands.entity(bullet_entity).insert(Sensor); //commands.entity(bullet_entity).insert(Sensor);
spawn_bullet_hit_marker(&mut commands, transform.translation, &mut meshes, &mut materials); spawn_bullet_hit_marker(
} &mut commands,
}, transform.translation,
CollisionEvent::Stopped(entity_a, entity_b, _) => { &mut meshes,
if entity_a == entity_b { // Avoid inner collisions &mut materials,
continue; );
}
if entity_a == &bullet_entity || entity_b == &bullet_entity{
commands.entity(bullet_entity).insert(Collider::ball(bullet.caliber.size()));
//commands.entity(bullet_entity).remove::<Sensor>();
//commands.entity(*entity_b).despawn();
spawn_bullet_exit_marker(&mut commands, transform.translation, &mut meshes, &mut materials);
continue;
} }
} }
//_ => {} CollisionEvent::Stopped(entity_a, entity_b, _) => {
if entity_a == entity_b {
// Avoid inner collisions
continue;
}
if entity_a == &bullet_entity || entity_b == &bullet_entity {
commands
.entity(bullet_entity)
.insert(Collider::ball(bullet.caliber.size()));
//commands.entity(bullet_entity).remove::<Sensor>();
//commands.entity(*entity_b).despawn();
spawn_bullet_exit_marker(
&mut commands,
transform.translation,
&mut meshes,
&mut materials,
);
continue;
}
} //_ => {}
} }
} }
if bullet.timer.finished() { if bullet.timer.finished() {
@ -65,27 +82,27 @@ fn spawn_bullet_hit_marker(
meshes: &mut ResMut<Assets<Mesh>>, meshes: &mut ResMut<Assets<Mesh>>,
materials: &mut ResMut<Assets<StandardMaterial>>, materials: &mut ResMut<Assets<StandardMaterial>>,
) { ) {
commands.spawn( commands.spawn((MaterialMeshBundle {
( mesh: {
MaterialMeshBundle { meshes.add(
mesh: { shape::UVSphere {
meshes.add( radius: 0.05,
shape::UVSphere { radius: 0.05, sectors: 36, stacks: 18 }.into() sectors: 36,
) stacks: 18,
}, }
material: materials.add(StandardMaterial { .into(),
base_color: Color::GREEN, )
//base_color_texture: Some(Color::GREEN), },
emissive: Color::GREEN, material: materials.add(StandardMaterial {
..Default::default() base_color: Color::GREEN,
//base_color_texture: Some(Color::GREEN),
}), emissive: Color::GREEN,
visibility: Visibility::Visible, ..Default::default()
transform: Transform::from_translation(at), }),
..Default::default() visibility: Visibility::Visible,
}, transform: Transform::from_translation(at),
) ..Default::default()
); },));
} }
fn spawn_bullet_exit_marker( fn spawn_bullet_exit_marker(
@ -94,25 +111,25 @@ fn spawn_bullet_exit_marker(
meshes: &mut ResMut<Assets<Mesh>>, meshes: &mut ResMut<Assets<Mesh>>,
materials: &mut ResMut<Assets<StandardMaterial>>, materials: &mut ResMut<Assets<StandardMaterial>>,
) { ) {
commands.spawn( commands.spawn((MaterialMeshBundle {
( mesh: {
MaterialMeshBundle { meshes.add(
mesh: { shape::UVSphere {
meshes.add( radius: 0.05,
shape::UVSphere { radius: 0.05, sectors: 36, stacks: 18 }.into() sectors: 36,
) stacks: 18,
}, }
material: materials.add(StandardMaterial { .into(),
base_color: Color::RED, )
//base_color_texture: Some(Color::GREEN), },
emissive: Color::RED, material: materials.add(StandardMaterial {
..Default::default() base_color: Color::RED,
//base_color_texture: Some(Color::GREEN),
}), emissive: Color::RED,
visibility: Visibility::Visible, ..Default::default()
transform: Transform::from_translation(at), }),
..Default::default() visibility: Visibility::Visible,
}, transform: Transform::from_translation(at),
) ..Default::default()
); },));
} }

View File

@ -1,4 +1,4 @@
use bevy::prelude::*; use bevy::prelude::*;
#[derive(Event)] #[derive(Event)]
pub struct SpawnFirearmEvent(); pub struct SpawnFirearmEvent();

View File

@ -1,4 +1,7 @@
use crate::comps::core::markers::{firearm::{FirearmData, FiringPoint}, holdable::HoldableObjectData}; use crate::comps::core::markers::{
firearm::{FirearmData, FiringPoint},
holdable::HoldableObjectData,
};
use bevy::prelude::*; use bevy::prelude::*;
use super::{caliber::Caliber, spray_pattern::FirearmSprayPattern}; use super::{caliber::Caliber, spray_pattern::FirearmSprayPattern};
@ -27,13 +30,13 @@ impl Firearm {
horizontal_recoil_modifier: 0.5, horizontal_recoil_modifier: 0.5,
recoil_pattern: FirearmSprayPattern { recoil_pattern: FirearmSprayPattern {
vertical: Vec::from([ vertical: Vec::from([
1.0, 1.2, 1.3, 1.6, 1.5, 1.7, 1.5, 1.5, 1.5, 2.0 // 10 for now 1.0, 1.2, 1.3, 1.6, 1.5, 1.7, 1.5, 1.5, 1.5, 2.0, // 10 for now
]), ]),
horizontal: Vec::from([ horizontal: Vec::from([
1.0, 1.2, 1.3, -1.6, 1.5, -1.7, -1.5, 1.5, -1.5, 2.0 // 10 for now 1.0, 1.2, 1.3, -1.6, 1.5, -1.7, -1.5, 1.5, -1.5, 2.0, // 10 for now
]), ]),
}, },
final_aimed_rotation: Quat::from_rotation_x(0.026), final_aimed_rotation: Quat::from_rotation_x(0.026),
final_rotation: Quat::default(), final_rotation: Quat::default(),
final_aimed_position: Vec3 { final_aimed_position: Vec3 {
@ -52,7 +55,7 @@ impl Firearm {
scale_factor: 1.0, scale_factor: 1.0,
asset_path: String::from("weapons/m4a1_rifle.glb"), asset_path: String::from("weapons/m4a1_rifle.glb"),
} }
}, }
Firearm::Glock17 => { Firearm::Glock17 => {
FirearmData { FirearmData {
firing_point: FiringPoint { firing_point: FiringPoint {
@ -68,13 +71,13 @@ impl Firearm {
horizontal_recoil_modifier: 1.0, horizontal_recoil_modifier: 1.0,
recoil_pattern: FirearmSprayPattern { recoil_pattern: FirearmSprayPattern {
vertical: Vec::from([ vertical: Vec::from([
1.0, 1.2, 1.3, 1.6, 1.5, 1.7, 1.5, 1.5, 1.5, 2.0 // 10 for now 1.0, 1.2, 1.3, 1.6, 1.5, 1.7, 1.5, 1.5, 1.5, 2.0, // 10 for now
]), ]),
horizontal: Vec::from([ horizontal: Vec::from([
1.0, 1.2, 1.3, -1.6, 1.5, -1.7, -1.5, 1.5, -1.5, 2.0 // 10 for now 1.0, 1.2, 1.3, -1.6, 1.5, -1.7, -1.5, 1.5, -1.5, 2.0, // 10 for now
]), ]),
}, },
final_aimed_rotation: Quat::from_rotation_x(0.026), final_aimed_rotation: Quat::from_rotation_x(0.026),
final_rotation: Quat::default(), final_rotation: Quat::default(),
final_aimed_position: Vec3 { final_aimed_position: Vec3 {
@ -93,7 +96,7 @@ impl Firearm {
scale_factor: 0.25, scale_factor: 0.25,
asset_path: String::from("weapons/glock_17_pistol.glb"), asset_path: String::from("weapons/glock_17_pistol.glb"),
} }
}, }
} }
} }
pub fn holdable_object_data(&self) -> HoldableObjectData { pub fn holdable_object_data(&self) -> HoldableObjectData {

View File

@ -1,7 +1,7 @@
pub mod caliber; pub mod caliber;
pub mod despawn_shots;
pub mod equip_firearm;
pub mod firearm; pub mod firearm;
pub mod player_firing; pub mod player_firing;
pub mod spray_pattern;
pub mod equip_firearm;
pub mod shoot; pub mod shoot;
pub mod despawn_shots; pub mod spray_pattern;

View File

@ -3,7 +3,7 @@ use std::time::Duration;
use bevy::prelude::*; use bevy::prelude::*;
use bevy_rapier3d::prelude::*; use bevy_rapier3d::prelude::*;
use crate::comps::core::markers::{muzzle_flash::MuzzleFlashMarker, bullet::BulletMarker}; use crate::comps::core::markers::{bullet::BulletMarker, muzzle_flash::MuzzleFlashMarker};
use super::caliber::Caliber; use super::caliber::Caliber;
@ -14,14 +14,19 @@ pub fn shoot_bullet(
firing_point: Transform, firing_point: Transform,
forward: Vec3, forward: Vec3,
up: Vec3, up: Vec3,
caliber: Caliber caliber: Caliber,
) { ) {
// Spawn muzzle flash LIGHT // Spawn muzzle flash LIGHT
commands.spawn( commands.spawn((
(PointLightBundle { PointLightBundle {
point_light: PointLight { point_light: PointLight {
//RGB 252, 238, 128 //RGB 252, 238, 128
color: Color::Rgba { red: 252., green: 238., blue: 128., alpha: 0.5 }, color: Color::Rgba {
red: 252.,
green: 238.,
blue: 128.,
alpha: 0.5,
},
intensity: 0.005, intensity: 0.005,
range: 50.0, range: 50.0,
shadows_enabled: true, shadows_enabled: true,
@ -30,8 +35,9 @@ pub fn shoot_bullet(
transform: firing_point, transform: firing_point,
visibility: Visibility::Visible, visibility: Visibility::Visible,
..Default::default() ..Default::default()
}, MuzzleFlashMarker(Timer::new(Duration::from_millis(10), TimerMode::Once))) },
); MuzzleFlashMarker(Timer::new(Duration::from_millis(10), TimerMode::Once)),
));
// Spawn Line // Spawn Line
/*commands.spawn( /*commands.spawn(
MaterialMeshBundle { MaterialMeshBundle {
@ -50,7 +56,15 @@ pub fn shoot_bullet(
} }
);*/ );*/
spawn_bullet(commands, meshes, materials, firing_point, forward, up, caliber); spawn_bullet(
commands,
meshes,
materials,
firing_point,
forward,
up,
caliber,
);
} }
pub fn spawn_bullet( pub fn spawn_bullet(
@ -60,45 +74,56 @@ pub fn spawn_bullet(
firing_point: Transform, firing_point: Transform,
forward: Vec3, forward: Vec3,
_up: Vec3, _up: Vec3,
caliber: Caliber caliber: Caliber,
) { ) {
commands.spawn( commands.spawn((
( Name::new("Bullet"),
Name::new("Bullet"), BulletMarker {
BulletMarker { caliber: caliber.clone(),
caliber: caliber.clone(), starting_point: firing_point.translation,
starting_point: firing_point.translation, timer: Timer::new(
timer: Timer::new(Duration::from_secs_f32(caliber.max_airtime_secs()), TimerMode::Once) Duration::from_secs_f32(caliber.max_airtime_secs()),
TimerMode::Once,
),
},
MaterialMeshBundle {
mesh: {
meshes.add(
shape::UVSphere {
radius: caliber.size(),
sectors: 36,
stacks: 18,
}
.into(),
)
}, },
MaterialMeshBundle { material: materials.add(StandardMaterial {
mesh: { base_color: Color::Rgba {
meshes.add( red: 253.,
shape::UVSphere { radius: caliber.size(), sectors: 36, stacks: 18 }.into() green: 207.,
) blue: 88.,
alpha: 1.0,
}, },
material: materials.add(StandardMaterial {
base_color: Color::Rgba { red: 253., green: 207., blue: 88., alpha: 1.0 },
..Default::default()
}),
visibility: Visibility::Visible,
transform: firing_point,
..Default::default() ..Default::default()
}, }),
RigidBody::Dynamic, visibility: Visibility::Visible,
GravityScale(4.0), transform: firing_point,
Collider::ball(caliber.size()), ..Default::default()
Velocity::zero(), },
Damping { RigidBody::Dynamic,
linear_damping: caliber.linear_damping(), GravityScale(4.0),
angular_damping: caliber.angular_damping(), Collider::ball(caliber.size()),
}, Velocity::zero(),
ColliderMassProperties::Mass(caliber.mass()), Damping {
ExternalImpulse { linear_damping: caliber.linear_damping(),
impulse: forward * caliber.impulse(), angular_damping: caliber.angular_damping(),
torque_impulse: Vec3::ZERO, },
}, ColliderMassProperties::Mass(caliber.mass()),
ActiveEvents::COLLISION_EVENTS, ExternalImpulse {
Ccd::enabled() impulse: forward * caliber.impulse(),
) torque_impulse: Vec3::ZERO,
); },
} ActiveEvents::COLLISION_EVENTS,
Ccd::enabled(),
));
}

View File

@ -1,7 +1,5 @@
use bevy::reflect::Reflect; use bevy::reflect::Reflect;
#[derive(Clone, Reflect)] #[derive(Clone, Reflect)]
pub struct FirearmSprayPattern { pub struct FirearmSprayPattern {
pub vertical: Vec<f32>, pub vertical: Vec<f32>,

View File

@ -1,2 +1,2 @@
pub mod guns; pub mod guns;
pub mod player; pub mod player;

View File

@ -0,0 +1 @@

View File

@ -3,7 +3,8 @@ use bevy::{input::mouse::MouseMotion, prelude::*, window::CursorGrabMode};
use crate::{ use crate::{
comps::core::markers::{camera::MainCamera, player::Player}, comps::core::markers::{camera::MainCamera, player::Player},
utils::rad_deg::radians_from_degrees, ui::game::settings::SettingsScreenUIConfiguration, ui::game::settings::SettingsScreenUIConfiguration,
utils::rad_deg::radians_from_degrees,
}; };
use super::{player_movement::PlayerLinearXZState, player_values_state::PlayerValuesState}; use super::{player_movement::PlayerLinearXZState, player_values_state::PlayerValuesState};
@ -80,11 +81,13 @@ pub fn follow_cursor_with_camera(
) { ) {
if let Ok(mut window) = primary_window.get_single_mut() { if let Ok(mut window) = primary_window.get_single_mut() {
if keyboard_input.just_pressed(KeyCode::Escape) { if keyboard_input.just_pressed(KeyCode::Escape) {
if settings_screen_config.settings_menu_shown { // Hide settings screen & Capture Cursor if settings_screen_config.settings_menu_shown {
// Hide settings screen & Capture Cursor
settings_screen_config.settings_menu_shown = false; settings_screen_config.settings_menu_shown = false;
window.cursor.grab_mode = CursorGrabMode::Locked; // use `Locked` mode to keep the cursor in one place window.cursor.grab_mode = CursorGrabMode::Locked; // use `Locked` mode to keep the cursor in one place
window.cursor.visible = false; // also hide the cursor window.cursor.visible = false; // also hide the cursor
} else { // Show Settings screen & Release Cursor } else {
// Show Settings screen & Release Cursor
settings_screen_config.settings_menu_shown = true; settings_screen_config.settings_menu_shown = true;
window.cursor.grab_mode = CursorGrabMode::None; // Release cursor window.cursor.grab_mode = CursorGrabMode::None; // Release cursor
window.cursor.visible = true; // Show cursor window.cursor.visible = true; // Show cursor
@ -112,14 +115,23 @@ pub fn follow_cursor_with_camera(
for motion in motions.read() { for motion in motions.read() {
let window_scale = window.height().min(window.width()); let window_scale = window.height().min(window.width());
if btn.pressed(MouseButton::Right) { if btn.pressed(MouseButton::Right) {
pitch -= ((settings.aimed_sensitivity * motion.delta.y as f64 * window_scale as f64) as f32) pitch -= ((settings.aimed_sensitivity
* motion.delta.y as f64
* window_scale as f64) as f32)
.to_radians(); .to_radians();
yaw -= ((settings.aimed_sensitivity * motion.delta.x as f64 * window_scale as f64) as f32) yaw -= ((settings.aimed_sensitivity
* motion.delta.x as f64
* window_scale as f64) as f32)
.to_radians(); .to_radians();
} else { } else {
pitch -= pitch -= ((settings.sensitivity
((settings.sensitivity * motion.delta.y as f64 * window_scale as f64) as f32).to_radians(); * motion.delta.y as f64
yaw -= ((settings.sensitivity * motion.delta.x as f64 * window_scale as f64) as f32).to_radians(); * window_scale as f64) as f32)
.to_radians();
yaw -=
((settings.sensitivity * motion.delta.x as f64 * window_scale as f64)
as f32)
.to_radians();
} }
} }
pitch = pitch.clamp(-1.54, 1.54); pitch = pitch.clamp(-1.54, 1.54);
@ -132,28 +144,53 @@ pub fn follow_cursor_with_camera(
let right = Vec3::new(local_z.z, camera_transform.translation.y, -local_z.x); let right = Vec3::new(local_z.z, camera_transform.translation.y, -local_z.x);
player_transform.rotation = desired_rotation_quat; player_transform.rotation = desired_rotation_quat;
if keyboard_input.pressed(KeyCode::Q) { if keyboard_input.pressed(KeyCode::Q) {
let final_quat = Quat::from_axis_angle(Vec3::Z, radians_from_degrees(player_values_state.player_lean_angle)); let final_quat = Quat::from_axis_angle(
camera_transform.rotation = camera_transform Vec3::Z,
.rotation radians_from_degrees(player_values_state.player_lean_angle),
.lerp(final_quat, time.delta_seconds() / player_values_state.player_lean_time); );
camera_transform.translation = camera_transform.translation.lerp(Vec3 { x: -right.x, y: camera_transform.translation.y, z: -right.z }, time.delta_seconds() / player_values_state.player_lean_time); camera_transform.rotation = camera_transform.rotation.lerp(
final_quat,
time.delta_seconds() / player_values_state.player_lean_time,
);
camera_transform.translation = camera_transform.translation.lerp(
Vec3 {
x: -right.x,
y: camera_transform.translation.y,
z: -right.z,
},
time.delta_seconds() / player_values_state.player_lean_time,
);
} else if keyboard_input.pressed(KeyCode::E) { } else if keyboard_input.pressed(KeyCode::E) {
let final_quat = let final_quat = Quat::from_axis_angle(
Quat::from_axis_angle(Vec3::Z, radians_from_degrees(-player_values_state.player_lean_angle)); Vec3::Z,
camera_transform.rotation = camera_transform radians_from_degrees(-player_values_state.player_lean_angle),
.rotation );
.lerp(final_quat, time.delta_seconds() / player_values_state.player_lean_time); camera_transform.rotation = camera_transform.rotation.lerp(
camera_transform.translation = camera_transform.translation.lerp(Vec3 { x: right.x, y: camera_transform.translation.y, z: right.z }, time.delta_seconds() / player_values_state.player_lean_time); final_quat,
time.delta_seconds() / player_values_state.player_lean_time,
);
camera_transform.translation = camera_transform.translation.lerp(
Vec3 {
x: right.x,
y: camera_transform.translation.y,
z: right.z,
},
time.delta_seconds() / player_values_state.player_lean_time,
);
} else { } else {
camera_transform.rotation = camera_transform camera_transform.rotation = camera_transform.rotation.lerp(
.rotation Quat::default(),
.lerp(Quat::default(), time.delta_seconds() / player_values_state.player_lean_time); time.delta_seconds() / player_values_state.player_lean_time,
);
camera_transform.translation = camera_transform.translation.lerp(Vec3 { camera_transform.translation = camera_transform.translation.lerp(
x: 0.0, Vec3 {
y: camera_transform.translation.y, x: 0.0,
z: 0.0, y: camera_transform.translation.y,
}, time.delta_seconds() / player_values_state.player_lean_time); z: 0.0,
},
time.delta_seconds() / player_values_state.player_lean_time,
);
} }
} }
} }

View File

@ -2,8 +2,24 @@ use bevy::prelude::*;
use bevy_rapier3d::prelude::*; use bevy_rapier3d::prelude::*;
use crate::{ use crate::{
comps::core::{markers::{firearm::{FirearmData, MagazineData}, holdable::InPlayerHands, player::{PlayerHand, Player}, camera::MainCamera, interactable::Interactable}, events::loot_container::LootContainerEvent}, comps::core::{
logic::core::guns::{player_firing::PlayerFiringInfo, shoot::shoot_bullet, firearm::Firearm}, utils::rad_deg::radians_from_degrees, setup::{animations::AllFirearmAnimations, load_state::GameLoadState, equipment::{EquipmentChangeEvent, Equipment}}, ui::game::{settings::SettingsScreenUIConfiguration, hud::hud::HudState}, events::loot_container::LootContainerEvent,
markers::{
camera::MainCamera,
firearm::{FirearmData, MagazineData},
holdable::InPlayerHands,
interactable::Interactable,
player::{Player, PlayerHand},
},
},
logic::core::guns::{firearm::Firearm, player_firing::PlayerFiringInfo, shoot::shoot_bullet},
setup::{
animations::AllFirearmAnimations,
equipment::{Equipment, EquipmentChangeEvent},
load_state::GameLoadState,
},
ui::game::{hud::hud::HudState, settings::SettingsScreenUIConfiguration},
utils::rad_deg::radians_from_degrees,
}; };
pub fn capture_hand_usage( pub fn capture_hand_usage(
@ -24,8 +40,7 @@ pub fn capture_hand_usage(
animation_clips: Res<Assets<AnimationClip>>, animation_clips: Res<Assets<AnimationClip>>,
game_load_state: Res<GameLoadState>, game_load_state: Res<GameLoadState>,
#[allow(unused)] #[allow(unused)] mut equipment_change_event_writer: EventWriter<EquipmentChangeEvent>,
mut equipment_change_event_writer: EventWriter<EquipmentChangeEvent>,
settings_screen_config: Res<SettingsScreenUIConfiguration>, settings_screen_config: Res<SettingsScreenUIConfiguration>,
mut meshes: ResMut<Assets<Mesh>>, mut meshes: ResMut<Assets<Mesh>>,
@ -40,18 +55,19 @@ pub fn capture_hand_usage(
// Equipping stuff // Equipping stuff
// Equipping gun // Equipping gun
if !settings_screen_config.settings_menu_shown { if !settings_screen_config.settings_menu_shown {
if keyboard_input.just_pressed(KeyCode::Key1) { if keyboard_input.just_pressed(KeyCode::Key1) {
equipment_change_event_writer.send(EquipmentChangeEvent(Equipment::Firearm(Firearm::M4A1))); equipment_change_event_writer
.send(EquipmentChangeEvent(Equipment::Firearm(Firearm::M4A1)));
} else if keyboard_input.just_pressed(KeyCode::Key2) { } else if keyboard_input.just_pressed(KeyCode::Key2) {
equipment_change_event_writer.send(EquipmentChangeEvent(Equipment::Firearm(Firearm::Glock17) )); equipment_change_event_writer
.send(EquipmentChangeEvent(Equipment::Firearm(Firearm::Glock17)));
} else if keyboard_input.just_pressed(KeyCode::Key3) { } else if keyboard_input.just_pressed(KeyCode::Key3) {
equipment_change_event_writer.send(EquipmentChangeEvent(Equipment::Nothing )); equipment_change_event_writer.send(EquipmentChangeEvent(Equipment::Nothing));
} }
} }
// Firearm stuff // Firearm stuff
if let Equipment::Firearm(player_firearm) = player_query.single().0.equipment.clone() { if let Equipment::Firearm(player_firearm) = player_query.single().0.equipment.clone() {
for mut player_firing_info in player_firing_info_query.iter_mut() { for mut player_firing_info in player_firing_info_query.iter_mut() {
@ -59,11 +75,16 @@ pub fn capture_hand_usage(
for (firearm_transform, firearm_data, mut magazine_data) in firearm_query.iter_mut() { for (firearm_transform, firearm_data, mut magazine_data) in firearm_query.iter_mut() {
for mut hand_transform in hand_query.iter_mut() { for mut hand_transform in hand_query.iter_mut() {
if player_firing_info.is_reloading { if player_firing_info.is_reloading {
for animation_player in &mut animation_players { for animation_player in &mut animation_players {
if let Some(firearm_animations) = all_firearm_animations.animations.iter().find(|animation| &animation.firearm == &player_firearm) { if let Some(firearm_animations) = all_firearm_animations
if let Some(animation_clip) = animation_clips.get(&firearm_animations.reload_magazine) { .animations
.iter()
.find(|animation| &animation.firearm == &player_firearm)
{
if let Some(animation_clip) =
animation_clips.get(&firearm_animations.reload_magazine)
{
if animation_player.elapsed() >= animation_clip.duration() { if animation_player.elapsed() >= animation_clip.duration() {
magazine_data.rounds_shot = 0; magazine_data.rounds_shot = 0;
player_firing_info.is_reloading = false; player_firing_info.is_reloading = false;
@ -71,12 +92,20 @@ pub fn capture_hand_usage(
} }
} }
} }
} else { // Player is not in a reload animation } else {
if keyboard_input.just_pressed(KeyCode::R) && !settings_screen_config.settings_menu_shown{ // Player is not in a reload animation
if keyboard_input.just_pressed(KeyCode::R)
&& !settings_screen_config.settings_menu_shown
{
// Start reload animation // Start reload animation
for mut animation_player in &mut animation_players { for mut animation_player in &mut animation_players {
if let Some(firearm_animations) = all_firearm_animations.animations.iter().find(|animation| &animation.firearm == &player_firearm) { if let Some(firearm_animations) = all_firearm_animations
animation_player.start(firearm_animations.reload_magazine.clone_weak()); .animations
.iter()
.find(|animation| &animation.firearm == &player_firearm)
{
animation_player
.start(firearm_animations.reload_magazine.clone_weak());
player_firing_info.is_reloading = true; player_firing_info.is_reloading = true;
} }
} }
@ -84,29 +113,38 @@ pub fn capture_hand_usage(
// At the end of reload animation, set magazine data to capacity = 0 // At the end of reload animation, set magazine data to capacity = 0
} }
// AIMING IN/OUT // AIMING IN/OUT
if mouse_buttons.pressed(MouseButton::Right) && !settings_screen_config.settings_menu_shown { if mouse_buttons.pressed(MouseButton::Right)
&& !settings_screen_config.settings_menu_shown
{
let rotation_lerp_quat = hand_transform.rotation.lerp( let rotation_lerp_quat = hand_transform.rotation.lerp(
firearm_data.final_aimed_rotation, firearm_data.final_aimed_rotation,
(time.delta_seconds() / firearm_data.rebound_time_seconds).clamp(0.0, 1.0), (time.delta_seconds() / firearm_data.rebound_time_seconds)
.clamp(0.0, 1.0),
); );
let position_lerp_vec3 = hand_transform.translation.lerp( let position_lerp_vec3 = hand_transform.translation.lerp(
firearm_data.final_aimed_position, firearm_data.final_aimed_position,
(time.delta_seconds() / firearm_data.rebound_time_seconds).clamp(0.0, 1.0), (time.delta_seconds() / firearm_data.rebound_time_seconds)
.clamp(0.0, 1.0),
); );
hand_transform.rotation = rotation_lerp_quat; hand_transform.rotation = rotation_lerp_quat;
hand_transform.translation = position_lerp_vec3; hand_transform.translation = position_lerp_vec3;
} else { } else {
hand_transform.rotation = hand_transform hand_transform.rotation = hand_transform.rotation.lerp(
.rotation firearm_data.final_rotation,
.lerp(firearm_data.final_rotation, (time.delta_seconds() / firearm_data.rebound_time_seconds).clamp(0.0, 1.0)); (time.delta_seconds() / firearm_data.rebound_time_seconds)
.clamp(0.0, 1.0),
);
hand_transform.translation = hand_transform.translation.lerp( hand_transform.translation = hand_transform.translation.lerp(
firearm_data.final_position, firearm_data.final_position,
(time.delta_seconds() / firearm_data.rebound_time_seconds).clamp(0.0, 1.0), (time.delta_seconds() / firearm_data.rebound_time_seconds)
.clamp(0.0, 1.0),
); );
} }
// SHOOTING & RECOIL // SHOOTING & RECOIL
if mouse_buttons.pressed(MouseButton::Left) && !settings_screen_config.settings_menu_shown { if mouse_buttons.pressed(MouseButton::Left)
&& !settings_screen_config.settings_menu_shown
{
if player_firing_info.full_auto_timer.finished() { if player_firing_info.full_auto_timer.finished() {
if magazine_data.rounds_shot < magazine_data.max_capacity { if magazine_data.rounds_shot < magazine_data.max_capacity {
// Get recoil numbers from patterns // Get recoil numbers from patterns
@ -129,10 +167,23 @@ pub fn capture_hand_usage(
let firearm_transform = firearm_transform.clone(); let firearm_transform = firearm_transform.clone();
// TODO: M4 holdableobject data has a Y ROT of -90. Apply that rotation here if it exists. // TODO: M4 holdableobject data has a Y ROT of -90. Apply that rotation here if it exists.
let firing_point = firearm_transform.translation() + (firearm_transform.forward() * firearm_data.firing_point.forward) + (firearm_transform.up() * firearm_data.firing_point.up) + (firearm_transform.right() * firearm_data.firing_point.right); let firing_point = firearm_transform.translation()
+ (firearm_transform.forward()
* firearm_data.firing_point.forward)
+ (firearm_transform.up() * firearm_data.firing_point.up)
+ (firearm_transform.right()
* firearm_data.firing_point.right);
let forward = firearm_transform.forward(); let forward = firearm_transform.forward();
let up = firearm_transform.up(); let up = firearm_transform.up();
shoot_bullet(&mut commands, &mut meshes, &mut materials, Transform::from_translation(firing_point), forward, up, firearm_data.caliber.clone()); shoot_bullet(
&mut commands,
&mut meshes,
&mut materials,
Transform::from_translation(firing_point),
forward,
up,
firearm_data.caliber.clone(),
);
// Increment indexes and timers // Increment indexes and timers
player_firing_info.current_round_index += 1; player_firing_info.current_round_index += 1;
player_firing_info.last_shot_timestamp = time.elapsed_seconds(); player_firing_info.last_shot_timestamp = time.elapsed_seconds();
@ -140,13 +191,17 @@ pub fn capture_hand_usage(
magazine_data.rounds_shot += 1; magazine_data.rounds_shot += 1;
// Apply recoil // Apply recoil
hand_transform hand_transform.rotate_x(radians_from_degrees(
.rotate_x(radians_from_degrees(firearm_data.vertical_recoil_modifier * vertical_recoil_number)); firearm_data.vertical_recoil_modifier
hand_transform.rotate_y(radians_from_degrees(firearm_data.horizontal_recoil_modifier * horizontal_recoil_number)); * vertical_recoil_number,
));
hand_transform.rotate_y(radians_from_degrees(
firearm_data.horizontal_recoil_modifier
* horizontal_recoil_number,
));
} else { } else {
//TODO: play magazine empty sound //TODO: play magazine empty sound
} }
} }
} else { } else {
if player_firing_info.full_auto_timer.finished() { if player_firing_info.full_auto_timer.finished() {
@ -154,19 +209,17 @@ pub fn capture_hand_usage(
} }
} }
} }
} }
} }
} }
} }
} }
/// Method that is run when player hits interact button. /// Method that is run when player hits interact button.
/// Should raycast where the player is looking and scan for interactable /// Should raycast where the player is looking and scan for interactable
pub fn interact_action( pub fn interact_action(
//mut commands: Commands, //mut commands: Commands,
player_query: Query<&Transform, (With<Player>, Without<MainCamera>)>, player_query: Query<(Entity, &Transform), (With<Player>, Without<MainCamera>)>,
camera_query: Query<&GlobalTransform, (With<MainCamera>, Without<Player>)>, camera_query: Query<&GlobalTransform, (With<MainCamera>, Without<Player>)>,
interactables_query: Query<(Entity, &Interactable)>, interactables_query: Query<(Entity, &Interactable)>,
keyboard_input: Res<Input<KeyCode>>, keyboard_input: Res<Input<KeyCode>>,
@ -174,32 +227,47 @@ pub fn interact_action(
mut hud_state: ResMut<HudState>, mut hud_state: ResMut<HudState>,
mut loot_container_event_writer: EventWriter<LootContainerEvent>, mut loot_container_event_writer: EventWriter<LootContainerEvent>,
) { ) {
for transform in player_query.iter() { for (player_entity, transform) in player_query.iter() {
for global_transform in camera_query.iter() { for global_transform in camera_query.iter() {
let ray_pos = global_transform.translation(); let ray_pos = global_transform.translation();
let ray_dir = transform.forward() * 2.0; // TODO: Move this into global Resource state let ray_dir = transform.forward() * 2.0; // TODO: Move this into global Resource state
let max_toi = 4.0; let max_toi = 4.0;
let solid = true; let solid = true;
if let Some((entity, _toi)) = rapier_context.cast_ray( if let Some((entity, _toi)) = rapier_context.cast_ray(
ray_pos, ray_dir, max_toi, solid, QueryFilter::only_fixed() ray_pos,
ray_dir,
max_toi,
solid,
QueryFilter::default().exclude_collider(player_entity),
) { ) {
for (interactable_entity, interactable) in interactables_query.iter() { for (interactable_entity, interactable) in interactables_query.iter() {
println!(
"Hit: {:?} == interactable_entity: {:?} interactable: {}",
entity, interactable_entity, interactable
);
//println!("Collided! {}, {}", entity.index(), interactable.to_string());
if interactable_entity == entity { if interactable_entity == entity {
hud_state.interaction_clue_shown = true; hud_state.interaction_clue_shown = true;
if keyboard_input.just_pressed(KeyCode::F) { // TODO: Move this key to Controls state global hud_state.interaction_clue_text = interactable.to_string();
println!("{interactable}");
if keyboard_input.just_pressed(KeyCode::F) {
// TODO: Move this key to Controls state global
println!("Interacted with interactable"); println!("Interacted with interactable");
match interactable { match interactable {
Interactable::Holdable => todo!(), Interactable::Holdable => todo!(),
Interactable::Lootable(any_inventory) => loot_container_event_writer.send(LootContainerEvent(any_inventory.clone())), Interactable::Lootable(any_inventory) => {
loot_container_event_writer
.send(LootContainerEvent(any_inventory.clone()))
}
Interactable::Item => todo!(), Interactable::Item => todo!(),
} }
} }
return;
} }
return;
} }
} }
} }
} }
hud_state.interaction_clue_shown = false; hud_state.interaction_clue_shown = false;
} }

View File

@ -2,5 +2,5 @@ pub mod camera_effects;
pub mod camera_player_sync; pub mod camera_player_sync;
pub mod hands; pub mod hands;
pub mod player_movement; pub mod player_movement;
pub mod player_values_state;
pub mod player_vertical_sync; pub mod player_vertical_sync;
pub mod player_values_state;

View File

@ -109,7 +109,7 @@ pub fn move_player(
With<Player>, With<Player>,
>, >,
time: Res<Time>, time: Res<Time>,
player_values_state: Res<PlayerValuesState> player_values_state: Res<PlayerValuesState>,
) { ) {
for ( for (
mut player_velocity, mut player_velocity,
@ -151,7 +151,7 @@ pub fn move_player(
player_velocity.linvel, player_velocity.linvel,
time.delta_seconds(), time.delta_seconds(),
sprint_multiplier * crouch_multiplier, sprint_multiplier * crouch_multiplier,
player_values_state.player_acceleration player_values_state.player_acceleration,
); );
} }
if player_movement_input.back { if player_movement_input.back {
@ -164,7 +164,7 @@ pub fn move_player(
player_velocity.linvel, player_velocity.linvel,
time.delta_seconds(), time.delta_seconds(),
crouch_multiplier, crouch_multiplier,
player_values_state.player_acceleration player_values_state.player_acceleration,
); );
} }
if player_movement_input.right { if player_movement_input.right {
@ -177,11 +177,13 @@ pub fn move_player(
player_velocity.linvel, player_velocity.linvel,
time.delta_seconds(), time.delta_seconds(),
if player_linear_xz_state.is_sprinting() { if player_linear_xz_state.is_sprinting() {
player_values_state.player_lateral_acceleration_while_sprinting_multiplier * crouch_multiplier player_values_state.player_lateral_acceleration_while_sprinting_multiplier
* crouch_multiplier
} else { } else {
player_values_state.player_lateral_acceleration_multiplier * crouch_multiplier player_values_state.player_lateral_acceleration_multiplier
* crouch_multiplier
}, },
player_values_state.player_acceleration player_values_state.player_acceleration,
); );
} }
if player_movement_input.left { if player_movement_input.left {
@ -194,17 +196,22 @@ pub fn move_player(
player_velocity.linvel, player_velocity.linvel,
time.delta_seconds(), time.delta_seconds(),
if player_linear_xz_state.is_sprinting() { if player_linear_xz_state.is_sprinting() {
player_values_state.player_lateral_acceleration_while_sprinting_multiplier * crouch_multiplier player_values_state.player_lateral_acceleration_while_sprinting_multiplier
* crouch_multiplier
} else { } else {
player_values_state.player_lateral_acceleration_multiplier * crouch_multiplier player_values_state.player_lateral_acceleration_multiplier
* crouch_multiplier
}, },
player_values_state.player_acceleration player_values_state.player_acceleration,
); );
} }
} }
if player_movement_input.up && player_linear_y_state.is_grounded(&player_values_state.player_jump_cooldown_s) { if player_movement_input.up
player_external_force.impulse = Vec3::new(0.0, player_values_state.player_jump_force, 0.0); && player_linear_y_state.is_grounded(&player_values_state.player_jump_cooldown_s)
{
player_external_force.impulse =
Vec3::new(0.0, player_values_state.player_jump_force, 0.0);
*player_linear_y_state = PlayerLinearYState::Jumping; *player_linear_y_state = PlayerLinearYState::Jumping;
*player_damping = Damping { *player_damping = Damping {
linear_damping: player_values_state.player_linear_damping_while_jumping, linear_damping: player_values_state.player_linear_damping_while_jumping,
@ -217,10 +224,12 @@ pub fn move_player(
{ {
let positive = player_velocity.linvel.x.is_sign_positive(); let positive = player_velocity.linvel.x.is_sign_positive();
if positive { if positive {
player_velocity.linvel.x = player_velocity.linvel.x = player_values_state.max_linear_player_velocity
player_values_state.max_linear_player_velocity * crouch_multiplier * sprint_multiplier * crouch_multiplier
* sprint_multiplier
} else { } else {
player_velocity.linvel.x = player_values_state.max_linear_player_velocity * -1.0 * crouch_multiplier player_velocity.linvel.x =
player_values_state.max_linear_player_velocity * -1.0 * crouch_multiplier
} }
} }
if player_velocity.linvel.z.abs() if player_velocity.linvel.z.abs()
@ -228,9 +237,11 @@ pub fn move_player(
{ {
let positive = player_velocity.linvel.z.is_sign_positive(); let positive = player_velocity.linvel.z.is_sign_positive();
if positive { if positive {
player_velocity.linvel.z = player_values_state.max_linear_player_velocity * crouch_multiplier player_velocity.linvel.z =
player_values_state.max_linear_player_velocity * crouch_multiplier
} else { } else {
player_velocity.linvel.z = player_values_state.max_linear_player_velocity * -1.0 * crouch_multiplier player_velocity.linvel.z =
player_values_state.max_linear_player_velocity * -1.0 * crouch_multiplier
} }
} }
if player_velocity.linvel.x > -1.0 if player_velocity.linvel.x > -1.0

View File

@ -1,5 +1,7 @@
use bevy::{prelude::{Resource, ReflectResource}, reflect::Reflect}; use bevy::{
prelude::{ReflectResource, Resource},
reflect::Reflect,
};
#[derive(Resource, Reflect)] #[derive(Resource, Reflect)]
#[reflect(Resource)] #[reflect(Resource)]
@ -7,7 +9,7 @@ pub struct PlayerValuesState {
pub max_linear_player_velocity: f32, pub max_linear_player_velocity: f32,
pub player_acceleration: f32, pub player_acceleration: f32,
pub player_jump_force: f32, pub player_jump_force: f32,
pub player_jump_cooldown_s: f64, pub player_jump_cooldown_s: f64,
pub player_sprint_speed_multiplier: f32, pub player_sprint_speed_multiplier: f32,
pub player_crouch_speed_multiplier: f32, pub player_crouch_speed_multiplier: f32,
@ -18,10 +20,10 @@ pub struct PlayerValuesState {
pub player_camera_height: f32, pub player_camera_height: f32,
pub player_crouch_height: f32, pub player_crouch_height: f32,
pub player_crouch_time_s: f32, pub player_crouch_time_s: f32,
pub player_linear_damping: f32, pub player_linear_damping: f32,
pub player_linear_damping_while_jumping: f32, pub player_linear_damping_while_jumping: f32,
pub player_lean_time: f32, pub player_lean_time: f32,
pub player_lean_angle: f32, pub player_lean_angle: f32,
@ -55,4 +57,4 @@ impl Default for PlayerValuesState {
player_linear_damping_time_offset_after_jump_in_s: 0.02, player_linear_damping_time_offset_after_jump_in_s: 0.02,
} }
} }
} }

View File

@ -9,7 +9,7 @@ use super::{player_movement::PlayerLinearYState, player_values_state::PlayerValu
pub fn sync_player_y_state( pub fn sync_player_y_state(
mut query: Query<(&Velocity, &mut PlayerLinearYState, &mut Damping), With<Player>>, mut query: Query<(&Velocity, &mut PlayerLinearYState, &mut Damping), With<Player>>,
time: Res<Time>, time: Res<Time>,
player_values_state: Res<PlayerValuesState> player_values_state: Res<PlayerValuesState>,
) { ) {
for (player_velocity, mut player_linear_y_state, mut player_damping) in &mut query { for (player_velocity, mut player_linear_y_state, mut player_damping) in &mut query {
if player_velocity.linvel.y < -1.0 { if player_velocity.linvel.y < -1.0 {
@ -26,7 +26,8 @@ pub fn sync_player_y_state(
let new_grounded_time = previous_grounded_time + time.delta().as_secs_f64(); let new_grounded_time = previous_grounded_time + time.delta().as_secs_f64();
*player_linear_y_state = PlayerLinearYState::Grounded(new_grounded_time); *player_linear_y_state = PlayerLinearYState::Grounded(new_grounded_time);
if new_grounded_time if new_grounded_time
> player_values_state.player_jump_cooldown_s - player_values_state.player_linear_damping_time_offset_after_jump_in_s > player_values_state.player_jump_cooldown_s
- player_values_state.player_linear_damping_time_offset_after_jump_in_s
{ {
*player_damping = Damping { *player_damping = Damping {
linear_damping: player_values_state.player_linear_damping, linear_damping: player_values_state.player_linear_damping,

View File

@ -2,15 +2,15 @@
use bevy::prelude::*; use bevy::prelude::*;
use bevy_rapier3d::prelude::*; use bevy_rapier3d::prelude::*;
use scenes::scene1; use scenes::scene1;
use ui::{game::plugin::MainGameUIPlugin, editor::plugin::MainEditorUiPlugin}; use ui::{editor::plugin::MainEditorUiPlugin, game::plugin::MainGameUIPlugin};
mod comps; mod comps;
mod constants; mod constants;
mod logic; mod logic;
mod scenes; mod scenes;
mod setup; mod setup;
mod utils;
mod ui; mod ui;
mod utils;
fn main() { fn main() {
let mut application = App::new(); let mut application = App::new();

View File

@ -7,11 +7,11 @@ pub fn spawn_ground(
mut materials: ResMut<Assets<StandardMaterial>>, mut materials: ResMut<Assets<StandardMaterial>>,
) { ) {
commands commands
.spawn((Collider::cuboid(50.0, 0.1, 50.0), Name::new("Ground"))) .spawn((Collider::cuboid(100.0, 0.1, 100.0), Name::new("Ground")))
.insert(TransformBundle::from(Transform::from_xyz(0.0, -2.0, 0.0))) .insert(TransformBundle::from(Transform::from_xyz(0.0, -2.0, 0.0)))
.insert(RigidBody::Fixed) .insert(RigidBody::Fixed)
.insert(PbrBundle { .insert(PbrBundle {
mesh: meshes.add(shape::Plane::from_size(100.0).into()), mesh: meshes.add(shape::Plane::from_size(200.0).into()),
material: materials.add(StandardMaterial { material: materials.add(StandardMaterial {
base_color: Color::WHITE, base_color: Color::WHITE,
perceptual_roughness: 1.0, perceptual_roughness: 1.0,

View File

@ -2,17 +2,30 @@ use bevy::prelude::*;
use crate::{ use crate::{
comps::core::controller::capture_input, comps::core::controller::capture_input,
logic::core::{player::{ logic::core::{
guns::despawn_shots::{despawn_muzzle_flashes, despawn_stray_bullets},
player::{
camera_player_sync::{ camera_player_sync::{
follow_cursor_with_camera, update_camera_vertical_position, MouseMovementSettings, follow_cursor_with_camera, update_camera_vertical_position, MouseMovementSettings,
}, },
hands::{capture_hand_usage, interact_action}, hands::{capture_hand_usage, interact_action},
player_vertical_sync::sync_player_y_state, player_values_state::PlayerValuesState, player_values_state::PlayerValuesState,
}, guns::despawn_shots::{despawn_muzzle_flashes, despawn_stray_bullets}}, setup::{assets::load_all_assets, load_state::GameLoadState, spawn::add_all_spawners, animations::{load_animations, AllFirearmAnimations}, equipment::{EquipmentChangeEvent, change_equipment}, spawners::player::player_spawner}, player_vertical_sync::sync_player_y_state,
},
},
setup::{
animations::{load_animations, AllFirearmAnimations},
assets::load_all_assets,
equipment::{change_equipment, EquipmentChangeEvent},
load_state::GameLoadState,
spawn::add_all_spawners,
spawners::player::player_spawner,
},
}; };
use super::{ use super::{
ground::spawn_ground, lighting::setup_lighting, obstacles::spawn_obstacles, skybox::set_skybox_if_loaded, spawn_points::set_spawn_points, ground::spawn_ground, items::spawn_items, lighting::setup_lighting, obstacles::spawn_obstacles,
skybox::set_skybox_if_loaded, spawn_points::set_spawn_points,
}; };
pub fn load_scene(application: &mut App) { pub fn load_scene(application: &mut App) {
@ -23,7 +36,10 @@ pub fn load_scene(application: &mut App) {
// Startup // Startup
application.add_systems(PreStartup, load_all_assets); application.add_systems(PreStartup, load_all_assets);
application.add_systems(Startup, spawn_ground); application.add_systems(Startup, spawn_ground);
application.add_systems(Startup, spawn_obstacles); application.add_systems(
Startup,
(spawn_obstacles, spawn_items.after(load_all_assets)),
);
application.add_systems(Startup, setup_lighting); application.add_systems(Startup, setup_lighting);
application.add_systems(Startup, set_spawn_points); application.add_systems(Startup, set_spawn_points);
// Update // Update
@ -32,7 +48,7 @@ pub fn load_scene(application: &mut App) {
application.add_systems(Update, sync_player_y_state); application.add_systems(Update, sync_player_y_state);
application.add_systems(Update, follow_cursor_with_camera); application.add_systems(Update, follow_cursor_with_camera);
application.add_systems(Update, load_animations); application.add_systems(Update, load_animations);
application.add_systems(Update, set_skybox_if_loaded); application.add_systems(Update, set_skybox_if_loaded);
application.add_systems(Update, update_camera_vertical_position); application.add_systems(Update, update_camera_vertical_position);
application.add_systems(Update, (capture_hand_usage, interact_action)); application.add_systems(Update, (capture_hand_usage, interact_action));

View File

@ -0,0 +1,16 @@
use bevy::{gltf::Gltf, prelude::*};
use crate::{
comps::core::items::{guns::m4a1::M4a1GunItem, item::Item},
setup::assets::GltfAssets,
};
pub fn spawn_items(
mut commands: Commands,
assets_gltf: Res<GltfAssets>,
loaded_gltf_assets: Res<Assets<Gltf>>,
) {
let transform = Transform::from_xyz(20.0, 1.0, 10.0);
let m4item = M4a1GunItem;
m4item.spawn(&mut commands, transform, &assets_gltf, &loaded_gltf_assets);
}

View File

@ -1,16 +1,19 @@
use bevy::prelude::*; use bevy::prelude::*;
pub fn setup_lighting(mut commands: Commands) { pub fn setup_lighting(mut commands: Commands) {
commands.spawn((SpotLightBundle { commands.spawn((
spot_light: SpotLight { SpotLightBundle {
color: Color::WHITE, spot_light: SpotLight {
intensity: 3000.0, color: Color::WHITE,
range: 500.0, intensity: 3000.0,
shadows_enabled: true, range: 500.0,
shadows_enabled: true,
..Default::default()
},
transform: Transform::from_xyz(20.0, 20.0, 20.0).looking_at(Vec3::ZERO, Vec3::Y),
visibility: Visibility::Visible,
..Default::default() ..Default::default()
}, },
transform: Transform::from_xyz(20.0, 20.0, 20.0).looking_at(Vec3::ZERO, Vec3::Y), Name::new("LightSource"),
visibility: Visibility::Visible, ));
..Default::default()
}, Name::new("LightSource")));
} }

View File

@ -1,7 +1,8 @@
pub mod init; pub mod init;
pub mod ground; pub mod ground;
pub mod items;
pub mod lighting; pub mod lighting;
pub mod obstacles; pub mod obstacles;
pub mod skybox; pub mod skybox;
pub mod spawn_points; pub mod spawn_points;

View File

@ -1,7 +1,9 @@
use bevy::prelude::*; use bevy::prelude::*;
use bevy_rapier3d::prelude::*; use bevy_rapier3d::prelude::*;
use crate::comps::core::{markers::interactable::Interactable, grid::UGrid, inventory::any_inventory::AnyInventory}; use crate::comps::core::{
grid::UGrid, inventory::any_inventory::AnyInventory, markers::interactable::Interactable,
};
pub fn spawn_obstacles( pub fn spawn_obstacles(
mut commands: Commands, mut commands: Commands,
@ -15,7 +17,10 @@ pub fn spawn_obstacles(
let box_4_mesh = shape::Box::new(3.0, 7.0, 3.0).into(); let box_4_mesh = shape::Box::new(3.0, 7.0, 3.0).into();
let box_5_mesh = shape::Box::new(2.0, 2.0, 2.0).into(); let box_5_mesh = shape::Box::new(2.0, 2.0, 2.0).into();
commands commands
.spawn((Collider::from_bevy_mesh(&box_1_mesh, &Default::default()).unwrap(), Name::new("Obstacle 1"))) .spawn((
Collider::from_bevy_mesh(&box_1_mesh, &Default::default()).unwrap(),
Name::new("Obstacle 1"),
))
.insert(RigidBody::Fixed) .insert(RigidBody::Fixed)
.insert(PbrBundle { .insert(PbrBundle {
mesh: meshes.add(box_1_mesh.into()), mesh: meshes.add(box_1_mesh.into()),
@ -29,7 +34,10 @@ pub fn spawn_obstacles(
}); });
commands commands
.spawn((Collider::from_bevy_mesh(&box_2_mesh, &Default::default()).unwrap(), Name::new("Obstacle 2"))) .spawn((
Collider::from_bevy_mesh(&box_2_mesh, &Default::default()).unwrap(),
Name::new("Obstacle 2"),
))
.insert(RigidBody::Fixed) .insert(RigidBody::Fixed)
.insert(PbrBundle { .insert(PbrBundle {
mesh: meshes.add(box_2_mesh.into()), mesh: meshes.add(box_2_mesh.into()),
@ -43,7 +51,10 @@ pub fn spawn_obstacles(
}); });
commands commands
.spawn((Collider::from_bevy_mesh(&box_3_mesh, &Default::default()).unwrap(), Name::new("Obstacle 3"))) .spawn((
Collider::from_bevy_mesh(&box_3_mesh, &Default::default()).unwrap(),
Name::new("Obstacle 3"),
))
.insert(RigidBody::Fixed) .insert(RigidBody::Fixed)
.insert(PbrBundle { .insert(PbrBundle {
mesh: meshes.add(box_3_mesh.into()), mesh: meshes.add(box_3_mesh.into()),
@ -57,7 +68,10 @@ pub fn spawn_obstacles(
}); });
commands commands
.spawn((Collider::from_bevy_mesh(&box_4_mesh, &Default::default()).unwrap(), Name::new("Obstacle 4"))) .spawn((
Collider::from_bevy_mesh(&box_4_mesh, &Default::default()).unwrap(),
Name::new("Obstacle 4"),
))
.insert(RigidBody::Fixed) .insert(RigidBody::Fixed)
.insert(PbrBundle { .insert(PbrBundle {
mesh: meshes.add(box_4_mesh.into()), mesh: meshes.add(box_4_mesh.into()),
@ -69,10 +83,13 @@ pub fn spawn_obstacles(
transform: Transform::from_xyz(15.0, 3.5, 15.0), transform: Transform::from_xyz(15.0, 3.5, 15.0),
..default() ..default()
}); });
// CRATE // CRATE
commands commands
.spawn((Collider::from_bevy_mesh(&box_5_mesh, &Default::default()).unwrap(), Name::new("Crate"))) .spawn((
Collider::from_bevy_mesh(&box_5_mesh, &Default::default()).unwrap(),
Name::new("Crate"),
))
.insert(RigidBody::Fixed) .insert(RigidBody::Fixed)
.insert(PbrBundle { .insert(PbrBundle {
mesh: meshes.add(box_5_mesh.into()), mesh: meshes.add(box_5_mesh.into()),
@ -84,7 +101,7 @@ pub fn spawn_obstacles(
transform: Transform::from_xyz(20.0, 2.0, 20.0), transform: Transform::from_xyz(20.0, 2.0, 20.0),
..default() ..default()
}) })
.insert( .insert(Interactable::Lootable(AnyInventory::new(
Interactable::Lootable(AnyInventory::new(UGrid::new_square(10))) UGrid::new_square(10),
); )));
} }

View File

@ -27,7 +27,8 @@ pub fn set_skybox_if_loaded(
mut cubemap: ResMut<Cubemap>, mut cubemap: ResMut<Cubemap>,
mut camera_query: Query<Entity, With<MainCamera>>, mut camera_query: Query<Entity, With<MainCamera>>,
) { ) {
if !cubemap.is_loaded && asset_server.get_load_state(&cubemap.image_handle) == Some(LoadState::Loaded) if !cubemap.is_loaded
&& asset_server.get_load_state(&cubemap.image_handle) == Some(LoadState::Loaded)
{ {
let image = images.get_mut(&cubemap.image_handle).unwrap(); let image = images.get_mut(&cubemap.image_handle).unwrap();
// NOTE: PNGs do not have any metadata that could indicate they contain a cubemap texture, // NOTE: PNGs do not have any metadata that could indicate they contain a cubemap texture,
@ -43,7 +44,9 @@ pub fn set_skybox_if_loaded(
} }
for camera_entity in camera_query.iter_mut() { for camera_entity in camera_query.iter_mut() {
commands.entity(camera_entity).insert(Skybox(cubemap.image_handle.clone())); commands
.entity(camera_entity)
.insert(Skybox(cubemap.image_handle.clone()));
cubemap.is_loaded = true; cubemap.is_loaded = true;
} }
} }

View File

@ -1,8 +1,20 @@
use bevy::prelude::*; use bevy::prelude::*;
use crate::{setup::spawn::SpawnPoint, comps::core::markers::player::{Player, PlayerData}}; use crate::{
comps::core::{
items::guns::m4a1::M4a1GunItem,
markers::player::{Player, PlayerData},
},
setup::spawn::SpawnPoint,
};
pub fn set_spawn_points(mut commands: Commands) { pub fn set_spawn_points(mut commands: Commands) {
commands.spawn(SpawnPoint { at: Transform::from_xyz(3.0, 5.0, 2.0), what: Player(PlayerData::default()) }); commands.spawn(SpawnPoint {
at: Transform::from_xyz(3.0, 5.0, 2.0),
} what: Player(PlayerData::default()),
});
commands.spawn(SpawnPoint {
at: Transform::from_xyz(20.0, 10.0, 10.0),
what: M4a1GunItem,
});
}

View File

@ -1,4 +1,4 @@
use bevy::{prelude::*, gltf::Gltf}; use bevy::{gltf::Gltf, prelude::*};
use crate::logic::core::guns::firearm::Firearm; use crate::logic::core::guns::firearm::Firearm;
@ -14,7 +14,6 @@ pub struct AllFirearmAnimations {
pub struct FirearmAnimations { pub struct FirearmAnimations {
pub firearm: Firearm, pub firearm: Firearm,
pub reload_magazine: Handle<AnimationClip>, pub reload_magazine: Handle<AnimationClip>,
} }
/// System to load animations once the Gltf file is loaded. /// System to load animations once the Gltf file is loaded.
@ -31,16 +30,21 @@ pub fn load_animations(
if assets_gltf.assets.len() != loaded_gltf_assets.len() { if assets_gltf.assets.len() != loaded_gltf_assets.len() {
return; return;
} }
let mut all_firearm_animations = AllFirearmAnimations { animations: Vec::new() }; let mut all_firearm_animations = AllFirearmAnimations {
animations: Vec::new(),
};
for gltf_asset in assets_gltf.assets.iter() { for gltf_asset in assets_gltf.assets.iter() {
if gltf_asset.asset_type.is_firearm() { if gltf_asset.asset_type.is_firearm() {
if let Some(loaded_gltf) = loaded_gltf_assets.get(&gltf_asset.asset) { if let Some(loaded_gltf) = loaded_gltf_assets.get(&gltf_asset.asset) {
// Needs to have all firearm animations // Needs to have all firearm animations
let reload_animation = &loaded_gltf.animations[0]; let reload_animation = &loaded_gltf.animations[0];
all_firearm_animations.animations.push(FirearmAnimations { firearm: gltf_asset.asset_type.get_firearm().clone(), reload_magazine: reload_animation.clone() }) all_firearm_animations.animations.push(FirearmAnimations {
firearm: gltf_asset.asset_type.get_firearm().clone(),
reload_magazine: reload_animation.clone(),
})
} }
} }
} }
commands.insert_resource(all_firearm_animations); commands.insert_resource(all_firearm_animations);
game_load_state.animations_loaded = true; game_load_state.animations_loaded = true;
} }

View File

@ -1,6 +1,9 @@
use bevy::{prelude::*, gltf::Gltf}; use bevy::{gltf::Gltf, prelude::*};
use crate::{logic::core::guns::firearm::Firearm, scenes::scene1::skybox::{CUBEMAPS, Cubemap}}; use crate::{
logic::core::guns::firearm::Firearm,
scenes::scene1::skybox::{Cubemap, CUBEMAPS},
};
use super::load_state::GameLoadState; use super::load_state::GameLoadState;
@ -10,18 +13,19 @@ pub enum GltfAssetType {
#[allow(unused)] #[allow(unused)]
Enemy, Enemy,
} }
#[derive(Resource, Reflect, Default)] #[derive(Resource, Reflect, Default)]
#[reflect(Resource)] #[reflect(Resource)]
pub struct GltfAssets { pub struct GltfAssets {
pub assets: Vec<GltfAsset> pub assets: Vec<GltfAsset>,
} }
#[derive(Reflect)] #[derive(Reflect)]
pub struct GltfAsset { pub struct GltfAsset {
pub asset_type: GltfAssetType, pub asset_type: GltfAssetType,
pub asset: Handle<Gltf>, pub asset: Handle<Gltf>,
} }
pub fn load_all_assets( pub fn load_all_assets(
mut commands: Commands, mut commands: Commands,
asset_server: Res<AssetServer>, asset_server: Res<AssetServer>,
@ -32,13 +36,16 @@ pub fn load_all_assets(
is_loaded: false, is_loaded: false,
image_handle: skybox_handle, image_handle: skybox_handle,
}); });
let m4a1_gltf_asset = GltfAsset { asset_type: GltfAssetType::Firearm(Firearm::M4A1), asset: asset_server.load(Firearm::M4A1.firearm_data().asset_path) } ; let m4a1_gltf_asset = GltfAsset {
let glock17_gltf_asset = GltfAsset { asset_type: GltfAssetType::Firearm(Firearm::Glock17), asset: asset_server.load(Firearm::Glock17.firearm_data().asset_path) }; asset_type: GltfAssetType::Firearm(Firearm::M4A1),
asset: asset_server.load(Firearm::M4A1.firearm_data().asset_path),
};
let glock17_gltf_asset = GltfAsset {
asset_type: GltfAssetType::Firearm(Firearm::Glock17),
asset: asset_server.load(Firearm::Glock17.firearm_data().asset_path),
};
commands.insert_resource(GltfAssets { commands.insert_resource(GltfAssets {
assets: Vec::from([ assets: Vec::from([m4a1_gltf_asset, glock17_gltf_asset]),
m4a1_gltf_asset,
glock17_gltf_asset
])
}); });
game_load_state.assets_loaded = true; game_load_state.assets_loaded = true;
// This works becaue this system is called on startup, so commands will finish running when game starts the update phase. // This works becaue this system is called on startup, so commands will finish running when game starts the update phase.
@ -49,7 +56,7 @@ impl GltfAssetType {
pub fn is_firearm(&self) -> bool { pub fn is_firearm(&self) -> bool {
match self { match self {
GltfAssetType::Firearm(_) => true, GltfAssetType::Firearm(_) => true,
_ => false _ => false,
} }
} }
pub fn get_firearm(&self) -> &Firearm { pub fn get_firearm(&self) -> &Firearm {
@ -58,4 +65,4 @@ impl GltfAssetType {
_ => panic!("Called get_firearm on Non-Firearm GltfAssetType"), _ => panic!("Called get_firearm on Non-Firearm GltfAssetType"),
} }
} }
} }

View File

@ -1,10 +1,18 @@
use std::time::Duration; use std::time::Duration;
use bevy::{prelude::*, gltf::Gltf}; use bevy::{gltf::Gltf, prelude::*};
use crate::{logic::core::guns::{firearm::Firearm, player_firing::PlayerFiringInfo}, comps::core::markers::{player::{Player, PlayerHand}, firearm::{MagazineData, FirearmData}, holdable::InPlayerHands}, utils}; use crate::{
comps::core::markers::{
firearm::{FirearmData, MagazineData},
holdable::InPlayerHands,
player::{Player, PlayerHand},
},
logic::core::guns::{firearm::Firearm, player_firing::PlayerFiringInfo},
utils,
};
use super::assets::{GltfAssets, GltfAssetType}; use super::assets::{GltfAssetType, GltfAssets};
#[derive(Event)] #[derive(Event)]
pub struct EquipmentChangeEvent(pub Equipment); pub struct EquipmentChangeEvent(pub Equipment);
@ -29,22 +37,27 @@ pub fn change_equipment(
for equipment_change_event in equipment_change_event_reader.read() { for equipment_change_event in equipment_change_event_reader.read() {
let Ok((mut player, player_firing_info)) = player_query.get_single_mut() else { let Ok((mut player, player_firing_info)) = player_query.get_single_mut() else {
return; return;
} ; };
// Primary firearm change // Primary firearm change
if equipment_change_event.0 != player.0.equipment { if equipment_change_event.0 != player.0.equipment {
let player_hands = player_hands_query.single_mut(); let player_hands = player_hands_query.single_mut();
commands.entity(player_hands).despawn_descendants(); // TODO: Don't do this without keeping the state from the last mag commands.entity(player_hands).despawn_descendants(); // TODO: Don't do this without keeping the state from the last mag
if let Equipment::Firearm(new_firearm) = equipment_change_event.0.clone() { if let Equipment::Firearm(new_firearm) = equipment_change_event.0.clone() {
spawn_firearm_on_player_hands(&mut commands, player_firing_info, player_hands, &assets_gltf, &loaded_gltf_assets, new_firearm); spawn_firearm_on_player_hands(
&mut commands,
player_firing_info,
player_hands,
&assets_gltf,
&loaded_gltf_assets,
new_firearm,
);
} }
// Set the player's equipment to the newly spawned equipment // Set the player's equipment to the newly spawned equipment
player.0.equipment = equipment_change_event.0.clone(); player.0.equipment = equipment_change_event.0.clone();
println!("Equipment change done"); println!("Equipment change done");
} }
} }
} }
@ -56,7 +69,11 @@ fn spawn_firearm_on_player_hands(
loaded_gltf_assets: &Assets<Gltf>, loaded_gltf_assets: &Assets<Gltf>,
firearm: Firearm, firearm: Firearm,
) { ) {
if let Some(asset_handle) = assets_gltf.assets.iter().find(|asset| asset.asset_type == GltfAssetType::Firearm(firearm.clone())) { if let Some(asset_handle) = assets_gltf
.assets
.iter()
.find(|asset| asset.asset_type == GltfAssetType::Firearm(firearm.clone()))
{
if let Some(gltf) = loaded_gltf_assets.get(&asset_handle.asset) { if let Some(gltf) = loaded_gltf_assets.get(&asset_handle.asset) {
let firearm_data: FirearmData = firearm.firearm_data(); let firearm_data: FirearmData = firearm.firearm_data();
let mut firearm_transform = Transform::from_xyz(0.0, 0.0, 0.0); let mut firearm_transform = Transform::from_xyz(0.0, 0.0, 0.0);
@ -65,19 +82,27 @@ fn spawn_firearm_on_player_hands(
firearm.holdable_object_data().y_rot, firearm.holdable_object_data().y_rot,
)); ));
firearm_transform.scale = firearm_transform.scale * firearm_data.scale_factor; firearm_transform.scale = firearm_transform.scale * firearm_data.scale_factor;
let scene = gltf.scenes[0].clone(); let scene = gltf.scenes[0].clone();
let firearm_asset_entity = commands.spawn((SceneBundle { let firearm_asset_entity = commands
scene, .spawn((
visibility: Visibility::Inherited, SceneBundle {
transform: firearm_transform, scene,
..default() visibility: Visibility::Inherited,
}, Name::new("Firearm Gltf Asset"))).id(); transform: firearm_transform,
..default()
},
Name::new("Firearm Gltf Asset"),
))
.id();
let firearm_entity = commands let firearm_entity = commands
.spawn(( .spawn((
firearm_data.clone(), firearm_data.clone(),
firearm.holdable_object_data(), firearm.holdable_object_data(),
MagazineData { rounds_shot: 0, max_capacity: firearm_data.max_capacity }, MagazineData {
rounds_shot: 0,
max_capacity: firearm_data.max_capacity,
},
InPlayerHands, InPlayerHands,
Name::new("Firearm"), Name::new("Firearm"),
TransformBundle { TransformBundle {
@ -88,18 +113,19 @@ fn spawn_firearm_on_player_hands(
visibility: Visibility::Inherited, visibility: Visibility::Inherited,
..Default::default() ..Default::default()
}, },
)).push_children(&[firearm_asset_entity]) ))
.push_children(&[firearm_asset_entity])
.id(); .id();
commands.entity(player_hands).push_children(&[firearm_entity]);
commands
let time_in_secs_between_each_round = .entity(player_hands)
1.0 / firearm_data.fire_rate * 60.0; .push_children(&[firearm_entity]);
let time_in_secs_between_each_round = 1.0 / firearm_data.fire_rate * 60.0;
player_firing_info.full_auto_timer = Timer::new( player_firing_info.full_auto_timer = Timer::new(
Duration::from_secs_f32(time_in_secs_between_each_round), Duration::from_secs_f32(time_in_secs_between_each_round),
TimerMode::Once, TimerMode::Once,
); );
} }
} }
} }

View File

@ -5,12 +5,11 @@ use bevy::prelude::*;
pub struct GameLoadState { pub struct GameLoadState {
pub assets_loaded: bool, pub assets_loaded: bool,
pub animations_loaded: bool, pub animations_loaded: bool,
pub player_loaded: bool, pub player_loaded: bool,
} }
impl GameLoadState { impl GameLoadState {
pub fn is_everything_except_player_loaded(&self) -> bool { pub fn is_everything_except_player_loaded(&self) -> bool {
self.assets_loaded && self.assets_loaded && self.animations_loaded
self.animations_loaded
} }
} }

View File

@ -1,6 +1,6 @@
pub mod assets;
pub mod animations; pub mod animations;
pub mod assets;
pub mod equipment;
pub mod load_state; pub mod load_state;
pub mod spawn; pub mod spawn;
pub mod spawners; pub mod spawners;
pub mod equipment;

View File

@ -1,14 +1,22 @@
use bevy::prelude::*; use bevy::prelude::*;
use super::{spawners::{player::player_spawner, firearm::firearm_spawner}, equipment::change_equipment}; use crate::comps::core::items::{guns::m4a1::M4a1GunItem, item::Item};
use super::{
equipment::change_equipment,
spawners::{item::item_spawner, player::player_spawner},
};
/// Where some Bundle T will replace this. /// Where some Bundle T will replace this.
#[derive(Component, Reflect)] #[derive(Component, Reflect)]
pub struct SpawnPoint<T: Bundle> { pub struct SpawnPoint<T: Bundle> {
pub at: Transform, pub at: Transform,
pub what: T pub what: T,
} }
pub fn add_all_spawners(application: &mut App) { pub fn add_all_spawners(application: &mut App) {
application.add_systems(Update, (player_spawner, firearm_spawner).after(change_equipment)); application.add_systems(
} Update,
(player_spawner, item_spawner::<M4a1GunItem>).after(change_equipment),
);
}

View File

@ -1,12 +0,0 @@
use bevy::prelude::*;
use crate::{logic::core::guns::firearm::Firearm, setup::{spawn::SpawnPoint, load_state::GameLoadState}};
#[allow(unused)]
pub fn firearm_spawner(
mut commands: Commands,
firearm_sp_query: Query<(Entity, &SpawnPoint<Firearm>)>,
mut game_load_state: ResMut<GameLoadState>,
) {
}

View File

@ -0,0 +1,22 @@
use bevy::{gltf::Gltf, prelude::*};
use crate::{
comps::core::items::{guns::m4a1::M4a1GunItem, item::Item},
setup::{assets::GltfAssets, load_state::GameLoadState, spawn::SpawnPoint},
};
pub fn item_spawner<T: Item>(
mut commands: Commands,
item_sp_query: Query<(Entity, &SpawnPoint<T>)>,
game_load_state: ResMut<GameLoadState>,
assets_gltf: Res<GltfAssets>,
loaded_gltf_assets: Res<Assets<Gltf>>,
) {
if game_load_state.is_everything_except_player_loaded() {
for (entity, item_sp) in item_sp_query.iter() {
let m4 = M4a1GunItem;
m4.spawn(&mut commands, item_sp.at, &assets_gltf, &loaded_gltf_assets);
commands.entity(entity).despawn();
}
}
}

View File

@ -1,2 +1,2 @@
pub mod item;
pub mod player; pub mod player;
pub mod firearm;

View File

@ -4,9 +4,16 @@ use bevy_rapier3d::prelude::*;
use crate::{ use crate::{
comps::core::markers::{ comps::core::markers::{
camera::MainCamera, camera::MainCamera,
player::{Player, PlayerHand, PlayerData}, player::{Player, PlayerData, PlayerHand},
}, },
logic::core::{player::{player_movement::{PlayerLinearYState, PlayerLinearXZState}, player_values_state::PlayerValuesState}, guns::player_firing::PlayerFiringInfo}, setup::{load_state::GameLoadState, equipment::EquipmentChangeEvent}, logic::core::{
guns::player_firing::PlayerFiringInfo,
player::{
player_movement::{PlayerLinearXZState, PlayerLinearYState},
player_values_state::PlayerValuesState,
},
},
setup::{equipment::EquipmentChangeEvent, load_state::GameLoadState},
}; };
use crate::setup::spawn::SpawnPoint; use crate::setup::spawn::SpawnPoint;
@ -28,7 +35,9 @@ pub fn player_spawner(
// Spawn hand // Spawn hand
let player_hand = commands let player_hand = commands
.spawn((PlayerHand, Name::new("Player Hand"))) .spawn((PlayerHand, Name::new("Player Hand")))
.insert(TransformBundle::from(Transform::from_xyz(0.6, -0.45, -20.0))) .insert(TransformBundle::from(Transform::from_xyz(
0.6, -0.45, -20.0,
)))
.insert(VisibilityBundle { .insert(VisibilityBundle {
visibility: Visibility::Inherited, visibility: Visibility::Inherited,
..Default::default() ..Default::default()
@ -76,7 +85,9 @@ pub fn player_spawner(
| LockedAxes::ROTATION_LOCKED_X | LockedAxes::ROTATION_LOCKED_X
| LockedAxes::ROTATION_LOCKED_Y, | LockedAxes::ROTATION_LOCKED_Y,
) )
.insert(ColliderMassProperties::Mass(player_values_state.player_initial_weight)) .insert(ColliderMassProperties::Mass(
player_values_state.player_initial_weight,
))
.insert(ExternalImpulse { .insert(ExternalImpulse {
impulse: Vec3::ZERO, impulse: Vec3::ZERO,
torque_impulse: Vec3::ZERO, torque_impulse: Vec3::ZERO,
@ -94,7 +105,9 @@ pub fn player_spawner(
.push_children(&[camera]); .push_children(&[camera]);
game_load_state.player_loaded = true; game_load_state.player_loaded = true;
equipment_change_event_writer.send(EquipmentChangeEvent(player_spawn_point.what.0.equipment.clone())); equipment_change_event_writer.send(EquipmentChangeEvent(
player_spawn_point.what.0.equipment.clone(),
));
commands.entity(player_spawn_point_entity).despawn(); commands.entity(player_spawn_point_entity).despawn();
} }
} }

View File

@ -1,6 +1,9 @@
use bevy::{prelude::*, window::PrimaryWindow}; use bevy::{prelude::*, window::PrimaryWindow};
use bevy_editor_pls::{controls::{self, EditorControls}, default_windows::cameras::EditorCamera}; use bevy_editor_pls::{
use bevy_inspector_egui::{egui, bevy_egui::EguiContext, bevy_inspector}; controls::{self, EditorControls},
default_windows::cameras::EditorCamera,
};
use bevy_inspector_egui::{bevy_egui::EguiContext, bevy_inspector, egui};
#[allow(unused)] #[allow(unused)]
pub fn inspector_ui(world: &mut World) { pub fn inspector_ui(world: &mut World) {
@ -9,10 +12,8 @@ pub fn inspector_ui(world: &mut World) {
.single(world) .single(world)
.clone(); .clone();
egui::Window::new("World") egui::Window::new("World").show(egui_context.get_mut(), |ui| {
.show(egui_context.get_mut(), |ui| { egui::ScrollArea::vertical().show(ui, |ui| {
egui::ScrollArea::vertical()
.show(ui, |ui| {
bevy_inspector::ui_for_world(world, ui); bevy_inspector::ui_for_world(world, ui);
}); });
}); });
@ -33,7 +34,9 @@ pub fn editor_controls() -> EditorControls {
} }
pub fn set_cam3d_controls( pub fn set_cam3d_controls(
mut query: Query<&mut bevy_editor_pls::default_windows::cameras::camera_3d_free::FlycamControls>, mut query: Query<
&mut bevy_editor_pls::default_windows::cameras::camera_3d_free::FlycamControls,
>,
mut query_camera_transforms: Query<&mut Transform, With<EditorCamera>>, mut query_camera_transforms: Query<&mut Transform, With<EditorCamera>>,
) { ) {
for mut controls in query.iter_mut() { for mut controls in query.iter_mut() {
@ -45,7 +48,11 @@ pub fn set_cam3d_controls(
} }
// TODO: run this after the position update already in the editor plugin // TODO: run this after the position update already in the editor plugin
for mut transform in query_camera_transforms.iter_mut() { for mut transform in query_camera_transforms.iter_mut() {
transform.translation = Vec3 { x: 6.5, y: 28.0, z: 41.6 }; transform.translation = Vec3 {
x: 6.5,
y: 28.0,
z: 41.6,
};
transform.look_at(Vec3::ZERO, Vec3::Y); transform.look_at(Vec3::ZERO, Vec3::Y);
} }
} }

View File

@ -1,8 +1,8 @@
//! Editor UI means everything that won't be in the actual game //! Editor UI means everything that won't be in the actual game
pub mod plugin;
pub mod inspector; pub mod inspector;
pub mod plugin;
/* /*
pub mod panels; pub mod panels;
pub mod state; pub mod state;
pub mod camera; pub mod camera;
*/ */

View File

@ -2,7 +2,31 @@ use bevy::prelude::*;
use bevy_editor_pls::EditorPlugin; use bevy_editor_pls::EditorPlugin;
use bevy_inspector_egui::bevy_egui::EguiPlugin; use bevy_inspector_egui::bevy_egui::EguiPlugin;
use crate::{logic::core::{guns::{player_firing::PlayerFiringInfo, caliber::Caliber, firearm::Firearm, spray_pattern::FirearmSprayPattern}, player::{player_values_state::PlayerValuesState, camera_player_sync::MouseMovementSettings, player_movement::{PlayerLinearYState, PlayerLinearXZState, PlayerMovementInput}}}, comps::core::markers::{firearm::{FirearmData, MagazineData}, holdable::{HoldableObjectData, InPlayerHands}, player::{PlayerData, Player, PlayerHand}}, scenes::scene1::skybox::Cubemap, setup::{animations::{AllFirearmAnimations, FirearmAnimations}, assets::{GltfAssetType, GltfAssets}, equipment::Equipment, load_state::GameLoadState}}; use crate::{
comps::core::markers::{
firearm::{FirearmData, MagazineData},
holdable::{HoldableObjectData, InPlayerHands},
player::{Player, PlayerData, PlayerHand},
},
logic::core::{
guns::{
caliber::Caliber, firearm::Firearm, player_firing::PlayerFiringInfo,
spray_pattern::FirearmSprayPattern,
},
player::{
camera_player_sync::MouseMovementSettings,
player_movement::{PlayerLinearXZState, PlayerLinearYState, PlayerMovementInput},
player_values_state::PlayerValuesState,
},
},
scenes::scene1::skybox::Cubemap,
setup::{
animations::{AllFirearmAnimations, FirearmAnimations},
assets::{GltfAssetType, GltfAssets},
equipment::Equipment,
load_state::GameLoadState,
},
};
use super::inspector::{editor_controls, set_cam3d_controls}; use super::inspector::{editor_controls, set_cam3d_controls};
@ -14,34 +38,33 @@ pub struct MainEditorUiPlugin;
impl Plugin for MainEditorUiPlugin { impl Plugin for MainEditorUiPlugin {
fn build(&self, app: &mut App) { fn build(&self, app: &mut App) {
app app.register_type::<PlayerFiringInfo>()
.register_type::<PlayerFiringInfo>() .register_type::<PlayerValuesState>()
.register_type::<PlayerValuesState>() .register_type::<FirearmData>()
.register_type::<FirearmData>() .register_type::<MagazineData>()
.register_type::<MagazineData>() .register_type::<HoldableObjectData>()
.register_type::<HoldableObjectData>() .register_type::<InPlayerHands>()
.register_type::<InPlayerHands>() .register_type::<PlayerData>()
.register_type::<PlayerData>() .register_type::<Player>()
.register_type::<Player>() .register_type::<PlayerHand>()
.register_type::<PlayerHand>() .register_type::<Caliber>()
.register_type::<Caliber>() .register_type::<Firearm>()
.register_type::<Firearm>() .register_type::<FirearmSprayPattern>()
.register_type::<FirearmSprayPattern>() .register_type::<MouseMovementSettings>()
.register_type::<MouseMovementSettings>() .register_type::<PlayerLinearYState>()
.register_type::<PlayerLinearYState>() .register_type::<PlayerLinearXZState>()
.register_type::<PlayerLinearXZState>() .register_type::<PlayerMovementInput>()
.register_type::<PlayerMovementInput>() .register_type::<Cubemap>()
.register_type::<Cubemap>() .register_type::<AllFirearmAnimations>()
.register_type::<AllFirearmAnimations>() .register_type::<FirearmAnimations>()
.register_type::<FirearmAnimations>() .register_type::<GltfAssetType>()
.register_type::<GltfAssetType>() .register_type::<GltfAssets>()
.register_type::<GltfAssets>() .register_type::<Equipment>()
.register_type::<Equipment>() .register_type::<GameLoadState>()
.register_type::<GameLoadState>() .add_plugins(EguiPlugin)
.add_plugins(EguiPlugin) .add_plugins(EditorPlugin::default())
.add_plugins(EditorPlugin::default()) .insert_resource(editor_controls())
.insert_resource(editor_controls()) .add_systems(PostStartup, set_cam3d_controls);
.add_systems(PostStartup, set_cam3d_controls);
//.add_plugins(ResourceInspectorPlugin::<MouseMovementSettings>::default()); //.add_plugins(ResourceInspectorPlugin::<MouseMovementSettings>::default());
//.add_plugins(bevy_inspector_egui::DefaultInspectorConfigPlugin) // adds default options and `InspectorEguiImpl`s //.add_plugins(bevy_inspector_egui::DefaultInspectorConfigPlugin) // adds default options and `InspectorEguiImpl`s
//.add_systems(Update, inspector_ui); //.add_systems(Update, inspector_ui);
@ -49,4 +72,4 @@ impl Plugin for MainEditorUiPlugin {
//app.add_systems(Update, editor_ui); //app.add_systems(Update, editor_ui);
//app.add_systems(PostUpdate, set_camera_viewport); //app.add_systems(PostUpdate, set_camera_viewport);
} }
} }

View File

@ -9,24 +9,37 @@ pub struct FpsCounterMarker {
} }
impl FpsCounterMarker { impl FpsCounterMarker {
pub fn new() -> Self { pub fn new() -> Self {
Self { timer: Timer::new(Duration::from_secs_f32(0.5), TimerMode::Repeating), frames_elapsed: 0, } Self {
timer: Timer::new(Duration::from_secs_f32(0.5), TimerMode::Repeating),
frames_elapsed: 0,
}
} }
} }
pub fn setup_fps_counter(mut commands: Commands, ) { pub fn setup_fps_counter(mut commands: Commands) {
commands.spawn((TextBundle { commands
text: Text::from_section("FPS: 0.0", TextStyle { .spawn((
font_size: 18.0, color: Color::GREEN, ..Default::default() TextBundle {
}).with_alignment(TextAlignment::Center), text: Text::from_section(
style: Style { "FPS: 0.0",
position_type: PositionType::Absolute, TextStyle {
right: Val::Px(10.0), font_size: 18.0,
top: Val::Px(30.0), color: Color::GREEN,
..Default::default() ..Default::default()
}, },
..Default::default() )
}, Name::new("Fps Counter"))) .with_alignment(TextAlignment::Center),
.insert(FpsCounterMarker::new()); style: Style {
position_type: PositionType::Absolute,
right: Val::Px(10.0),
top: Val::Px(30.0),
..Default::default()
},
..Default::default()
},
Name::new("Fps Counter"),
))
.insert(FpsCounterMarker::new());
} }
pub fn tick_fps_counter( pub fn tick_fps_counter(
@ -45,4 +58,4 @@ pub fn tick_fps_counter(
} }
} }
} }
} }

View File

@ -4,5 +4,5 @@ use bevy::prelude::*;
#[reflect(Resource)] #[reflect(Resource)]
pub struct HudState { pub struct HudState {
pub interaction_clue_shown: bool, pub interaction_clue_shown: bool,
pub interaction_clue_text: String,
} }

View File

@ -1,4 +1,4 @@
use bevy::{prelude::*, ui::FocusPolicy}; use bevy::prelude::*;
use crate::ui::game::settings::SettingsScreenUIConfiguration; use crate::ui::game::settings::SettingsScreenUIConfiguration;
@ -9,51 +9,51 @@ pub struct InteractClueHudMarker;
pub fn setup_interact_clue(mut commands: Commands) { pub fn setup_interact_clue(mut commands: Commands) {
commands.spawn(( commands.spawn((
NodeBundle { TextBundle {
text: Text::from_section(
"Interact",
TextStyle {
font_size: 12.0,
color: Color::WHITE,
..Default::default()
},
)
.with_alignment(TextAlignment::Center),
style: Style { style: Style {
display: Display::Flex, position_type: PositionType::Absolute,
width: Val::Percent(100.0), top: Val::Percent(50.0),
height: Val::Percent(100.0), left: Val::Percent(50.0),
justify_content: JustifyContent::Center,
align_items: AlignItems::Center,
..Default::default() ..Default::default()
}, },
visibility: Visibility::Hidden, visibility: Visibility::Visible,
background_color: BackgroundColor(Color::NONE),
focus_policy: FocusPolicy::Pass,
..Default::default() ..Default::default()
}, Name::new("Interaction Clue Background"), },
InteractClueHudMarker) Name::new("Interaction Clue text"),
).with_children(|parent| { InteractClueHudMarker,
parent.spawn((TextBundle {
text: Text::from_section("Loot", TextStyle {
font_size: 12.0, color: Color::WHITE, ..Default::default()
}).with_alignment(TextAlignment::Center),
..Default::default()
}, Name::new("Interaction Clue text"),
)); ));
});
} }
pub fn update_interact_clue( pub fn update_interact_clue(
//mut commands: Commands, //mut commands: Commands,
interact_clue: Res<HudState>, interact_clue: Res<HudState>,
settings_screen_config: Res<SettingsScreenUIConfiguration>, settings_screen_config: Res<SettingsScreenUIConfiguration>,
mut query: Query<&mut Visibility, With<InteractClueHudMarker>> mut query: Query<(&mut Visibility, &mut Text), With<InteractClueHudMarker>>,
) { ) {
if !settings_screen_config.is_changed() && !interact_clue.is_changed() { if !settings_screen_config.is_changed() && !interact_clue.is_changed() {
return; return;
} }
for mut vis in query.iter_mut() { for (mut vis, mut text) in query.iter_mut() {
if settings_screen_config.settings_menu_shown { if settings_screen_config.settings_menu_shown {
*vis = Visibility::Hidden; *vis = Visibility::Hidden;
return; return;
} }
if interact_clue.interaction_clue_shown { if interact_clue.interaction_clue_shown {
*vis = Visibility::Visible; *vis = Visibility::Visible;
if let Some(section) = text.sections.first_mut() {
section.value = interact_clue.interaction_clue_text.clone();
}
} else { } else {
*vis = Visibility::Hidden; *vis = Visibility::Hidden;
} }
} }
}
}

View File

@ -1,3 +1,3 @@
pub mod hud;
pub mod interact_clue; pub mod interact_clue;
pub mod plugin; pub mod plugin;
pub mod hud;

View File

@ -4,7 +4,6 @@ use crate::ui::game::hud::hud::HudState;
use super::interact_clue::{setup_interact_clue, update_interact_clue}; use super::interact_clue::{setup_interact_clue, update_interact_clue};
pub struct HudOverlayPlugin; pub struct HudOverlayPlugin;
impl Plugin for HudOverlayPlugin { impl Plugin for HudOverlayPlugin {
@ -14,4 +13,4 @@ impl Plugin for HudOverlayPlugin {
app.add_systems(Startup, setup_interact_clue); app.add_systems(Startup, setup_interact_clue);
app.add_systems(Update, update_interact_clue); app.add_systems(Update, update_interact_clue);
} }
} }

View File

@ -2,15 +2,9 @@ use bevy::prelude::*;
use crate::comps::core::events::loot_container::LootContainerEvent; use crate::comps::core::events::loot_container::LootContainerEvent;
/// # Inventory Screen /// # Inventory Screen
/// Should contain player inventory and if player is looting something as well /// Should contain player inventory and if player is looting something as well
pub fn setup_inventory_screen( pub fn setup_inventory_screen(mut commands: Commands) {}
mut commands: Commands,
) {
}
pub fn update_inventory_screen( pub fn update_inventory_screen(
mut commands: Commands, mut commands: Commands,
@ -19,4 +13,4 @@ pub fn update_inventory_screen(
for loot_container_event in event_reader.read() { for loot_container_event in event_reader.read() {
//let a = loot_container_event.0.clone(); //let a = loot_container_event.0.clone();
} }
} }

View File

@ -1,2 +1,2 @@
pub mod menu; pub mod menu;
pub mod plugin; pub mod plugin;

View File

@ -4,7 +4,6 @@ use crate::comps::core::events::loot_container::LootContainerEvent;
use super::menu::{setup_inventory_screen, update_inventory_screen}; use super::menu::{setup_inventory_screen, update_inventory_screen};
pub struct InventoryMenuPlugin; pub struct InventoryMenuPlugin;
impl Plugin for InventoryMenuPlugin { impl Plugin for InventoryMenuPlugin {
@ -13,4 +12,4 @@ impl Plugin for InventoryMenuPlugin {
app.add_systems(Startup, setup_inventory_screen); app.add_systems(Startup, setup_inventory_screen);
app.add_systems(Update, update_inventory_screen); app.add_systems(Update, update_inventory_screen);
} }
} }

View File

@ -1,7 +1,7 @@
//! Game UI means all the UI that will be part of the actual game //! Game UI means all the UI that will be part of the actual game
pub mod plugin;
pub mod fps_counter; pub mod fps_counter;
pub mod hud;
pub mod inventory;
pub mod plugin;
pub mod settings; pub mod settings;
pub mod settings_screen; pub mod settings_screen;
pub mod inventory;
pub mod hud;

View File

@ -2,7 +2,9 @@ use bevy::prelude::*;
use crate::ui::game::settings::GameConfiguration; use crate::ui::game::settings::GameConfiguration;
use super::{fps_counter, settings_screen, settings::SettingsScreenUIConfiguration, inventory, hud}; use super::{
fps_counter, hud, inventory, settings::SettingsScreenUIConfiguration, settings_screen,
};
pub struct MainGameUIPlugin; pub struct MainGameUIPlugin;
@ -12,15 +14,21 @@ impl Plugin for MainGameUIPlugin {
app.add_plugins(inventory::plugin::InventoryMenuPlugin); app.add_plugins(inventory::plugin::InventoryMenuPlugin);
app.insert_resource(GameConfiguration::default()); app.insert_resource(GameConfiguration::default());
app.insert_resource(SettingsScreenUIConfiguration::default()); app.insert_resource(SettingsScreenUIConfiguration::default());
app.add_systems(Startup, ( app.add_systems(
settings_screen::setup_settings_screen, Startup,
fps_counter::setup_fps_counter, (
inventory::menu::setup_inventory_screen, settings_screen::setup_settings_screen,
)); fps_counter::setup_fps_counter,
app.add_systems(Update, ( inventory::menu::setup_inventory_screen,
settings_screen::toggle_settings_screen, ),
settings_screen::handle_settings_button_click, );
fps_counter::tick_fps_counter, app.add_systems(
)); Update,
(
settings_screen::toggle_settings_screen,
settings_screen::handle_settings_button_click,
fps_counter::tick_fps_counter,
),
);
} }
} }

View File

@ -8,7 +8,9 @@ pub struct SettingsScreenUIConfiguration {
impl Default for SettingsScreenUIConfiguration { impl Default for SettingsScreenUIConfiguration {
fn default() -> Self { fn default() -> Self {
Self { settings_menu_shown: false } Self {
settings_menu_shown: false,
}
} }
} }
@ -16,13 +18,12 @@ impl Default for SettingsScreenUIConfiguration {
#[reflect(Resource)] #[reflect(Resource)]
pub struct GameConfiguration { pub struct GameConfiguration {
pub fps_counter_enabled: bool, pub fps_counter_enabled: bool,
} }
impl Default for GameConfiguration { impl Default for GameConfiguration {
fn default() -> Self { fn default() -> Self {
Self { Self {
fps_counter_enabled: true, fps_counter_enabled: true,
} }
} }
} }

View File

@ -1,4 +1,4 @@
use bevy::{prelude::*, ui::FocusPolicy, app::AppExit}; use bevy::{app::AppExit, prelude::*, ui::FocusPolicy};
use super::settings::SettingsScreenUIConfiguration; use super::settings::SettingsScreenUIConfiguration;
@ -12,64 +12,86 @@ pub enum SettingsScreenActions {
} }
pub fn setup_settings_screen(mut commands: Commands) { pub fn setup_settings_screen(mut commands: Commands) {
commands.spawn(( commands
NodeBundle { .spawn((
style: Style { NodeBundle {
display: Display::Flex,
width: Val::Percent(100.0),
height: Val::Percent(100.0),
justify_content: JustifyContent::Center,
align_items: AlignItems::Center,
flex_direction: FlexDirection::Column,
..Default::default()
},
visibility: Visibility::Hidden,
background_color: BackgroundColor(Color::rgba(0.0, 0.0, 0.0, 0.9)),
focus_policy: FocusPolicy::Block,
..Default::default()
}, Name::new("Settings Menu"))
)
.insert(SettingsScreenMarker)
.with_children(|parent| {
// RESUME BUTTON
parent.spawn((
ButtonBundle {
style: Style { style: Style {
display: Display::Flex,
width: Val::Percent(100.0),
height: Val::Percent(100.0),
justify_content: JustifyContent::Center,
align_items: AlignItems::Center,
flex_direction: FlexDirection::Column,
..Default::default() ..Default::default()
}, },
background_color: BackgroundColor(Color::NONE), visibility: Visibility::Hidden,
background_color: BackgroundColor(Color::rgba(0.0, 0.0, 0.0, 0.9)),
focus_policy: FocusPolicy::Block,
..Default::default() ..Default::default()
}, },
Name::new("Resume Button") Name::new("Settings Menu"),
)) ))
.insert(SettingsScreenActions::Resume) .insert(SettingsScreenMarker)
.with_children(|parent| { .with_children(|parent| {
parent.spawn((TextBundle { // RESUME BUTTON
text: Text::from_section("Resume", TextStyle { font_size: 32.0, ..Default::default() }), parent
..Default::default() .spawn((
}, Name::new("Resume Button Text"))); ButtonBundle {
style: Style {
..Default::default()
},
background_color: BackgroundColor(Color::NONE),
..Default::default()
},
Name::new("Resume Button"),
))
.insert(SettingsScreenActions::Resume)
.with_children(|parent| {
parent.spawn((
TextBundle {
text: Text::from_section(
"Resume",
TextStyle {
font_size: 32.0,
..Default::default()
},
),
..Default::default()
},
Name::new("Resume Button Text"),
));
});
// QUIT BUTTON
parent
.spawn((
ButtonBundle {
style: Style {
..Default::default()
},
background_color: BackgroundColor(Color::NONE),
//focus_policy: FocusPolicy::Block,
..Default::default()
},
Name::new("Quit Button"),
))
.insert(SettingsScreenActions::Quit)
.with_children(|parent| {
parent.spawn((
TextBundle {
text: Text::from_section(
"Quit",
TextStyle {
font_size: 32.0,
..Default::default()
},
),
..Default::default()
},
Name::new("Quit Button text"),
));
});
// END BUTTONS
}); });
// QUIT BUTTON
parent.spawn((
ButtonBundle {
style: Style {
..Default::default()
},
background_color: BackgroundColor(Color::NONE),
//focus_policy: FocusPolicy::Block,
..Default::default()
},
Name::new("Quit Button")
))
.insert(SettingsScreenActions::Quit)
.with_children(|parent| {
parent.spawn((TextBundle {
text: Text::from_section("Quit", TextStyle { font_size: 32.0, ..Default::default() }),
..Default::default()
}, Name::new("Quit Button text")));
});
// END BUTTONS
});
} }
pub fn toggle_settings_screen( pub fn toggle_settings_screen(
@ -77,7 +99,9 @@ pub fn toggle_settings_screen(
mut settings_screen_query: Query<(&mut Visibility, &mut Style), With<SettingsScreenMarker>>, mut settings_screen_query: Query<(&mut Visibility, &mut Style), With<SettingsScreenMarker>>,
) { ) {
if settings.is_changed() { if settings.is_changed() {
for (mut settings_screen_visibility, mut settings_screen_style) in settings_screen_query.iter_mut() { for (mut settings_screen_visibility, mut settings_screen_style) in
settings_screen_query.iter_mut()
{
if settings.settings_menu_shown { if settings.settings_menu_shown {
*settings_screen_visibility = Visibility::Visible; *settings_screen_visibility = Visibility::Visible;
settings_screen_style.display = Display::Flex; settings_screen_style.display = Display::Flex;
@ -102,15 +126,15 @@ pub fn handle_settings_button_click(
SettingsScreenActions::Quit => { SettingsScreenActions::Quit => {
// QUIT GAME // QUIT GAME
exit.send(AppExit); exit.send(AppExit);
}, }
SettingsScreenActions::Resume => { SettingsScreenActions::Resume => {
// RESUME GAME // RESUME GAME
settings.settings_menu_shown = false; settings.settings_menu_shown = false;
mouse_buttons.release(MouseButton::Left); mouse_buttons.release(MouseButton::Left);
} }
} }
}, }
_ => {} _ => {}
} }
} }
} }

View File

@ -1,2 +1,2 @@
pub mod editor;
pub mod game; pub mod game;
pub mod editor;