High ready + Low ready system. With animations and logic flows with sprinting, shooting, reloading, and aiming
This commit is contained in:
parent
1a7a5e6024
commit
24df81424b
@ -23,12 +23,17 @@ Multiplayer
|
|||||||
- [x] Snap back leaning too quick
|
- [x] Snap back leaning too quick
|
||||||
- [x] Issue with moving around quickly
|
- [x] Issue with moving around quickly
|
||||||
- [x] Bring Crouching back
|
- [x] Bring Crouching back
|
||||||
- [ ] Inspect animation (procedural)
|
- [x] Inspect animation & state (procedural)
|
||||||
|
- [ ] Attachment editor system when in inspect mode
|
||||||
|
- [x] High Ready & Low Ready system with state
|
||||||
|
- [x] High ready animation (procedural)
|
||||||
|
- [x] Low ready animation (procedural)
|
||||||
- [ ] Reload animation (procedural)
|
- [ ] Reload animation (procedural)
|
||||||
- [ ] Real world magazines
|
- [ ] Real world magazines
|
||||||
- [ ] Rewriting bullet physics to use raycasts & kinematic rigidbodies (logic controlled)
|
- [ ] Rewriting bullet physics to use raycasts & kinematic rigidbodies (logic controlled)
|
||||||
- [ ] Low Ready & High ready (low ready == more speed | high ready == more accuracy)
|
- [ ] Low Ready & High ready (low ready == more speed | high ready == more accuracy)
|
||||||
- [ ] Auto Low ready when gun collider hits object OR when player starts sprinting
|
- [ ] Auto Low ready when gun collider hits object OR when player starts sprinting
|
||||||
|
- [ ] Create a Controls struct that holds mappings to all the game keys and replace them in all the game's code
|
||||||
|
|
||||||
|
|
||||||
# Design
|
# Design
|
||||||
|
Binary file not shown.
@ -2,12 +2,12 @@ use bevy::prelude::*;
|
|||||||
use bevy_rapier3d::prelude::*;
|
use bevy_rapier3d::prelude::*;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
logic::core::player::{
|
logic::core::{player::{
|
||||||
player_movement::{
|
player_movement::{
|
||||||
move_player, PlayerLinearXZState, PlayerLinearYState, PlayerMovementInput,
|
move_player, PlayerLinearXZState, PlayerLinearYState, PlayerMovementInput,
|
||||||
},
|
},
|
||||||
player_values_state::PlayerValuesState,
|
player_values_state::PlayerValuesState,
|
||||||
},
|
}, guns::player_firing::PlayerFiringInfo},
|
||||||
ui::game::game_ui_state::GameUiState,
|
ui::game::game_ui_state::GameUiState,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -24,6 +24,7 @@ pub fn capture_input(
|
|||||||
&mut PlayerLinearXZState,
|
&mut PlayerLinearXZState,
|
||||||
&mut Transform,
|
&mut Transform,
|
||||||
&mut Damping,
|
&mut Damping,
|
||||||
|
&mut PlayerFiringInfo,
|
||||||
),
|
),
|
||||||
With<Player>,
|
With<Player>,
|
||||||
>,
|
>,
|
||||||
|
31
src/logic/core/guns/inspect.rs
Normal file
31
src/logic/core/guns/inspect.rs
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
use bevy::prelude::*;
|
||||||
|
|
||||||
|
use crate::comps::core::markers::{proxy::{character::in_player_hands_parent::InPlayerHandsParent, physics::utils::TransformExt}, player::Player};
|
||||||
|
|
||||||
|
use super::player_firing::PlayerFiringInfo;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
pub fn inspect_firearm(
|
||||||
|
//mut commands: Commands,
|
||||||
|
mut in_player_hands_parent_query: Query<&mut Transform, With<InPlayerHandsParent>>,
|
||||||
|
mut player_firing_info_query: Query<&mut PlayerFiringInfo, With<Player>>,
|
||||||
|
time: Res<Time>,
|
||||||
|
keyboard_input: Res<Input<KeyCode>>,
|
||||||
|
) {
|
||||||
|
for mut player_firing_info in player_firing_info_query.iter_mut() {
|
||||||
|
for mut in_player_hands_parent_transform in in_player_hands_parent_query.iter_mut() {
|
||||||
|
if player_firing_info.is_inspecting {
|
||||||
|
let inspect_hand_transform: Transform = Transform {
|
||||||
|
translation: Vec3 { x: 0.0, y: -0.1, z: -0.8 },
|
||||||
|
rotation: Quat::from_euler(EulerRot::XYZ, -2.6, -1.0, -2.5),
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
*in_player_hands_parent_transform = in_player_hands_parent_transform.lerp(inspect_hand_transform, time.delta_seconds() / 0.5);
|
||||||
|
if keyboard_input.just_pressed(KeyCode::Return) {
|
||||||
|
player_firing_info.is_inspecting = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,3 +1,4 @@
|
|||||||
pub mod despawn_shots;
|
pub mod despawn_shots;
|
||||||
pub mod player_firing;
|
pub mod player_firing;
|
||||||
pub mod shoot;
|
pub mod shoot;
|
||||||
|
pub mod inspect;
|
@ -2,6 +2,13 @@ use std::time::Duration;
|
|||||||
|
|
||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
|
|
||||||
|
#[derive(Reflect, Default, PartialEq, Eq, PartialOrd, Ord, Clone)]
|
||||||
|
pub enum GunReadyPose {
|
||||||
|
#[default]
|
||||||
|
LowReady,
|
||||||
|
HighReady,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Component, Reflect)]
|
#[derive(Component, Reflect)]
|
||||||
#[reflect(Component)]
|
#[reflect(Component)]
|
||||||
pub struct PlayerFiringInfo {
|
pub struct PlayerFiringInfo {
|
||||||
@ -15,6 +22,8 @@ pub struct PlayerFiringInfo {
|
|||||||
pub current_round_index: usize,
|
pub current_round_index: usize,
|
||||||
pub full_auto_timer: Timer,
|
pub full_auto_timer: Timer,
|
||||||
pub is_reloading: bool,
|
pub is_reloading: bool,
|
||||||
|
pub gun_ready_pose: GunReadyPose,
|
||||||
|
pub is_inspecting: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for PlayerFiringInfo {
|
impl Default for PlayerFiringInfo {
|
||||||
@ -25,6 +34,8 @@ impl Default for PlayerFiringInfo {
|
|||||||
current_round_index: Default::default(),
|
current_round_index: Default::default(),
|
||||||
full_auto_timer: Timer::new(Duration::from_secs_f32(0.0), TimerMode::Repeating),
|
full_auto_timer: Timer::new(Duration::from_secs_f32(0.0), TimerMode::Repeating),
|
||||||
is_reloading: false,
|
is_reloading: false,
|
||||||
|
gun_ready_pose: GunReadyPose::LowReady,
|
||||||
|
is_inspecting: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -38,8 +38,9 @@ pub fn shoot_bullet(
|
|||||||
},
|
},
|
||||||
MuzzleFlashMarker(Timer::new(Duration::from_millis(10), TimerMode::Once)),
|
MuzzleFlashMarker(Timer::new(Duration::from_millis(10), TimerMode::Once)),
|
||||||
));
|
));
|
||||||
// Spawn Line
|
|
||||||
|
|
||||||
|
// Spawn Line
|
||||||
|
if player_settings.shot_lines_enabled {
|
||||||
commands.spawn(
|
commands.spawn(
|
||||||
MaterialMeshBundle {
|
MaterialMeshBundle {
|
||||||
mesh: {
|
mesh: {
|
||||||
@ -56,6 +57,7 @@ pub fn shoot_bullet(
|
|||||||
..Default::default()
|
..Default::default()
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
|
||||||
spawn_bullet(
|
spawn_bullet(
|
||||||
commands,
|
commands,
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use bevy::{ecs::system::SystemParam, prelude::*, gltf::Gltf};
|
use bevy::{ecs::system::SystemParam, prelude::*, gltf::Gltf, input::mouse::MouseWheel};
|
||||||
use bevy_rapier3d::prelude::*;
|
use bevy_rapier3d::prelude::*;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
@ -9,10 +9,10 @@ use crate::{
|
|||||||
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, utils::TransformExt}},
|
||||||
}, weapons::{firearm::Firearm, firearm_state::FirearmState, parts::firing_point::FiringPoint},
|
}, weapons::{firearm::Firearm, firearm_state::FirearmState, parts::firing_point::FiringPoint},
|
||||||
},
|
},
|
||||||
logic::core::guns::{player_firing::PlayerFiringInfo, shoot::shoot_bullet},
|
logic::core::guns::{player_firing::{PlayerFiringInfo, GunReadyPose}, 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,
|
||||||
@ -21,7 +21,7 @@ use crate::{
|
|||||||
utils::{rad_deg::radians_from_degrees, hierarchy::find_child_in_parent_children},
|
utils::{rad_deg::radians_from_degrees, hierarchy::find_child_in_parent_children},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::player_settings::PlayerSettings;
|
use super::{player_settings::PlayerSettings, player_movement::PlayerLinearXZState};
|
||||||
|
|
||||||
#[derive(SystemParam)]
|
#[derive(SystemParam)]
|
||||||
pub struct CaptureHandUsageResourcesParams<'w> {
|
pub struct CaptureHandUsageResourcesParams<'w> {
|
||||||
@ -45,7 +45,7 @@ pub struct CaptureHandUsageQueryParams<'w, 's> {
|
|||||||
in_hand_query: Query<'w, 's, (&'static Parent, &'static mut Transform), (With<InPlayerHands>, Without<InPlayerHandsParent>, Without<PlayerInventory>)>,
|
in_hand_query: Query<'w, 's, (&'static Parent, &'static mut Transform), (With<InPlayerHands>, Without<InPlayerHandsParent>, Without<PlayerInventory>)>,
|
||||||
firearms_query: Query<'w, 's, (Entity, &'static GlobalTransform, &'static Firearm, &'static mut FirearmState),>,
|
firearms_query: Query<'w, 's, (Entity, &'static GlobalTransform, &'static Firearm, &'static mut FirearmState),>,
|
||||||
firing_point_query: Query<'w, 's, (&'static GlobalTransform, &'static Parent), With<FiringPoint>>,
|
firing_point_query: Query<'w, 's, (&'static GlobalTransform, &'static Parent), With<FiringPoint>>,
|
||||||
player_query: Query<'w, 's, (&'static Player, &'static mut PlayerInventory, Entity, &'static Transform, &'static mut PlayerFiringInfo), Without<InPlayerHands>>,
|
player_query: Query<'w, 's, (&'static Player, &'static mut PlayerInventory, Entity, &'static Transform, &'static mut PlayerFiringInfo, &'static PlayerLinearXZState), Without<InPlayerHands>>,
|
||||||
children: Query<'w, 's, &'static Children>,
|
children: Query<'w, 's, &'static Children>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -58,6 +58,7 @@ pub fn capture_hand_usage(
|
|||||||
|
|
||||||
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>,
|
||||||
|
mut mouse_wheel_events: EventReader<MouseWheel>,
|
||||||
) {
|
) {
|
||||||
if !resources.game_load_state.player_loaded {
|
if !resources.game_load_state.player_loaded {
|
||||||
return;
|
return;
|
||||||
@ -65,9 +66,32 @@ pub fn capture_hand_usage(
|
|||||||
|
|
||||||
// Equipping stuff
|
// Equipping stuff
|
||||||
|
|
||||||
for (player, mut player_inventory, player_entity, player_transform, mut player_firing_info) in queries.player_query.iter_mut() {
|
for (player, mut player_inventory, player_entity, player_transform, mut player_firing_info, player_linear_xz_state) in queries.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 player_firing_info.is_inspecting {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for (mut hand_transform, _) in queries.hand_query.iter_mut() {
|
||||||
|
let default_hand_transform: Transform = match player_firing_info.gun_ready_pose {
|
||||||
|
GunReadyPose::LowReady => {
|
||||||
|
Transform {
|
||||||
|
translation: Vec3 { x: -0.2, y: -0.3, z: -0.8 },
|
||||||
|
rotation: Quat::from_euler(EulerRot::XYZ, -3.6, -0.6, -3.3),
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
GunReadyPose::HighReady => {
|
||||||
|
Transform {
|
||||||
|
translation: Vec3 { x: 0.039, y: -0.193, z: -0.453 },
|
||||||
|
rotation: Quat::from_euler(EulerRot::XYZ, -180.0f32.to_radians(), 0.0, -180.0f32.to_radians()),
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
*hand_transform = hand_transform.lerp(default_hand_transform, resources.time.delta_seconds() / 0.25);
|
||||||
|
}
|
||||||
|
|
||||||
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() {
|
||||||
@ -113,6 +137,20 @@ pub fn capture_hand_usage(
|
|||||||
},
|
},
|
||||||
None => {},
|
None => {},
|
||||||
}
|
}
|
||||||
|
} else if resources.keyboard_input.just_pressed(KeyCode::I) {
|
||||||
|
if player.0.equipment.is_firearm() {
|
||||||
|
player_firing_info.is_inspecting = true;
|
||||||
|
}
|
||||||
|
} else if !mouse_wheel_events.is_empty() {
|
||||||
|
if player.0.equipment.is_firearm() {
|
||||||
|
for mouse_wheel_event in mouse_wheel_events.read() {
|
||||||
|
if mouse_wheel_event.y >= 0.0 {
|
||||||
|
player_firing_info.gun_ready_pose = GunReadyPose::HighReady;
|
||||||
|
} else {
|
||||||
|
player_firing_info.gun_ready_pose = GunReadyPose::LowReady;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -158,8 +196,9 @@ pub fn capture_hand_usage(
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
if resources.mouse_buttons.pressed(MouseButton::Right)
|
if resources.mouse_buttons.pressed(MouseButton::Right)
|
||||||
&& !resources.game_ui_state.any_window()
|
&& !resources.game_ui_state.any_window() && !player_linear_xz_state.is_sprinting()
|
||||||
{
|
{
|
||||||
|
player_firing_info.gun_ready_pose = GunReadyPose::HighReady;
|
||||||
let rotation_lerp_quat = in_hand_transform.rotation.lerp(
|
let rotation_lerp_quat = in_hand_transform.rotation.lerp(
|
||||||
firearm_data.final_aimed_rotation + resources.player_settings.rot_aimed_offset,
|
firearm_data.final_aimed_rotation + resources.player_settings.rot_aimed_offset,
|
||||||
(resources.time.delta_seconds()
|
(resources.time.delta_seconds()
|
||||||
@ -191,7 +230,7 @@ pub fn capture_hand_usage(
|
|||||||
|
|
||||||
// SHOOTING & RECOIL
|
// SHOOTING & RECOIL
|
||||||
if resources.mouse_buttons.pressed(MouseButton::Left)
|
if resources.mouse_buttons.pressed(MouseButton::Left)
|
||||||
&& !resources.game_ui_state.any_window()
|
&& !resources.game_ui_state.any_window() && player_firing_info.gun_ready_pose == GunReadyPose::HighReady
|
||||||
{
|
{
|
||||||
if let Some(magazine_data) = &mut firearm_state.magazine_data {
|
if let Some(magazine_data) = &mut firearm_state.magazine_data {
|
||||||
if player_firing_info.full_auto_timer.finished() {
|
if player_firing_info.full_auto_timer.finished() {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
use bevy_rapier3d::prelude::*;
|
use bevy_rapier3d::prelude::*;
|
||||||
|
|
||||||
use crate::comps::core::markers::player::Player;
|
use crate::{comps::core::markers::player::Player, logic::core::guns::player_firing::{PlayerFiringInfo, GunReadyPose}};
|
||||||
|
|
||||||
use super::player_values_state::PlayerValuesState;
|
use super::player_values_state::PlayerValuesState;
|
||||||
|
|
||||||
@ -111,6 +111,7 @@ pub fn move_player(
|
|||||||
&mut PlayerLinearXZState,
|
&mut PlayerLinearXZState,
|
||||||
&mut Transform,
|
&mut Transform,
|
||||||
&mut Damping,
|
&mut Damping,
|
||||||
|
&mut PlayerFiringInfo,
|
||||||
),
|
),
|
||||||
With<Player>,
|
With<Player>,
|
||||||
>,
|
>,
|
||||||
@ -124,12 +125,17 @@ pub fn move_player(
|
|||||||
mut player_linear_xz_state,
|
mut player_linear_xz_state,
|
||||||
player_transform,
|
player_transform,
|
||||||
mut player_damping,
|
mut player_damping,
|
||||||
|
mut player_firing_info,
|
||||||
) in &mut query
|
) in &mut query
|
||||||
{
|
{
|
||||||
|
if player_linear_xz_state.is_sprinting() {
|
||||||
|
player_firing_info.gun_ready_pose = GunReadyPose::LowReady;
|
||||||
|
}
|
||||||
if player_movement_input.down {
|
if player_movement_input.down {
|
||||||
player_linear_xz_state.toggle_crouch(time.elapsed().as_secs_f32());
|
player_linear_xz_state.toggle_crouch(time.elapsed().as_secs_f32());
|
||||||
}
|
}
|
||||||
let crouch_multiplier = if player_linear_xz_state.is_crouched() {
|
let crouch_multiplier =
|
||||||
|
if player_linear_xz_state.is_crouched() {
|
||||||
player_values_state.player_crouch_speed_multiplier
|
player_values_state.player_crouch_speed_multiplier
|
||||||
} else {
|
} else {
|
||||||
1.0
|
1.0
|
||||||
|
@ -8,7 +8,7 @@ pub struct PlayerSettings {
|
|||||||
//pub gun_offset: f32,
|
//pub gun_offset: f32,
|
||||||
pub fov: f32,
|
pub fov: f32,
|
||||||
|
|
||||||
/// Debug thing for me
|
/// Debug things for me
|
||||||
pub pos_aimed_offset: Vec3,
|
pub pos_aimed_offset: Vec3,
|
||||||
pub pos_offset: Vec3,
|
pub pos_offset: Vec3,
|
||||||
|
|
||||||
@ -16,6 +16,8 @@ pub struct PlayerSettings {
|
|||||||
pub rot_offset: Quat,
|
pub rot_offset: Quat,
|
||||||
|
|
||||||
pub third_person_toggle: bool,
|
pub third_person_toggle: bool,
|
||||||
|
pub shot_lines_enabled: bool,
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for PlayerSettings {
|
impl Default for PlayerSettings {
|
||||||
@ -26,7 +28,8 @@ impl Default for PlayerSettings {
|
|||||||
pos_offset: Vec3::ZERO,
|
pos_offset: Vec3::ZERO,
|
||||||
rot_aimed_offset: Quat::default(),
|
rot_aimed_offset: Quat::default(),
|
||||||
rot_offset: Quat::default(),
|
rot_offset: Quat::default(),
|
||||||
third_person_toggle: false
|
third_person_toggle: false,
|
||||||
|
shot_lines_enabled: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -7,7 +7,7 @@ use crate::{
|
|||||||
spawners::{player::player_spawner, spawn::SpawnerPlugin},
|
spawners::{player::player_spawner, spawn::SpawnerPlugin},
|
||||||
},
|
},
|
||||||
logic::core::{
|
logic::core::{
|
||||||
guns::despawn_shots::{despawn_muzzle_flashes, despawn_stray_bullets},
|
guns::{despawn_shots::{despawn_muzzle_flashes, despawn_stray_bullets}, inspect::inspect_firearm},
|
||||||
player::{
|
player::{
|
||||||
camera_player_sync::{
|
camera_player_sync::{
|
||||||
follow_cursor_with_camera, update_camera_vertical_position, MouseMovementSettings,
|
follow_cursor_with_camera, update_camera_vertical_position, MouseMovementSettings,
|
||||||
@ -59,6 +59,7 @@ pub fn load_scene(application: &mut App) {
|
|||||||
|
|
||||||
application.add_systems(Update, change_equipment.before(player_spawner));
|
application.add_systems(Update, change_equipment.before(player_spawner));
|
||||||
application.add_systems(Update, (despawn_muzzle_flashes, despawn_stray_bullets));
|
application.add_systems(Update, (despawn_muzzle_flashes, despawn_stray_bullets));
|
||||||
|
application.add_systems(Update, inspect_firearm);
|
||||||
|
|
||||||
//application.add_systems(Update, animate_player);
|
//application.add_systems(Update, animate_player);
|
||||||
//application.add_systems(Update, register_bullet_hits);
|
//application.add_systems(Update, register_bullet_hits);
|
||||||
|
@ -23,6 +23,15 @@ pub enum Equipment {
|
|||||||
Nothing,
|
Nothing,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Equipment {
|
||||||
|
pub fn is_firearm(&self) -> bool {
|
||||||
|
match self {
|
||||||
|
Equipment::Firearm(_, _) => true,
|
||||||
|
Equipment::Nothing => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Called whenever player wants to change equipment
|
/// Called whenever player wants to change equipment
|
||||||
pub fn change_equipment(
|
pub fn change_equipment(
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
|
Loading…
Reference in New Issue
Block a user