Organs base and attachment reducing recoil, crouching reduces recoil
This commit is contained in:
parent
e99708cef9
commit
dd9496d110
20
Design.md
20
Design.md
@ -46,9 +46,11 @@ Multiplayer
|
|||||||
- [x] Make the player's collider bigger towards the front
|
- [x] Make the player's collider bigger towards the front
|
||||||
- [ ] Make the weapon's collider cover the firing point
|
- [ ] Make the weapon's collider cover the firing point
|
||||||
- [ ] If possible, create a new gun pose, like pushed back
|
- [ ] If possible, create a new gun pose, like pushed back
|
||||||
- [ ] Bobbing
|
- [x] Bobbing
|
||||||
- [ ] TODO: Gun Bob on run
|
- [x] Gun Bob on run
|
||||||
- [ ] TODO: Gun Bob on walk
|
- [x] Gun Bob on walk
|
||||||
|
- [ ] Check if Bobbing could be too exagerated
|
||||||
|
- [ ] Leaning neutralizes Bobbing for some reason
|
||||||
- [ ] Reload animation (procedural)
|
- [ ] Reload animation (procedural)
|
||||||
- [ ] Real world magazines
|
- [ ] Real world magazines
|
||||||
- [x] Rewriting bullet physics to use raycasts & kinematic rigidbodies (logic controlled)
|
- [x] Rewriting bullet physics to use raycasts & kinematic rigidbodies (logic controlled)
|
||||||
@ -58,6 +60,18 @@ Multiplayer
|
|||||||
- [x] Gun colliding with ground and going into low ready
|
- [x] Gun colliding with ground and going into low ready
|
||||||
- [x] With introduction of floor collision groups now bullets go through floors
|
- [x] With introduction of floor collision groups now bullets go through floors
|
||||||
- [x] Huge bug all attachments get despawned and spawned when gun shoots
|
- [x] Huge bug all attachments get despawned and spawned when gun shoots
|
||||||
|
- [ ] Bloom on bullets is making them way too bright, bring down the emissive mat color & size of the bullets.
|
||||||
|
- [ ] Red dot sight needs to be zeroed. (Height over bore)
|
||||||
|
- [ ] Red dot on sight is too quick on a trackpad.
|
||||||
|
- [ ] Red dot is automatically going up to max when shift is pressed for the first time.
|
||||||
|
- [ ] Multiplayer
|
||||||
|
- [ ] Start work on a multiplayer server
|
||||||
|
- [ ] Map
|
||||||
|
- [ ] Start building a map for your hideout
|
||||||
|
- [ ] Player model hitbox
|
||||||
|
- [ ] Organs
|
||||||
|
- [ ] Heart
|
||||||
|
- [ ] Brain
|
||||||
|
|
||||||
# Design
|
# Design
|
||||||
|
|
||||||
|
Binary file not shown.
BIN
assets/character/other_player_character.glb
Normal file
BIN
assets/character/other_player_character.glb
Normal file
Binary file not shown.
@ -11,6 +11,7 @@ bitflags! {
|
|||||||
/// The value `C`, at bit position `2`.
|
/// The value `C`, at bit position `2`.
|
||||||
const SOLIDS = 0b00000100;
|
const SOLIDS = 0b00000100;
|
||||||
const PLAYER = 0b00001000;
|
const PLAYER = 0b00001000;
|
||||||
|
const ENEMY = 0b00010000;
|
||||||
|
|
||||||
const FLOOR = 0b00010000;
|
const FLOOR = 0b00010000;
|
||||||
|
|
||||||
|
@ -9,4 +9,5 @@ pub mod settings_screen;
|
|||||||
pub mod proxy;
|
pub mod proxy;
|
||||||
pub mod inspect_screen;
|
pub mod inspect_screen;
|
||||||
pub mod collider_flags;
|
pub mod collider_flags;
|
||||||
pub mod firearm_scene;
|
pub mod firearm_scene;
|
||||||
|
pub mod player_health;
|
28
src/comps/core/markers/player_health.rs
Normal file
28
src/comps/core/markers/player_health.rs
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
use super::proxy::other_players::human_body_part::HumanBodyPart;
|
||||||
|
|
||||||
|
|
||||||
|
pub const MAX_BLOOD_ML: f32 = 6000.0;
|
||||||
|
/// Health for a player
|
||||||
|
pub struct PlayerHealth {
|
||||||
|
/// Vision state. TODO: Create an enum for Partial blindness, Full blindness, Full blindness.
|
||||||
|
pub vision: bool,
|
||||||
|
/// Measured in milliliters
|
||||||
|
pub current_blood: f32,
|
||||||
|
/// The average adult has about 4 to 6 liters of blood (9 to 12 US pints) in their body. The average man has more blood than the average woman, and people who weigh more or are taller than others have more blood.[1] This means a person can die from losing 2 1/2 to 4 liters of blood. To compare, this is five to eight times as much blood as people usually give in a blood donation.[2]
|
||||||
|
/// [Source](https://simple.wikipedia.org/wiki/Exsanguination#:~:text=People%20can%20die%20from%20losing,two%2Dthirds%20of%20their%20blood.&text=The%20average%20adult%20has%20about,than%20others%20have%20more%20blood.)
|
||||||
|
/// Measured in milliliters
|
||||||
|
pub max_blood: f32,
|
||||||
|
pub human_body_parts_state: Vec<HumanBodyPartState>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct HumanBodyPartState {
|
||||||
|
pub body_part: HumanBodyPart,
|
||||||
|
pub well: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
impl Default for PlayerHealth {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self { current_blood: MAX_BLOOD_ML, max_blood: MAX_BLOOD_ML, vision: true, human_body_parts_state: Vec::new() } // TODO: add human body parts here
|
||||||
|
}
|
||||||
|
}
|
@ -1,7 +1,7 @@
|
|||||||
use bevy::{prelude::*, core_pipeline::{tonemapping::Tonemapping, bloom::BloomSettings}};
|
use bevy::{prelude::*, core_pipeline::{tonemapping::Tonemapping, bloom::BloomSettings}};
|
||||||
use bevy_rapier3d::prelude::*;
|
use bevy_rapier3d::prelude::*;
|
||||||
|
|
||||||
use crate::{comps::core::markers::{proxy::physics::rapier::LinkToPlayer, camera::MainCamera}, logic::core::player::player_values_state::PlayerValuesState};
|
use crate::{comps::core::markers::{proxy::physics::rapier::LinkToPlayer, camera::MainCamera, player::Player}, logic::core::player::player_values_state::PlayerValuesState, utils::hierarchy::find_child_in_parent_children};
|
||||||
|
|
||||||
use super::{third_person_camera::{ThirdPersonCameraProxy, ThirdPersonCamera}, in_player_hands_parent::InPlayerHandsParent};
|
use super::{third_person_camera::{ThirdPersonCameraProxy, ThirdPersonCamera}, in_player_hands_parent::InPlayerHandsParent};
|
||||||
|
|
||||||
@ -12,40 +12,47 @@ pub struct PlayerEye;
|
|||||||
|
|
||||||
pub fn insert_components_into_spawned_player(
|
pub fn insert_components_into_spawned_player(
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
|
player_query: Query<Entity, With<Player>>,
|
||||||
eye_query: Query<Entity, Added<PlayerEye>>,
|
eye_query: Query<Entity, Added<PlayerEye>>,
|
||||||
third_person_camera_query: Query<Entity, Added<ThirdPersonCameraProxy>>,
|
third_person_camera_query: Query<Entity, Added<ThirdPersonCameraProxy>>,
|
||||||
player_collider_query: Query<Entity, (With<LinkToPlayer>, With<Collider>, Added<Collider>)>,
|
player_collider_query: Query<Entity, (With<LinkToPlayer>, With<Collider>, Added<Collider>)>,
|
||||||
mut hand_query: Query<(Entity, &mut Transform), (With<InPlayerHandsParent>, Without<LinkToPlayer>, Without<Collider>)>,
|
mut hand_query: Query<(Entity, &mut Transform), (With<InPlayerHandsParent>, Without<LinkToPlayer>, Without<Collider>)>,
|
||||||
player_values_state: Res<PlayerValuesState>,
|
player_values_state: Res<PlayerValuesState>,
|
||||||
|
children: Query<&Children>,
|
||||||
) {
|
) {
|
||||||
for eye in eye_query.iter() {
|
for eye in eye_query.iter() {
|
||||||
// Spawn camera
|
for player in player_query.iter() {
|
||||||
let camera = commands
|
if find_child_in_parent_children(&mut commands, player, eye, &children) {
|
||||||
.spawn(MainCamera)
|
// Spawn camera
|
||||||
.insert(Camera3dBundle {
|
let camera = commands
|
||||||
transform: Transform::from_xyz(0.0, 0.0, 0.0),
|
.spawn(MainCamera)
|
||||||
camera: Camera {
|
.insert(Camera3dBundle {
|
||||||
hdr: true,
|
transform: Transform::from_xyz(0.0, 0.0, 0.0),
|
||||||
..Default::default()
|
camera: Camera {
|
||||||
},
|
hdr: true,
|
||||||
tonemapping: Tonemapping::TonyMcMapface,
|
..Default::default()
|
||||||
..Default::default()
|
},
|
||||||
})
|
tonemapping: Tonemapping::TonyMcMapface,
|
||||||
.insert(BloomSettings {
|
..Default::default()
|
||||||
..Default::default()
|
})
|
||||||
})
|
.insert(BloomSettings {
|
||||||
//s.insert(Skybox(skybox_handle.clone()))
|
..Default::default()
|
||||||
.insert(VisibilityBundle {
|
})
|
||||||
visibility: Visibility::Inherited,
|
//s.insert(Skybox(skybox_handle.clone()))
|
||||||
..Default::default()
|
.insert(VisibilityBundle {
|
||||||
})
|
visibility: Visibility::Inherited,
|
||||||
//.push_children(&[player_hand])
|
..Default::default()
|
||||||
.id();
|
})
|
||||||
for (hand, mut hand_transform) in hand_query.iter_mut() {
|
//.push_children(&[player_hand])
|
||||||
hand_transform.rotate_y(180.0f32.to_radians());
|
.id();
|
||||||
commands.entity(hand).set_parent(camera);
|
for (hand, mut hand_transform) in hand_query.iter_mut() {
|
||||||
|
hand_transform.rotate_y(180.0f32.to_radians());
|
||||||
|
commands.entity(hand).set_parent(camera);
|
||||||
|
}
|
||||||
|
commands.entity(eye).add_child(camera);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
commands.entity(eye).add_child(camera);
|
|
||||||
}
|
}
|
||||||
for third_person_camera in third_person_camera_query.iter() {
|
for third_person_camera in third_person_camera_query.iter() {
|
||||||
|
|
||||||
|
@ -2,4 +2,5 @@ pub mod character;
|
|||||||
pub mod plugin;
|
pub mod plugin;
|
||||||
pub mod physics;
|
pub mod physics;
|
||||||
pub mod bevy;
|
pub mod bevy;
|
||||||
pub mod weapons;
|
pub mod weapons;
|
||||||
|
pub mod other_players;
|
@ -0,0 +1,38 @@
|
|||||||
|
use bevy::{ecs::{component::Component, reflect::ReflectComponent}, reflect::Reflect};
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(Component, Reflect, Clone, PartialEq, Default, Debug)]
|
||||||
|
#[reflect(Component)]
|
||||||
|
pub enum HumanBodyPart {
|
||||||
|
Heart,
|
||||||
|
Brain,
|
||||||
|
#[default]
|
||||||
|
Torso,
|
||||||
|
Legs,
|
||||||
|
Hands,
|
||||||
|
Feet,
|
||||||
|
Eyes,
|
||||||
|
Head,
|
||||||
|
Spine,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
impl HumanBodyPart {
|
||||||
|
/// For the sake of simplicity.
|
||||||
|
/// A value of true means an instant death if a bullet hits this body part.
|
||||||
|
/// A value of false means no instant death.
|
||||||
|
pub fn is_vital(&self) -> bool {
|
||||||
|
match self {
|
||||||
|
HumanBodyPart::Heart => true,
|
||||||
|
HumanBodyPart::Brain => true,
|
||||||
|
HumanBodyPart::Spine => true,
|
||||||
|
_ => false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Take a mutable reference to the player_health
|
||||||
|
pub fn effect_when_lost() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
1
src/comps/core/markers/proxy/other_players/mod.rs
Normal file
1
src/comps/core/markers/proxy/other_players/mod.rs
Normal file
@ -0,0 +1 @@
|
|||||||
|
pub mod human_body_part;
|
@ -62,36 +62,35 @@ pub fn physics_replace_proxies(
|
|||||||
|
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
) {
|
) {
|
||||||
for (player_entity, _) in player_query.iter() {
|
|
||||||
for proxy_colider in proxy_colliders.iter_mut() {
|
for proxy_colider in proxy_colliders.iter_mut() {
|
||||||
let (entity, collider_proxy, name, mut visibility, link_to_player_opt, _) = proxy_colider;
|
let (entity, collider_proxy, name, mut visibility, _, _) = proxy_colider;
|
||||||
// we hide the collider meshes: perhaps they should be removed altogether once processed ?
|
// we hide the collider meshes: perhaps they should be removed altogether once processed ?
|
||||||
if name.ends_with("_collider") || name.ends_with("_sensor") {
|
if name.ends_with("_collider") || name.ends_with("_sensor") {
|
||||||
*visibility = Visibility::Hidden;
|
*visibility = Visibility::Hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
let entity_to_insert_collider_on = if link_to_player_opt.is_some() { player_entity } else { entity };
|
|
||||||
|
|
||||||
let mut rapier_collider: RapierCollider;
|
let mut rapier_collider: RapierCollider;
|
||||||
match collider_proxy {
|
match collider_proxy {
|
||||||
Collider::Ball(radius) => {
|
Collider::Ball(radius) => {
|
||||||
println!("proxy: ball");
|
println!("proxy: ball");
|
||||||
rapier_collider = RapierCollider::ball(*radius);
|
rapier_collider = RapierCollider::ball(*radius);
|
||||||
commands.entity(entity_to_insert_collider_on)
|
commands.entity(entity)
|
||||||
.insert(rapier_collider)
|
.insert(rapier_collider)
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
Collider::Cuboid(size) => {
|
Collider::Cuboid(size) => {
|
||||||
println!("proxy: cuboid");
|
println!("proxy: cuboid");
|
||||||
rapier_collider = RapierCollider::cuboid(size.x, size.y, size.z);
|
rapier_collider = RapierCollider::cuboid(size.x, size.y, size.z);
|
||||||
commands.entity(entity_to_insert_collider_on)
|
commands.entity(entity)
|
||||||
.insert(rapier_collider)
|
.insert(rapier_collider)
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
Collider::Capsule(a, b, radius) => {
|
Collider::Capsule(a, b, radius) => {
|
||||||
println!("proxy: capsule");
|
println!("proxy: capsule");
|
||||||
rapier_collider = RapierCollider::capsule(*a, *b, *radius);
|
rapier_collider = RapierCollider::capsule(*a, *b, *radius);
|
||||||
commands.entity(entity_to_insert_collider_on)
|
commands.entity(entity)
|
||||||
.insert(rapier_collider)
|
.insert(rapier_collider)
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
@ -110,6 +109,7 @@ pub fn physics_replace_proxies(
|
|||||||
commands.entity(impulse_entity).insert(impulse_to_be_applied.0);
|
commands.entity(impulse_entity).insert(impulse_to_be_applied.0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//rapier_collider.set_scale(Vec3 { x: 3.0, y: 3.0, z: 3.0 }, 1);
|
//rapier_collider.set_scale(Vec3 { x: 3.0, y: 3.0, z: 3.0 }, 1);
|
||||||
commands
|
commands
|
||||||
.entity(entity)
|
.entity(entity)
|
||||||
@ -123,6 +123,10 @@ pub fn physics_replace_proxies(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (entity, proxy_rigidbody, link_to_player_opt, _) in proxy_rigidbodies.iter() {
|
for (entity, proxy_rigidbody, link_to_player_opt, _) in proxy_rigidbodies.iter() {
|
||||||
|
let mut entity_to_insert_collider_on = entity ;
|
||||||
|
for (player_entity, _) in player_query.iter() {
|
||||||
|
entity_to_insert_collider_on = if link_to_player_opt.is_some() { player_entity } else { entity };
|
||||||
|
}
|
||||||
let rapier_rigidbody: RapierRigidBody;
|
let rapier_rigidbody: RapierRigidBody;
|
||||||
match proxy_rigidbody {
|
match proxy_rigidbody {
|
||||||
RigidBodyBlender::Fixed => rapier_rigidbody = RapierRigidBody::Fixed,
|
RigidBodyBlender::Fixed => rapier_rigidbody = RapierRigidBody::Fixed,
|
||||||
@ -130,11 +134,10 @@ pub fn physics_replace_proxies(
|
|||||||
}
|
}
|
||||||
commands
|
commands
|
||||||
.entity(
|
.entity(
|
||||||
if link_to_player_opt.is_some() { player_entity } else { entity }
|
if link_to_player_opt.is_some() { entity_to_insert_collider_on } else { entity }
|
||||||
)
|
)
|
||||||
.insert(rapier_rigidbody)
|
.insert(rapier_rigidbody)
|
||||||
;
|
;
|
||||||
commands.entity(entity).remove::<RigidBodyBlender>();
|
commands.entity(entity).remove::<RigidBodyBlender>();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
@ -2,7 +2,7 @@ use bevy::app::{Plugin, Update};
|
|||||||
|
|
||||||
use crate::{setup::load_state::update_game_load_state, comps::core::weapons::{firearm::Firearm, attachments::{weapon_attachment::WeaponAttachment, optic::Optic, stock::Stock, compensator::Compensator, magazine::Magazine, foregrip::ForeGrip}, parts::{charging_handle::ChargingHandle, fire_selector::FireSelector, firing_point::FiringPoint, trigger::Trigger}, slot::{compensator_slot::CompensatorSlot, fore_grip_slot::ForeGripSlot, magazine_slot::MagazineSlot, stock_slot::StockSlot, utility_slot::UtilitySlot, slot::WeaponSlot}}};
|
use crate::{setup::load_state::update_game_load_state, comps::core::weapons::{firearm::Firearm, attachments::{weapon_attachment::WeaponAttachment, optic::Optic, stock::Stock, compensator::Compensator, magazine::Magazine, foregrip::ForeGrip}, parts::{charging_handle::ChargingHandle, fire_selector::FireSelector, firing_point::FiringPoint, trigger::Trigger}, slot::{compensator_slot::CompensatorSlot, fore_grip_slot::ForeGripSlot, magazine_slot::MagazineSlot, stock_slot::StockSlot, utility_slot::UtilitySlot, slot::WeaponSlot}}};
|
||||||
|
|
||||||
use super::{character::{player_hitbox::PlayerHitBox, player_character::PlayerCharacter, player_eye::{PlayerEye, insert_components_into_spawned_player}, in_player_hands_parent::{InPlayerHandsParent, insert_components_into_player_hand}, third_person_camera::ThirdPersonCameraProxy}, physics::{rapier::{AutoAABBCollider, physics_replace_proxies}, self}, weapons::{firearm::insert_firearm_state_to_firearms, gun_colliders::{GunFirearmCollider, update_gun_collider}, sight_placement::{SightPlacementStart, SightPlacementEnd}, optic_sight_glass::{OpticSightGlass, replace_optic_sight_material, DebugMaterialResource}}};
|
use super::{character::{player_hitbox::PlayerHitBox, player_character::PlayerCharacter, player_eye::{PlayerEye, insert_components_into_spawned_player}, in_player_hands_parent::{InPlayerHandsParent, insert_components_into_player_hand}, third_person_camera::ThirdPersonCameraProxy}, physics::{rapier::{AutoAABBCollider, physics_replace_proxies}, self}, weapons::{firearm::insert_firearm_state_to_firearms, gun_colliders::{GunFirearmCollider, update_gun_collider}, sight_placement::{SightPlacementStart, SightPlacementEnd}, optic_sight_glass::{OpticSightGlass, replace_optic_sight_material, DebugMaterialResource}}, other_players::human_body_part::HumanBodyPart};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -20,6 +20,9 @@ impl Plugin for ProxyComponentsPlugin {
|
|||||||
app.register_type::<InPlayerHandsParent>();
|
app.register_type::<InPlayerHandsParent>();
|
||||||
app.register_type::<ThirdPersonCameraProxy>();
|
app.register_type::<ThirdPersonCameraProxy>();
|
||||||
|
|
||||||
|
// OtherPlayer
|
||||||
|
app.register_type::<HumanBodyPart>();
|
||||||
|
|
||||||
// Firearms
|
// Firearms
|
||||||
app.register_type::<Firearm>();
|
app.register_type::<Firearm>();
|
||||||
app.register_type::<GunFirearmCollider>();
|
app.register_type::<GunFirearmCollider>();
|
||||||
|
71
src/comps/core/spawners/dummy.rs
Normal file
71
src/comps/core/spawners/dummy.rs
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
use bevy::{prelude::*, gltf::Gltf};
|
||||||
|
use bevy_rapier3d::prelude::*;
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
comps::core::markers::collider_flags::ColliderFlags,
|
||||||
|
setup::{load_state::GameLoadState, assets::GltfAssets},
|
||||||
|
};
|
||||||
|
|
||||||
|
use super::spawn_point::SpawnPoint;
|
||||||
|
|
||||||
|
#[derive(Component)]
|
||||||
|
pub struct DummySpawnPoint {
|
||||||
|
pub transform: Transform,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SpawnPoint for DummySpawnPoint {
|
||||||
|
fn get_transform(&self) -> Transform {
|
||||||
|
self.transform
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// System that runs every fame checking if player has been spawned.
|
||||||
|
/// For player to spawn, everything inside GameLoadState must be loaded Except player.
|
||||||
|
pub fn dummy_spawner(
|
||||||
|
mut commands: Commands,
|
||||||
|
dummy_sp_query: Query<(Entity, &DummySpawnPoint)>,
|
||||||
|
game_load_state: Res<GameLoadState>,
|
||||||
|
assets: Res<GltfAssets>,
|
||||||
|
loaded_gltf_assets: Res<Assets<Gltf>>,
|
||||||
|
) {
|
||||||
|
if !game_load_state.is_everything_except_player_loaded() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (dummy_spawn_point_entity, dummy_spawn_point) in dummy_sp_query.iter() {
|
||||||
|
let dummy_scene = commands.spawn(
|
||||||
|
(
|
||||||
|
SceneBundle {
|
||||||
|
scene: loaded_gltf_assets.get(assets.assets[3].asset.clone()).unwrap().scenes[0].clone(),
|
||||||
|
transform: Transform::from_translation(Vec3::ZERO).with_scale(Vec3 { x: 3.0, y: 3.0, z: 3.0 }),
|
||||||
|
visibility: Visibility::Inherited,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
Name::new("Dummy Scene Bundle")
|
||||||
|
)
|
||||||
|
).id();
|
||||||
|
|
||||||
|
// Spawn dummy
|
||||||
|
commands
|
||||||
|
.spawn(TransformBundle {
|
||||||
|
local: dummy_spawn_point.get_transform(),
|
||||||
|
..Default::default()
|
||||||
|
})
|
||||||
|
.insert(
|
||||||
|
LockedAxes::ROTATION_LOCKED_Z
|
||||||
|
| LockedAxes::ROTATION_LOCKED_X
|
||||||
|
| LockedAxes::ROTATION_LOCKED_Y,
|
||||||
|
)
|
||||||
|
.insert(VisibilityBundle {
|
||||||
|
visibility: Visibility::Visible,
|
||||||
|
..Default::default()
|
||||||
|
})
|
||||||
|
// Data
|
||||||
|
.insert(CollisionGroups::new(Group::from_bits_retain(ColliderFlags::ENEMY.bits()), Group::from_bits_retain((ColliderFlags::SOLIDS | ColliderFlags::PLAYER | ColliderFlags::BULLETS | ColliderFlags::FLOOR).bits())))
|
||||||
|
.insert(Name::new("Dummy"))
|
||||||
|
.add_child(dummy_scene);
|
||||||
|
|
||||||
|
commands.entity(dummy_spawn_point_entity).despawn();
|
||||||
|
println!("Spawned dummy");
|
||||||
|
}
|
||||||
|
}
|
@ -3,3 +3,4 @@ pub mod item;
|
|||||||
pub mod player;
|
pub mod player;
|
||||||
pub mod spawn;
|
pub mod spawn;
|
||||||
pub mod spawn_point;
|
pub mod spawn_point;
|
||||||
|
pub mod dummy;
|
@ -3,13 +3,13 @@ use bevy::prelude::*;
|
|||||||
use super::{
|
use super::{
|
||||||
item::{item_spawner, ItemSpawnPointPlugin},
|
item::{item_spawner, ItemSpawnPointPlugin},
|
||||||
player::player_spawner,
|
player::player_spawner,
|
||||||
spawn_point::SpawnPointPlugin,
|
spawn_point::SpawnPointPlugin, dummy::dummy_spawner,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct SpawnerPlugin;
|
pub struct SpawnerPlugin;
|
||||||
impl Plugin for SpawnerPlugin {
|
impl Plugin for SpawnerPlugin {
|
||||||
fn build(&self, app: &mut App) {
|
fn build(&self, app: &mut App) {
|
||||||
app.add_plugins((SpawnPointPlugin, ItemSpawnPointPlugin));
|
app.add_plugins((SpawnPointPlugin, ItemSpawnPointPlugin));
|
||||||
app.add_systems(Update, (player_spawner, item_spawner));
|
app.add_systems(Update, (player_spawner, item_spawner, dummy_spawner));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
|
|
||||||
use crate::comps::core::spawners::player::PlayerSpawnPoint;
|
use crate::comps::core::spawners::{player::PlayerSpawnPoint, dummy::DummySpawnPoint};
|
||||||
|
|
||||||
#[bevy_trait_query::queryable]
|
#[bevy_trait_query::queryable]
|
||||||
pub trait SpawnPoint {
|
pub trait SpawnPoint {
|
||||||
@ -12,5 +12,6 @@ impl Plugin for SpawnPointPlugin {
|
|||||||
fn build(&self, app: &mut App) {
|
fn build(&self, app: &mut App) {
|
||||||
use bevy_trait_query::RegisterExt;
|
use bevy_trait_query::RegisterExt;
|
||||||
app.register_component_as::<dyn SpawnPoint, PlayerSpawnPoint>();
|
app.register_component_as::<dyn SpawnPoint, PlayerSpawnPoint>();
|
||||||
|
app.register_component_as::<dyn SpawnPoint, DummySpawnPoint>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,9 @@ pub trait Attachment {
|
|||||||
/// Starts at 1
|
/// Starts at 1
|
||||||
fn current_attachment_index(&self) -> u32;
|
fn current_attachment_index(&self) -> u32;
|
||||||
fn all_attachments() -> Vec<Self> where Self: Sized;
|
fn all_attachments() -> Vec<Self> where Self: Sized;
|
||||||
|
/// Horizontal recoil % to remove. Additive
|
||||||
|
fn horizontal_recoil_modifier(&self) -> f32;
|
||||||
|
fn vertical_recoil_modifier(&self) -> f32;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Used to switch attachments.
|
/// Used to switch attachments.
|
||||||
|
@ -20,4 +20,14 @@ impl Attachment for Compensator {
|
|||||||
fn all_attachments() -> Vec<Self> where Self: Sized {
|
fn all_attachments() -> Vec<Self> where Self: Sized {
|
||||||
Vec::from([Self::FirstCompensator])
|
Vec::from([Self::FirstCompensator])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn horizontal_recoil_modifier(&self) -> f32 {
|
||||||
|
0.12
|
||||||
|
}
|
||||||
|
|
||||||
|
fn vertical_recoil_modifier(&self) -> f32 {
|
||||||
|
0.12
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
@ -20,4 +20,12 @@ impl Attachment for ForeGrip {
|
|||||||
fn all_attachments() -> Vec<Self> where Self: Sized {
|
fn all_attachments() -> Vec<Self> where Self: Sized {
|
||||||
Vec::from([Self::Pk5])
|
Vec::from([Self::Pk5])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn horizontal_recoil_modifier(&self) -> f32 {
|
||||||
|
0.06
|
||||||
|
}
|
||||||
|
|
||||||
|
fn vertical_recoil_modifier(&self) -> f32 {
|
||||||
|
0.06
|
||||||
|
}
|
||||||
}
|
}
|
@ -33,4 +33,12 @@ impl Attachment for Magazine {
|
|||||||
fn all_attachments() -> Vec<Self> where Self: Sized {
|
fn all_attachments() -> Vec<Self> where Self: Sized {
|
||||||
Vec::from([Self::Ak105])
|
Vec::from([Self::Ak105])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn horizontal_recoil_modifier(&self) -> f32 {
|
||||||
|
0.0
|
||||||
|
}
|
||||||
|
|
||||||
|
fn vertical_recoil_modifier(&self) -> f32 {
|
||||||
|
0.0
|
||||||
|
}
|
||||||
}
|
}
|
@ -64,5 +64,13 @@ impl Attachment for Optic {
|
|||||||
fn all_attachments() -> Vec<Self> where Self: Sized {
|
fn all_attachments() -> Vec<Self> where Self: Sized {
|
||||||
Vec::from([Self::AimpointT1])
|
Vec::from([Self::AimpointT1])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn horizontal_recoil_modifier(&self) -> f32 {
|
||||||
|
0.0
|
||||||
|
}
|
||||||
|
|
||||||
|
fn vertical_recoil_modifier(&self) -> f32 {
|
||||||
|
0.0
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,4 +20,12 @@ impl Attachment for Silencer {
|
|||||||
fn all_attachments() -> Vec<Self> where Self: Sized {
|
fn all_attachments() -> Vec<Self> where Self: Sized {
|
||||||
Vec::from([Self::FirstSilencer])
|
Vec::from([Self::FirstSilencer])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn horizontal_recoil_modifier(&self) -> f32 {
|
||||||
|
0.10
|
||||||
|
}
|
||||||
|
|
||||||
|
fn vertical_recoil_modifier(&self) -> f32 {
|
||||||
|
0.10
|
||||||
|
}
|
||||||
}
|
}
|
@ -20,4 +20,12 @@ impl Attachment for Stock {
|
|||||||
fn all_attachments() -> Vec<Self> where Self: Sized {
|
fn all_attachments() -> Vec<Self> where Self: Sized {
|
||||||
Vec::from([Self::MagpullTan])
|
Vec::from([Self::MagpullTan])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn horizontal_recoil_modifier(&self) -> f32 {
|
||||||
|
0.23
|
||||||
|
}
|
||||||
|
|
||||||
|
fn vertical_recoil_modifier(&self) -> f32 {
|
||||||
|
0.23
|
||||||
|
}
|
||||||
}
|
}
|
@ -23,20 +23,20 @@ impl Default for WeaponAttachment {
|
|||||||
impl WeaponAttachment {
|
impl WeaponAttachment {
|
||||||
pub fn vertical_recoil_modifier(&self) -> f32 {
|
pub fn vertical_recoil_modifier(&self) -> f32 {
|
||||||
match self {
|
match self {
|
||||||
WeaponAttachment::Compensator(_) => 0.0,
|
WeaponAttachment::Compensator(comp) => comp.vertical_recoil_modifier(),
|
||||||
WeaponAttachment::Magazine(_) => 0.0,
|
WeaponAttachment::Magazine(mag) => mag.vertical_recoil_modifier(),
|
||||||
WeaponAttachment::Stock(_) => 0.0,
|
WeaponAttachment::Stock(stock) => stock.vertical_recoil_modifier(),
|
||||||
WeaponAttachment::ForeGrip(_) => 0.0,
|
WeaponAttachment::ForeGrip(foregrip) => foregrip.vertical_recoil_modifier(),
|
||||||
WeaponAttachment::Optic(_) => 0.0,
|
WeaponAttachment::Optic(optic) => optic.vertical_recoil_modifier(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn horizontal_recoil_modifier(&self) -> f32 {
|
pub fn horizontal_recoil_modifier(&self) -> f32 {
|
||||||
match self {
|
match self {
|
||||||
WeaponAttachment::Compensator(_) => 0.0,
|
WeaponAttachment::Compensator(comp) => comp.horizontal_recoil_modifier(),
|
||||||
WeaponAttachment::Magazine(_) => 0.0,
|
WeaponAttachment::Magazine(mag) => mag.horizontal_recoil_modifier(),
|
||||||
WeaponAttachment::Stock(_) => 0.0,
|
WeaponAttachment::Stock(stock) => stock.horizontal_recoil_modifier(),
|
||||||
WeaponAttachment::ForeGrip(_) => 0.0,
|
WeaponAttachment::ForeGrip(foregrip) => foregrip.horizontal_recoil_modifier(),
|
||||||
WeaponAttachment::Optic(_) => 0.0,
|
WeaponAttachment::Optic(optic) => optic.horizontal_recoil_modifier(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn asset_path<'a>(&self) -> &'a str {
|
pub fn asset_path<'a>(&self) -> &'a str {
|
||||||
|
@ -1,12 +1,17 @@
|
|||||||
use bevy::reflect::Reflect;
|
use bevy::reflect::Reflect;
|
||||||
|
|
||||||
/// Unit = m/s
|
/// Unit = m/s
|
||||||
pub const MIN_LETHAL_BULLET_VELOCITY: f32 = 60.0;
|
/// When a bullet reaches this speed (213 fps == 64.92), it is no longer able to penetrate human bone.
|
||||||
|
///
|
||||||
|
/// Quote: `The speed at which a projectile must travel to penetrate skin is 163 fps and to break bone is 213 fps, both of which are quite low, so other factors are more important in producing damage. (Belkin, 1978)`
|
||||||
|
///
|
||||||
|
/// [Source](https://webpath.med.utah.edu/TUTORIAL/GUNS/GUNBLST.html#:~:text=The%20speed%20at%20which%20a,more%20important%20in%20producing%20damage.)
|
||||||
|
pub const MIN_LETHAL_BULLET_VELOCITY: f32 = 64.92;
|
||||||
|
|
||||||
#[allow(unused)]
|
|
||||||
#[derive(Clone, Reflect, Default)]
|
#[derive(Clone, Reflect, Default)]
|
||||||
pub enum Caliber {
|
pub enum Caliber {
|
||||||
/// 5.56x45mm
|
/// 5.56x45mm
|
||||||
|
/// Reference [Wikipedia](https://en.wikipedia.org/wiki/5.56%C3%9745mm_NATO)
|
||||||
NATO556,
|
NATO556,
|
||||||
/// 9x19mm Parabellum (NATO)
|
/// 9x19mm Parabellum (NATO)
|
||||||
/// Reference: [Wikipedia](https://en.wikipedia.org/wiki/9%C3%9719mm_Parabellum)
|
/// Reference: [Wikipedia](https://en.wikipedia.org/wiki/9%C3%9719mm_Parabellum)
|
||||||
@ -36,30 +41,19 @@ impl Caliber {
|
|||||||
Caliber::RU545 => 0.00343,
|
Caliber::RU545 => 0.00343,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn linear_damping(&self) -> f32 {
|
/// Unit = meters
|
||||||
match self {
|
/// Real life value (BULLET DIAMETER/2)
|
||||||
Caliber::NATO556 => 1.0,
|
|
||||||
Caliber::NATOParabellum9mm => 2.0,
|
|
||||||
Caliber::RU545 => 1.5,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub fn angular_damping(&self) -> f32 {
|
|
||||||
match self {
|
|
||||||
Caliber::NATO556 => 1.0,
|
|
||||||
Caliber::NATOParabellum9mm => 1.0,
|
|
||||||
Caliber::RU545 => 1.0,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub fn size(&self) -> f32 {
|
pub fn size(&self) -> f32 {
|
||||||
match self {
|
match self {
|
||||||
Caliber::NATO556 => 0.07,
|
Caliber::NATO556 => 0.07,
|
||||||
Caliber::NATOParabellum9mm => 0.05,
|
Caliber::NATOParabellum9mm => 0.05,
|
||||||
Caliber::RU545 => 0.06
|
Caliber::RU545 => 0.0056/2.0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Unit = m/s
|
/// Unit = m/s
|
||||||
/// Real life value
|
/// Real life value (Muzzle velocity)
|
||||||
|
/// (TODO: Factor in the barrel that it is being shot from)
|
||||||
pub fn muzzle_velocity(&self) -> f32 {
|
pub fn muzzle_velocity(&self) -> f32 {
|
||||||
match self {
|
match self {
|
||||||
Caliber::NATO556 => 991.0,
|
Caliber::NATO556 => 991.0,
|
||||||
|
@ -55,4 +55,23 @@ impl FirearmState {
|
|||||||
None => None,
|
None => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_horizontal_recoil_modifier(&self) -> f32 {
|
||||||
|
let mut total = 0.0;
|
||||||
|
self.attachment_slots.iter().for_each(|attachment| {
|
||||||
|
if let Some(attachment) = &attachment.attachment {
|
||||||
|
total += attachment.horizontal_recoil_modifier()
|
||||||
|
}
|
||||||
|
});
|
||||||
|
1.0 - total
|
||||||
|
}
|
||||||
|
pub fn get_vertical_recoil_modifier(&self) -> f32 {
|
||||||
|
let mut total = 0.0;
|
||||||
|
self.attachment_slots.iter().for_each(|attachment| {
|
||||||
|
if let Some(attachment) = &attachment.attachment {
|
||||||
|
total += attachment.vertical_recoil_modifier()
|
||||||
|
}
|
||||||
|
});
|
||||||
|
1.0 - total
|
||||||
|
}
|
||||||
}
|
}
|
@ -9,17 +9,15 @@
|
|||||||
use bevy::{prelude::*, ecs::system::SystemParam};
|
use bevy::{prelude::*, ecs::system::SystemParam};
|
||||||
use bevy_rapier3d::{pipeline::CollisionEvent, rapier::geometry::CollisionEventFlags, geometry::Sensor};
|
use bevy_rapier3d::{pipeline::CollisionEvent, rapier::geometry::CollisionEventFlags, geometry::Sensor};
|
||||||
|
|
||||||
use crate::comps::core::{markers::{bullet::BulletMarker, proxy::weapons::gun_colliders::GunFirearmCollider}, events::{bullet_collision::BulletCollisionEvent, equipped_gun_collision::EquippedGunCollisionEvent, collision_event_type::CollisionEventType}};
|
use crate::comps::core::{markers::{bullet::BulletMarker, proxy::weapons::gun_colliders::GunFirearmCollider}, events::{equipped_gun_collision::EquippedGunCollisionEvent, collision_event_type::CollisionEventType}};
|
||||||
|
|
||||||
#[derive(SystemParam)]
|
#[derive(SystemParam)]
|
||||||
pub struct CollisionHandlerQueryParams<'w, 's> {
|
pub struct CollisionHandlerQueryParams<'w, 's> {
|
||||||
bullets: Query<'w, 's, (Entity, &'static Transform), With<BulletMarker>>,
|
|
||||||
firearms: Query<'w, 's, Entity, (With<Sensor>, With<GunFirearmCollider>, Without<BulletMarker>)>,
|
firearms: Query<'w, 's, Entity, (With<Sensor>, With<GunFirearmCollider>, Without<BulletMarker>)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(SystemParam)]
|
#[derive(SystemParam)]
|
||||||
pub struct CollisionHandlerEventParams<'w> {
|
pub struct CollisionHandlerEventParams<'w> {
|
||||||
bullet_collision_events: EventWriter<'w, BulletCollisionEvent>,
|
|
||||||
equipped_gun_collision_events: EventWriter<'w, EquippedGunCollisionEvent>,
|
equipped_gun_collision_events: EventWriter<'w, EquippedGunCollisionEvent>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -62,25 +60,5 @@ pub fn collision_handler(
|
|||||||
}
|
}
|
||||||
continue; // Continue, as we already handled sensor collisions
|
continue; // Continue, as we already handled sensor collisions
|
||||||
}
|
}
|
||||||
// ######
|
|
||||||
// Bullet collisions
|
|
||||||
// ######
|
|
||||||
for (bullet, bullet_transform) in queries.bullets.iter() {
|
|
||||||
if entity_a == &bullet {
|
|
||||||
events.bullet_collision_events.send(BulletCollisionEvent {
|
|
||||||
bullet,
|
|
||||||
other: *entity_b,
|
|
||||||
at: *bullet_transform,
|
|
||||||
collision_type,
|
|
||||||
});
|
|
||||||
} else if entity_b == &bullet {
|
|
||||||
events.bullet_collision_events.send(BulletCollisionEvent {
|
|
||||||
bullet,
|
|
||||||
other: *entity_a,
|
|
||||||
at: *bullet_transform,
|
|
||||||
collision_type,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,39 +1,58 @@
|
|||||||
use bevy::prelude::*;
|
use bevy::{prelude::*, ecs::system::SystemParam};
|
||||||
|
|
||||||
use crate::comps::core::{markers::proxy::weapons::{optic_sight_glass::OpticSightGlass, reticle::DrawnReticle}, weapons::firearm_state::FirearmState};
|
use crate::comps::core::{markers::{proxy::weapons::{optic_sight_glass::OpticSightGlass, reticle::DrawnReticle}, camera::MainCamera}, weapons::{firearm_state::FirearmState, parts::firing_point::FiringPoint}};
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(SystemParam)]
|
||||||
|
pub struct UpdateReticleQueryParams<'w, 's> {
|
||||||
|
sight_query_added: Query<'w, 's, (Entity, &'static OpticSightGlass), Added<OpticSightGlass>>,
|
||||||
|
sight_query: Query<'w, 's, (Entity, &'static OpticSightGlass)>,
|
||||||
|
reticle_query: Query<'w, 's, (&'static Parent, &'static Handle<StandardMaterial>, &'static DrawnReticle, &'static mut Transform),>,
|
||||||
|
firearm_state: Query<'w, 's, &'static FirearmState, Changed<FirearmState>>,
|
||||||
|
firing_point_query: Query<'w, 's, &'static GlobalTransform, (With<FiringPoint>, Without<DrawnReticle>)>,
|
||||||
|
main_camera_query: Query<'w, 's, (&'static Camera, &'static GlobalTransform), (With<MainCamera>, Without<FiringPoint>, Without<DrawnReticle>)>,
|
||||||
|
}
|
||||||
/// How?
|
/// How?
|
||||||
/// Achieve parallax on all reticles by drawing a line straight out of the barrel and a straight line from the sight that intersected at the specified zeroed range for the optic.
|
/// Achieve parallax on all reticles by drawing a line straight out of the barrel and a straight line from the sight that intersected at the specified zeroed range for the optic.
|
||||||
/// Make sure that the reticle is where the bullets will land at the specified zeroed range.
|
/// Make sure that the reticle is where the bullets will land at the specified zeroed range.
|
||||||
pub fn update_reticle(
|
pub fn update_reticle(
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
// TODO: make this identify which optic is on the gun, but meanwhile just start doing it to all the optics in
|
// TODO: make this identify which optic is on the gun, but meanwhile just start doing it to all the optics in
|
||||||
sight_query_added: Query<(Entity, &OpticSightGlass), Added<OpticSightGlass>>,
|
mut query: UpdateReticleQueryParams,
|
||||||
sight_query: Query<(Entity, &OpticSightGlass)>,
|
|
||||||
reticle_query: Query<(&Parent, &Handle<StandardMaterial>, &DrawnReticle),>,
|
|
||||||
firearm_state: Query<&FirearmState, Changed<FirearmState>>,
|
|
||||||
mut meshes: ResMut<Assets<Mesh>>,
|
mut meshes: ResMut<Assets<Mesh>>,
|
||||||
mut materials: ResMut<Assets<StandardMaterial>>,
|
mut materials: ResMut<Assets<StandardMaterial>>,
|
||||||
) {
|
) {
|
||||||
|
|
||||||
// Spawn reticles
|
// Spawn reticles
|
||||||
for (entity, sight) in sight_query_added.iter() {
|
for (entity, sight) in query.sight_query_added.iter() {
|
||||||
let reticle = sight.0.reticle();
|
let reticle = sight.0.reticle();
|
||||||
reticle.spawn(&mut commands, entity, &mut meshes, &mut materials);
|
reticle.spawn(&mut commands, entity, &mut meshes, &mut materials);
|
||||||
println!("Added reticle");
|
|
||||||
}
|
}
|
||||||
// Modify reticle brightness
|
// Modify reticle brightness
|
||||||
|
for (optic_entity, optic_sight_glass) in query.sight_query.iter() {
|
||||||
for (optic_entity, optic_sight_glass) in sight_query.iter() {
|
for (reticle_parent, reticle_material, _, mut reticle_transform) in query.reticle_query.iter_mut () {
|
||||||
for (reticle_parent, reticle_material, _) in reticle_query.iter() {
|
|
||||||
if optic_entity != reticle_parent.get() { continue; }
|
if optic_entity != reticle_parent.get() { continue; }
|
||||||
for firearm_state in firearm_state.iter() {
|
for firearm_state in query.firearm_state.iter() {
|
||||||
if let Some(ref optic_data) = firearm_state.optic_data {
|
if let Some(ref optic_data) = firearm_state.optic_data {
|
||||||
if let Some(mat) = materials.get_mut(reticle_material) {
|
if let Some(mat) = materials.get_mut(reticle_material) {
|
||||||
mat.emissive = optic_sight_glass.0.reticle().get_color() * optic_data.reticle_brightness;
|
mat.emissive = optic_sight_glass.0.reticle().get_color() * optic_data.reticle_brightness;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for firing_point_transform in query.firing_point_query.iter() {
|
||||||
|
for (cam, cam_transform) in query.main_camera_query.iter() {
|
||||||
|
let point_at_range = firing_point_transform.translation() + firing_point_transform.forward() * 50.0;
|
||||||
|
/*match cam.world_to_viewport(cam_transform, point_at_range) {
|
||||||
|
Some(_) => todo!(),
|
||||||
|
None => todo!(),
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
reticle_transform.translation.x = point_at_range.x;
|
||||||
|
reticle_transform.translation.y = point_at_range.y;*/
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -92,6 +92,6 @@ pub fn spawn_bullet(
|
|||||||
},
|
},
|
||||||
RigidBody::KinematicPositionBased,
|
RigidBody::KinematicPositionBased,
|
||||||
ActiveEvents::COLLISION_EVENTS,
|
ActiveEvents::COLLISION_EVENTS,
|
||||||
CollisionGroups::new(Group::from_bits_retain(ColliderFlags::BULLETS.bits()), Group::from_bits_retain((ColliderFlags::SOLIDS | ColliderFlags::FLOOR).bits())),
|
CollisionGroups::new(Group::from_bits_retain(ColliderFlags::BULLETS.bits()), Group::from_bits_retain((ColliderFlags::SOLIDS | ColliderFlags::FLOOR | ColliderFlags::ENEMY).bits())),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
@ -53,7 +53,7 @@ pub fn update_bullet(
|
|||||||
},
|
},
|
||||||
material: materials.add(StandardMaterial {
|
material: materials.add(StandardMaterial {
|
||||||
base_color: Color::RED,
|
base_color: Color::RED,
|
||||||
emissive: Color::RED,
|
emissive: Color::RED * 10.0,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}),
|
}),
|
||||||
visibility: Visibility::Visible,
|
visibility: Visibility::Visible,
|
||||||
|
@ -60,6 +60,8 @@ 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>,
|
mut mouse_wheel_events: EventReader<MouseWheel>,
|
||||||
|
|
||||||
|
mut gizmos: Gizmos,
|
||||||
) {
|
) {
|
||||||
if !resources.game_load_state.player_loaded {
|
if !resources.game_load_state.player_loaded {
|
||||||
return;
|
return;
|
||||||
@ -245,7 +247,9 @@ pub fn capture_hand_usage(
|
|||||||
if resources.mouse_buttons.pressed(MouseButton::Left) // Shooting (LClick)
|
if resources.mouse_buttons.pressed(MouseButton::Left) // Shooting (LClick)
|
||||||
&& !resources.game_ui_state.any_window() && player_firing_info.gun_ready_pose == GunReadyPose::HighReady
|
&& !resources.game_ui_state.any_window() && player_firing_info.gun_ready_pose == GunReadyPose::HighReady
|
||||||
{
|
{
|
||||||
if let Some(magazine_data) = &mut firearm_state.magazine_data {
|
let firearm_vert_recoil_modifier = firearm_state.get_vertical_recoil_modifier();
|
||||||
|
let firearm_horiz_recoil_modifier = firearm_state.get_horizontal_recoil_modifier();
|
||||||
|
if let Some(ref mut magazine_data) = firearm_state.magazine_data {
|
||||||
if player_firing_info.full_auto_timer.finished() {
|
if player_firing_info.full_auto_timer.finished() {
|
||||||
if magazine_data.rounds_shot < magazine_data.max_capacity {
|
if magazine_data.rounds_shot < magazine_data.max_capacity {
|
||||||
// Get recoil numbers from patterns
|
// Get recoil numbers from patterns
|
||||||
@ -284,16 +288,24 @@ pub fn capture_hand_usage(
|
|||||||
player_firing_info.full_auto_timer.reset();
|
player_firing_info.full_auto_timer.reset();
|
||||||
magazine_data.rounds_shot += 1;
|
magazine_data.rounds_shot += 1;
|
||||||
|
|
||||||
|
|
||||||
|
let crouch_recoil_modifier = if player_linear_xz_state.is_crouched() {
|
||||||
|
0.6
|
||||||
|
} else {
|
||||||
|
1.0
|
||||||
|
};
|
||||||
// Apply recoil
|
// Apply recoil
|
||||||
in_hand_transform.rotate_x(radians_from_degrees(
|
in_hand_transform.rotate_x(radians_from_degrees(
|
||||||
//TODO: Recoil modifier firearm_data.vertical_recoil_modifier
|
|
||||||
-1.0 * 2.0
|
-1.0 * 2.0
|
||||||
* vertical_recoil_number,
|
* vertical_recoil_number
|
||||||
|
* firearm_horiz_recoil_modifier
|
||||||
|
* crouch_recoil_modifier,
|
||||||
));
|
));
|
||||||
in_hand_transform.rotate_y(radians_from_degrees(
|
in_hand_transform.rotate_y(radians_from_degrees(
|
||||||
//TODO: Recoil modifier firearm_data.horizontal_recoil_modifier
|
|
||||||
1.0 * 0.5
|
1.0 * 0.5
|
||||||
* horizontal_recoil_number,
|
* horizontal_recoil_number
|
||||||
|
* firearm_vert_recoil_modifier
|
||||||
|
* crouch_recoil_modifier,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -308,6 +320,11 @@ pub fn capture_hand_usage(
|
|||||||
player_firing_info.current_round_index = 0;
|
player_firing_info.current_round_index = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if player_firing_info.gun_ready_pose == GunReadyPose::HighReady {
|
||||||
|
for (firing_point_transform, firing_point_parent) in queries.firing_point_query.iter() {
|
||||||
|
gizmos.line(firing_point_transform.translation(), firing_point_transform.forward() * 100000.0, Color::RED);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,7 @@ fn setup_plugins(application: &mut App) {
|
|||||||
}))
|
}))
|
||||||
//.add_plugins(DefaultInspectorConfigPlugin)
|
//.add_plugins(DefaultInspectorConfigPlugin)
|
||||||
.add_plugins(RapierPhysicsPlugin::<NoUserData>::default())
|
.add_plugins(RapierPhysicsPlugin::<NoUserData>::default())
|
||||||
//.add_plugins(RapierDebugRenderPlugin::default())
|
.add_plugins(RapierDebugRenderPlugin::default())
|
||||||
.add_plugins(ComponentsFromGltfPlugin)
|
.add_plugins(ComponentsFromGltfPlugin)
|
||||||
//.add_plugins(bevy_egui::EguiPlugin)
|
//.add_plugins(bevy_egui::EguiPlugin)
|
||||||
//.add_plugins(WorldInspectorPlugin::new())
|
//.add_plugins(WorldInspectorPlugin::new())
|
||||||
|
@ -5,7 +5,7 @@ use crate::{
|
|||||||
markers::player::{Player, PlayerData},
|
markers::player::{Player, PlayerData},
|
||||||
spawners::{
|
spawners::{
|
||||||
guns::ak105_spawner::Ak105SpawnPoint,
|
guns::ak105_spawner::Ak105SpawnPoint,
|
||||||
player::PlayerSpawnPoint,
|
player::PlayerSpawnPoint, dummy::DummySpawnPoint,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
utils,
|
utils,
|
||||||
@ -30,6 +30,10 @@ pub fn set_spawn_points(mut commands: Commands) {
|
|||||||
transform
|
transform
|
||||||
},
|
},
|
||||||
});*/
|
});*/
|
||||||
|
|
||||||
|
commands.spawn(DummySpawnPoint {
|
||||||
|
transform: Transform::from_xyz(15.0, 0.1, 20.0),
|
||||||
|
});
|
||||||
|
|
||||||
commands.spawn(Ak105SpawnPoint::new_fully_kitted_default({
|
commands.spawn(Ak105SpawnPoint::new_fully_kitted_default({
|
||||||
let mut transform = Transform::from_xyz(18.0, 10.0, 18.0);
|
let mut transform = Transform::from_xyz(18.0, 10.0, 18.0);
|
||||||
|
@ -7,8 +7,7 @@ pub enum GltfAssetType {
|
|||||||
Firearm(Firearm),
|
Firearm(Firearm),
|
||||||
Attachment(WeaponAttachment),
|
Attachment(WeaponAttachment),
|
||||||
Character,
|
Character,
|
||||||
#[allow(unused)]
|
OtherPlayer,
|
||||||
Enemy,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Resource, Reflect, Default)]
|
#[derive(Resource, Reflect, Default)]
|
||||||
@ -87,11 +86,16 @@ pub fn load_all_assets(
|
|||||||
asset_type: GltfAssetType::Character,
|
asset_type: GltfAssetType::Character,
|
||||||
asset: asset_server.load("character/main_character.glb"),
|
asset: asset_server.load("character/main_character.glb"),
|
||||||
};
|
};
|
||||||
|
let other_player_character_asset = GltfAsset {
|
||||||
|
asset_type: GltfAssetType::OtherPlayer,
|
||||||
|
asset: asset_server.load("character/other_player_character.glb"),
|
||||||
|
};
|
||||||
|
|
||||||
commands.insert_resource(GltfAssets {
|
commands.insert_resource(GltfAssets {
|
||||||
assets: Vec::from([/*m4a1_gltf_asset, */
|
assets: Vec::from([/*m4a1_gltf_asset, */
|
||||||
ak105_gltf_asset, glock17_gltf_asset, // Firearms
|
ak105_gltf_asset, glock17_gltf_asset, // Firearms
|
||||||
main_character_asset, // Characters
|
main_character_asset, // Characters
|
||||||
|
other_player_character_asset, // Enemies
|
||||||
aimpoint_t1_gltf_asset, pk5_foregrip_gltf_asset, ak105_magazine_gltf_asset, first_compensator_gltf_asset, tan_magpull_stock_gltf_asset // Attachments
|
aimpoint_t1_gltf_asset, pk5_foregrip_gltf_asset, ak105_magazine_gltf_asset, first_compensator_gltf_asset, tan_magpull_stock_gltf_asset // Attachments
|
||||||
]),
|
]),
|
||||||
});
|
});
|
||||||
|
@ -43,38 +43,40 @@ 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() {
|
||||||
let Ok((mut player, player_firing_info)) = player_query.get_single_mut() else {
|
let Ok((mut player, mut player_firing_info)) = player_query.get_single_mut() else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
//if player_firing_info.is_reloading { return; }
|
//if player_firing_info.is_reloading { return; }
|
||||||
// Primary firearm change
|
// Primary firearm change
|
||||||
let player_hands = player_hands_query.single_mut();
|
for player_hands in player_hands_query.iter_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, firearm_state) = equipment_change_event.0.clone() {
|
if let Equipment::Firearm(new_firearm, firearm_state) = equipment_change_event.0.clone() {
|
||||||
// Add sensor to firearm collider if it is a child of player_hands
|
// Add sensor to firearm collider if it is a child of player_hands
|
||||||
spawn_firearm_on_player_hands(
|
spawn_firearm_on_player_hands(
|
||||||
&mut commands,
|
&mut commands,
|
||||||
player_firing_info,
|
&mut player_firing_info,
|
||||||
player_hands,
|
player_hands,
|
||||||
&assets_gltf,
|
&assets_gltf,
|
||||||
&loaded_gltf_assets,
|
&loaded_gltf_assets,
|
||||||
new_firearm,
|
new_firearm,
|
||||||
firearm_state,
|
firearm_state,
|
||||||
equipment_change_event.1.clone().expect("Spawning firearm on player hands without an ItemId"),
|
equipment_change_event.1.clone().expect("Spawning firearm on player hands without an ItemId"),
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn spawn_firearm_on_player_hands(
|
fn spawn_firearm_on_player_hands(
|
||||||
commands: &mut Commands,
|
commands: &mut Commands,
|
||||||
mut player_firing_info: Mut<PlayerFiringInfo>,
|
player_firing_info: &mut PlayerFiringInfo,
|
||||||
player_hands: Entity,
|
player_hands: Entity,
|
||||||
assets_gltf: &GltfAssets,
|
assets_gltf: &GltfAssets,
|
||||||
loaded_gltf_assets: &Assets<Gltf>,
|
loaded_gltf_assets: &Assets<Gltf>,
|
||||||
|
@ -74,12 +74,10 @@ pub fn update_inspect_screen(
|
|||||||
for player_firing_info in player_firing_info_query.iter() {
|
for player_firing_info in player_firing_info_query.iter() {
|
||||||
if player_firing_info.is_inspecting {
|
if player_firing_info.is_inspecting {
|
||||||
*inspect_screen_visibility = Visibility::Visible;
|
*inspect_screen_visibility = Visibility::Visible;
|
||||||
// TODO: Build
|
|
||||||
for (camera, camera_transform) in camera_query.iter() {
|
for (camera, camera_transform) in camera_query.iter() {
|
||||||
for (mut inspect_slot_visibility, mut inspect_slot, mut inspect_slot_style, mut inspect_slot_border_color) in inspect_slots_query.iter_mut() {
|
for (mut inspect_slot_visibility, mut inspect_slot, mut inspect_slot_style, mut inspect_slot_border_color) in inspect_slots_query.iter_mut() {
|
||||||
for (slot, slot_transform) in slots_query.iter() {
|
for (slot, slot_transform) in slots_query.iter() {
|
||||||
if &inspect_slot.slot == slot {
|
if &inspect_slot.slot == slot {
|
||||||
//inspect_slot_text.sections.first_mut().expect("No section in an already created text...").value = format!("{}", slot.get_index());
|
|
||||||
match camera.world_to_viewport(camera_transform, slot_transform.translation()) {
|
match camera.world_to_viewport(camera_transform, slot_transform.translation()) {
|
||||||
Some(pos_vec) => {
|
Some(pos_vec) => {
|
||||||
*inspect_slot_visibility = Visibility::Visible;
|
*inspect_slot_visibility = Visibility::Visible;
|
||||||
|
Loading…
Reference in New Issue
Block a user