Centered interact clue text, still needs work, but is much better.

This commit is contained in:
Franklin 2023-11-13 13:53:30 -04:00
parent 45f412c7c0
commit affacae0a0
20 changed files with 192 additions and 53 deletions

View File

@ -0,0 +1,7 @@
use bevy::prelude::*;
/// This will be what is triggered after picking up an item or dropping an item.
#[derive(Event)]
pub struct InventoryChangedEvent {
}

View File

@ -1,2 +1,3 @@
//pub mod loot_container; //pub mod loot_container;
pub mod pickup_item; pub mod pickup_item;
pub mod inventory_changed;

View File

@ -4,5 +4,12 @@ use bevy::prelude::*;
use crate::comps::core::items::item::Item; use crate::comps::core::items::item::Item;
/// 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...
#[derive(Event)] #[derive(Event)]
pub struct PickupItemEvent(pub Arc<dyn Item>); pub struct PickupItemEvent {
/// Item entity
pub entity: Entity,
pub item: Arc<dyn Item>,
pub player: Entity,
}

View File

@ -2,3 +2,4 @@
//pub mod inventory_item; //pub mod inventory_item;
pub mod item_inventory; pub mod item_inventory;
pub mod player_inventory; pub mod player_inventory;
pub mod plugin;

View File

@ -1,5 +1,7 @@
use bevy::prelude::*; use bevy::prelude::*;
use crate::comps::core::items::item::Item;
use super::item_inventory::ItemInventory; use super::item_inventory::ItemInventory;
#[derive(Component)] #[derive(Component)]
@ -18,3 +20,20 @@ impl Default for PlayerInventory {
} }
} }
} }
impl PlayerInventory {
pub fn primary_occupied(&self) -> bool {
self.primary.item.is_some()
}
pub fn secondary_occupied(&self) -> bool {
self.secondary.item.is_some()
}
pub fn get_primary(&self) -> &Option<Box<dyn Item>> {
&self.primary.item
}
pub fn get_secondary(&self) -> &Option<Box<dyn Item>> {
&self.secondary.item
}
}

View File

@ -0,0 +1,12 @@
use bevy::prelude::*;
use crate::{comps::core::events::pickup_item::PickupItemEvent, logic::core::player::inventory::update_player_inventory_system};
pub struct InventoryPlugin;
impl Plugin for InventoryPlugin {
fn build(&self, app: &mut App) {
app.add_event::<PickupItemEvent>();
app.add_systems(Update, update_player_inventory_system);
}
}

View File

@ -38,10 +38,10 @@ impl Item for Glock17GunItem {
} }
fn inventory_title(&self) -> String { fn inventory_title(&self) -> String {
String::from("Glock17 Firearm") String::from("Glock17")
} }
fn inventory_description(&self) -> String { fn inventory_description(&self) -> String {
String::from("Glock17 Firearm chambered in 9x19mm.") String::from("Pistol chambered in 9x19mm.")
} }
} }

View File

@ -4,7 +4,7 @@ use crate::{
markers::{firearm::FirearmData, holdable::HoldableObjectType, interactable::Interactable}, markers::{firearm::FirearmData, holdable::HoldableObjectType, interactable::Interactable},
}, },
setup::assets::{GltfAssetType, GltfAssets}, setup::assets::{GltfAssetType, GltfAssets},
utils, utils, logic::core::guns::firearm::Firearm,
}; };
use bevy::{gltf::Gltf, prelude::*}; use bevy::{gltf::Gltf, prelude::*};
use bevy_rapier3d::prelude::*; use bevy_rapier3d::prelude::*;
@ -81,12 +81,14 @@ pub trait Item: Sync + Send {
..Default::default() ..Default::default()
}, },
RigidBody::Dynamic, RigidBody::Dynamic,
ColliderMassProperties::Mass(5.0),
GravityScale(4.0),
Collider::cuboid( Collider::cuboid(
firearm_size.x, firearm_size.x,
firearm_size.y, firearm_size.y,
firearm_size.z, firearm_size.z,
), ),
Interactable::Item(firearm.get_item()), Interactable::Item(firearm.get_item_arc()),
)) ))
.push_children(&[firearm_asset_entity]); .push_children(&[firearm_asset_entity]);
} }
@ -98,4 +100,12 @@ pub trait Item: Sync + Send {
ItemType::Consumable => todo!(), ItemType::Consumable => todo!(),
}; };
} }
fn get_firearm(&self) -> Option<Firearm> {
match self.get_type() {
ItemType::Holdable(holdable) => match holdable {
HoldableObjectType::Firearm(firearm) => Some(firearm),
},
_ => None
}
}
} }

View File

@ -19,7 +19,7 @@ impl Display for Interactable {
match self { match self {
Interactable::Holdable => write!(f, "Holdable"), Interactable::Holdable => write!(f, "Holdable"),
//Interactable::Lootable(_) => write!(f, "Lootable"), //Interactable::Lootable(_) => write!(f, "Lootable"),
Interactable::Item(_) => write!(f, "Item"), Interactable::Item(item) => write!(f, "Pickup [{}]", item.inventory_title()),
} }
} }
} }

View File

@ -122,13 +122,23 @@ impl Firearm {
y: 0.7, y: 0.7,
z: 2.5, z: 2.5,
}, },
Firearm::Glock17 => Vec3::ZERO, Firearm::Glock17 => Vec3 {
x: 0.3,
y: 0.4,
z: 1.0,
},
} }
} }
pub fn get_item(&self) -> Arc<dyn Item> { pub fn get_item_arc(&self) -> Arc<dyn Item> {
match self { match self {
Firearm::M4A1 => Arc::new(M4a1GunItem), Firearm::M4A1 => Arc::new(M4a1GunItem),
Firearm::Glock17 => Arc::new(Glock17GunItem), Firearm::Glock17 => Arc::new(Glock17GunItem),
} }
} }
pub fn get_item_box(&self) -> Box<dyn Item> {
match self {
Firearm::M4A1 => Box::new(M4a1GunItem),
Firearm::Glock17 => Box::new(Glock17GunItem),
}
}
} }

View File

@ -5,10 +5,10 @@ use crate::{
comps::core::{markers::{ comps::core::{markers::{
camera::MainCamera, camera::MainCamera,
firearm::{FirearmData, MagazineData}, firearm::{FirearmData, MagazineData},
holdable::InPlayerHands, holdable::{InPlayerHands, HoldableObjectType},
interactable::Interactable, interactable::Interactable,
player::{Player, PlayerHand}, player::{Player, PlayerHand},
}, events::pickup_item::PickupItemEvent}, }, events::pickup_item::PickupItemEvent, inventory::player_inventory::PlayerInventory, items::item::ItemType},
logic::core::guns::{firearm::Firearm, player_firing::PlayerFiringInfo, shoot::shoot_bullet}, logic::core::guns::{firearm::Firearm, player_firing::PlayerFiringInfo, shoot::shoot_bullet},
setup::{ setup::{
animations::AllFirearmAnimations, animations::AllFirearmAnimations,
@ -32,6 +32,7 @@ pub struct CaptureHandUsageResourcesParams<'w> {
time: Res<'w, Time>, time: Res<'w, Time>,
} }
#[allow(irrefutable_let_patterns)]
pub fn capture_hand_usage( pub fn capture_hand_usage(
mut resources: CaptureHandUsageResourcesParams, mut resources: CaptureHandUsageResourcesParams,
mut commands: Commands, mut commands: Commands,
@ -46,7 +47,7 @@ pub fn capture_hand_usage(
), ),
(With<InPlayerHands>, Without<PlayerHand>), (With<InPlayerHands>, Without<PlayerHand>),
>, >,
player_query: Query<&Player>, player_query: Query<(&Player, &PlayerInventory, Entity)>,
mut player_firing_info_query: Query<&mut PlayerFiringInfo, With<Player>>, mut player_firing_info_query: Query<&mut PlayerFiringInfo, With<Player>>,
mut animation_players: Query<(Entity, &mut AnimationPlayer)>, mut animation_players: Query<(Entity, &mut AnimationPlayer)>,
@ -64,20 +65,37 @@ pub fn capture_hand_usage(
// Equipping stuff // Equipping stuff
// Equipping gun // Equipping gun
// Validate player has primary item, and secondary item in inventory
if !resources.settings_screen_config.settings_menu_shown { if !resources.settings_screen_config.settings_menu_shown {
if resources.keyboard_input.just_pressed(KeyCode::Key1) { if resources.keyboard_input.just_pressed(KeyCode::Key1) {
equipment_change_event_writer if let Some(primary_item) = player_query.single().1.get_primary() {
.send(EquipmentChangeEvent(Equipment::Firearm(Firearm::M4A1))); 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)));
}
}
}
} else if resources.keyboard_input.just_pressed(KeyCode::Key2) { } else if resources.keyboard_input.just_pressed(KeyCode::Key2) {
equipment_change_event_writer if let Some(secondary_item) = player_query.single().1.get_secondary() {
.send(EquipmentChangeEvent(Equipment::Firearm(Firearm::Glock17))); 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::Key3) { } else if resources.keyboard_input.just_pressed(KeyCode::Key3) {
equipment_change_event_writer.send(EquipmentChangeEvent(Equipment::Nothing)); if Equipment::Nothing != player_query.single().0.0.equipment {
equipment_change_event_writer.send(EquipmentChangeEvent(Equipment::Nothing));
}
} }
} }
// Firearm stuff // Firearm stuff
if let Equipment::Firearm(player_firearm) = player_query.single().0.equipment.clone() { if let Equipment::Firearm(player_firearm) = player_query.single().0.0.equipment.clone() {
for mut player_firing_info in player_firing_info_query.iter_mut() { for mut player_firing_info in player_firing_info_query.iter_mut() {
player_firing_info player_firing_info
.full_auto_timer .full_auto_timer
@ -276,11 +294,6 @@ pub fn interact_action(
QueryFilter::default().exclude_collider(player_entity), QueryFilter::default().exclude_collider(player_entity),
) { ) {
for (interactable_entity, interactable) in interactables_query.iter() { for (interactable_entity, interactable) in interactables_query.iter() {
println!(
"Hit: {:?} == interactable_entity: {:?} interactable: {}",
entity, interactable_entity, interactable
);
//println!("Collided! {}, {}", entity.index(), interactable.to_string());
if interactable_entity == entity { if interactable_entity == entity {
hud_state.interaction_clue_shown = true; hud_state.interaction_clue_shown = true;
hud_state.interaction_clue_text = interactable.to_string(); hud_state.interaction_clue_text = interactable.to_string();
@ -293,8 +306,7 @@ pub fn interact_action(
.send(LootContainerEvent(any_inventory.clone())) .send(LootContainerEvent(any_inventory.clone()))
}*/ }*/
Interactable::Item(item) => { Interactable::Item(item) => {
pickup_item_event_writer.send(PickupItemEvent { entity: interactable_entity, item: item.clone(), player: player_entity });
pickup_item_event_writer.send(PickupItemEvent(item.clone()));
} }
} }
} }

View File

@ -0,0 +1,50 @@
use bevy::{prelude::*, gltf::Gltf};
use crate::{comps::core::{events::pickup_item::PickupItemEvent, markers::{player::Player, holdable::HoldableObjectType, firearm::FirearmType}, inventory::player_inventory::PlayerInventory, items::item::ItemType}, setup::assets::GltfAssets};
pub fn update_player_inventory_system(
mut commands: Commands,
mut pickup_item_events: EventReader<PickupItemEvent>,
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 (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();
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, Transform::from_translation(player_transform.translation + player_transform.up() * 5.0 + player_transform.forward()), &assets_gltf, &loaded_gltf_assets);
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, Transform::from_translation(player_transform.translation + player_transform.up() * 5.0 + player_transform.forward()), &assets_gltf, &loaded_gltf_assets);
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!(),
}
}
}
}
}

View File

@ -4,3 +4,4 @@ pub mod hands;
pub mod player_movement; pub mod player_movement;
pub mod player_values_state; pub mod player_values_state;
pub mod player_vertical_sync; pub mod player_vertical_sync;
pub mod inventory;

View File

@ -3,7 +3,7 @@ use bevy::prelude::*;
use crate::{ use crate::{
comps::core::{ comps::core::{
controller::capture_input, controller::capture_input,
spawners::{player::player_spawner, spawn::SpawnerPlugin}, spawners::{player::player_spawner, spawn::SpawnerPlugin}, inventory::plugin::InventoryPlugin,
}, },
logic::core::{ logic::core::{
guns::despawn_shots::{despawn_muzzle_flashes, despawn_stray_bullets}, guns::despawn_shots::{despawn_muzzle_flashes, despawn_stray_bullets},
@ -36,6 +36,7 @@ pub fn load_scene(application: &mut App) {
application.insert_resource(PlayerValuesState::default()); application.insert_resource(PlayerValuesState::default());
application.add_plugins(SpawnerPlugin); application.add_plugins(SpawnerPlugin);
application.add_plugins(InventoryPlugin);
// Startup // Startup
application.add_systems(PreStartup, load_all_assets); application.add_systems(PreStartup, load_all_assets);
application.add_systems(Startup, spawn_ground); application.add_systems(Startup, spawn_ground);

View File

@ -11,7 +11,7 @@ pub fn spawn_obstacles(
let box_2_mesh = shape::Box::new(3.0, 7.0, 3.0).into(); let box_2_mesh = shape::Box::new(3.0, 7.0, 3.0).into();
let box_3_mesh = shape::Box::new(3.0, 7.0, 3.0).into(); let box_3_mesh = shape::Box::new(3.0, 7.0, 3.0).into();
let box_4_mesh = shape::Box::new(3.0, 7.0, 3.0).into(); let box_4_mesh = shape::Box::new(3.0, 7.0, 3.0).into();
let box_5_mesh = shape::Box::new(2.0, 2.0, 2.0).into(); //let box_5_mesh = shape::Box::new(2.0, 2.0, 2.0).into();
commands commands
.spawn(( .spawn((
Collider::from_bevy_mesh(&box_1_mesh, &Default::default()).unwrap(), Collider::from_bevy_mesh(&box_1_mesh, &Default::default()).unwrap(),
@ -81,7 +81,7 @@ pub fn spawn_obstacles(
}); });
// CRATE // CRATE
commands /*commands
.spawn(( .spawn((
Collider::from_bevy_mesh(&box_5_mesh, &Default::default()).unwrap(), Collider::from_bevy_mesh(&box_5_mesh, &Default::default()).unwrap(),
Name::new("Crate"), Name::new("Crate"),
@ -99,5 +99,5 @@ pub fn spawn_obstacles(
}) })
/*.insert(Interactable::Lootable(AnyInventory::new( /*.insert(Interactable::Lootable(AnyInventory::new(
UGrid::new_square(10), UGrid::new_square(10),
)))*/; )))*/;*/
} }

View File

@ -30,4 +30,18 @@ pub fn set_spawn_points(mut commands: Commands) {
transform transform
}, },
}); });
commands.spawn(M4a1SpawnPoint {
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(Glock17SpawnPoint {
transform: {
let mut transform = Transform::from_xyz(20.0, 10.0, 20.0);
transform.rotate_z(utils::rad_deg::radians_from_degrees(-90.0));
transform
},
});
} }

View File

@ -6,7 +6,7 @@ use crate::{
comps::core::markers::{ comps::core::markers::{
firearm::{FirearmData, MagazineData}, firearm::{FirearmData, MagazineData},
holdable::InPlayerHands, holdable::InPlayerHands,
player::{Player, PlayerHand}, player::{Player, PlayerHand, PlayerData},
}, },
logic::core::guns::{firearm::Firearm, player_firing::PlayerFiringInfo}, logic::core::guns::{firearm::Firearm, player_firing::PlayerFiringInfo},
utils, utils,
@ -39,25 +39,23 @@ pub fn change_equipment(
return; return;
}; };
// Primary firearm change // Primary firearm change
if equipment_change_event.0 != player.0.equipment { let player_hands = player_hands_query.single_mut();
let player_hands = player_hands_query.single_mut();
commands.entity(player_hands).despawn_descendants(); // TODO: Don't do this without keeping the state from the last mag commands.entity(player_hands).despawn_descendants(); // TODO: Don't do this without keeping the state from the last mag
if let Equipment::Firearm(new_firearm) = equipment_change_event.0.clone() { if let Equipment::Firearm(new_firearm) = equipment_change_event.0.clone() {
spawn_firearm_on_player_hands( spawn_firearm_on_player_hands(
&mut commands, &mut commands,
player_firing_info, player_firing_info,
player_hands, player_hands,
&assets_gltf, &assets_gltf,
&loaded_gltf_assets, &loaded_gltf_assets,
new_firearm, new_firearm,
); );
}
// Set the player's equipment to the newly spawned equipment
player.0.equipment = equipment_change_event.0.clone();
println!("Equipment change done");
} }
// Set the player's equipment to the newly spawned equipment
player.0.equipment = equipment_change_event.0.clone();
println!("Equipment change done");
} }
} }

View File

@ -22,7 +22,8 @@ pub fn setup_interact_clue(mut commands: Commands) {
style: Style { style: Style {
position_type: PositionType::Absolute, position_type: PositionType::Absolute,
top: Val::Percent(50.0), top: Val::Percent(50.0),
left: Val::Percent(50.0), left: Val::Percent(47.0),
//right: Val::Percent(50.0),
..Default::default() ..Default::default()
}, },
visibility: Visibility::Visible, visibility: Visibility::Visible,

View File

@ -8,6 +8,6 @@ pub fn setup_inventory_screen(mut _commands: Commands) {}
pub fn update_inventory_screen( pub fn update_inventory_screen(
mut _commands: Commands, mut _commands: Commands,
//mut event_reader: EventReader<LootContainerEvent>,
) { ) {
} }

View File

@ -1,16 +1,11 @@
use bevy::prelude::*; use bevy::prelude::*;
//use crate::comps::core::events::loot_container::LootContainerEvent;
use crate::comps::core::events::pickup_item::PickupItemEvent;
use super::menu::{setup_inventory_screen, update_inventory_screen}; use super::menu::{setup_inventory_screen, update_inventory_screen};
pub struct InventoryMenuPlugin; pub struct InventoryMenuPlugin;
impl Plugin for InventoryMenuPlugin { impl Plugin for InventoryMenuPlugin {
fn build(&self, app: &mut App) { fn build(&self, app: &mut App) {
app.add_event::<PickupItemEvent>();
app.add_systems(Startup, setup_inventory_screen); app.add_systems(Startup, setup_inventory_screen);
app.add_systems(Update, update_inventory_screen); app.add_systems(Update, update_inventory_screen);
} }