Dropping weapons with G. Updates on inventory and slots

This commit is contained in:
Franklin 2023-11-15 10:49:34 -04:00
parent a81b2f340e
commit 9538f73075
12 changed files with 216 additions and 110 deletions

View File

@ -1,5 +1,13 @@
use std::sync::Arc;
use bevy::prelude::*; 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. /// This will be what is triggered after picking up an item or dropping an item.
#[derive(Event)] #[derive(Event)]
pub struct InventoryChangedEvent {} pub struct PlayerInventoryChangedEvent {
/// A None value will remove the item from the inventory slot
pub item: Option<Arc<dyn Item>>,
pub slot_type: PlayerInventorySlotType
}

View File

@ -1,8 +1,11 @@
use bevy::reflect::Reflect;
use crate::comps::core::items::item::Item; use crate::comps::core::items::item::Item;
/// # ItemInventory /// # ItemInventory
/// Specifically made to hold single items such as Guns, Pieces of armor. /// Specifically made to hold single items such as Guns, Pieces of armor.
#[derive(Default)] #[derive(Default, Reflect)]
pub struct ItemInventory { pub struct ItemInventory {
#[reflect(ignore)]
pub item: Option<Box<dyn Item>>, pub item: Option<Box<dyn Item>>,
} }

View File

@ -3,3 +3,4 @@
pub mod item_inventory; pub mod item_inventory;
pub mod player_inventory; pub mod player_inventory;
pub mod plugin; pub mod plugin;
pub mod slot;

View File

@ -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 struct PlayerInventory {
pub primary: ItemInventory, pub primary: ItemInventory,
pub secondary: ItemInventory, pub secondary: ItemInventory,
//pub backpack: AnyInventory, //pub backpack: AnyInventory,
pub current_slot: Option<PlayerInventorySlotType>,
} }
impl Default for PlayerInventory { impl Default for PlayerInventory {
@ -17,10 +19,13 @@ impl Default for PlayerInventory {
primary: Default::default(), primary: Default::default(),
secondary: Default::default(), secondary: Default::default(),
//backpack: AnyInventory::new(UGrid::new_square(10)), //backpack: AnyInventory::new(UGrid::new_square(10)),
current_slot: None
} }
} }
} }
#[allow(unused)]
impl PlayerInventory { impl PlayerInventory {
pub fn primary_occupied(&self) -> bool { pub fn primary_occupied(&self) -> bool {
self.primary.item.is_some() self.primary.item.is_some()
@ -35,4 +40,98 @@ impl PlayerInventory {
pub fn get_secondary(&self) -> &Option<Box<dyn Item>> { pub fn get_secondary(&self) -> &Option<Box<dyn Item>> {
&self.secondary.item &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<PlayerInventoryChangedEvent>,
player_inventory: &mut PlayerInventory,
assets_gltf: &Res<GltfAssets>,
loaded_gltf_assets: &Res<Assets<Gltf>>,
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
};
}

View File

@ -1,15 +1,20 @@
use bevy::prelude::*; use bevy::prelude::*;
use crate::{ 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, logic::core::player::inventory::update_player_inventory_system,
}; };
use super::player_inventory::PlayerInventory;
pub struct InventoryPlugin; pub struct InventoryPlugin;
impl Plugin for InventoryPlugin { impl Plugin for InventoryPlugin {
fn build(&self, app: &mut App) { fn build(&self, app: &mut App) {
app.register_type::<PlayerInventory>();
app.add_event::<PickupItemEvent>(); app.add_event::<PickupItemEvent>();
app.add_event::<PlayerInventoryChangedEvent>();
app.add_systems(Update, update_player_inventory_system); app.add_systems(Update, update_player_inventory_system);
} }
} }

View File

@ -0,0 +1,11 @@
use bevy::reflect::Reflect;
#[derive(Clone, Copy, Reflect, Default)]
pub enum PlayerInventorySlotType {
#[default]
Primary,
Secondary,
//Slots, // TODO: Pass which slot
}

View File

@ -4,12 +4,12 @@ use crate::{
comps::core::{ comps::core::{
grid::UGrid, grid::UGrid,
items::item::{Item, ItemType}, items::item::{Item, ItemType},
markers::holdable::HoldableObjectType, markers::holdable::HoldableObjectType, inventory::slot::PlayerInventorySlotType,
}, },
logic::core::guns::firearm::Firearm, logic::core::guns::firearm::Firearm,
}; };
#[derive(Component)] #[derive(Component, Reflect)]
pub struct Glock17GunItem; pub struct Glock17GunItem;
impl Item for Glock17GunItem { impl Item for Glock17GunItem {
@ -44,4 +44,8 @@ impl Item for Glock17GunItem {
fn inventory_description(&self) -> String { fn inventory_description(&self) -> String {
String::from("Pistol chambered in 9x19mm.") String::from("Pistol chambered in 9x19mm.")
} }
fn get_item_slot(&self) -> PlayerInventorySlotType {
PlayerInventorySlotType::Secondary
}
} }

View File

@ -4,12 +4,12 @@ use crate::{
comps::core::{ comps::core::{
grid::UGrid, grid::UGrid,
items::item::{Item, ItemType}, items::item::{Item, ItemType},
markers::holdable::HoldableObjectType, markers::holdable::HoldableObjectType, inventory::slot::PlayerInventorySlotType,
}, },
logic::core::guns::firearm::Firearm, logic::core::guns::firearm::Firearm,
}; };
#[derive(Component)] #[derive(Component, Reflect)]
pub struct M4a1GunItem; pub struct M4a1GunItem;
impl Item for M4a1GunItem { impl Item for M4a1GunItem {
@ -43,4 +43,8 @@ impl Item for M4a1GunItem {
fn inventory_description(&self) -> String { fn inventory_description(&self) -> String {
String::from("Rifle chambered in 5.56x45mm NATO, shoots 800 rounds per minute.") String::from("Rifle chambered in 5.56x45mm NATO, shoots 800 rounds per minute.")
} }
fn get_item_slot(&self) -> PlayerInventorySlotType {
PlayerInventorySlotType::Primary
}
} }

View File

@ -1,7 +1,7 @@
use crate::{ use crate::{
comps::core::{ comps::core::{
grid::UGrid, grid::UGrid,
markers::{firearm::FirearmData, holdable::HoldableObjectType, interactable::Interactable}, markers::{firearm::FirearmData, holdable::HoldableObjectType, interactable::Interactable}, inventory::slot::PlayerInventorySlotType,
}, },
logic::core::guns::firearm::Firearm, logic::core::guns::firearm::Firearm,
setup::assets::{GltfAssetType, GltfAssets}, setup::assets::{GltfAssetType, GltfAssets},
@ -18,7 +18,7 @@ pub enum ItemType {
} }
#[bevy_trait_query::queryable] #[bevy_trait_query::queryable]
pub trait Item: Sync + Send { pub trait Item: Sync + Send + Reflect {
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
@ -114,4 +114,5 @@ pub trait Item: Sync + Send {
_ => None, _ => None,
} }
} }
fn get_item_slot(&self) -> PlayerInventorySlotType;
} }

View File

@ -1,10 +1,10 @@
use bevy::{ecs::system::SystemParam, prelude::*}; use bevy::{ecs::system::SystemParam, prelude::*, gltf::Gltf};
use bevy_rapier3d::prelude::*; use bevy_rapier3d::prelude::*;
use crate::{ use crate::{
comps::core::{ comps::core::{
events::pickup_item::PickupItemEvent, events::{pickup_item::PickupItemEvent, inventory_changed::PlayerInventoryChangedEvent},
inventory::player_inventory::PlayerInventory, inventory::{player_inventory::{PlayerInventory, self}, slot::PlayerInventorySlotType},
markers::{ markers::{
camera::MainCamera, camera::MainCamera,
firearm::{FirearmData, MagazineData}, firearm::{FirearmData, MagazineData},
@ -17,7 +17,7 @@ use crate::{
setup::{ setup::{
animations::AllFirearmAnimations, animations::AllFirearmAnimations,
equipment::{Equipment, EquipmentChangeEvent}, equipment::{Equipment, EquipmentChangeEvent},
load_state::GameLoadState, load_state::GameLoadState, assets::GltfAssets,
}, },
ui::game::{game_ui_state::GameUiState, hud::hud::HudState}, ui::game::{game_ui_state::GameUiState, hud::hud::HudState},
utils::{self, rad_deg::radians_from_degrees}, utils::{self, rad_deg::radians_from_degrees},
@ -34,6 +34,8 @@ pub struct CaptureHandUsageResourcesParams<'w> {
animation_clips: Res<'w, Assets<AnimationClip>>, animation_clips: Res<'w, Assets<AnimationClip>>,
all_firearm_animations: Res<'w, AllFirearmAnimations>, all_firearm_animations: Res<'w, AllFirearmAnimations>,
time: Res<'w, Time>, time: Res<'w, Time>,
assets_gltf: Res<'w, GltfAssets>,
loaded_gltf_assets: Res<'w, Assets<Gltf>>,
} }
#[allow(irrefutable_let_patterns)] #[allow(irrefutable_let_patterns)]
@ -41,7 +43,7 @@ pub fn capture_hand_usage(
mut resources: CaptureHandUsageResourcesParams, mut resources: CaptureHandUsageResourcesParams,
mut commands: Commands, mut commands: Commands,
mut hand_query: Query<&mut Transform, With<PlayerHand>>, mut hand_query: Query<&mut Transform, (With<PlayerHand>, Without<Player>)>,
mut firearm_query: Query< mut firearm_query: Query<
( (
Entity, Entity,
@ -51,13 +53,13 @@ pub fn capture_hand_usage(
), ),
(With<InPlayerHands>, Without<PlayerHand>), (With<InPlayerHands>, Without<PlayerHand>),
>, >,
player_query: Query<(&Player, &PlayerInventory, Entity)>, mut player_query: Query<(&Player, &mut PlayerInventory, Entity, &Transform, &mut PlayerFiringInfo)>,
mut player_firing_info_query: Query<&mut PlayerFiringInfo, With<Player>>,
mut animation_players: Query<(Entity, &mut AnimationPlayer)>, 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>,
) { ) {
if !resources.game_load_state.player_loaded { if !resources.game_load_state.player_loaded {
return; return;
@ -68,41 +70,54 @@ pub fn capture_hand_usage(
// Equipping stuff // Equipping stuff
// Equipping gun for (player, mut player_inventory, _player_entity, player_transform, mut player_firing_info) in player_query.iter_mut() {
// Validate player has primary item, and secondary item in inventory // Equipping gun
if !resources.game_ui_state.any_window() { // Validate player has primary item, and secondary item in inventory
if resources.keyboard_input.just_pressed(KeyCode::Key1) { if !resources.game_ui_state.any_window() {
if let Some(primary_item) = player_query.single().1.get_primary() { if resources.keyboard_input.just_pressed(KeyCode::Key1) {
if let Some(primary_firearm) = primary_item.get_firearm() { if let Some(primary_item) = player_inventory.get_primary() {
if Equipment::Firearm(primary_firearm.clone()) if let Some(primary_firearm) = primary_item.get_firearm() {
!= player_query.single().0 .0.equipment if Equipment::Firearm(primary_firearm.clone())
{ != player.0.equipment
equipment_change_event_writer {
.send(EquipmentChangeEvent(Equipment::Firearm(primary_firearm))); 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) {
} else if resources.keyboard_input.just_pressed(KeyCode::Key2) { if let Some(secondary_item) = player_inventory.get_secondary() {
if let Some(secondary_item) = player_query.single().1.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()) != player.0.equipment
!= player_query.single().0 .0.equipment {
{ equipment_change_event_writer
equipment_change_event_writer .send(EquipmentChangeEvent(Equipment::Firearm(secondary_firearm)));
.send(EquipmentChangeEvent(Equipment::Firearm(secondary_firearm))); player_inventory.current_slot = Some(PlayerInventorySlotType::Secondary);
}
} }
} }
} } else if resources.keyboard_input.just_pressed(KeyCode::Key3) {
} else if resources.keyboard_input.just_pressed(KeyCode::Key3) { if Equipment::Nothing != player.0.equipment {
if Equipment::Nothing != player_query.single().0 .0.equipment { equipment_change_event_writer.send(EquipmentChangeEvent(Equipment::Nothing));
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 player_firing_info
.full_auto_timer .full_auto_timer
.tick(resources.time.delta()); .tick(resources.time.delta());
@ -268,9 +283,13 @@ pub fn capture_hand_usage(
} }
} }
} }
} }
} }
} }
} }
/// Method that is run when player hits interact button. /// Method that is run when player hits interact button.

View File

@ -2,10 +2,9 @@ use bevy::{gltf::Gltf, prelude::*};
use crate::{ use crate::{
comps::core::{ comps::core::{
events::pickup_item::PickupItemEvent, events::{pickup_item::PickupItemEvent, inventory_changed::PlayerInventoryChangedEvent},
inventory::player_inventory::PlayerInventory, inventory::player_inventory::{PlayerInventory, self},
items::item::ItemType, markers::player::Player,
markers::{firearm::FirearmType, holdable::HoldableObjectType, player::Player},
}, },
setup::assets::GltfAssets, setup::assets::GltfAssets,
}; };
@ -13,6 +12,7 @@ use crate::{
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 player_query: Query<(Entity, &mut PlayerInventory, &Transform), With<Player>>, mut player_query: Query<(Entity, &mut PlayerInventory, &Transform), With<Player>>,
assets_gltf: Res<GltfAssets>, assets_gltf: Res<GltfAssets>,
loaded_gltf_assets: Res<Assets<Gltf>>, loaded_gltf_assets: Res<Assets<Gltf>>,
@ -21,64 +21,15 @@ pub fn update_player_inventory_system(
for (player_entity, mut player_inventory, player_transform) in player_query.iter_mut() { for (player_entity, mut player_inventory, player_transform) in player_query.iter_mut() {
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
match event.item.get_type() { commands
ItemType::Holdable(holdable_object) => { .entity(event.entity)
match holdable_object { .despawn_descendants()
HoldableObjectType::Firearm(firearm) => { .despawn();
commands
.entity(event.entity) 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());
.despawn_descendants() player_inventory.pickup_item(event.item.as_ref(), event.item.get_item_slot());
.despawn(); // TODO: Equip
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!(),
}
} }
} }
} }