From a447e49036e09ad6b5a39e5c8618f9db9eedbc82 Mon Sep 17 00:00:00 2001 From: Franklin Date: Tue, 21 Nov 2023 14:35:26 -0400 Subject: [PATCH] Shooting, weapon customization, magazine data in gun not in magazine --- assets/character/main_character.glb | Bin 49370340 -> 49370400 bytes assets/weapons/ak105_rifle.glb | Bin 8226628 -> 8226716 bytes src/comps/core/items/guns/ak105.rs | 7 +- src/comps/core/items/item.rs | 7 +- .../core/markers/proxy/weapons/firearm.rs | 42 ++- .../proxy/weapons/initial_attachments.rs | 9 + src/comps/core/markers/proxy/weapons/mod.rs | 3 +- src/comps/core/spawners/guns/ak105_spawner.rs | 31 +- .../core/weapons/attachments/magazine.rs | 7 +- .../weapons/attachments/weapon_attachment.rs | 11 + src/comps/core/weapons/firearm.rs | 22 +- src/comps/core/weapons/firearm_data.rs | 7 +- src/comps/core/weapons/firearm_state.rs | 7 +- src/logic/core/player/camera_switching.rs | 1 + src/logic/core/player/hands.rs | 329 ++++++++---------- src/logic/core/player/mod.rs | 3 +- src/logic/core/player/player_settings.rs | 32 ++ src/scenes/scene1/spawn_points.rs | 14 +- src/ui/editor/inspector.rs | 2 +- src/ui/editor/plugin.rs | 7 +- src/ui/game/settings/plugin.rs | 1 + 21 files changed, 311 insertions(+), 231 deletions(-) create mode 100644 src/comps/core/markers/proxy/weapons/initial_attachments.rs create mode 100644 src/logic/core/player/player_settings.rs diff --git a/assets/character/main_character.glb b/assets/character/main_character.glb index 7d5b880461116f9824fe8f378b3aec81831fee8d..500d9d5c87e3740d6ccba6deffdae02b16033c05 100644 GIT binary patch delta 3658 zcmXBUbx;&c0ETfr6cbyqQEWv#?v4vPu^TMx0z^R&yAu^#6kBWs3k$mtySoz$yIa5a znQwQV-|WuL&g@^CvLV?uHZIxKC7`dbk0DK(G{yWr7@`wgz8!SsWIV*=VvE&5oG(UQTY~1Ct^HlhP`Ka#HD3`ozE_=X7Nv zgHxSV29;4|Qkhj2l~uW@Y%06Tp>nERD!0m`@~V8wRpnO&R6$ip6;?%5QRSwJsp86A zl~5&BDOFnWjfls!GbJyp&0ql|^|gtFkG(a;VCximIxrsp_hRs;O$J z+NzGKtLiBqRbMqw4OJu6ST#{iRWsFGwNNcpE7e;0DnHdmwN>p@d(}bttB$IZ>a4n` zuBw~ru6n4Rs+a1m0#u+1Qhijg>Z|&x5EZKWt1uO=2B-)%Pz_Rp)etpQ4O7F_2sKiT zQlr%vHCByN;9BDGj8 zQA^b_wOqxj6>6ngrBL0bxb9zWn(8&Z+b2g1V?Ksmtn$x~i_J>*|KO zscxy;>W;dr?y39gfqJMOsmJPxN>NYMGxc1(P%l-gdZk{gH|ni=r{1d%>ZAIkKC3V4 ztNNzCs~_s8`lWuWKkBdg7ZseEcBTRYI6*o{56+MQGD0TE3|Sy6xIi|@4mltvF z!7v1d!Y~*PBVZ(qg3&Mr#=Dy2SKumKgX?eu zZo)0N4R_!!+=Kh@03O04cnnV<1)jn)cn&Y%C8WYDcnxphExd#G@Bu!;C-@9s;46HC z@9+bD!Y}v@f8a0tORMkCpha3RfD@#H^xzB`AR}ag%#a1Lf(vAW?2rR;LN3S+c_1(3 z16Rlo1)v}lg2GS)ih>&ygW}*0C7>jfg3?e1%0f9P4;8=zDuO3e0wZ{V3Cv&tZ?J+5 z?BIaPPz9<&HK-0XpeEFU+E54TLOt+-`p^IxLL+DlO`s_>gXYizT0$#m4Zh$9ZJ;f* zgZ9t?{GlUsg3izdxRZ6U@VM-@h|}bcET=5gx#7e1dc)y9D`&y4kzFwoPyJE2F}7cI1d-#B3y#Ya0RZyHMkBp;3nLH v+i(Z&!acYT58xp@g2(U#Qs5~(gXi!9UP3Cog4gf{-oiV>A$@;_p?&@Xys9F; delta 3603 zcmWmES6mJZ7>04ZrL2&ZojsGccUAVx-XVJ?lD)D=2qA=Qkx`jh*-^6h-ZLS4@6UH% z2iO1i96m>PbbP97T3o8Db6~KauOU;WOlf`}4gLwv-;yIkom{LIlhMa)vzjd4HgBV+ zr`6rl!(#LFve?XKtI_0RGn(9u9$rSX$>wGDv08j=W}CMqDm}p7Ei@)2EGETH8I-+p zP?-~BQXC!1hs9<%DkqgiWmVZ!c9laptDGvA%B@^f9+g++Q~6Z^<*Ev*LaMMTqKc|w zsRG!MD%*vvy%BH-OxAIZdRCQHD z)l{`qZB<9rRrOST)j%~=zN(RGteU8%s+nr8TBw$)m1?cpsJ5z|@>A_q2h~yet4^x3 z>Y}=;ZmPTLp?a!bs<-N+`l zjaB2+cr`&yRFl+XHAPKT(^ROMu4bs2Doo8%v(+3GuI8$FYQBn43)DijNJXl}YKdB^ zqSP|AT&++m)he}Gtx;=Lv|6Xus~ELGZB(1oW)-XARJ_`vwyJGvyV{|4ssy!5?N)o# zUbRmps{QJKI;ak*!|I4Ss*=<(bzCK@6m>$Ss*~!JI<3yAv+A5WuP&&I>XN#wuBfZ( zn!2uTsGI7Rx~=Z0yXv00uO6s}>XCY^o~WnlnMza7Rl0hiUaD6rL%mjS)LZpVy;mR9 zNA*d4R$tUt^-X*vtfHUNT zT#y@FAP?k)e2^asfGZS)LQoirKv5_L#la0qKuIVCrJ)Rzg>q0HDnLc31eL)Zs(=Sn z1tWNZ3Cv&tE7-sbyuk;mL3OABHK7*NhB{Ce>Op;I01d$x8bM=d0!^VAG=~<@5?VoP zXajAb9r!_e=l~tTA38y2=mK4#8+3;r&=Yz=Z|DPkAprV8AoPa;5Cj7u7zV*$7y?6K z7z~FIFcL<=Xcz+_Fc!wac$feaVG>M+DKHhLK`2az888#VU>3}VIS>wWVIItf2v`6M zVG%^aVpsx8Aqtkka##T?VHK=~HLw<Tuow10BJ76)a1ai`VK@RuAqkGbaY%*~I030}5>CNsI0I+l9Gr&>a1k!SWw-)Y z;Tl|r8*meD!ELw$ci|q~hX?Qw9>HUH0#D%?q``AYhZpb?UO@)DhBxpQ-obnL03YEK ze12$O2g*8)SzZ;0!q-7vu&P z$OCyHALNGu;0gty5EOoFI1i?TEhCwhGhQLr52E$M99wxv_2F!#om<6+84ur#8mamx9E3w~7>>YENP=T<9FidgPCzQ0gi~-D&cInX2j}4eT!c$-8Lq%pxCYnZ z2Hb>Oa2xKxUAPDL;Q>5^NAMV)z*BezY49A<;RU>eSC9d(;SIcncktejr1>+11pN>C CQ^~ym diff --git a/assets/weapons/ak105_rifle.glb b/assets/weapons/ak105_rifle.glb index ac866e2b096f67ca6d22afd399cd5af57bb98714..2605cd1811e49949beaa14e608e8ca58abe5d315 100644 GIT binary patch delta 591 zcmZwBCs#rN06^i#0~7}iaEk*K6$i3;xF@(L?uiQrZbeZ^2F@{Ppb#uJgT+Je5BM|u z4>q#bZurVg_v5{(GoA8Ml*3#lBjSEV-L72jkUli6jrxUG`g zX_p)}tK@XWe&mn;2*?7aC}hhkO*E z5Jf0P2}+?u8Ol+CO6XCAYSiHGsTOsphY<~EL=&1}LJQ2WzzQ4eaKH%{B)HLvHngJy zo#;Y0deDnL^kV=Xcrl0}3}XbN7{fRwFo`KlV+KCVVh;0Iz#^8gj1{b64eQu|ADh_1 rHg>R!0QRtt0~{iVBOK!dr#QnoE^vt}gm8@;gmH^I+<(Rmk$3+ub4J(- delta 553 zcmWm8$ySX4007|Ie=jmzBpOt@rAw1is5BrdG%AUrlqQsDMAL?II>(|GZ9RZRn@)>f zz$5e^cT;Ph#kc={ZykmIZXSiBlheH|K`0bz+E@$y+>I6m+lN8Q-g@vSX}c!!YwsYE zofnS9Vm}h`jYK?&fG`n`ahww*bCOe><_uBJa*p$)aDh}Va)~t3$sm)>, - + pub initial_attachments: Option, } impl Item for Ak105GunItem { @@ -102,6 +102,9 @@ impl Item for Ak105GunItem { Some(ref state) => { commands.entity(firearm_asset_entity).insert(state.clone()); }, None => {}, }; + if let Some(initial_attachments) = &self.initial_attachments { + commands.entity(firearm_asset_entity).insert(initial_attachments.clone()); + } let firearm_size = firearm.get_size(); commands .spawn(( diff --git a/src/comps/core/items/item.rs b/src/comps/core/items/item.rs index 611799f..7fadc75 100644 --- a/src/comps/core/items/item.rs +++ b/src/comps/core/items/item.rs @@ -1,16 +1,13 @@ use crate::{ comps::core::{ grid::UGrid, - markers::{holdable::HoldableObjectType, interactable::Interactable}, inventory::slot::PlayerInventorySlotType, weapons::{firearm_data::FirearmData, firearm::Firearm}, events::pickup_item::ItemState, + markers::holdable::HoldableObjectType, inventory::slot::PlayerInventorySlotType, weapons::firearm::Firearm, events::pickup_item::ItemState, }, - setup::assets::{GltfAssetType, GltfAssets}, - utils, + setup::assets::GltfAssets, }; use bevy::{gltf::Gltf, prelude::*}; -use bevy_rapier3d::prelude::*; use uuid::Uuid; -#[allow(unused)] pub enum ItemType { Holdable(HoldableObjectType), Equippable, diff --git a/src/comps/core/markers/proxy/weapons/firearm.rs b/src/comps/core/markers/proxy/weapons/firearm.rs index 57df19a..e548a2a 100644 --- a/src/comps/core/markers/proxy/weapons/firearm.rs +++ b/src/comps/core/markers/proxy/weapons/firearm.rs @@ -2,47 +2,49 @@ use bevy::{prelude::*, gltf::Gltf, ecs::system::SystemParam, scene::SceneInstanc use crate::{comps::core::{weapons::{firearm::Firearm, firearm_state::FirearmState, slot::slot::WeaponSlot, attachment_slot::AttachmentSlot, attachments::weapon_attachment::WeaponAttachment}, events::pickup_item::ItemState, markers::holdable::InPlayerHands, inventory::player_inventory::PlayerInventory, items::item::ItemId}, setup::assets::{GltfAssets, GltfAssetType}}; +use super::initial_attachments::InitialAttachments; + #[derive(SystemParam)] pub struct InsertFirearmStateIntoFirearmsParams<'w, 's> { - firearm_scene_bundle: Query<'w, 's, (Entity, Option<&'static ItemState>, &'static Children), With>, - firearm_query: Query<'w, 's, (Entity, &'static Firearm, &'static Parent, Option<&'static FirearmState>), Or<(Without, Changed)>>, + firearm_scene_bundle: Query<'w, 's, (Entity, Option<&'static ItemState>, Option<&'static InitialAttachments>, &'static Children), With>, + firearm_query: Query<'w, 's, (Entity, &'static Firearm, &'static Parent, Option<&'static mut FirearmState>), Or<(Without, Changed)>>, slots_query: Query<'w, 's, (Entity, &'static WeaponSlot, &'static Parent)>, attachments_query: Query<'w, 's, (Entity, &'static WeaponAttachment, &'static Parent)>, in_player_hands_query: Query<'w, 's, &'static ItemId, With>, - player_inventories_query: Query<'w, 's, &'static PlayerInventory> + player_inventories_query: Query<'w, 's, &'static PlayerInventory>, + } /// This query inserts FirearmState into firearms, updates firearm assets that already have a FirearmState, /// And Re-inserts FirearmState into spawned Firearms that have a passed in ItemState at the root of the SceneBundle pub fn insert_firearm_state_to_firearms( // needed for tri meshes - queries: InsertFirearmStateIntoFirearmsParams, + mut queries: InsertFirearmStateIntoFirearmsParams, assets_gltf: Res, loaded_gltf_assets: Res>, mut commands: Commands, ) { - for (firearm_scene_entity, item_state_opt, scene_bundle_children) in queries.firearm_scene_bundle.iter() { + for (firearm_scene_entity, item_state_opt, initial_attchments_opt, scene_bundle_children) in queries.firearm_scene_bundle.iter() { for scene_bundle_child in scene_bundle_children.iter() { - for (firearm_entity, _, firearm_parent, firearm_state_opt) in queries.firearm_query.iter() { + for (firearm_entity, _, firearm_parent, firearm_state_opt) in queries.firearm_query.iter_mut() { if &firearm_parent.get() == scene_bundle_child { if let Some(item_state) = item_state_opt { // Firearm State is already created and item is being spawned again into world #[allow(irrefutable_let_patterns)] - if let ItemState::Weapon(firearm_state) = item_state { + if let ItemState::Weapon(mut firearm_state) = item_state.clone() { commands.entity(firearm_scene_entity).remove::(); + spawn_attachments_in_firearm(&mut commands, firearm_entity, &mut firearm_state, &queries.slots_query, &assets_gltf, &loaded_gltf_assets); commands .entity(firearm_entity) - .insert(firearm_state.clone()); - spawn_attachments_in_firearm(&mut commands, firearm_entity, firearm_state, &queries.slots_query, &assets_gltf, &loaded_gltf_assets); + .insert(firearm_state); return; } } match firearm_state_opt { - Some(firearm_state) => { + Some(mut firearm_state) => { // Change the Slots - spawn_attachments_in_firearm(&mut commands, firearm_entity, firearm_state, &queries.slots_query, &assets_gltf, &loaded_gltf_assets); - //TODO: Change firearm state inside inventory + spawn_attachments_in_firearm(&mut commands, firearm_entity, &mut firearm_state, &queries.slots_query, &assets_gltf, &loaded_gltf_assets); for in_player_hands_item_id in queries.in_player_hands_query.iter() { for player_inventory in queries.player_inventories_query.iter() { if let Some(current_item) = player_inventory.get_current_slot_item() { @@ -56,6 +58,7 @@ pub fn insert_firearm_state_to_firearms( None => { // Create the firearm_state let mut firearm_slots = Vec::new(); + let magazine_data = None; for (slot_entity, slot, parent_entity) in queries.slots_query.iter() { if firearm_entity == parent_entity.get() { let mut attachment = None; @@ -70,7 +73,13 @@ pub fn insert_firearm_state_to_firearms( }); } } - let firearm_state = FirearmState::new(firearm_slots); + if let Some(initial_attachments) = initial_attchments_opt { + for initial_attachment in initial_attachments.attachments.iter() { + firearm_slots.iter_mut().for_each(|firearm_slot| if initial_attachment.fits_into_slot(&firearm_slot.slot_type) { firearm_slot.attachment = Some(initial_attachment.clone()) }); + } + commands.entity(firearm_scene_entity).remove::(); + } + let firearm_state = FirearmState::new(firearm_slots, magazine_data); commands .entity(firearm_entity) .insert(firearm_state.clone()); @@ -85,7 +94,7 @@ pub fn insert_firearm_state_to_firearms( fn spawn_attachments_in_firearm( commands: &mut Commands, firearm_entity: Entity, - firearm_state: &FirearmState, + firearm_state: &mut FirearmState, slots_query: &Query<(Entity, &WeaponSlot, &Parent)>, assets_gltf: &GltfAssets, loaded_gltf_assets: &Assets, @@ -112,6 +121,11 @@ fn spawn_attachments_in_firearm( commands.entity(slot_entity).add_child( scene_bundle ); + if let None = &firearm_state.magazine_data { + if let WeaponAttachment::Magazine(magazine) = attachment { + firearm_state.magazine_data = Some(magazine.magazine_data()); + } + } }}, None => {}, }; diff --git a/src/comps/core/markers/proxy/weapons/initial_attachments.rs b/src/comps/core/markers/proxy/weapons/initial_attachments.rs new file mode 100644 index 0000000..bcb40f6 --- /dev/null +++ b/src/comps/core/markers/proxy/weapons/initial_attachments.rs @@ -0,0 +1,9 @@ +use bevy::prelude::*; + +use crate::comps::core::weapons::attachments::weapon_attachment::WeaponAttachment; + +#[derive(Component, Reflect, Default, Clone)] +#[reflect(Component)] +pub struct InitialAttachments { + pub attachments: Vec +} \ No newline at end of file diff --git a/src/comps/core/markers/proxy/weapons/mod.rs b/src/comps/core/markers/proxy/weapons/mod.rs index 21435c1..77a0ef8 100644 --- a/src/comps/core/markers/proxy/weapons/mod.rs +++ b/src/comps/core/markers/proxy/weapons/mod.rs @@ -1 +1,2 @@ -pub mod firearm; \ No newline at end of file +pub mod firearm; +pub mod initial_attachments; \ No newline at end of file diff --git a/src/comps/core/spawners/guns/ak105_spawner.rs b/src/comps/core/spawners/guns/ak105_spawner.rs index 5834727..e981000 100644 --- a/src/comps/core/spawners/guns/ak105_spawner.rs +++ b/src/comps/core/spawners/guns/ak105_spawner.rs @@ -4,12 +4,13 @@ use uuid::Uuid; use crate::comps::core::{ items::{guns::ak105::Ak105GunItem, item::{Item, ItemId}}, - spawners::item::ItemSpawnPoint, + spawners::item::ItemSpawnPoint, weapons::attachments::{weapon_attachment::WeaponAttachment, compensator::Compensator, foregrip::ForeGrip, magazine::Magazine, stock::Stock}, markers::proxy::weapons::initial_attachments::InitialAttachments, }; #[derive(Component)] pub struct Ak105SpawnPoint { pub transform: Transform, + pub attachments: Vec } impl ItemSpawnPoint for Ak105SpawnPoint { @@ -18,6 +19,32 @@ impl ItemSpawnPoint for Ak105SpawnPoint { } fn get_item(&self) -> Box { - Box::new(Ak105GunItem { state: Mutex::new(None), id: ItemId(Uuid::new_v4()) }) + let initial_attachments = if self.attachments.is_empty() { + None + } else { + Some(InitialAttachments { attachments: self.attachments.clone() }) + }; + Box::new(Ak105GunItem { state: Mutex::new(None), id: ItemId(Uuid::new_v4()), initial_attachments }) + } +} + +#[allow(unused)] +impl Ak105SpawnPoint { + pub fn new(transform: Transform) -> Self { + Self { + transform, + attachments: Vec::new(), + } + } + pub fn new_fully_kitted_default(transform: Transform) -> Self { + Self { + transform, + attachments: Vec::from([ + WeaponAttachment::Compensator(Compensator::FirstCompensator), + WeaponAttachment::ForeGrip(ForeGrip::Pk5), + WeaponAttachment::Magazine(Magazine::Ak105), + WeaponAttachment::Stock(Stock::MagpullTan), + ]), + } } } diff --git a/src/comps/core/weapons/attachments/magazine.rs b/src/comps/core/weapons/attachments/magazine.rs index 995b899..6d397db 100644 --- a/src/comps/core/weapons/attachments/magazine.rs +++ b/src/comps/core/weapons/attachments/magazine.rs @@ -1,5 +1,7 @@ use bevy::{reflect::{Reflect, std_traits::ReflectDefault}, ecs::{component::Component, reflect::ReflectComponent}}; +use crate::comps::core::weapons::magazine_data::MagazineData; + #[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Reflect, Component, Debug, Default)] #[reflect(Component, Default)] @@ -9,7 +11,10 @@ pub enum Magazine { } impl Magazine { - pub fn capacity(&self) -> u32 { + pub fn magazine_data(&self) -> MagazineData { + MagazineData { rounds_shot: 0, max_capacity: self.capacity() } + } + pub fn capacity(&self) -> usize { match self { Magazine::Ak105 => 30, } diff --git a/src/comps/core/weapons/attachments/weapon_attachment.rs b/src/comps/core/weapons/attachments/weapon_attachment.rs index fabb90e..fbcfacb 100644 --- a/src/comps/core/weapons/attachments/weapon_attachment.rs +++ b/src/comps/core/weapons/attachments/weapon_attachment.rs @@ -1,5 +1,7 @@ use bevy::prelude::*; +use crate::comps::core::weapons::{attachment_slot::AttachmentSlot, slot::slot::WeaponSlot}; + use super::{compensator::Compensator, magazine::Magazine, stock::Stock, foregrip::ForeGrip, optic::Optic}; #[derive(Component, PartialEq, Eq, PartialOrd, Ord, Clone, Reflect, Debug)] @@ -56,4 +58,13 @@ impl WeaponAttachment { }, } } + pub fn fits_into_slot(&self, slot: &WeaponSlot) -> bool { + match self { + WeaponAttachment::Compensator(_) => slot == &WeaponSlot::CompensatorSlot, + WeaponAttachment::Magazine(_) => slot == &WeaponSlot::MagazineSlot, + WeaponAttachment::Stock(_) => slot == &WeaponSlot::StockSlot, + WeaponAttachment::ForeGrip(_) => slot == &WeaponSlot::ForeGripSlot, + WeaponAttachment::Optic(_) => slot == &WeaponSlot::SightPlacementStartSlot || slot == &WeaponSlot::SightPlacementEndSlot, + } + } } \ No newline at end of file diff --git a/src/comps/core/weapons/firearm.rs b/src/comps/core/weapons/firearm.rs index cf11f42..62dafaa 100644 --- a/src/comps/core/weapons/firearm.rs +++ b/src/comps/core/weapons/firearm.rs @@ -41,7 +41,7 @@ impl Firearm { }, final_aimed_rotation: Quat::default(),//Quat::from_rotation_x(0.026), - final_rotation: Quat::default(), + rotation_offset: Quat::default(), final_aimed_position: Vec3 { // x: -0.003, // y: -0.35, @@ -50,7 +50,7 @@ impl Firearm { y: -0.35, z: -1.6, }, - final_position: Vec3::ZERO, /*Vec3 { + translation_offset: Vec3::ZERO, /*Vec3 { x: 0.6, y: -0.45, z: -2.7, @@ -64,7 +64,8 @@ impl Firearm { FirearmData { caliber: Caliber::Parabellum9mm, fire_rate: 600.0, - rebound_time_seconds: 0.1, + aim_time_seconds: 0.1, + rebound_time_seconds: 0.5, recoil_pattern: FirearmSprayPattern { 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 @@ -75,7 +76,7 @@ impl Firearm { }, final_aimed_rotation: Quat::from_rotation_x(0.026), - final_rotation: Quat::default(), + rotation_offset: Quat::default(), final_aimed_position: Vec3 { // x: -0.003, // y: -0.35, @@ -84,7 +85,7 @@ impl Firearm { y: -0.5, z: -1.6, }, - final_position: Vec3 { + translation_offset: Vec3 { x: 1.0, y: -0.45, z: -2.7, @@ -97,7 +98,8 @@ impl Firearm { Firearm::Ak105 => FirearmData { caliber: Caliber::RU545, fire_rate: 600.0, - rebound_time_seconds: 0.2, + aim_time_seconds: 0.25, + rebound_time_seconds: 0.6, asset_path: String::from("weapons/ak105_rifle.glb"), recoil_pattern: FirearmSprayPattern { vertical: Vec::from([ @@ -108,10 +110,10 @@ impl Firearm { ]), }, final_aimed_rotation: Quat::default(), - final_rotation: Quat::default(), - final_aimed_position: Vec3::ZERO, - final_position: Vec3::ZERO, - scale_factor: 0.3, + rotation_offset: Quat::default(), + final_aimed_position: Vec3 { x: 0.016, y: 0.0, z: -0.1 }, + translation_offset: Vec3 { x: -0.2, y: -0.03, z: 0.0 }, + scale_factor: 0.2, firearm_type: FirearmType::Primary, }, } diff --git a/src/comps/core/weapons/firearm_data.rs b/src/comps/core/weapons/firearm_data.rs index 70768f4..e25b61f 100644 --- a/src/comps/core/weapons/firearm_data.rs +++ b/src/comps/core/weapons/firearm_data.rs @@ -9,19 +9,20 @@ pub struct FirearmData { pub caliber: Caliber, /// Rounds per minute pub fire_rate: f32, + /// Amount of time it takes for the gun to aim in or aim out. + pub aim_time_seconds: f32, /// Amount of seconds it takes for gun to come down from shooting - /// Also is the time it takes for the gun to aim in or aim out. pub rebound_time_seconds: f32, pub asset_path: String, pub recoil_pattern: FirearmSprayPattern, /// Final rotation of hands when aimed in pub final_aimed_rotation: Quat, /// Final rotation of hands when not aimed in - pub final_rotation: Quat, + pub rotation_offset: Quat, /// Final position of hands when aimed in pub final_aimed_position: Vec3, /// Final position of hands when not aimed in - pub final_position: Vec3, + pub translation_offset: Vec3, pub scale_factor: f32, pub firearm_type: FirearmType, } diff --git a/src/comps/core/weapons/firearm_state.rs b/src/comps/core/weapons/firearm_state.rs index 413d6d3..b6de066 100644 --- a/src/comps/core/weapons/firearm_state.rs +++ b/src/comps/core/weapons/firearm_state.rs @@ -1,15 +1,16 @@ use bevy::prelude::*; -use super::{attachment_slot::AttachmentSlot, slot::slot::WeaponSlot}; +use super::{attachment_slot::AttachmentSlot, slot::slot::WeaponSlot, magazine_data::MagazineData}; #[derive(Component, Reflect, PartialEq, Eq, PartialOrd, Ord, Debug, Clone)] pub struct FirearmState { pub attachment_slots: Vec, + pub magazine_data: Option, } impl FirearmState { - pub fn new(attachment_slots: Vec) -> Self { - Self { attachment_slots } + pub fn new(attachment_slots: Vec, magazine_data: Option) -> Self { + Self { attachment_slots, magazine_data: None } } } \ No newline at end of file diff --git a/src/logic/core/player/camera_switching.rs b/src/logic/core/player/camera_switching.rs index 638b8c4..4d125ad 100644 --- a/src/logic/core/player/camera_switching.rs +++ b/src/logic/core/player/camera_switching.rs @@ -9,6 +9,7 @@ pub fn switch_camera( keyboard_input: Res>, ) { if keyboard_input.just_pressed(KeyCode::Key0) { + return; for mut main_cam in main_camera_query.iter_mut() { main_cam.is_active = !main_cam.is_active; } diff --git a/src/logic/core/player/hands.rs b/src/logic/core/player/hands.rs index 3316c9f..ac88db9 100644 --- a/src/logic/core/player/hands.rs +++ b/src/logic/core/player/hands.rs @@ -10,9 +10,9 @@ use crate::{ holdable::InPlayerHands, interactable::Interactable, player::Player, proxy::{character::in_player_hands_parent::InPlayerHandsParent, physics::rapier::LinkToPlayer}, - }, weapons::{firearm::Firearm, firearm_state::FirearmState}, + }, weapons::{firearm::Firearm, firearm_state::FirearmState, parts::firing_point::FiringPoint}, }, - logic::core::guns::{player_firing::PlayerFiringInfo}, + logic::core::guns::{player_firing::PlayerFiringInfo, shoot::shoot_bullet}, setup::{ equipment::{Equipment, EquipmentChangeEvent}, load_state::GameLoadState, assets::GltfAssets, //animations::AllAnimations, @@ -21,8 +21,11 @@ use crate::{ utils::{rad_deg::radians_from_degrees, hierarchy::find_child_in_parent_children}, }; +use super::player_settings::PlayerSettings; + #[derive(SystemParam)] pub struct CaptureHandUsageResourcesParams<'w> { + player_settings: Res<'w, PlayerSettings>, mouse_buttons: Res<'w, Input>, keyboard_input: Res<'w, Input>, game_load_state: Res<'w, GameLoadState>, @@ -36,37 +39,32 @@ pub struct CaptureHandUsageResourcesParams<'w> { loaded_gltf_assets: Res<'w, Assets>, } +#[derive(SystemParam)] +pub struct CaptureHandUsageQueryParams<'w, 's> { + hand_query: Query<'w, 's, (&'static mut Transform, Entity), (With, Without)>, + in_hand_query: Query<'w, 's, (&'static Parent, &'static mut Transform), (With, Without, Without)>, + firearms_query: Query<'w, 's, (Entity, &'static GlobalTransform, &'static Firearm, &'static mut FirearmState),>, + firing_point_query: Query<'w, 's, (&'static GlobalTransform, &'static Parent), With>, + player_query: Query<'w, 's, (&'static Player, &'static mut PlayerInventory, Entity, &'static Transform, &'static mut PlayerFiringInfo), Without>, + children: Query<'w, 's, &'static Children>, +} + #[allow(irrefutable_let_patterns)] pub fn capture_hand_usage( mut resources: CaptureHandUsageResourcesParams, + mut queries: CaptureHandUsageQueryParams, mut commands: Commands, - mut hand_query: Query<(&mut Transform, Entity), (With, Without)>, - mut firearms_query: Query< - ( - Entity, - &Firearm, - &FirearmState, - &GlobalTransform, - ), - >, - mut player_query: Query<(&Player, &mut PlayerInventory, Entity, &Transform, &mut PlayerFiringInfo)>, - - children: Query<&Children>, - mut equipment_change_event_writer: EventWriter, mut inventory_changed_events: EventWriter, ) { if !resources.game_load_state.player_loaded { return; } - if player_query.iter().len() == 0 { - return; - } // Equipping stuff - for (player, mut player_inventory, player_entity, player_transform, mut player_firing_info) in player_query.iter_mut() { + for (player, mut player_inventory, player_entity, player_transform, mut player_firing_info) in queries.player_query.iter_mut() { // Equipping gun // Validate player has primary item, and secondary item in inventory if !resources.game_ui_state.any_window() && !player_firing_info.is_reloading { @@ -102,9 +100,9 @@ pub fn capture_hand_usage( } else if resources.keyboard_input.just_pressed(KeyCode::G) { match player_inventory.current_slot { Some(current_slot) => { - for (_, in_player_hands_entity) in hand_query.iter() { - for (firearm_entity, _, firearm_state, _) in firearms_query.iter() { - if find_child_in_parent_children(&mut commands, in_player_hands_entity, firearm_entity, &children) { + for (_, in_player_hands_entity) in queries.hand_query.iter() { + for (firearm_entity, _, _, firearm_state) in queries.firearms_query.iter() { + if find_child_in_parent_children(&mut commands, in_player_hands_entity, firearm_entity, &queries.children) { player_inventory::drop_slot_in_game_world(&mut commands, player_transform, &mut inventory_changed_events, &mut player_inventory, &resources.assets_gltf, &resources.loaded_gltf_assets, current_slot, Some(ItemState::Weapon(firearm_state.clone()))); equipment_change_event_writer.send(EquipmentChangeEvent(Equipment::Nothing, None)); player_inventory.current_slot = None; @@ -118,176 +116,149 @@ pub fn capture_hand_usage( } // Firearm stuff - if let Equipment::Firearm(_f, _) = player.0.equipment.clone() { + if let Equipment::Firearm(_, _) = player.0.equipment.clone() { player_firing_info .full_auto_timer .tick(resources.time.delta()); - for (_f, firearm_transform, _, _) in - firearms_query.iter_mut() + for (firearm_entity, firearm_transform, firearm, mut firearm_state) in + queries.firearms_query.iter_mut() { - for mut hand_transform in hand_query.iter_mut() { - if player_firing_info.is_reloading { - /* TODO: - for (animation_player_entity, animation_player) in &mut animation_players { - //children.get_component(entity) - // Only reload if this animation_player_entity is a child of the firearm_entity - if utils::hierarchy::find_child_in_parent_children( - &mut commands, - firearm_entity, - animation_player_entity, - &children, - ) { - if let Some(firearm_animations) = resources - .all_animations - .firearm_animations - .iter() - .find(|animation| &animation.firearm == &player_firearm) + for (mut hand_transform, hand_entity) in queries.hand_query.iter_mut() { + if !find_child_in_parent_children(&mut commands, hand_entity, firearm_entity, &queries.children) { + continue; + } + for (in_hand_parent, mut in_hand_transform) in queries.in_hand_query.iter_mut() { + if in_hand_parent.get() == hand_entity { + if player_firing_info.is_reloading { + // TODO: Here you should keep track of reload animation & time, then set player_firing_info.is_reloading = false + } else { + // Player is not currently reloading + // TODO: Add item check (make sure he has extra mags) + if resources.keyboard_input.just_pressed(KeyCode::R) + && !resources.game_ui_state.any_window() { - if let Some(animation_clip) = resources - .animation_clips - .get(&firearm_animations.reload_magazine) - { - if animation_player.elapsed() >= animation_clip.duration() { - magazine_data.rounds_shot = 0; - player_firing_info.is_reloading = false; + if let Some(magazine_data) = &mut firearm_state.magazine_data { + magazine_data.rounds_shot = 0; + } + // TODO: start reloading + // TODO: Drop magazine in game world + + // Set is_reloading = true + } + // AIMING IN/OUT + let firearm_data = firearm.firearm_data(); + + let lerp_time = if player_firing_info.current_round_index > 0 { firearm_data.rebound_time_seconds } else { + if resources.time.elapsed_seconds() - player_firing_info.last_shot_timestamp > firearm_data.rebound_time_seconds * 1.5 { + firearm_data.aim_time_seconds + } else { + firearm_data.rebound_time_seconds + } + }; + if resources.mouse_buttons.pressed(MouseButton::Right) + && !resources.game_ui_state.any_window() + { + let rotation_lerp_quat = in_hand_transform.rotation.lerp( + firearm_data.final_aimed_rotation + resources.player_settings.rot_aimed_offset, + (resources.time.delta_seconds() + / lerp_time) + .clamp(0.0, 1.0), + ); + let position_lerp_vec3 = in_hand_transform.translation.lerp( + firearm_data.final_aimed_position + resources.player_settings.pos_aimed_offset, + (resources.time.delta_seconds() + / lerp_time) + .clamp(0.0, 1.0), + ); + in_hand_transform.rotation = rotation_lerp_quat; + in_hand_transform.translation = position_lerp_vec3; + } else { + in_hand_transform.rotation = in_hand_transform.rotation.lerp( + firearm_data.rotation_offset + resources.player_settings.rot_offset, + (resources.time.delta_seconds() + / lerp_time) + .clamp(0.0, 1.0), + ); + in_hand_transform.translation = in_hand_transform.translation.lerp( + firearm_data.translation_offset + resources.player_settings.pos_offset, + (resources.time.delta_seconds() + / lerp_time) + .clamp(0.0, 1.0), + ); + } + + // SHOOTING & RECOIL + if resources.mouse_buttons.pressed(MouseButton::Left) + && !resources.game_ui_state.any_window() + { + if let Some(magazine_data) = &mut firearm_state.magazine_data { + if player_firing_info.full_auto_timer.finished() { + if magazine_data.rounds_shot < magazine_data.max_capacity { + // Get recoil numbers from patterns + let vertical_recoil_number: f32 = match firearm_data.recoil_pattern.vertical.get(player_firing_info.current_round_index) { + Some(vert_recoil_number) => *vert_recoil_number, + None => { + *firearm_data.recoil_pattern.vertical.last().expect("FOUND A FIREARM_DATA WITHOUT ANY FIREARM_RECOIL_PATTERN.") + }, + }; + let horizontal_recoil_number: f32 = match firearm_data.recoil_pattern.horizontal.get(player_firing_info.current_round_index) { + Some(horizontal_recoil_number) => *horizontal_recoil_number, + None => { + *firearm_data.recoil_pattern.horizontal.last().expect("FOUND A FIREARM_DATA WITHOUT ANY FIREARM_RECOIL_PATTERN.") + }, + }; + + for (firing_point_transform, firing_point_parent) in queries.firing_point_query.iter() { + if firing_point_parent.get() == firearm_entity { + //let firearm_transform = firearm_transform.clone(); + let firing_point = firing_point_transform.translation(); + let forward = firing_point_transform.forward() ; + let up = firing_point_transform.up(); + shoot_bullet( + &mut commands, + &mut resources.meshes, + &mut resources.materials, + Transform::from_translation(firing_point), + forward, + up, + firearm_data.caliber.clone(), + ); + // Increment indexes and timers + player_firing_info.current_round_index += 1; + player_firing_info.last_shot_timestamp = + resources.time.elapsed_seconds(); + player_firing_info.full_auto_timer.reset(); + magazine_data.rounds_shot += 1; + + // Apply recoil + in_hand_transform.rotate_x(radians_from_degrees( + //TODO: Recoil modifier firearm_data.vertical_recoil_modifier + -1.0 * 2.0 + * vertical_recoil_number, + )); + in_hand_transform.rotate_y(radians_from_degrees( + //TODO: Recoil modifier firearm_data.horizontal_recoil_modifier + 1.0 * 0.5 + * horizontal_recoil_number, + )); + } + } + + } else { + //TODO: play magazine empty sound + } } } - } - } - }*/ - } else { - // Player is not in a reload animation - if resources.keyboard_input.just_pressed(KeyCode::R) - && !resources.game_ui_state.any_window() - {} - /* - // Start reload animation - for (animation_player_entity, mut animation_player) in - &mut animation_players - { - // Only reload if this animation_player_entity is a child of the firearm_entity - if utils::hierarchy::find_child_in_parent_children( - &mut commands, - firearm_entity, - animation_player_entity, - &children, - ) { - if let Some(firearm_animations) = resources - .all_animations - .firearm_animations - .iter() - .find(|animation| &animation.firearm == &player_firearm) - { - animation_player - .start(firearm_animations.reload_magazine.clone_weak()); - player_firing_info.is_reloading = true; + } else { + if player_firing_info.full_auto_timer.finished() { + player_firing_info.current_round_index = 0; } } - }*/ - // Set is_reloading = true - // At the end of reload animation, set magazine data to capacity = 0 - } - // AIMING IN/OUT - /* - if resources.mouse_buttons.pressed(MouseButton::Right) - && !resources.game_ui_state.any_window() - { - let rotation_lerp_quat = hand_transform.rotation.lerp( - firearm_data.final_aimed_rotation, - (resources.time.delta_seconds() - / firearm_data.rebound_time_seconds) - .clamp(0.0, 1.0), - ); - let position_lerp_vec3 = hand_transform.translation.lerp( - firearm_data.final_aimed_position, - (resources.time.delta_seconds() - / firearm_data.rebound_time_seconds) - .clamp(0.0, 1.0), - ); - hand_transform.rotation = rotation_lerp_quat; - hand_transform.translation = position_lerp_vec3; - } else { - hand_transform.rotation = hand_transform.rotation.lerp( - firearm_data.final_rotation, - (resources.time.delta_seconds() - / firearm_data.rebound_time_seconds) - .clamp(0.0, 1.0), - ); - hand_transform.translation = hand_transform.translation.lerp( - firearm_data.final_position, - (resources.time.delta_seconds() - / firearm_data.rebound_time_seconds) - .clamp(0.0, 1.0), - ); - } - - // SHOOTING & RECOIL - if resources.mouse_buttons.pressed(MouseButton::Left) - && !resources.game_ui_state.any_window() - { - if player_firing_info.full_auto_timer.finished() { - if magazine_data.rounds_shot < magazine_data.max_capacity { - // Get recoil numbers from patterns - let vertical_recoil_number: f32 = match firearm_data.recoil_pattern.vertical.get(player_firing_info.current_round_index) { - Some(vert_recoil_number) => *vert_recoil_number, - None => { - *firearm_data.recoil_pattern.vertical.last().expect("FOUND A FIREARM_DATA WITHOUT ANY FIREARM_RECOIL_PATTERN.") - }, - }; - let horizontal_recoil_number: f32 = match firearm_data.recoil_pattern.horizontal.get(player_firing_info.current_round_index) { - Some(horizontal_recoil_number) => *horizontal_recoil_number, - None => { - *firearm_data.recoil_pattern.horizontal.last().expect("FOUND A FIREARM_DATA WITHOUT ANY FIREARM_RECOIL_PATTERN.") - }, - }; - - let firearm_transform = firearm_transform.clone(); - 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 up = firearm_transform.up(); - shoot_bullet( - &mut commands, - &mut resources.meshes, - &mut resources.materials, - Transform::from_translation(firing_point), - forward, - up, - firearm_data.caliber.clone(), - ); - // Increment indexes and timers - player_firing_info.current_round_index += 1; - player_firing_info.last_shot_timestamp = - resources.time.elapsed_seconds(); - player_firing_info.full_auto_timer.reset(); - magazine_data.rounds_shot += 1; - - // Apply recoil - hand_transform.rotate_x(radians_from_degrees( - firearm_data.vertical_recoil_modifier - * vertical_recoil_number, - )); - hand_transform.rotate_y(radians_from_degrees( - firearm_data.horizontal_recoil_modifier - * horizontal_recoil_number, - )); - } else { - //TODO: play magazine empty sound - } - } - } else { - if player_firing_info.full_auto_timer.finished() { - player_firing_info.current_round_index = 0; } } - }*/ + } } - } } } diff --git a/src/logic/core/player/mod.rs b/src/logic/core/player/mod.rs index 2b14905..e63834a 100644 --- a/src/logic/core/player/mod.rs +++ b/src/logic/core/player/mod.rs @@ -6,4 +6,5 @@ pub mod player_movement; pub mod player_values_state; pub mod player_vertical_sync; pub mod animate_player; -pub mod camera_switching; \ No newline at end of file +pub mod camera_switching; +pub mod player_settings; \ No newline at end of file diff --git a/src/logic/core/player/player_settings.rs b/src/logic/core/player/player_settings.rs new file mode 100644 index 0000000..200747c --- /dev/null +++ b/src/logic/core/player/player_settings.rs @@ -0,0 +1,32 @@ +use bevy::prelude::*; + +#[derive(Resource, Reflect)] +#[reflect(Resource)] +pub struct PlayerSettings { + /// X Value of hand when something is equipped. + /// Applied to the object inside the hand (InPlayerHands) + //pub gun_offset: f32, + pub fov: f32, + + /// Debug thing for me + pub pos_aimed_offset: Vec3, + pub pos_offset: Vec3, + + pub rot_aimed_offset: Quat, + pub rot_offset: Quat, + + pub third_person_toggle: bool, +} + +impl Default for PlayerSettings { + fn default() -> Self { + Self { + fov: 0.0, + pos_aimed_offset: Vec3::ZERO, + pos_offset: Vec3::ZERO, + rot_aimed_offset: Quat::default(), + rot_offset: Quat::default(), + third_person_toggle: false + } + } +} \ No newline at end of file diff --git a/src/scenes/scene1/spawn_points.rs b/src/scenes/scene1/spawn_points.rs index 80bf218..aa753df 100644 --- a/src/scenes/scene1/spawn_points.rs +++ b/src/scenes/scene1/spawn_points.rs @@ -30,13 +30,13 @@ pub fn set_spawn_points(mut commands: Commands) { transform }, }); - commands.spawn(Ak105SpawnPoint { - transform: { - let mut transform = Transform::from_xyz(18.0, 10.0, 18.0); - transform.rotate_z(utils::rad_deg::radians_from_degrees(-90.0)); - transform - }, - }); + + commands.spawn(Ak105SpawnPoint ::new_fully_kitted_default({ + let mut transform = Transform::from_xyz(18.0, 10.0, 18.0); + transform.rotate_z(utils::rad_deg::radians_from_degrees(-90.0)); + transform + })); + commands.spawn(Glock17SpawnPoint { transform: { let mut transform = Transform::from_xyz(20.0, 10.0, 20.0); diff --git a/src/ui/editor/inspector.rs b/src/ui/editor/inspector.rs index b7e5361..aa816d3 100644 --- a/src/ui/editor/inspector.rs +++ b/src/ui/editor/inspector.rs @@ -26,7 +26,7 @@ pub fn editor_controls() -> EditorControls { editor_controls.insert( controls::Action::PlayPauseEditor, controls::Binding { - input: controls::UserInput::Single(controls::Button::Keyboard(KeyCode::Back)), + input: controls::UserInput::Single(controls::Button::Keyboard(KeyCode::Grave)), conditions: vec![controls::BindingCondition::ListeningForText(false)], }, ); diff --git a/src/ui/editor/plugin.rs b/src/ui/editor/plugin.rs index d13705e..fb9c24d 100644 --- a/src/ui/editor/plugin.rs +++ b/src/ui/editor/plugin.rs @@ -12,7 +12,7 @@ use crate::{ player::{ camera_player_sync::MouseMovementSettings, player_movement::{PlayerLinearXZState, PlayerLinearYState, PlayerMovementInput}, - player_values_state::PlayerValuesState, + player_values_state::PlayerValuesState, player_settings::PlayerSettings, }, }, scenes::scene1::skybox::Cubemap, @@ -34,7 +34,8 @@ pub struct MainEditorUiPlugin; impl Plugin for MainEditorUiPlugin { fn build(&self, app: &mut App) { - app.register_type::() + app + .register_type::() .register_type::() .register_type::() .register_type::() @@ -52,6 +53,7 @@ impl Plugin for MainEditorUiPlugin { .register_type::() .register_type::() .register_type::() + .register_type::() //.register_type::() //.register_type::() .register_type::() @@ -61,6 +63,7 @@ impl Plugin for MainEditorUiPlugin { .add_plugins(EguiPlugin) .add_plugins(EditorPlugin::default()) .insert_resource(editor_controls()) + .insert_resource(PlayerSettings::default()) .add_systems(PostStartup, set_cam3d_controls); //.add_plugins(ResourceInspectorPlugin::::default()); //.add_plugins(bevy_inspector_egui::DefaultInspectorConfigPlugin) // adds default options and `InspectorEguiImpl`s diff --git a/src/ui/game/settings/plugin.rs b/src/ui/game/settings/plugin.rs index 5175c05..5c2054e 100644 --- a/src/ui/game/settings/plugin.rs +++ b/src/ui/game/settings/plugin.rs @@ -6,6 +6,7 @@ pub struct SettingsMenuPlugin; impl Plugin for SettingsMenuPlugin { fn build(&self, app: &mut bevy::prelude::App) { + app.add_systems(Startup, menu::setup_settings_screen); app.add_systems( Update,