From 9538f7307503be547322f23915bd5f1639adeea0 Mon Sep 17 00:00:00 2001 From: Franklin Date: Wed, 15 Nov 2023 10:49:34 -0400 Subject: [PATCH] Dropping weapons with G. Updates on inventory and slots --- ...ntainer.rs => COMMENTED_loot_container.rs} | 0 src/comps/core/events/inventory_changed.rs | 10 +- src/comps/core/inventory/item_inventory.rs | 5 +- src/comps/core/inventory/mod.rs | 1 + src/comps/core/inventory/player_inventory.rs | 107 +++++++++++++++++- src/comps/core/inventory/plugin.rs | 7 +- src/comps/core/inventory/slot.rs | 11 ++ src/comps/core/items/guns/glock17.rs | 8 +- src/comps/core/items/guns/m4a1.rs | 8 +- src/comps/core/items/item.rs | 5 +- src/logic/core/player/hands.rs | 89 +++++++++------ src/logic/core/player/inventory.rs | 75 +++--------- 12 files changed, 216 insertions(+), 110 deletions(-) rename src/comps/core/events/{loot_container.rs => COMMENTED_loot_container.rs} (100%) create mode 100644 src/comps/core/inventory/slot.rs diff --git a/src/comps/core/events/loot_container.rs b/src/comps/core/events/COMMENTED_loot_container.rs similarity index 100% rename from src/comps/core/events/loot_container.rs rename to src/comps/core/events/COMMENTED_loot_container.rs diff --git a/src/comps/core/events/inventory_changed.rs b/src/comps/core/events/inventory_changed.rs index 79b9334..a25f868 100644 --- a/src/comps/core/events/inventory_changed.rs +++ b/src/comps/core/events/inventory_changed.rs @@ -1,5 +1,13 @@ +use std::sync::Arc; + use bevy::prelude::*; +use crate::comps::core::{items::item::Item, inventory::slot::PlayerInventorySlotType}; + /// This will be what is triggered after picking up an item or dropping an item. #[derive(Event)] -pub struct InventoryChangedEvent {} +pub struct PlayerInventoryChangedEvent { + /// A None value will remove the item from the inventory slot + pub item: Option>, + pub slot_type: PlayerInventorySlotType +} diff --git a/src/comps/core/inventory/item_inventory.rs b/src/comps/core/inventory/item_inventory.rs index b79c7b5..d0bbf09 100644 --- a/src/comps/core/inventory/item_inventory.rs +++ b/src/comps/core/inventory/item_inventory.rs @@ -1,8 +1,11 @@ +use bevy::reflect::Reflect; + use crate::comps::core::items::item::Item; /// # ItemInventory /// Specifically made to hold single items such as Guns, Pieces of armor. -#[derive(Default)] +#[derive(Default, Reflect)] pub struct ItemInventory { + #[reflect(ignore)] pub item: Option>, } diff --git a/src/comps/core/inventory/mod.rs b/src/comps/core/inventory/mod.rs index 2da8b59..fff4b23 100644 --- a/src/comps/core/inventory/mod.rs +++ b/src/comps/core/inventory/mod.rs @@ -3,3 +3,4 @@ pub mod item_inventory; pub mod player_inventory; pub mod plugin; +pub mod slot; \ No newline at end of file diff --git a/src/comps/core/inventory/player_inventory.rs b/src/comps/core/inventory/player_inventory.rs index 6b5a604..c279f04 100644 --- a/src/comps/core/inventory/player_inventory.rs +++ b/src/comps/core/inventory/player_inventory.rs @@ -1,14 +1,16 @@ -use bevy::prelude::*; +use bevy::{prelude::*, gltf::Gltf}; -use crate::comps::core::items::item::Item; +use crate::{comps::core::{items::item::Item, events::inventory_changed::PlayerInventoryChangedEvent, markers::firearm::FirearmType}, setup::assets::GltfAssets}; -use super::item_inventory::ItemInventory; +use super::{item_inventory::ItemInventory, slot::PlayerInventorySlotType}; -#[derive(Component)] +#[derive(Component, Reflect)] pub struct PlayerInventory { pub primary: ItemInventory, pub secondary: ItemInventory, //pub backpack: AnyInventory, + + pub current_slot: Option, } impl Default for PlayerInventory { @@ -17,10 +19,13 @@ impl Default for PlayerInventory { primary: Default::default(), secondary: Default::default(), //backpack: AnyInventory::new(UGrid::new_square(10)), + + current_slot: None } } } +#[allow(unused)] impl PlayerInventory { pub fn primary_occupied(&self) -> bool { self.primary.item.is_some() @@ -35,4 +40,98 @@ impl PlayerInventory { pub fn get_secondary(&self) -> &Option> { &self.secondary.item } + + pub fn get_primary_mut(&mut self) -> &mut ItemInventory { + &mut self.primary + } + pub fn get_secondary_mut(&mut self) -> &mut ItemInventory { + &mut self.secondary + } + /// This comes from a PickupItemEvent usually + pub fn pickup_item(&mut self, item: &dyn Item, slot: PlayerInventorySlotType) { + let mut inventory_slot = match slot { + PlayerInventorySlotType::Primary => &mut self.primary, + PlayerInventorySlotType::Secondary => &mut self.secondary, + }; + let Some(firearm) = item.get_firearm() else { return; }; + inventory_slot.item = Some(firearm.get_item_box()); + } + pub fn drop_item(&mut self, slot: PlayerInventorySlotType) { + match slot { + PlayerInventorySlotType::Primary => self.primary.item = None, + PlayerInventorySlotType::Secondary => self.secondary.item = None, + } + } } + +/// Drop item from a specific slot. +/// This fn does not equip an item +pub fn drop_slot_in_game_world( + commands: &mut Commands, + player_transform: &Transform, + inventory_changed_events: &mut EventWriter, + player_inventory: &mut PlayerInventory, + assets_gltf: &Res, + loaded_gltf_assets: &Res>, + slot: PlayerInventorySlotType, +) { + let drop_position = Transform::from_translation( + player_transform.translation + + player_transform.up() * 3.0 + + player_transform.forward() * 2.0, + ); + let drop_impulse = player_transform.translation + + player_transform.up() * 100.0 + + player_transform.forward() * 30.0; + + let item_inventory_slot = match slot { + PlayerInventorySlotType::Primary => { + player_inventory.get_primary_mut() + }, + PlayerInventorySlotType::Secondary => { + player_inventory.get_secondary_mut() + }, + }; + + match &item_inventory_slot.item { + Some(ref item) => { + match item.get_firearm() { + Some(firearm) => { + match firearm.firearm_data().firearm_type { + FirearmType::Primary => { + // Send equipment_changed_event + if let Some(primary_item) = player_inventory.get_primary() { + // Drop this one + primary_item.spawn( + commands, + drop_position, + &assets_gltf, + &loaded_gltf_assets, + drop_impulse, + ); + } + player_inventory.drop_item(PlayerInventorySlotType::Primary); + inventory_changed_events.send(PlayerInventoryChangedEvent { item: Some(firearm.get_item_arc()), slot_type: PlayerInventorySlotType::Primary }); + } + FirearmType::Secondary => { + if let Some(secondary) = player_inventory.get_secondary() { + secondary.spawn( + commands, + drop_position, + &assets_gltf, + &loaded_gltf_assets, + drop_impulse, + ); + } + player_inventory.drop_item(PlayerInventorySlotType::Secondary); + inventory_changed_events.send(PlayerInventoryChangedEvent { item: Some(firearm.get_item_arc()), slot_type: PlayerInventorySlotType::Secondary }); + } + } + }, + None => { unimplemented!("Item being dropped from inventory is not a Firearm. This still isn't implemented") } // Item isn't a firearm. Unimplemented + } + }, + None => { return; }, // No item to drop + }; + +} \ No newline at end of file diff --git a/src/comps/core/inventory/plugin.rs b/src/comps/core/inventory/plugin.rs index 22a71bd..291b962 100644 --- a/src/comps/core/inventory/plugin.rs +++ b/src/comps/core/inventory/plugin.rs @@ -1,15 +1,20 @@ use bevy::prelude::*; use crate::{ - comps::core::events::pickup_item::PickupItemEvent, + comps::core::events::{pickup_item::PickupItemEvent, inventory_changed::PlayerInventoryChangedEvent}, logic::core::player::inventory::update_player_inventory_system, }; +use super::player_inventory::PlayerInventory; + pub struct InventoryPlugin; impl Plugin for InventoryPlugin { fn build(&self, app: &mut App) { + app.register_type::(); + app.add_event::(); + app.add_event::(); app.add_systems(Update, update_player_inventory_system); } } diff --git a/src/comps/core/inventory/slot.rs b/src/comps/core/inventory/slot.rs new file mode 100644 index 0000000..f2f31e9 --- /dev/null +++ b/src/comps/core/inventory/slot.rs @@ -0,0 +1,11 @@ +use bevy::reflect::Reflect; + + + +#[derive(Clone, Copy, Reflect, Default)] +pub enum PlayerInventorySlotType { + #[default] + Primary, + Secondary, + //Slots, // TODO: Pass which slot +} \ No newline at end of file diff --git a/src/comps/core/items/guns/glock17.rs b/src/comps/core/items/guns/glock17.rs index 6bdfa31..8bb98ad 100644 --- a/src/comps/core/items/guns/glock17.rs +++ b/src/comps/core/items/guns/glock17.rs @@ -4,12 +4,12 @@ use crate::{ comps::core::{ grid::UGrid, items::item::{Item, ItemType}, - markers::holdable::HoldableObjectType, + markers::holdable::HoldableObjectType, inventory::slot::PlayerInventorySlotType, }, logic::core::guns::firearm::Firearm, }; -#[derive(Component)] +#[derive(Component, Reflect)] pub struct Glock17GunItem; impl Item for Glock17GunItem { @@ -44,4 +44,8 @@ impl Item for Glock17GunItem { fn inventory_description(&self) -> String { String::from("Pistol chambered in 9x19mm.") } + + fn get_item_slot(&self) -> PlayerInventorySlotType { + PlayerInventorySlotType::Secondary + } } diff --git a/src/comps/core/items/guns/m4a1.rs b/src/comps/core/items/guns/m4a1.rs index d870e6a..ca2c014 100644 --- a/src/comps/core/items/guns/m4a1.rs +++ b/src/comps/core/items/guns/m4a1.rs @@ -4,12 +4,12 @@ use crate::{ comps::core::{ grid::UGrid, items::item::{Item, ItemType}, - markers::holdable::HoldableObjectType, + markers::holdable::HoldableObjectType, inventory::slot::PlayerInventorySlotType, }, logic::core::guns::firearm::Firearm, }; -#[derive(Component)] +#[derive(Component, Reflect)] pub struct M4a1GunItem; impl Item for M4a1GunItem { @@ -43,4 +43,8 @@ impl Item for M4a1GunItem { fn inventory_description(&self) -> String { String::from("Rifle chambered in 5.56x45mm NATO, shoots 800 rounds per minute.") } + + fn get_item_slot(&self) -> PlayerInventorySlotType { + PlayerInventorySlotType::Primary + } } diff --git a/src/comps/core/items/item.rs b/src/comps/core/items/item.rs index 125adeb..a19c3bc 100644 --- a/src/comps/core/items/item.rs +++ b/src/comps/core/items/item.rs @@ -1,7 +1,7 @@ use crate::{ comps::core::{ grid::UGrid, - markers::{firearm::FirearmData, holdable::HoldableObjectType, interactable::Interactable}, + markers::{firearm::FirearmData, holdable::HoldableObjectType, interactable::Interactable}, inventory::slot::PlayerInventorySlotType, }, logic::core::guns::firearm::Firearm, setup::assets::{GltfAssetType, GltfAssets}, @@ -18,7 +18,7 @@ pub enum ItemType { } #[bevy_trait_query::queryable] -pub trait Item: Sync + Send { +pub trait Item: Sync + Send + Reflect { fn get_type(&self) -> ItemType; fn asset_path(&self) -> &str; /// Optional Stackable. If value is Some(x) x is the max quantity per stack @@ -114,4 +114,5 @@ pub trait Item: Sync + Send { _ => None, } } + fn get_item_slot(&self) -> PlayerInventorySlotType; } diff --git a/src/logic/core/player/hands.rs b/src/logic/core/player/hands.rs index 2753235..e182c74 100644 --- a/src/logic/core/player/hands.rs +++ b/src/logic/core/player/hands.rs @@ -1,10 +1,10 @@ -use bevy::{ecs::system::SystemParam, prelude::*}; +use bevy::{ecs::system::SystemParam, prelude::*, gltf::Gltf}; use bevy_rapier3d::prelude::*; use crate::{ comps::core::{ - events::pickup_item::PickupItemEvent, - inventory::player_inventory::PlayerInventory, + events::{pickup_item::PickupItemEvent, inventory_changed::PlayerInventoryChangedEvent}, + inventory::{player_inventory::{PlayerInventory, self}, slot::PlayerInventorySlotType}, markers::{ camera::MainCamera, firearm::{FirearmData, MagazineData}, @@ -17,7 +17,7 @@ use crate::{ setup::{ animations::AllFirearmAnimations, equipment::{Equipment, EquipmentChangeEvent}, - load_state::GameLoadState, + load_state::GameLoadState, assets::GltfAssets, }, ui::game::{game_ui_state::GameUiState, hud::hud::HudState}, utils::{self, rad_deg::radians_from_degrees}, @@ -34,6 +34,8 @@ pub struct CaptureHandUsageResourcesParams<'w> { animation_clips: Res<'w, Assets>, all_firearm_animations: Res<'w, AllFirearmAnimations>, time: Res<'w, Time>, + assets_gltf: Res<'w, GltfAssets>, + loaded_gltf_assets: Res<'w, Assets>, } #[allow(irrefutable_let_patterns)] @@ -41,7 +43,7 @@ pub fn capture_hand_usage( mut resources: CaptureHandUsageResourcesParams, mut commands: Commands, - mut hand_query: Query<&mut Transform, With>, + mut hand_query: Query<&mut Transform, (With, Without)>, mut firearm_query: Query< ( Entity, @@ -51,13 +53,13 @@ pub fn capture_hand_usage( ), (With, Without), >, - player_query: Query<(&Player, &PlayerInventory, Entity)>, - mut player_firing_info_query: Query<&mut PlayerFiringInfo, With>, + mut player_query: Query<(&Player, &mut PlayerInventory, Entity, &Transform, &mut PlayerFiringInfo)>, mut animation_players: Query<(Entity, &mut AnimationPlayer)>, children: Query<&Children>, mut equipment_change_event_writer: EventWriter, + mut inventory_changed_events: EventWriter, ) { if !resources.game_load_state.player_loaded { return; @@ -68,41 +70,54 @@ pub fn capture_hand_usage( // Equipping stuff - // Equipping gun - // Validate player has primary item, and secondary item in inventory - if !resources.game_ui_state.any_window() { - if resources.keyboard_input.just_pressed(KeyCode::Key1) { - if let Some(primary_item) = player_query.single().1.get_primary() { - if let Some(primary_firearm) = primary_item.get_firearm() { - if Equipment::Firearm(primary_firearm.clone()) - != player_query.single().0 .0.equipment - { - equipment_change_event_writer - .send(EquipmentChangeEvent(Equipment::Firearm(primary_firearm))); + for (player, mut player_inventory, _player_entity, player_transform, mut player_firing_info) in player_query.iter_mut() { + // Equipping gun + // Validate player has primary item, and secondary item in inventory + if !resources.game_ui_state.any_window() { + if resources.keyboard_input.just_pressed(KeyCode::Key1) { + if let Some(primary_item) = player_inventory.get_primary() { + if let Some(primary_firearm) = primary_item.get_firearm() { + if Equipment::Firearm(primary_firearm.clone()) + != player.0.equipment + { + equipment_change_event_writer + .send(EquipmentChangeEvent(Equipment::Firearm(primary_firearm))); + player_inventory.current_slot = Some(PlayerInventorySlotType::Primary); + } } } - } - } else if resources.keyboard_input.just_pressed(KeyCode::Key2) { - if let Some(secondary_item) = player_query.single().1.get_secondary() { - if let Some(secondary_firearm) = secondary_item.get_firearm() { - if Equipment::Firearm(secondary_firearm.clone()) - != player_query.single().0 .0.equipment - { - equipment_change_event_writer - .send(EquipmentChangeEvent(Equipment::Firearm(secondary_firearm))); + } else if resources.keyboard_input.just_pressed(KeyCode::Key2) { + if let Some(secondary_item) = player_inventory.get_secondary() { + if let Some(secondary_firearm) = secondary_item.get_firearm() { + if Equipment::Firearm(secondary_firearm.clone()) + != player.0.equipment + { + equipment_change_event_writer + .send(EquipmentChangeEvent(Equipment::Firearm(secondary_firearm))); + player_inventory.current_slot = Some(PlayerInventorySlotType::Secondary); + } } } - } - } else if resources.keyboard_input.just_pressed(KeyCode::Key3) { - if Equipment::Nothing != player_query.single().0 .0.equipment { - equipment_change_event_writer.send(EquipmentChangeEvent(Equipment::Nothing)); + } else if resources.keyboard_input.just_pressed(KeyCode::Key3) { + if Equipment::Nothing != player.0.equipment { + equipment_change_event_writer.send(EquipmentChangeEvent(Equipment::Nothing)); + player_inventory.current_slot = None; + } + } else if resources.keyboard_input.just_pressed(KeyCode::G) { + match player_inventory.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); + equipment_change_event_writer.send(EquipmentChangeEvent(Equipment::Nothing)); + }, + None => {}, + } } } - } - // Firearm stuff - if let Equipment::Firearm(player_firearm) = player_query.single().0 .0.equipment.clone() { - for mut player_firing_info in player_firing_info_query.iter_mut() { + + + // Firearm stuff + if let Equipment::Firearm(player_firearm) = player.0.equipment.clone() { player_firing_info .full_auto_timer .tick(resources.time.delta()); @@ -268,9 +283,13 @@ pub fn capture_hand_usage( } } } + } } } + + + } /// Method that is run when player hits interact button. diff --git a/src/logic/core/player/inventory.rs b/src/logic/core/player/inventory.rs index d96db80..8819f67 100644 --- a/src/logic/core/player/inventory.rs +++ b/src/logic/core/player/inventory.rs @@ -2,10 +2,9 @@ use bevy::{gltf::Gltf, prelude::*}; use crate::{ comps::core::{ - events::pickup_item::PickupItemEvent, - inventory::player_inventory::PlayerInventory, - items::item::ItemType, - markers::{firearm::FirearmType, holdable::HoldableObjectType, player::Player}, + events::{pickup_item::PickupItemEvent, inventory_changed::PlayerInventoryChangedEvent}, + inventory::player_inventory::{PlayerInventory, self}, + markers::player::Player, }, setup::assets::GltfAssets, }; @@ -13,6 +12,7 @@ use crate::{ pub fn update_player_inventory_system( mut commands: Commands, mut pickup_item_events: EventReader, + mut inventory_changed_events: EventWriter, mut player_query: Query<(Entity, &mut PlayerInventory, &Transform), With>, assets_gltf: Res, loaded_gltf_assets: Res>, @@ -21,64 +21,15 @@ pub fn update_player_inventory_system( for (player_entity, mut player_inventory, player_transform) in player_query.iter_mut() { if player_entity == event.player { // Get item type and where it should go - match event.item.get_type() { - ItemType::Holdable(holdable_object) => { - match holdable_object { - HoldableObjectType::Firearm(firearm) => { - commands - .entity(event.entity) - .despawn_descendants() - .despawn(); - let drop_position = Transform::from_translation( - player_transform.translation - + player_transform.up() * 3.0 - + player_transform.forward() * 2.0, - ); - let drop_impulse = player_transform.translation - + player_transform.up() * 100.0 - + player_transform.forward() * 30.0; - match firearm.firearm_data().firearm_type { - FirearmType::Primary => { - // Send equipment_changed_event - if let Some(primary_item) = player_inventory.get_primary() { - // Drop this one - primary_item.spawn( - &mut commands, - drop_position, - &assets_gltf, - &loaded_gltf_assets, - drop_impulse, - ); - player_inventory.primary.item = - Some(firearm.get_item_box()) - } else { - player_inventory.primary.item = - Some(firearm.get_item_box()) - } - } - FirearmType::Secondary => { - if let Some(secondary) = player_inventory.get_secondary() { - secondary.spawn( - &mut commands, - drop_position, - &assets_gltf, - &loaded_gltf_assets, - drop_impulse, - ); - player_inventory.secondary.item = - Some(firearm.get_item_box()) - } else { - player_inventory.secondary.item = - Some(firearm.get_item_box()) - } - } - } - } - } - } - ItemType::Equippable => todo!(), - ItemType::Consumable => todo!(), - } + commands + .entity(event.entity) + .despawn_descendants() + .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.pickup_item(event.item.as_ref(), event.item.get_item_slot()); + // TODO: Equip + } } }