Gun state gets persisted on drop and equip

This commit is contained in:
Franklin 2023-11-20 16:01:13 -04:00
parent be895b0021
commit 45845fcd6c
14 changed files with 145 additions and 79 deletions

View File

@ -9,6 +9,15 @@ pub enum ItemState {
Weapon(FirearmState), Weapon(FirearmState),
} }
impl ItemState {
pub fn as_firearm_state(self) -> FirearmState {
match self {
ItemState::Weapon(firearm_state) => firearm_state,
_ => panic!("Not a weapon ItemState variant...")
}
}
}
/// When an item gets picked up in the game world, this event should handle all the physical properties on the game world. /// When an item gets picked up in the game world, this event should handle all the physical properties on the game world.
/// Mainly, removing the item from the game world, triggering inventory events, changing the player's equipment, etc... /// Mainly, removing the item from the game world, triggering inventory events, changing the player's equipment, etc...
#[derive(Event)] #[derive(Event)]
@ -17,5 +26,4 @@ pub struct PickupItemEvent {
pub entity: Entity, pub entity: Entity,
pub item: Arc<dyn Item>, pub item: Arc<dyn Item>,
pub player: Entity, pub player: Entity,
pub state: Option<ItemState>
} }

View File

@ -15,7 +15,7 @@ pub struct InventoryItem {
#[allow(unused)] #[allow(unused)]
impl InventoryItem { impl InventoryItem {
pub fn item(&self) -> &dyn Item { pub fn item(&self) -> &dyn Item {
self.item.as_ref() self.item
} }
pub fn rotated(&self) -> Option<bool> { pub fn rotated(&self) -> Option<bool> {
self.rotated self.rotated

View File

@ -1,3 +1,5 @@
use std::sync::Arc;
use bevy::reflect::Reflect; use bevy::reflect::Reflect;
use crate::comps::core::items::item::Item; use crate::comps::core::items::item::Item;
@ -7,5 +9,5 @@ use crate::comps::core::items::item::Item;
#[derive(Default, Reflect)] #[derive(Default, Reflect)]
pub struct ItemInventory { pub struct ItemInventory {
#[reflect(ignore)] #[reflect(ignore)]
pub item: Option<Box<dyn Item>>, pub item: Option<Arc<dyn Item>>,
} }

View File

@ -1,6 +1,8 @@
use std::sync::Arc;
use bevy::{prelude::*, gltf::Gltf}; use bevy::{prelude::*, gltf::Gltf};
use crate::{comps::core::{items::item::Item, events::inventory_changed::PlayerInventoryChangedEvent, weapons::firearm_data::FirearmType}, setup::assets::GltfAssets}; use crate::{comps::core::{items::item::Item, events::{inventory_changed::PlayerInventoryChangedEvent, pickup_item::ItemState}, weapons::firearm_data::FirearmType}, setup::assets::GltfAssets};
use super::{item_inventory::ItemInventory, slot::PlayerInventorySlotType}; use super::{item_inventory::ItemInventory, slot::PlayerInventorySlotType};
@ -34,10 +36,10 @@ impl PlayerInventory {
self.secondary.item.is_some() self.secondary.item.is_some()
} }
pub fn get_primary(&self) -> &Option<Box<dyn Item>> { pub fn get_primary(&self) -> &Option<Arc<dyn Item>> {
&self.primary.item &self.primary.item
} }
pub fn get_secondary(&self) -> &Option<Box<dyn Item>> { pub fn get_secondary(&self) -> &Option<Arc<dyn Item>> {
&self.secondary.item &self.secondary.item
} }
@ -48,14 +50,15 @@ impl PlayerInventory {
&mut self.secondary &mut self.secondary
} }
/// This comes from a PickupItemEvent usually /// This comes from a PickupItemEvent usually
pub fn pickup_item(&mut self, item: &dyn Item, slot: PlayerInventorySlotType) { pub fn pickup_item(&mut self, item: Arc<dyn Item>, slot: PlayerInventorySlotType) {
let mut inventory_slot = match slot { let mut inventory_slot = match slot {
PlayerInventorySlotType::Primary => &mut self.primary, PlayerInventorySlotType::Primary => &mut self.primary,
PlayerInventorySlotType::Secondary => &mut self.secondary, PlayerInventorySlotType::Secondary => &mut self.secondary,
_ => unimplemented!(), _ => unimplemented!(),
}; };
let Some(firearm) = item.get_firearm() else { return; }; let Some(firearm) = item.get_firearm() else { return; };
inventory_slot.item = Some(firearm.get_item_box()); println!("Pickup item: {:?}", item.get_state());
inventory_slot.item = Some(item);
} }
pub fn drop_item(&mut self, slot: PlayerInventorySlotType) { pub fn drop_item(&mut self, slot: PlayerInventorySlotType) {
match slot { match slot {
@ -76,6 +79,7 @@ pub fn drop_slot_in_game_world(
assets_gltf: &Res<GltfAssets>, assets_gltf: &Res<GltfAssets>,
loaded_gltf_assets: &Res<Assets<Gltf>>, loaded_gltf_assets: &Res<Assets<Gltf>>,
slot: PlayerInventorySlotType, slot: PlayerInventorySlotType,
item_state: Option<ItemState>,
) { ) {
let drop_position = Transform::from_translation( let drop_position = Transform::from_translation(
player_transform.translation player_transform.translation
@ -104,6 +108,7 @@ pub fn drop_slot_in_game_world(
FirearmType::Primary => { FirearmType::Primary => {
// Send equipment_changed_event // Send equipment_changed_event
if let Some(primary_item) = player_inventory.get_primary() { if let Some(primary_item) = player_inventory.get_primary() {
println!("drop_slot_in_game_world {:?}", primary_item.get_state());
// Drop this one // Drop this one
primary_item.spawn( primary_item.spawn(
commands, commands,
@ -111,7 +116,7 @@ pub fn drop_slot_in_game_world(
&assets_gltf, &assets_gltf,
&loaded_gltf_assets, &loaded_gltf_assets,
drop_impulse, drop_impulse,
None primary_item.get_state()
); );
} }
player_inventory.drop_item(PlayerInventorySlotType::Primary); player_inventory.drop_item(PlayerInventorySlotType::Primary);
@ -125,7 +130,7 @@ pub fn drop_slot_in_game_world(
&assets_gltf, &assets_gltf,
&loaded_gltf_assets, &loaded_gltf_assets,
drop_impulse, drop_impulse,
None item_state
); );
} }
player_inventory.drop_item(PlayerInventorySlotType::Secondary); player_inventory.drop_item(PlayerInventorySlotType::Secondary);

View File

@ -1,4 +1,7 @@
use std::sync::Arc;
use bevy::{prelude::*, gltf::Gltf}; use bevy::{prelude::*, gltf::Gltf};
use bevy_inspector_egui::egui::mutex::Mutex;
use bevy_rapier3d::{dynamics::{RigidBody, GravityScale, ExternalImpulse}, geometry::{ColliderMassProperties, Collider}}; use bevy_rapier3d::{dynamics::{RigidBody, GravityScale, ExternalImpulse}, geometry::{ColliderMassProperties, Collider}};
use crate::{comps::core::{ use crate::{comps::core::{
@ -7,8 +10,10 @@ use crate::{comps::core::{
markers::{holdable::HoldableObjectType, interactable::Interactable}, inventory::slot::PlayerInventorySlotType, weapons::{firearm::Firearm, firearm_data::FirearmData}, events::pickup_item::ItemState, markers::{holdable::HoldableObjectType, interactable::Interactable}, inventory::slot::PlayerInventorySlotType, weapons::{firearm::Firearm, firearm_data::FirearmData}, events::pickup_item::ItemState,
}, setup::assets::{GltfAssets, GltfAssetType}, utils}; }, setup::assets::{GltfAssets, GltfAssetType}, utils};
#[derive(Component, Reflect)] #[derive(Component)]
pub struct Ak105GunItem; pub struct Ak105GunItem {
pub state: Mutex<Option<ItemState>>
}
impl Item for Ak105GunItem { impl Item for Ak105GunItem {
fn get_type(&self) -> ItemType { fn get_type(&self) -> ItemType {
@ -88,7 +93,7 @@ impl Item for Ak105GunItem {
)) ))
.id(); .id();
match item_state { match item_state {
Some(state) => { commands.entity(firearm_asset_entity).insert(state); }, Some(ref state) => { commands.entity(firearm_asset_entity).insert(state.clone()); },
None => {}, None => {},
}; };
let firearm_size = firearm.get_size(); let firearm_size = firearm.get_size();
@ -116,10 +121,19 @@ impl Item for Ak105GunItem {
impulse: with_impulse, impulse: with_impulse,
..Default::default() ..Default::default()
}, },
Interactable::Item(firearm.get_item_arc()), Interactable::Item(Arc::new(Ak105GunItem { state: Mutex::new(item_state) })),
)) ))
.push_children(&[firearm_asset_entity]); .push_children(&[firearm_asset_entity]);
} }
} }
} }
fn get_state(&self) -> Option<ItemState> {
self.state.lock().clone()
}
fn set_state(&self, state: Option<ItemState>) {
*self.state.lock() = state
}
} }

View File

@ -1,3 +1,5 @@
use std::sync::Arc;
use bevy::{prelude::*, gltf::Gltf}; use bevy::{prelude::*, gltf::Gltf};
use bevy_rapier3d::{geometry::{ColliderMassProperties, Collider}, dynamics::{RigidBody, GravityScale, ExternalImpulse}}; use bevy_rapier3d::{geometry::{ColliderMassProperties, Collider}, dynamics::{RigidBody, GravityScale, ExternalImpulse}};
@ -116,10 +118,19 @@ impl Item for Glock17GunItem {
impulse: with_impulse, impulse: with_impulse,
..Default::default() ..Default::default()
}, },
Interactable::Item(firearm.get_item_arc()), Interactable::Item(Arc::new(Glock17GunItem) ),
)) ))
.push_children(&[firearm_asset_entity]); .push_children(&[firearm_asset_entity]);
} }
} }
} }
fn get_state(&self) -> Option<ItemState> {
todo!()
}
fn set_state(&self, state: Option<ItemState>) {
todo!()
}
} }

View File

@ -17,7 +17,7 @@ pub enum ItemType {
} }
#[bevy_trait_query::queryable] #[bevy_trait_query::queryable]
pub trait Item: Sync + Send + Reflect { pub trait Item: Sync + Send {
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
@ -26,8 +26,11 @@ pub trait Item: Sync + Send + Reflect {
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 inventory_description(&self) -> String;
fn set_state(&self, state: Option<ItemState>);
fn get_state(&self) -> Option<ItemState>;
/// Spawn an item on the game world. Every item should implement this /// Spawn an item on the game world. Every item should implement this
/// The transform passed to this function should be a GlobalTransform.into() /// The transform passed to this function should be a GlobalTransform.into()
///
fn spawn( fn spawn(
&self, &self,
commands: &mut Commands, commands: &mut Commands,
@ -36,7 +39,7 @@ pub trait Item: Sync + Send + Reflect {
loaded_gltf_assets: &Assets<Gltf>, loaded_gltf_assets: &Assets<Gltf>,
with_impulse: Vec3, with_impulse: Vec3,
item_state: Option<ItemState>, item_state: Option<ItemState>,
) { ) ;/*{
match self.get_type() { match self.get_type() {
ItemType::Holdable(object_type) => { ItemType::Holdable(object_type) => {
match object_type { match object_type {
@ -96,7 +99,7 @@ pub trait Item: Sync + Send + Reflect {
impulse: with_impulse, impulse: with_impulse,
..Default::default() ..Default::default()
}, },
Interactable::Item(firearm.get_item_arc()), Interactable::Item(firearm.get),
)) ))
.push_children(&[firearm_asset_entity]); .push_children(&[firearm_asset_entity]);
} }
@ -107,7 +110,7 @@ pub trait Item: Sync + Send + Reflect {
ItemType::Equippable => todo!(), ItemType::Equippable => todo!(),
ItemType::Consumable => todo!(), ItemType::Consumable => todo!(),
}; };
} }*/
fn get_firearm(&self) -> Option<Firearm> { fn get_firearm(&self) -> Option<Firearm> {
match self.get_type() { match self.get_type() {
ItemType::Holdable(holdable) => match holdable { ItemType::Holdable(holdable) => match holdable {

View File

@ -7,7 +7,7 @@ use crate::comps::core::items::item::Item;
//use crate::comps::core::inventory::any_inventory::AnyInventory; //use crate::comps::core::inventory::any_inventory::AnyInventory;
#[allow(unused)] #[allow(unused)]
#[derive(Component)] #[derive(Component, Clone)]
pub enum Interactable { pub enum Interactable {
Holdable, Holdable,
//Lootable(AnyInventory), //Lootable(AnyInventory),

View File

@ -1,10 +1,10 @@
use bevy::{prelude::*, gltf::Gltf, ecs::system::SystemParam}; use bevy::{prelude::*, gltf::Gltf, ecs::system::SystemParam, scene::SceneInstance};
use crate::{comps::core::{weapons::{firearm::Firearm, firearm_state::FirearmState, slot::slot::WeaponSlot, attachment_slot::AttachmentSlot, attachments::weapon_attachment::WeaponAttachment}, events::pickup_item::ItemState}, setup::assets::{GltfAssets, GltfAssetType}}; use crate::{comps::core::{weapons::{firearm::Firearm, firearm_state::FirearmState, slot::slot::WeaponSlot, attachment_slot::AttachmentSlot, attachments::weapon_attachment::WeaponAttachment}, events::pickup_item::ItemState}, setup::assets::{GltfAssets, GltfAssetType}};
#[derive(SystemParam)] #[derive(SystemParam)]
pub struct InsertFirearmStateIntoFirearmsParams<'w, 's> { pub struct InsertFirearmStateIntoFirearmsParams<'w, 's> {
firearm_scene_bundle: Query<'w, 's, (Entity, Option<&'static ItemState>, &'static Children)>, firearm_scene_bundle: Query<'w, 's, (Entity, Option<&'static ItemState>, &'static Children), With<SceneInstance>>,
firearm_query: Query<'w, 's, (Entity, &'static Firearm, &'static Parent, Option<&'static FirearmState>), Or<(Without<FirearmState>, Changed<FirearmState>)>>, firearm_query: Query<'w, 's, (Entity, &'static Firearm, &'static Parent, Option<&'static FirearmState>), Or<(Without<FirearmState>, Changed<FirearmState>)>>,
slots_query: Query<'w, 's, (Entity, &'static WeaponSlot, &'static Parent)>, slots_query: Query<'w, 's, (Entity, &'static WeaponSlot, &'static Parent)>,
attachments_query: Query<'w, 's, (Entity, &'static WeaponAttachment, &'static Parent)>, attachments_query: Query<'w, 's, (Entity, &'static WeaponAttachment, &'static Parent)>,
@ -31,8 +31,7 @@ pub fn insert_firearm_state_to_firearms(
commands commands
.entity(firearm_entity) .entity(firearm_entity)
.insert(firearm_state.clone()); .insert(firearm_state.clone());
//TODO: spawn in attachments spawn_attachments_in_firearm(&mut commands, firearm_entity, firearm_state, &queries.slots_query, &assets_gltf, &loaded_gltf_assets);
println!("Reused firearm_state");
return; return;
} }
} }
@ -40,7 +39,7 @@ pub fn insert_firearm_state_to_firearms(
match firearm_state_opt { match firearm_state_opt {
Some(firearm_state) => { Some(firearm_state) => {
// Change the Slots // Change the Slots
spawn_attachments_in_firearm(&mut commands, firearm_entity, firearm_state, &queries.slots_query, &assets_gltf, &loaded_gltf_assets) spawn_attachments_in_firearm(&mut commands, firearm_entity, firearm_state, &queries.slots_query, &assets_gltf, &loaded_gltf_assets);
}, },
None => { None => {
// Create the firearm_state // Create the firearm_state
@ -59,9 +58,10 @@ pub fn insert_firearm_state_to_firearms(
}); });
} }
} }
let firearm_state = FirearmState::new(firearm_slots);
commands commands
.entity(firearm_entity) .entity(firearm_entity)
.insert(FirearmState::new(firearm_slots)); .insert(firearm_state.clone());
}, },
}; };
} }

View File

@ -1,4 +1,5 @@
use bevy::prelude::*; use bevy::prelude::*;
use bevy_inspector_egui::egui::mutex::Mutex;
use crate::comps::core::{ use crate::comps::core::{
items::{guns::ak105::Ak105GunItem, item::Item}, items::{guns::ak105::Ak105GunItem, item::Item},
@ -16,6 +17,6 @@ impl ItemSpawnPoint for Ak105SpawnPoint {
} }
fn get_item(&self) -> Box<dyn Item> { fn get_item(&self) -> Box<dyn Item> {
Box::new(Ak105GunItem) Box::new(Ak105GunItem { state: Mutex::new(None) })
} }
} }

View File

@ -1,6 +1,7 @@
use std::sync::Arc; use std::sync::{Arc};
use bevy::prelude::*; use bevy::prelude::*;
use bevy_inspector_egui::egui::mutex::Mutex;
use crate::comps::core::{markers::holdable::HoldableObjectData, items::{item::Item, guns::{glock17::Glock17GunItem, ak105::Ak105GunItem}}}; use crate::comps::core::{markers::holdable::HoldableObjectData, items::{item::Item, guns::{glock17::Glock17GunItem, ak105::Ak105GunItem}}};
@ -157,14 +158,14 @@ impl Firearm {
match self { match self {
//Firearm::M4A1 => Arc::new(M4a1GunItem), //Firearm::M4A1 => Arc::new(M4a1GunItem),
Firearm::Glock17 => Arc::new(Glock17GunItem), Firearm::Glock17 => Arc::new(Glock17GunItem),
Firearm::Ak105 => Arc::new(Ak105GunItem), Firearm::Ak105 => Arc::new(Ak105GunItem { state: Mutex::new(None) }),
} }
} }
pub fn get_item_box(&self) -> Box<dyn Item> { pub fn get_item_box(&self) -> Box<dyn Item> {
match self { match self {
//Firearm::M4A1 => Box::new(M4a1GunItem), //Firearm::M4A1 => Box::new(M4a1GunItem),
Firearm::Glock17 => Box::new(Glock17GunItem), Firearm::Glock17 => Box::new(Glock17GunItem),
Firearm::Ak105 => Box::new(Ak105GunItem), Firearm::Ak105 => Box::new(Ak105GunItem { state: Mutex::new(None) }),
} }
} }
} }

View File

@ -3,22 +3,22 @@ use bevy_rapier3d::prelude::*;
use crate::{ use crate::{
comps::core::{ comps::core::{
events::{pickup_item::PickupItemEvent, inventory_changed::PlayerInventoryChangedEvent}, events::{pickup_item::{PickupItemEvent, ItemState}, inventory_changed::PlayerInventoryChangedEvent},
inventory::{player_inventory::{PlayerInventory, self}, slot::PlayerInventorySlotType}, inventory::{player_inventory::{PlayerInventory, self}, slot::PlayerInventorySlotType},
markers::{ markers::{
camera::MainCamera, camera::MainCamera,
holdable::InPlayerHands, holdable::InPlayerHands,
interactable::Interactable, interactable::Interactable,
player::Player, proxy::{character::in_player_hands_parent::InPlayerHandsParent, physics::rapier::LinkToPlayer}, player::Player, proxy::{character::in_player_hands_parent::InPlayerHandsParent, physics::rapier::LinkToPlayer},
}, weapons::{firearm::Firearm, firearm_state::FirearmState},
}, },
}, logic::core::guns::{player_firing::PlayerFiringInfo},
logic::core::guns::{player_firing::PlayerFiringInfo, shoot::shoot_bullet},
setup::{ setup::{
equipment::{Equipment, EquipmentChangeEvent}, equipment::{Equipment, EquipmentChangeEvent},
load_state::GameLoadState, assets::GltfAssets, //animations::AllAnimations, load_state::GameLoadState, assets::GltfAssets, //animations::AllAnimations,
}, },
ui::game::{game_ui_state::GameUiState, hud::hud::HudState}, ui::game::{game_ui_state::GameUiState, hud::hud::HudState},
utils::rad_deg::radians_from_degrees, utils::{rad_deg::radians_from_degrees, hierarchy::find_child_in_parent_children},
}; };
#[derive(SystemParam)] #[derive(SystemParam)]
@ -41,18 +41,18 @@ pub fn capture_hand_usage(
mut resources: CaptureHandUsageResourcesParams, mut resources: CaptureHandUsageResourcesParams,
mut commands: Commands, mut commands: Commands,
mut hand_query: Query<&mut Transform, (With<InPlayerHandsParent>, Without<Player>)>, mut hand_query: Query<(&mut Transform, Entity), (With<InPlayerHandsParent>, Without<Player>)>,
mut firearm_query: Query< mut firearms_query: Query<
( (
Entity, Entity,
&Firearm,
&FirearmState,
&GlobalTransform, &GlobalTransform,
), ),
(With<InPlayerHands>, Without<InPlayerHandsParent>),
>, >,
mut player_query: Query<(&Player, &mut PlayerInventory, Entity, &Transform, &mut PlayerFiringInfo)>, mut player_query: Query<(&Player, &mut PlayerInventory, Entity, &Transform, &mut PlayerFiringInfo)>,
//mut animation_players: Query<(Entity, &mut AnimationPlayer)>,
//children: Query<&Children>, children: Query<&Children>,
mut equipment_change_event_writer: EventWriter<EquipmentChangeEvent>, mut equipment_change_event_writer: EventWriter<EquipmentChangeEvent>,
mut inventory_changed_events: EventWriter<PlayerInventoryChangedEvent>, mut inventory_changed_events: EventWriter<PlayerInventoryChangedEvent>,
@ -66,18 +66,19 @@ pub fn capture_hand_usage(
// Equipping stuff // 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 player_query.iter_mut() {
// Equipping gun // Equipping gun
// Validate player has primary item, and secondary item in inventory // Validate player has primary item, and secondary item in inventory
if !resources.game_ui_state.any_window() && !player_firing_info.is_reloading { if !resources.game_ui_state.any_window() && !player_firing_info.is_reloading {
if resources.keyboard_input.just_pressed(KeyCode::Key1) { if resources.keyboard_input.just_pressed(KeyCode::Key1) {
if let Some(primary_item) = player_inventory.get_primary() { if let Some(primary_item) = player_inventory.get_primary() {
if let Some(primary_firearm) = primary_item.get_firearm() { if let Some(primary_firearm) = primary_item.get_firearm() {
if Equipment::Firearm(primary_firearm.clone()) if Equipment::Firearm(primary_firearm.clone(), primary_item.get_state().expect("No item state in an equipped Item.").as_firearm_state())
!= player.0.equipment != player.0.equipment
{ {
println!("CaptureHandUsage {:?}", primary_item.get_state().expect("No item state in an equipped Item.").as_firearm_state());
equipment_change_event_writer equipment_change_event_writer
.send(EquipmentChangeEvent(Equipment::Firearm(primary_firearm))); .send(EquipmentChangeEvent(Equipment::Firearm(primary_firearm, primary_item.get_state().expect("No item state in an equipped Item.").as_firearm_state())));
player_inventory.current_slot = Some(PlayerInventorySlotType::Primary); player_inventory.current_slot = Some(PlayerInventorySlotType::Primary);
} }
} }
@ -85,11 +86,11 @@ pub fn capture_hand_usage(
} else if resources.keyboard_input.just_pressed(KeyCode::Key2) { } else if resources.keyboard_input.just_pressed(KeyCode::Key2) {
if let Some(secondary_item) = player_inventory.get_secondary() { if let Some(secondary_item) = player_inventory.get_secondary() {
if let Some(secondary_firearm) = secondary_item.get_firearm() { if let Some(secondary_firearm) = secondary_item.get_firearm() {
if Equipment::Firearm(secondary_firearm.clone()) if Equipment::Firearm(secondary_firearm.clone(), secondary_item.get_state().expect("No item state in an equipped Item.").as_firearm_state())
!= player.0.equipment != player.0.equipment
{ {
equipment_change_event_writer equipment_change_event_writer
.send(EquipmentChangeEvent(Equipment::Firearm(secondary_firearm))); .send(EquipmentChangeEvent(Equipment::Firearm(secondary_firearm, secondary_item.get_state().expect("No item state in an equipped Item.").as_firearm_state())));
player_inventory.current_slot = Some(PlayerInventorySlotType::Secondary); player_inventory.current_slot = Some(PlayerInventorySlotType::Secondary);
} }
} }
@ -102,9 +103,15 @@ pub fn capture_hand_usage(
} else if resources.keyboard_input.just_pressed(KeyCode::G) { } else if resources.keyboard_input.just_pressed(KeyCode::G) {
match player_inventory.current_slot { match player_inventory.current_slot {
Some(current_slot) => { Some(current_slot) => {
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); 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) {
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)); equipment_change_event_writer.send(EquipmentChangeEvent(Equipment::Nothing));
player_inventory.current_slot = None; player_inventory.current_slot = None;
}
}
}
}, },
None => {}, None => {},
} }
@ -112,13 +119,13 @@ pub fn capture_hand_usage(
} }
// Firearm stuff // Firearm stuff
if let Equipment::Firearm(_f) = player.0.equipment.clone() { if let Equipment::Firearm(_f, _) = player.0.equipment.clone() {
player_firing_info player_firing_info
.full_auto_timer .full_auto_timer
.tick(resources.time.delta()); .tick(resources.time.delta());
for (_f, firearm_transform) in for (_f, firearm_transform, _, _) in
firearm_query.iter_mut() firearms_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 {
@ -290,28 +297,35 @@ pub fn capture_hand_usage(
} }
#[derive(SystemParam)]
pub struct InteractActionParams<'w, 's> {
player_query: Query<'w, 's, Entity, (With<Player>, Without<MainCamera>)>,
player_collider_query: Query<'w, 's, Entity, (With<LinkToPlayer>, With<Collider>, Without<MainCamera>)>,
camera_query: Query<'w, 's, &'static GlobalTransform, (With<MainCamera>, Without<Player>)>,
interactables_query: Query<'w, 's, (Entity, &'static Interactable)>,
firearms_query: Query<'w, 's, (Entity, &'static Firearm, &'static FirearmState)>
}
/// 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<Entity, (With<Player>, Without<MainCamera>)>, children: Query<&Children>,
player_collider_query: Query<Entity, (With<LinkToPlayer>, With<Collider>, Without<MainCamera>)>, query: InteractActionParams,
camera_query: Query<&GlobalTransform, (With<MainCamera>, Without<Player>)>,
interactables_query: Query<(Entity, &Interactable)>,
keyboard_input: Res<Input<KeyCode>>, keyboard_input: Res<Input<KeyCode>>,
rapier_context: Res<RapierContext>, rapier_context: Res<RapierContext>,
mut hud_state: ResMut<HudState>, mut hud_state: ResMut<HudState>,
mut pickup_item_event_writer: EventWriter<PickupItemEvent>, mut pickup_item_event_writer: EventWriter<PickupItemEvent>,
game_ui_state: Res<GameUiState>, game_ui_state: Res<GameUiState>,
) { ) {
for player_entity in player_query.iter() { for player_entity in query.player_query.iter() {
for global_transform in camera_query.iter() { for global_transform in query.camera_query.iter() {
let ray_pos = global_transform.translation(); let ray_pos = global_transform.translation();
let ray_dir = global_transform.forward() * 2.0; // TODO: Move this into global Resource state let ray_dir = global_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;
for player_collider_entity in player_collider_query.iter() { for player_collider_entity in query.player_collider_query.iter() {
if let Some((entity, _)) = rapier_context.cast_ray( if let Some((entity, _)) = rapier_context.cast_ray(
ray_pos, ray_pos,
ray_dir, ray_dir,
@ -319,24 +333,32 @@ pub fn interact_action(
solid, solid,
QueryFilter::default().exclude_collider(player_collider_entity), QueryFilter::default().exclude_collider(player_collider_entity),
) { ) {
for (interactable_entity, interactable) in interactables_query.iter() { for (interactable_entity, interactable) in query.interactables_query.iter() {
if interactable_entity == entity { if interactable_entity == entity {
hud_state.interaction_clue_shown = true; hud_state.interaction_clue_shown = true;
hud_state.interaction_clue_text = interactable.to_string(); hud_state.interaction_clue_text = interactable.to_string();
if keyboard_input.just_pressed(KeyCode::F) && !game_ui_state.any_window() { if keyboard_input.just_pressed(KeyCode::F) && !game_ui_state.any_window() {
// TODO: Move this key to Controls state global // TODO: Move this key to Controls state global
match interactable { match interactable.clone() {
Interactable::Holdable => todo!(), Interactable::Holdable => todo!(),
/*Interactable::Lootable(any_inventory) => { /*Interactable::Lootable(any_inventory) => {
loot_container_event_writer loot_container_event_writer
.send(LootContainerEvent(any_inventory.clone())) .send(LootContainerEvent(any_inventory.clone()))
}*/ }*/
Interactable::Item(item) => { Interactable::Item(item) => {
let mut item_state = None;
for (firearm_entity, _, firearm_state) in query.firearms_query.iter() {
if find_child_in_parent_children(&mut commands, interactable_entity, firearm_entity, &children) {
item_state = Some(ItemState::Weapon(firearm_state.clone()));
}
}
println!("Setting item state: {:?}", item_state);
item.set_state(item_state);
pickup_item_event_writer.send(PickupItemEvent { pickup_item_event_writer.send(PickupItemEvent {
entity: interactable_entity, entity: interactable_entity,
item: item.clone(), item,
player: player_entity, player: player_entity,
state: None
}); });
} }
} }

View File

@ -1,26 +1,19 @@
use bevy::{gltf::Gltf, prelude::*}; use bevy::prelude::*;
use crate::{ use crate::comps::core::{
comps::core::{
events::{pickup_item::PickupItemEvent, inventory_changed::PlayerInventoryChangedEvent}, events::{pickup_item::PickupItemEvent, inventory_changed::PlayerInventoryChangedEvent},
inventory::player_inventory::{PlayerInventory, self}, inventory::player_inventory::PlayerInventory,
markers::player::Player, markers::player::Player,
}, };
setup::assets::GltfAssets,
};
pub fn update_player_inventory_system( pub fn update_player_inventory_system(
mut commands: Commands, mut commands: Commands,
mut pickup_item_events: EventReader<PickupItemEvent>, mut pickup_item_events: EventReader<PickupItemEvent>,
mut inventory_changed_events: EventWriter<PlayerInventoryChangedEvent>, mut inventory_changed_events: EventWriter<PlayerInventoryChangedEvent>,
mut player_query: Query<(Entity, &mut PlayerInventory, &Transform), With<Player>>, mut player_query: Query<(Entity, &mut PlayerInventory, &Transform), With<Player>>,
assets_gltf: Res<GltfAssets>,
loaded_gltf_assets: Res<Assets<Gltf>>,
) { ) {
for event in pickup_item_events.read() { for event in pickup_item_events.read() {
println!("Pickup Item Event received"); for (player_entity, mut player_inventory, _) in player_query.iter_mut() {
for (player_entity, mut player_inventory, player_transform) in player_query.iter_mut() {
println!("Player found");
if player_entity == event.player { if player_entity == event.player {
// Get item type and where it should go // Get item type and where it should go
commands commands
@ -28,8 +21,8 @@ pub fn update_player_inventory_system(
.despawn_descendants() .despawn_descendants()
.despawn(); .despawn();
player_inventory::drop_slot_in_game_world(&mut commands, player_transform, &mut inventory_changed_events, &mut player_inventory, &assets_gltf, &loaded_gltf_assets, event.item.get_item_slot()); //player_inventory::drop_slot_in_game_world(&mut commands, player_transform, &mut inventory_changed_events, &mut player_inventory, &assets_gltf, &loaded_gltf_assets, event.item.get_item_slot(), event.item.get_state().clone());
player_inventory.pickup_item(event.item.as_ref(), event.item.get_item_slot()); player_inventory.pickup_item(event.item.clone(), event.item.get_item_slot());
inventory_changed_events.send(PlayerInventoryChangedEvent { item: Some(event.item.clone()), slot_type: event.item.get_item_slot() }); inventory_changed_events.send(PlayerInventoryChangedEvent { item: Some(event.item.clone()), slot_type: event.item.get_item_slot() });
println!("Inventory Changed Event sent"); println!("Inventory Changed Event sent");
} }

View File

@ -6,7 +6,7 @@ use crate::{
comps::core::{markers::{ comps::core::{markers::{
holdable::InPlayerHands, holdable::InPlayerHands,
player::Player, proxy::character::in_player_hands_parent::InPlayerHandsParent, player::Player, proxy::character::in_player_hands_parent::InPlayerHandsParent,
}, weapons::{firearm::Firearm, firearm_data::FirearmData}}, }, weapons::{firearm::Firearm, firearm_data::FirearmData, firearm_state::FirearmState}, events::pickup_item::ItemState},
logic::core::guns::player_firing::PlayerFiringInfo, logic::core::guns::player_firing::PlayerFiringInfo,
utils, utils,
}; };
@ -18,7 +18,7 @@ pub struct EquipmentChangeEvent(pub Equipment);
/// Foundation for inventory System. /// Foundation for inventory System.
#[derive(Component, Clone, Default, Reflect, PartialEq, PartialOrd)] #[derive(Component, Clone, Default, Reflect, PartialEq, PartialOrd)]
pub enum Equipment { pub enum Equipment {
Firearm(Firearm), Firearm(Firearm, FirearmState),
#[default] #[default]
Nothing, Nothing,
} }
@ -42,7 +42,10 @@ pub fn change_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() { println!("");
if let Equipment::Firearm(new_firearm, firearm_state) = equipment_change_event.0.clone() {
println!("Equipping: {:?}", firearm_state);
spawn_firearm_on_player_hands( spawn_firearm_on_player_hands(
&mut commands, &mut commands,
player_firing_info, player_firing_info,
@ -50,6 +53,7 @@ pub fn change_equipment(
&assets_gltf, &assets_gltf,
&loaded_gltf_assets, &loaded_gltf_assets,
new_firearm, new_firearm,
firearm_state,
); );
} }
@ -66,6 +70,7 @@ fn spawn_firearm_on_player_hands(
assets_gltf: &GltfAssets, assets_gltf: &GltfAssets,
loaded_gltf_assets: &Assets<Gltf>, loaded_gltf_assets: &Assets<Gltf>,
firearm: Firearm, firearm: Firearm,
firearm_state: FirearmState,
) { ) {
if let Some(asset_handle) = assets_gltf if let Some(asset_handle) = assets_gltf
.assets .assets
@ -90,6 +95,7 @@ fn spawn_firearm_on_player_hands(
transform: firearm_transform, transform: firearm_transform,
..default() ..default()
}, },
ItemState::Weapon(firearm_state),
Name::new("Firearm Gltf Asset"), Name::new("Firearm Gltf Asset"),
)) ))
.id(); .id();