Inventory backend
This commit is contained in:
parent
26d03de52e
commit
3f95e2cd5a
|
@ -0,0 +1,61 @@
|
||||||
|
use bevy::{prelude::*, ecs::component::SparseStorage};
|
||||||
|
|
||||||
|
use super::{item::Item, inventory_item::InventoryItem, grid::UGrid};
|
||||||
|
|
||||||
|
#[derive(Component)]
|
||||||
|
pub struct AnyInventory {
|
||||||
|
size: UGrid,
|
||||||
|
items: Vec<InventoryItem>
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(unused)]
|
||||||
|
impl AnyInventory {
|
||||||
|
pub fn new(size: UGrid) -> Self {
|
||||||
|
Self { size, items: Vec::new() }
|
||||||
|
}
|
||||||
|
pub fn add_item_at(
|
||||||
|
&mut self,
|
||||||
|
position: UGrid,
|
||||||
|
item: impl Item<Storage = SparseStorage>,
|
||||||
|
) {
|
||||||
|
// Is Item bigger than inventory?
|
||||||
|
// Does position + item size exceed bounds?
|
||||||
|
if !self.valid_item_and_size_for_inventory(position, &item) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Is there an item in any of those places already?
|
||||||
|
if !self.item_fits_at(position, &item) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let spots_to_occupy = Self::get_spots_from_item_at_pos(position, &item);
|
||||||
|
self.items.push(InventoryItem::new(item, spots_to_occupy));
|
||||||
|
}
|
||||||
|
// Is there any items in inventory that are in any of the spots that this new item will be in
|
||||||
|
pub fn item_fits_at(&self, position: UGrid, item: &impl Item<Storage = SparseStorage>) -> bool {
|
||||||
|
let spots_to_occupy = Self::get_spots_from_item_at_pos(position, item);
|
||||||
|
for inventory_item in self.items.iter() {
|
||||||
|
if inventory_item.is_in_range(&spots_to_occupy) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
true
|
||||||
|
}
|
||||||
|
pub fn get_spots_from_item_at_pos(position: UGrid, item: &impl Item<Storage = SparseStorage>) -> Vec<UGrid> {
|
||||||
|
let end_position = position + item.inventory_size();
|
||||||
|
let mut spots = Vec::new();
|
||||||
|
for pos_width in position.width..end_position.width {
|
||||||
|
for pos_height in position.height..end_position.height {
|
||||||
|
spots.push(UGrid { width: pos_width, height: pos_height });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
spots
|
||||||
|
}
|
||||||
|
pub fn valid_item_and_size_for_inventory(
|
||||||
|
&self,
|
||||||
|
position: UGrid,
|
||||||
|
item: &impl Item<Storage = SparseStorage>,
|
||||||
|
) -> bool {
|
||||||
|
let item_bounds = position + item.inventory_size();
|
||||||
|
!(item_bounds.width > self.size.width || item_bounds.height > self.size.height)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Default, Debug, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
|
pub struct UGrid {
|
||||||
|
pub width: u32,
|
||||||
|
pub height: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::ops::Add for UGrid {
|
||||||
|
type Output = UGrid;
|
||||||
|
|
||||||
|
fn add(self, rhs: Self) -> Self::Output {
|
||||||
|
Self { width: self.width + rhs.width, height: self.height + rhs.height }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::ops::Sub for UGrid {
|
||||||
|
type Output = UGrid;
|
||||||
|
|
||||||
|
fn sub(self, rhs: Self) -> Self::Output {
|
||||||
|
Self { width: self.width - rhs.width, height: self.height - rhs.height }
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
use bevy::ecs::component::SparseStorage;
|
||||||
|
|
||||||
|
use super::{item::Item, grid::UGrid};
|
||||||
|
|
||||||
|
|
||||||
|
//#[derive()]
|
||||||
|
pub struct InventoryItem {
|
||||||
|
item: Box<dyn Item<Storage = SparseStorage>>,
|
||||||
|
/// Coordinates that this InventoryItem occupies inside an AnyInventory
|
||||||
|
occupied_spots: Vec<UGrid>,
|
||||||
|
rotated: Option<bool>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(unused)]
|
||||||
|
impl InventoryItem {
|
||||||
|
pub fn item(&self) -> &dyn Item<Storage = SparseStorage> {
|
||||||
|
self.item.as_ref()
|
||||||
|
}
|
||||||
|
pub fn rotated(&self) -> Option<bool> {
|
||||||
|
self.rotated
|
||||||
|
}
|
||||||
|
pub fn new(
|
||||||
|
item: impl Item<Storage = SparseStorage>,
|
||||||
|
occupied_spots: Vec<UGrid>,
|
||||||
|
) -> Self {
|
||||||
|
let size = item.inventory_size();
|
||||||
|
let rotated = item.inventory_rotatable().then(|| false);
|
||||||
|
Self { item: Box::new(item), occupied_spots, rotated }
|
||||||
|
}
|
||||||
|
/// Returns true if there is overlap between both
|
||||||
|
pub fn is_in_range(&self, spots_to_occupy: &Vec<UGrid>) -> bool {
|
||||||
|
for occupied_spot in self.occupied_spots.iter() {
|
||||||
|
if spots_to_occupy.contains(occupied_spot) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
use bevy::prelude::*;
|
||||||
|
|
||||||
|
use super::grid::UGrid;
|
||||||
|
|
||||||
|
|
||||||
|
pub enum ItemType {
|
||||||
|
Holdable,
|
||||||
|
Equippable,
|
||||||
|
Consumable,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait Item: Component {
|
||||||
|
fn get_type(&self) -> ItemType;
|
||||||
|
fn asset_path(&self) -> &str;
|
||||||
|
/// Optional Stackable. If value is Some(x) x is the max quantity per stack
|
||||||
|
fn stackable(&self) -> Option<u32>;
|
||||||
|
fn inventory_size(&self) -> UGrid;
|
||||||
|
fn inventory_rotatable(&self) -> bool;
|
||||||
|
fn inventory_title(&self) -> String;
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
use bevy::prelude::Component;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#[allow(unused)]
|
||||||
|
#[derive(Component)]
|
||||||
|
pub enum Interactable {
|
||||||
|
Holdable,
|
||||||
|
Lootable,
|
||||||
|
}
|
|
@ -4,3 +4,4 @@ pub mod holdable;
|
||||||
pub mod player;
|
pub mod player;
|
||||||
pub mod muzzle_flash;
|
pub mod muzzle_flash;
|
||||||
pub mod bullet;
|
pub mod bullet;
|
||||||
|
pub mod interactable;
|
|
@ -1,2 +1,6 @@
|
||||||
pub mod controller;
|
pub mod controller;
|
||||||
pub mod markers;
|
pub mod markers;
|
||||||
|
pub mod any_inventory;
|
||||||
|
pub mod item;
|
||||||
|
pub mod grid;
|
||||||
|
pub mod inventory_item;
|
|
@ -2,7 +2,7 @@ use bevy::prelude::*;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
comps::core::markers::{firearm::{FirearmData, MagazineData}, holdable::InPlayerHands, player::{PlayerHand, Player}},
|
comps::core::markers::{firearm::{FirearmData, MagazineData}, holdable::InPlayerHands, player::{PlayerHand, Player}},
|
||||||
logic::core::guns::{player_firing::PlayerFiringInfo, firearm::Firearm, shoot::shoot_bullet}, utils::rad_deg::radians_from_degrees, setup::{animations::AllFirearmAnimations, load_state::GameLoadState, equipment::{EquipmentChangeEvent, Equipment}}, ui::game::settings::SettingsScreenUIConfiguration,
|
logic::core::guns::{player_firing::PlayerFiringInfo, shoot::shoot_bullet}, utils::rad_deg::radians_from_degrees, setup::{animations::AllFirearmAnimations, load_state::GameLoadState, equipment::{EquipmentChangeEvent, Equipment}}, ui::game::settings::SettingsScreenUIConfiguration,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn capture_hand_usage(
|
pub fn capture_hand_usage(
|
||||||
|
@ -23,7 +23,7 @@ pub fn capture_hand_usage(
|
||||||
animation_clips: Res<Assets<AnimationClip>>,
|
animation_clips: Res<Assets<AnimationClip>>,
|
||||||
|
|
||||||
game_load_state: Res<GameLoadState>,
|
game_load_state: Res<GameLoadState>,
|
||||||
|
#[allow(unused)]
|
||||||
mut equipment_change_event_writer: EventWriter<EquipmentChangeEvent>,
|
mut equipment_change_event_writer: EventWriter<EquipmentChangeEvent>,
|
||||||
settings_screen_config: Res<SettingsScreenUIConfiguration>,
|
settings_screen_config: Res<SettingsScreenUIConfiguration>,
|
||||||
|
|
||||||
|
@ -36,7 +36,23 @@ pub fn capture_hand_usage(
|
||||||
if player_query.iter().len() == 0 {
|
if player_query.iter().len() == 0 {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if let Some(player_firearm) = player_query.single().0.equipment.primary_firearm.clone() {
|
|
||||||
|
// Equipping stuff
|
||||||
|
|
||||||
|
|
||||||
|
// Equipping gun
|
||||||
|
/*if !settings_screen_config.settings_menu_shown {
|
||||||
|
if keyboard_input.just_pressed(KeyCode::Key1) {
|
||||||
|
equipment_change_event_writer.send(EquipmentChangeEvent(Equipment { primary_firearm: Some(Firearm::M4A1) } ));
|
||||||
|
} else if keyboard_input.just_pressed(KeyCode::Key2) {
|
||||||
|
equipment_change_event_writer.send(EquipmentChangeEvent(Equipment { primary_firearm: Some(Firearm::Glock17) } ));
|
||||||
|
} else if keyboard_input.just_pressed(KeyCode::Key3) {
|
||||||
|
equipment_change_event_writer.send(EquipmentChangeEvent(Equipment { primary_firearm: None } ));
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
|
||||||
|
// Firearm stuff
|
||||||
|
if let Equipment::Firearm(player_firearm) = player_query.single().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.full_auto_timer.tick(time.delta());
|
player_firing_info.full_auto_timer.tick(time.delta());
|
||||||
|
|
||||||
|
@ -87,12 +103,7 @@ pub fn capture_hand_usage(
|
||||||
(time.delta_seconds() / firearm_data.rebound_time_seconds).clamp(0.0, 1.0),
|
(time.delta_seconds() / firearm_data.rebound_time_seconds).clamp(0.0, 1.0),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
// Equipping gun
|
|
||||||
if keyboard_input.just_pressed(KeyCode::Key1) && !settings_screen_config.settings_menu_shown {
|
|
||||||
equipment_change_event_writer.send(EquipmentChangeEvent(Equipment{ primary_firearm: Some(Firearm::M4A1) }));
|
|
||||||
} else if keyboard_input.just_pressed(KeyCode::Key2) && !settings_screen_config.settings_menu_shown {
|
|
||||||
equipment_change_event_writer.send(EquipmentChangeEvent(Equipment{ primary_firearm: Some(Firearm::Glock17) }));
|
|
||||||
}
|
|
||||||
// SHOOTING & RECOIL
|
// SHOOTING & RECOIL
|
||||||
if mouse_buttons.pressed(MouseButton::Left) && !settings_screen_config.settings_menu_shown {
|
if mouse_buttons.pressed(MouseButton::Left) && !settings_screen_config.settings_menu_shown {
|
||||||
if player_firing_info.full_auto_timer.finished() {
|
if player_firing_info.full_auto_timer.finished() {
|
||||||
|
@ -149,3 +160,12 @@ pub fn capture_hand_usage(
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(unused)]
|
||||||
|
/// Method that is run when player hits interact button.
|
||||||
|
/// Should raycast where the player is looking and scan for interactable
|
||||||
|
pub fn interact_action(
|
||||||
|
|
||||||
|
) {
|
||||||
|
|
||||||
|
}
|
|
@ -1,3 +1,4 @@
|
||||||
|
#![feature(step_trait)]
|
||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
use bevy_rapier3d::prelude::*;
|
use bevy_rapier3d::prelude::*;
|
||||||
use scenes::scene1;
|
use scenes::scene1;
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
|
|
||||||
use crate::{setup::{spawn::SpawnPoint, equipment::Equipment}, comps::core::markers::player::{Player, PlayerData}, logic::core::guns::firearm::Firearm};
|
use crate::{setup::{spawn::SpawnPoint, equipment::Equipment}, comps::core::markers::player::{Player, PlayerData}};
|
||||||
|
|
||||||
pub fn set_spawn_points(mut commands: Commands) {
|
pub fn set_spawn_points(mut commands: Commands) {
|
||||||
commands.spawn(SpawnPoint { at: Transform::from_xyz(3.0, 5.0, 2.0), what: Player(PlayerData{ equipment: Equipment { primary_firearm: Some(Firearm::Glock17) }}) });
|
commands.spawn(SpawnPoint { at: Transform::from_xyz(3.0, 5.0, 2.0), what: Player(PlayerData { equipment: Equipment::Nothing }) });
|
||||||
|
|
||||||
}
|
}
|
|
@ -9,9 +9,11 @@ use super::assets::{GltfAssets, GltfAssetType};
|
||||||
#[derive(Event)]
|
#[derive(Event)]
|
||||||
pub struct EquipmentChangeEvent(pub Equipment);
|
pub struct EquipmentChangeEvent(pub Equipment);
|
||||||
/// Foundation for inventory System.
|
/// Foundation for inventory System.
|
||||||
#[derive(Component, Clone, Default, Reflect)]
|
#[derive(Component, Clone, Default, Reflect, PartialEq, PartialOrd)]
|
||||||
pub struct Equipment {
|
pub enum Equipment {
|
||||||
pub primary_firearm: Option<Firearm>,
|
Firearm(Firearm),
|
||||||
|
#[default]
|
||||||
|
Nothing,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Called whenever player wants to change equipment
|
/// Called whenever player wants to change equipment
|
||||||
|
@ -25,22 +27,21 @@ pub fn change_equipment(
|
||||||
loaded_gltf_assets: Res<Assets<Gltf>>,
|
loaded_gltf_assets: Res<Assets<Gltf>>,
|
||||||
) {
|
) {
|
||||||
for equipment_change_event in equipment_change_event_reader.read() {
|
for equipment_change_event in equipment_change_event_reader.read() {
|
||||||
// TODO: Equipment change
|
|
||||||
let Ok((mut player, player_firing_info)) = player_query.get_single_mut() else {
|
let Ok((mut player, player_firing_info)) = player_query.get_single_mut() else {
|
||||||
return;
|
return;
|
||||||
} ;
|
} ;
|
||||||
// Primary firearm change
|
// Primary firearm change
|
||||||
if equipment_change_event.0.primary_firearm != player.0.equipment.primary_firearm {
|
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(); // 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 Some(new_firearm) = equipment_change_event.0.primary_firearm.clone() {
|
if let Equipment::Firearm(new_firearm) = equipment_change_event.0.clone() {
|
||||||
spawn_firearm_on_player_hands(&mut commands, player_firing_info, player_hands, &assets_gltf, &loaded_gltf_assets, new_firearm);
|
spawn_firearm_on_player_hands(&mut commands, player_firing_info, player_hands, &assets_gltf, &loaded_gltf_assets, new_firearm);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the player's equipment to the newly spawned equipment
|
// Set the player's equipment to the newly spawned equipment
|
||||||
player.0.equipment.primary_firearm = equipment_change_event.0.primary_firearm.clone();
|
player.0.equipment = equipment_change_event.0.clone();
|
||||||
println!("Equipment change done");
|
println!("Equipment change done");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
use bevy::prelude::*;
|
||||||
|
|
||||||
|
//use crate::comps::core::any_inventory::AnyInventory;
|
||||||
|
|
||||||
|
|
||||||
|
#[allow(unused)]
|
||||||
|
pub fn setup_inventory_screen(
|
||||||
|
mut commands: Commands,
|
||||||
|
|
||||||
|
) {
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
pub mod menu;
|
|
@ -3,3 +3,4 @@ pub mod plugin;
|
||||||
pub mod fps_counter;
|
pub mod fps_counter;
|
||||||
pub mod settings;
|
pub mod settings;
|
||||||
pub mod settings_screen;
|
pub mod settings_screen;
|
||||||
|
pub mod inventory;
|
|
@ -2,7 +2,7 @@ use bevy::prelude::*;
|
||||||
|
|
||||||
use crate::ui::game::settings::GameConfiguration;
|
use crate::ui::game::settings::GameConfiguration;
|
||||||
|
|
||||||
use super::{fps_counter, settings_screen, settings::SettingsScreenUIConfiguration};
|
use super::{fps_counter, settings_screen, settings::SettingsScreenUIConfiguration, inventory};
|
||||||
|
|
||||||
pub struct MainGameUIPlugin;
|
pub struct MainGameUIPlugin;
|
||||||
|
|
||||||
|
@ -12,7 +12,9 @@ impl Plugin for MainGameUIPlugin {
|
||||||
app.insert_resource(SettingsScreenUIConfiguration::default());
|
app.insert_resource(SettingsScreenUIConfiguration::default());
|
||||||
app.add_systems(Startup, (
|
app.add_systems(Startup, (
|
||||||
settings_screen::setup_settings_screen,
|
settings_screen::setup_settings_screen,
|
||||||
fps_counter::setup_fps_counter));
|
fps_counter::setup_fps_counter,
|
||||||
|
inventory::menu::setup_inventory_screen,
|
||||||
|
));
|
||||||
app.add_systems(Update, (
|
app.add_systems(Update, (
|
||||||
settings_screen::toggle_settings_screen,
|
settings_screen::toggle_settings_screen,
|
||||||
settings_screen::handle_settings_button_click,
|
settings_screen::handle_settings_button_click,
|
||||||
|
|
Loading…
Reference in New Issue