use bevy hierarchy system
This commit is contained in:
parent
35413b563c
commit
cfe2631578
15 changed files with 246 additions and 643 deletions
|
|
@ -1,6 +1,6 @@
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
|
||||||
use bevy_ecs::{entity::Entity, world::World};
|
use bevy_ecs::{prelude::*, relationship::RelatedSpawner};
|
||||||
use strum::Display;
|
use strum::Display;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
|
@ -186,8 +186,8 @@ impl ArmourDto {
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn spawn(self, world: &mut World) -> Entity {
|
pub fn spawn(self, spawner: &mut RelatedSpawner<'_, ChildOf>) -> Entity {
|
||||||
let mut commands = world.spawn(draw_id());
|
let mut commands = spawner.spawn(draw_id());
|
||||||
|
|
||||||
commands.insert((
|
commands.insert((
|
||||||
Name(self.name.to_string()),
|
Name(self.name.to_string()),
|
||||||
|
|
|
||||||
|
|
@ -52,19 +52,6 @@ pub struct PlayerDto {
|
||||||
|
|
||||||
impl PlayerDto {
|
impl PlayerDto {
|
||||||
pub fn spawn(self, world: &mut World) -> EntityWorldMut<'_> {
|
pub fn spawn(self, world: &mut World) -> EntityWorldMut<'_> {
|
||||||
let primary = self.weapons.primary.map(|p| p.spawn(world));
|
|
||||||
let secondary = self.weapons.secondary.map(|s| s.spawn(world));
|
|
||||||
let melee = self.weapons.melee.map(|m| m.spawn(world));
|
|
||||||
let temporary = self.weapons.temporary.map(|m| m.spawn(world));
|
|
||||||
let fists = WeaponDto::FISTS.spawn(world);
|
|
||||||
let kick = WeaponDto::KITCHEN_KNIFE.spawn(world);
|
|
||||||
|
|
||||||
let head = self.armour.helmet.map(|a| a.spawn(world));
|
|
||||||
let torso = self.armour.body.map(|a| a.spawn(world));
|
|
||||||
let legs = self.armour.pants.map(|a| a.spawn(world));
|
|
||||||
let hands = self.armour.gloves.map(|a| a.spawn(world));
|
|
||||||
let feet = self.armour.boots.map(|a| a.spawn(world));
|
|
||||||
|
|
||||||
let mut commands = world.spawn(draw_id());
|
let mut commands = world.spawn(draw_id());
|
||||||
|
|
||||||
commands.insert((
|
commands.insert((
|
||||||
|
|
@ -85,7 +72,16 @@ impl PlayerDto {
|
||||||
faction,
|
faction,
|
||||||
});
|
});
|
||||||
|
|
||||||
commands.insert(Weapons {
|
let mut weapons = None;
|
||||||
|
commands.with_children(|spawner| {
|
||||||
|
let primary = self.weapons.primary.map(|p| p.spawn(spawner));
|
||||||
|
let secondary = self.weapons.secondary.map(|s| s.spawn(spawner));
|
||||||
|
let melee = self.weapons.melee.map(|m| m.spawn(spawner));
|
||||||
|
let temporary = self.weapons.temporary.map(|m| m.spawn(spawner));
|
||||||
|
let fists = WeaponDto::FISTS.spawn(spawner);
|
||||||
|
let kick = WeaponDto::KICK.spawn(spawner);
|
||||||
|
|
||||||
|
weapons = Some(Weapons {
|
||||||
primary,
|
primary,
|
||||||
secondary,
|
secondary,
|
||||||
melee,
|
melee,
|
||||||
|
|
@ -93,15 +89,32 @@ impl PlayerDto {
|
||||||
kick,
|
kick,
|
||||||
fists,
|
fists,
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
if let Some(weapons) = weapons {
|
||||||
|
commands.insert(weapons);
|
||||||
|
}
|
||||||
|
|
||||||
commands.insert(PlayerArmour {
|
let mut armour = None;
|
||||||
|
commands.with_children(|spawner| {
|
||||||
|
let head = self.armour.helmet.map(|a| a.spawn(spawner));
|
||||||
|
let torso = self.armour.body.map(|a| a.spawn(spawner));
|
||||||
|
let legs = self.armour.pants.map(|a| a.spawn(spawner));
|
||||||
|
let hands = self.armour.gloves.map(|a| a.spawn(spawner));
|
||||||
|
let feet = self.armour.boots.map(|a| a.spawn(spawner));
|
||||||
|
|
||||||
|
armour = Some(PlayerArmour {
|
||||||
torso,
|
torso,
|
||||||
head,
|
head,
|
||||||
legs,
|
legs,
|
||||||
feet,
|
feet,
|
||||||
hands,
|
hands,
|
||||||
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if let Some(armour) = armour {
|
||||||
|
commands.insert(armour);
|
||||||
|
}
|
||||||
|
|
||||||
commands
|
commands
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
|
||||||
use bevy_ecs::prelude::*;
|
use bevy_ecs::{prelude::*, relationship::RelatedSpawner};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
bundle::{
|
bundle::{
|
||||||
|
|
@ -252,8 +252,8 @@ impl WeaponDto {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn spawn(self, world: &mut World) -> Entity {
|
pub fn spawn(self, spawner: &mut RelatedSpawner<'_, ChildOf>) -> Entity {
|
||||||
let mut commands = world.spawn(draw_id());
|
let mut commands = spawner.spawn(draw_id());
|
||||||
|
|
||||||
let verb = match self.kind {
|
let verb = match self.kind {
|
||||||
WeaponSlot::Primary | WeaponSlot::Secondary => WeaponVerb::Fired,
|
WeaponSlot::Primary | WeaponSlot::Secondary => WeaponVerb::Fired,
|
||||||
|
|
|
||||||
|
|
@ -1,178 +0,0 @@
|
||||||
use bevy_ecs::{
|
|
||||||
prelude::*,
|
|
||||||
system::{Command, EntityCommands},
|
|
||||||
};
|
|
||||||
|
|
||||||
#[derive(Component, Debug, Clone, Copy)]
|
|
||||||
pub struct Parent(Entity);
|
|
||||||
|
|
||||||
impl Parent {
|
|
||||||
pub fn get(&self) -> Entity {
|
|
||||||
self.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Component, Debug, Clone, Default)]
|
|
||||||
pub struct Children(Vec<Entity>);
|
|
||||||
|
|
||||||
impl Children {
|
|
||||||
pub fn get(&self) -> &[Entity] {
|
|
||||||
&self.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct AddChild {
|
|
||||||
parent: Entity,
|
|
||||||
child: Entity,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Command for AddChild {
|
|
||||||
fn apply(self, world: &mut World) {
|
|
||||||
let mut parent = world.entity_mut(self.parent);
|
|
||||||
if let Some(mut children) = parent.get_mut::<Children>() {
|
|
||||||
children.0.push(self.child);
|
|
||||||
} else {
|
|
||||||
parent.insert(Children(vec![self.child]));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct AddChildren {
|
|
||||||
parent: Entity,
|
|
||||||
children: Vec<Entity>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Command for AddChildren {
|
|
||||||
fn apply(mut self, world: &mut World) {
|
|
||||||
let mut parent = world.entity_mut(self.parent);
|
|
||||||
if let Some(mut children) = parent.get_mut::<Children>() {
|
|
||||||
children.0.append(&mut self.children);
|
|
||||||
} else {
|
|
||||||
parent.insert(Children(self.children));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct RemoveChild {
|
|
||||||
parent: Entity,
|
|
||||||
child: Entity,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Command for RemoveChild {
|
|
||||||
fn apply(self, world: &mut World) {
|
|
||||||
let mut parent = world.entity_mut(self.parent);
|
|
||||||
let mut children = parent
|
|
||||||
.get_mut::<Children>()
|
|
||||||
.expect("Parent component has no children");
|
|
||||||
children.0.retain(|child| *child != self.child);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait HierarchyBuilder {
|
|
||||||
fn add_child(&mut self, child: Entity) -> &mut Self;
|
|
||||||
|
|
||||||
fn add_children(&mut self, children: impl AsRef<[Entity]>) -> &mut Self;
|
|
||||||
|
|
||||||
fn remove_child(&mut self, child: Entity) -> &mut Self;
|
|
||||||
|
|
||||||
fn set_parent(&mut self, parent: Entity) -> &mut Self;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> HierarchyBuilder for EntityCommands<'a> {
|
|
||||||
fn add_child(&mut self, child: Entity) -> &mut Self {
|
|
||||||
let parent = self.id();
|
|
||||||
self.commands().queue(AddChild { parent, child });
|
|
||||||
self.commands().entity(child).insert(Parent(parent));
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
fn add_children(&mut self, children: impl AsRef<[Entity]>) -> &mut Self {
|
|
||||||
let children = children.as_ref();
|
|
||||||
let parent = self.id();
|
|
||||||
self.commands().queue(AddChildren {
|
|
||||||
parent,
|
|
||||||
children: children.to_owned(),
|
|
||||||
});
|
|
||||||
self.commands().insert_batch(
|
|
||||||
children
|
|
||||||
.iter()
|
|
||||||
.map(|e| (*e, Parent(parent)))
|
|
||||||
.collect::<Vec<_>>(),
|
|
||||||
);
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
fn remove_child(&mut self, child: Entity) -> &mut Self {
|
|
||||||
let parent = self.id();
|
|
||||||
self.commands().queue(RemoveChild { parent, child });
|
|
||||||
self.commands().entity(child).remove::<Parent>();
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
fn set_parent(&mut self, parent: Entity) -> &mut Self {
|
|
||||||
let child = self.id();
|
|
||||||
self.commands().queue(AddChild { parent, child });
|
|
||||||
self.commands().entity(child).insert(Parent(parent));
|
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'w> HierarchyBuilder for EntityWorldMut<'w> {
|
|
||||||
fn add_child(&mut self, child: Entity) -> &mut Self {
|
|
||||||
let parent_id = self.id();
|
|
||||||
unsafe {
|
|
||||||
self.world_mut()
|
|
||||||
.entity_mut(child)
|
|
||||||
.insert(Parent(parent_id))
|
|
||||||
.update_location();
|
|
||||||
}
|
|
||||||
if let Some(mut children) = self.get_mut::<Children>() {
|
|
||||||
children.0.push(child);
|
|
||||||
self
|
|
||||||
} else {
|
|
||||||
self.insert(Children(vec![child]))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn add_children(&mut self, children: impl AsRef<[Entity]>) -> &mut Self {
|
|
||||||
let parent_id = self.id();
|
|
||||||
unsafe {
|
|
||||||
for child in children.as_ref() {
|
|
||||||
self.world_mut()
|
|
||||||
.entity_mut(*child)
|
|
||||||
.insert(Parent(parent_id))
|
|
||||||
.update_location();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if let Some(mut old_children) = self.get_mut::<Children>() {
|
|
||||||
old_children.0.append(&mut children.as_ref().to_owned());
|
|
||||||
self
|
|
||||||
} else {
|
|
||||||
self.insert(Children(children.as_ref().to_owned()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn remove_child(&mut self, child: Entity) -> &mut Self {
|
|
||||||
unsafe {
|
|
||||||
self.world_mut()
|
|
||||||
.entity_mut(child)
|
|
||||||
.remove::<Parent>()
|
|
||||||
.update_location();
|
|
||||||
}
|
|
||||||
if let Some(mut children) = self.get_mut::<Children>() {
|
|
||||||
children.0.retain(|c| *c != child);
|
|
||||||
}
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
fn set_parent(&mut self, parent: Entity) -> &mut Self {
|
|
||||||
let child_id = self.id();
|
|
||||||
unsafe {
|
|
||||||
self.world_mut()
|
|
||||||
.entity_mut(parent)
|
|
||||||
.add_child(child_id)
|
|
||||||
.update_location()
|
|
||||||
}
|
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,3 +1,2 @@
|
||||||
pub mod bundle;
|
pub mod bundle;
|
||||||
pub mod dto;
|
pub mod dto;
|
||||||
// pub mod hierarchy;
|
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,15 @@
|
||||||
use bevy_ecs::prelude::*;
|
use bevy_ecs::prelude::*;
|
||||||
use proxisim_models::{
|
use proxisim_models::bundle::armour::{
|
||||||
bundle::armour::{
|
ArmourBodyPart, ArmourBodyPartSlot, ArmourBodyParts, ArmourCoverage, ArmourValue, ArmourVec,
|
||||||
ArmourBodyPart, ArmourBodyPartSlot, ArmourBodyParts, ArmourCoverage, ArmourValue,
|
BodyPartCoverage, Immunities, Immunity, PlayerArmour,
|
||||||
ArmourVec, BodyPartCoverage, Immunities, Immunity, PlayerArmour,
|
|
||||||
},
|
|
||||||
hierarchy::HierarchyBuilder,
|
|
||||||
};
|
};
|
||||||
use strum::IntoEnumIterator;
|
use strum::IntoEnumIterator;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
Stages,
|
||||||
player::status_effect::{
|
player::status_effect::{
|
||||||
ConcussionGrenade, FlashGrenade, PepperSpray, TearGas, TempDebuffImmunity,
|
ConcussionGrenade, FlashGrenade, PepperSpray, TearGas, TempDebuffImmunity,
|
||||||
},
|
},
|
||||||
Stages,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
fn generate_body_parts(
|
fn generate_body_parts(
|
||||||
|
|
@ -24,7 +21,7 @@ fn generate_body_parts(
|
||||||
let mut parts = ArmourVec::<ArmourBodyPart>::default();
|
let mut parts = ArmourVec::<ArmourBodyPart>::default();
|
||||||
|
|
||||||
for (armour, coverage, armour_value, immunities) in armour_q.iter_many(equipped_armour) {
|
for (armour, coverage, armour_value, immunities) in armour_q.iter_many(equipped_armour) {
|
||||||
commands.entity(armour).set_parent(player);
|
// commands.entity(player).add_child(armour);
|
||||||
|
|
||||||
if let Some(immunities) = immunities {
|
if let Some(immunities) = immunities {
|
||||||
let mut player = commands.entity(player);
|
let mut player = commands.entity(player);
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,7 @@
|
||||||
use std::{any::TypeId, collections::HashMap, sync::Mutex};
|
use std::{any::TypeId, collections::HashMap, sync::Mutex};
|
||||||
|
|
||||||
use bevy_ecs::{prelude::*, system::SystemParam};
|
use bevy_ecs::{prelude::*, system::SystemParam};
|
||||||
use proxisim_models::{
|
use proxisim_models::bundle::player::{Current, Defender, Player};
|
||||||
bundle::player::{Current, Defender, Player},
|
|
||||||
hierarchy::{HierarchyBuilder, Parent},
|
|
||||||
};
|
|
||||||
|
|
||||||
use crate::Stages;
|
use crate::Stages;
|
||||||
|
|
||||||
|
|
@ -77,13 +74,9 @@ impl<'w, 's> Effects<'w, 's> {
|
||||||
) -> Entity {
|
) -> Entity {
|
||||||
let id = self.registry.type_map.get(&TypeId::of::<T>()).unwrap();
|
let id = self.registry.type_map.get(&TypeId::of::<T>()).unwrap();
|
||||||
|
|
||||||
let spawned_effect = self
|
let spawned_effect = self.commands.spawn(effect).insert(*id).insert(addins).id();
|
||||||
.commands
|
|
||||||
.spawn(effect)
|
self.commands.entity(to).add_child(spawned_effect);
|
||||||
.insert(*id)
|
|
||||||
.insert(addins)
|
|
||||||
.set_parent(to)
|
|
||||||
.id();
|
|
||||||
|
|
||||||
self.scheduled
|
self.scheduled
|
||||||
.create
|
.create
|
||||||
|
|
@ -202,7 +195,7 @@ pub(crate) fn run_effects(world: &mut World) {
|
||||||
};
|
};
|
||||||
|
|
||||||
for entity in entities {
|
for entity in entities {
|
||||||
let parent = world.entity(entity).get::<Parent>().unwrap().get();
|
let parent = world.entity(entity).get::<ChildOf>().unwrap().parent();
|
||||||
world.entity_mut(parent).remove_child(entity);
|
world.entity_mut(parent).remove_child(entity);
|
||||||
world.despawn(entity);
|
world.despawn(entity);
|
||||||
}
|
}
|
||||||
|
|
@ -277,12 +270,12 @@ fn mark_permanent_effects(effect_q: Query<Entity, With<EffectId>>, mut commands:
|
||||||
}
|
}
|
||||||
|
|
||||||
fn remove_transient_effects(
|
fn remove_transient_effects(
|
||||||
effect_q: Query<(Entity, &Parent), (With<EffectId>, Without<Permanent>)>,
|
effect_q: Query<(Entity, &ChildOf), (With<EffectId>, Without<Permanent>)>,
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
) {
|
) {
|
||||||
for (effect, target) in effect_q.iter() {
|
for (effect, target) in effect_q.iter() {
|
||||||
commands.entity(effect).despawn();
|
commands.entity(effect).despawn();
|
||||||
commands.entity(target.get()).remove_child(effect);
|
commands.entity(target.parent()).remove_child(effect);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,12 +3,11 @@ use std::collections::HashMap;
|
||||||
use bevy_ecs::prelude::*;
|
use bevy_ecs::prelude::*;
|
||||||
use proxisim_models::{
|
use proxisim_models::{
|
||||||
bundle::{
|
bundle::{
|
||||||
|
Id, Name,
|
||||||
player::{Attacker, Player},
|
player::{Attacker, Player},
|
||||||
weapon::Weapon,
|
weapon::Weapon,
|
||||||
Id, Name,
|
|
||||||
},
|
},
|
||||||
dto::metrics::EntityInfo,
|
dto::metrics::EntityInfo,
|
||||||
hierarchy::Parent,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::Stages;
|
use crate::Stages;
|
||||||
|
|
@ -18,7 +17,7 @@ pub struct EntityRegistry(pub HashMap<Entity, EntityInfo>);
|
||||||
|
|
||||||
fn read_entities(
|
fn read_entities(
|
||||||
player_q: Query<(Entity, &Name, &Id, Has<Attacker>), With<Player>>,
|
player_q: Query<(Entity, &Name, &Id, Has<Attacker>), With<Player>>,
|
||||||
weapon_q: Query<(Entity, &Parent, &Name, &Id), With<Weapon>>,
|
weapon_q: Query<(Entity, &ChildOf, &Name, &Id), With<Weapon>>,
|
||||||
mut registry: ResMut<EntityRegistry>,
|
mut registry: ResMut<EntityRegistry>,
|
||||||
) {
|
) {
|
||||||
for (player, name, id, is_attacker) in player_q.iter() {
|
for (player, name, id, is_attacker) in player_q.iter() {
|
||||||
|
|
@ -33,7 +32,7 @@ fn read_entities(
|
||||||
}
|
}
|
||||||
|
|
||||||
for (weapon, player, name, id) in weapon_q.iter() {
|
for (weapon, player, name, id) in weapon_q.iter() {
|
||||||
let (_, _, player_id, _) = player_q.get(player.get()).unwrap();
|
let (_, _, player_id, _) = player_q.get(player.parent()).unwrap();
|
||||||
registry.0.insert(
|
registry.0.insert(
|
||||||
weapon,
|
weapon,
|
||||||
EntityInfo::Weapon {
|
EntityInfo::Weapon {
|
||||||
|
|
|
||||||
178
src/hierarchy.rs
178
src/hierarchy.rs
|
|
@ -1,178 +0,0 @@
|
||||||
use bevy_ecs::{
|
|
||||||
prelude::*,
|
|
||||||
system::{Command, EntityCommands},
|
|
||||||
};
|
|
||||||
|
|
||||||
#[derive(Component, Clone, Copy)]
|
|
||||||
pub struct Parent(Entity);
|
|
||||||
|
|
||||||
impl Parent {
|
|
||||||
pub fn get(&self) -> Entity {
|
|
||||||
self.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Component, Clone, Default)]
|
|
||||||
pub struct Children(Vec<Entity>);
|
|
||||||
|
|
||||||
impl Children {
|
|
||||||
pub fn get(&self) -> &[Entity] {
|
|
||||||
&self.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct AddChild {
|
|
||||||
parent: Entity,
|
|
||||||
child: Entity,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Command for AddChild {
|
|
||||||
fn apply(self, world: &mut World) {
|
|
||||||
let mut parent = world.entity_mut(self.parent);
|
|
||||||
if let Some(mut children) = parent.get_mut::<Children>() {
|
|
||||||
children.0.push(self.child);
|
|
||||||
} else {
|
|
||||||
parent.insert(Children(vec![self.child]));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct AddChildren {
|
|
||||||
parent: Entity,
|
|
||||||
children: Vec<Entity>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Command for AddChildren {
|
|
||||||
fn apply(mut self, world: &mut World) {
|
|
||||||
let mut parent = world.entity_mut(self.parent);
|
|
||||||
if let Some(mut children) = parent.get_mut::<Children>() {
|
|
||||||
children.0.append(&mut self.children);
|
|
||||||
} else {
|
|
||||||
parent.insert(Children(self.children));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct RemoveChild {
|
|
||||||
parent: Entity,
|
|
||||||
child: Entity,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Command for RemoveChild {
|
|
||||||
fn apply(self, world: &mut World) {
|
|
||||||
let mut parent = world.entity_mut(self.parent);
|
|
||||||
let mut children = parent
|
|
||||||
.get_mut::<Children>()
|
|
||||||
.expect("Parent component has no children");
|
|
||||||
children.0.retain(|child| *child != self.child);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait HierarchyBuilder {
|
|
||||||
fn add_child(&mut self, child: Entity) -> &mut Self;
|
|
||||||
|
|
||||||
fn add_children(&mut self, children: impl AsRef<[Entity]>) -> &mut Self;
|
|
||||||
|
|
||||||
fn remove_child(&mut self, child: Entity) -> &mut Self;
|
|
||||||
|
|
||||||
fn set_parent(&mut self, parent: Entity) -> &mut Self;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> HierarchyBuilder for EntityCommands<'a> {
|
|
||||||
fn add_child(&mut self, child: Entity) -> &mut Self {
|
|
||||||
let parent = self.id();
|
|
||||||
self.commands().queue(AddChild { parent, child });
|
|
||||||
self.commands().entity(child).insert(Parent(parent));
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
fn add_children(&mut self, children: impl AsRef<[Entity]>) -> &mut Self {
|
|
||||||
let children = children.as_ref();
|
|
||||||
let parent = self.id();
|
|
||||||
self.commands().queue(AddChildren {
|
|
||||||
parent,
|
|
||||||
children: children.to_owned(),
|
|
||||||
});
|
|
||||||
self.commands().insert_batch(
|
|
||||||
children
|
|
||||||
.iter()
|
|
||||||
.map(|e| (*e, Parent(parent)))
|
|
||||||
.collect::<Vec<_>>(),
|
|
||||||
);
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
fn remove_child(&mut self, child: Entity) -> &mut Self {
|
|
||||||
let parent = self.id();
|
|
||||||
self.commands().queue(RemoveChild { parent, child });
|
|
||||||
self.commands().entity(child).remove::<Parent>();
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
fn set_parent(&mut self, parent: Entity) -> &mut Self {
|
|
||||||
let child = self.id();
|
|
||||||
self.commands().queue(AddChild { parent, child });
|
|
||||||
self.commands().entity(child).insert(Parent(parent));
|
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'w> HierarchyBuilder for EntityWorldMut<'w> {
|
|
||||||
fn add_child(&mut self, child: Entity) -> &mut Self {
|
|
||||||
let parent_id = self.id();
|
|
||||||
unsafe {
|
|
||||||
self.world_mut()
|
|
||||||
.entity_mut(child)
|
|
||||||
.insert(Parent(parent_id))
|
|
||||||
.update_location();
|
|
||||||
}
|
|
||||||
if let Some(mut children) = self.get_mut::<Children>() {
|
|
||||||
children.0.push(child);
|
|
||||||
self
|
|
||||||
} else {
|
|
||||||
self.insert(Children(vec![child]))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn add_children(&mut self, children: impl AsRef<[Entity]>) -> &mut Self {
|
|
||||||
let parent_id = self.id();
|
|
||||||
unsafe {
|
|
||||||
for child in children.as_ref() {
|
|
||||||
self.world_mut()
|
|
||||||
.entity_mut(*child)
|
|
||||||
.insert(Parent(parent_id))
|
|
||||||
.update_location();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if let Some(mut old_children) = self.get_mut::<Children>() {
|
|
||||||
old_children.0.append(&mut children.as_ref().to_owned());
|
|
||||||
self
|
|
||||||
} else {
|
|
||||||
self.insert(Children(children.as_ref().to_owned()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn remove_child(&mut self, child: Entity) -> &mut Self {
|
|
||||||
unsafe {
|
|
||||||
self.world_mut()
|
|
||||||
.entity_mut(child)
|
|
||||||
.remove::<Parent>()
|
|
||||||
.update_location();
|
|
||||||
}
|
|
||||||
if let Some(mut children) = self.get_mut::<Children>() {
|
|
||||||
children.0.retain(|c| *c != child);
|
|
||||||
}
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
fn set_parent(&mut self, parent: Entity) -> &mut Self {
|
|
||||||
let child_id = self.id();
|
|
||||||
unsafe {
|
|
||||||
self.world_mut()
|
|
||||||
.entity_mut(parent)
|
|
||||||
.add_child(child_id)
|
|
||||||
.update_location()
|
|
||||||
}
|
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
15
src/log.rs
15
src/log.rs
|
|
@ -1,16 +1,13 @@
|
||||||
use std::sync::Mutex;
|
use std::sync::Mutex;
|
||||||
|
|
||||||
use bevy_ecs::{prelude::*, query::QuerySingleError, system::SystemParam};
|
use bevy_ecs::{prelude::*, query::QuerySingleError, system::SystemParam};
|
||||||
use proxisim_models::{
|
use proxisim_models::bundle::{
|
||||||
bundle::{
|
|
||||||
stat::{
|
stat::{
|
||||||
AdditiveBonus, BaselineStat, ClipSize, Clips, CritRate, DamageBonus, Defence,
|
AdditiveBonus, BaselineStat, ClipSize, Clips, CritRate, DamageBonus, Defence, Dexterity,
|
||||||
Dexterity, EffectiveStat, MultiplicativeBonus, SimpleStatBaseline, SimpleStatBonus,
|
EffectiveStat, MultiplicativeBonus, SimpleStatBaseline, SimpleStatBonus,
|
||||||
SimpleStatEffective, SimpleStatMarker, Speed, StatMarker, Strength, WeaponAccuracy,
|
SimpleStatEffective, SimpleStatMarker, Speed, StatMarker, Strength, WeaponAccuracy,
|
||||||
},
|
},
|
||||||
weapon::WeaponVerb,
|
weapon::WeaponVerb,
|
||||||
},
|
|
||||||
hierarchy::Children,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{Stages, entity_registry::EntityRegistry};
|
use crate::{Stages, entity_registry::EntityRegistry};
|
||||||
|
|
@ -533,11 +530,11 @@ fn log_stat_changes<Stat: StatMarker>(
|
||||||
) {
|
) {
|
||||||
for (player, baseline, effective, children) in stat_q.iter() {
|
for (player, baseline, effective, children) in stat_q.iter() {
|
||||||
let effects_add: Vec<_> = add_q
|
let effects_add: Vec<_> = add_q
|
||||||
.iter_many(children.get())
|
.iter_many(children)
|
||||||
.map(|bonus| (bonus.label, 100.0 * bonus.value))
|
.map(|bonus| (bonus.label, 100.0 * bonus.value))
|
||||||
.collect();
|
.collect();
|
||||||
let effects_mult: Vec<_> = mult_q
|
let effects_mult: Vec<_> = mult_q
|
||||||
.iter_many(children.get())
|
.iter_many(children)
|
||||||
.map(|bonus| (bonus.label, 100.0 * bonus.value))
|
.map(|bonus| (bonus.label, 100.0 * bonus.value))
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
|
|
@ -570,7 +567,7 @@ fn log_simple_stat_changes<Stat: SimpleStatMarker>(
|
||||||
{
|
{
|
||||||
for (target, baseline, effective, children) in stat_q.iter() {
|
for (target, baseline, effective, children) in stat_q.iter() {
|
||||||
let bonuses: Vec<_> = bonus_q
|
let bonuses: Vec<_> = bonus_q
|
||||||
.iter_many(children.get())
|
.iter_many(children)
|
||||||
.map(|bonus| (bonus.label, Stat::denormalise_bonus(bonus.value)))
|
.map(|bonus| (bonus.label, Stat::denormalise_bonus(bonus.value)))
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,23 +1,18 @@
|
||||||
use bevy_ecs::prelude::*;
|
use bevy_ecs::prelude::*;
|
||||||
use proxisim_models::{
|
use proxisim_models::bundle::{
|
||||||
bundle::{
|
|
||||||
armour::{ArmourBodyPart, ArmourBodyParts},
|
armour::{ArmourBodyPart, ArmourBodyParts},
|
||||||
passive::{FactionUpgrades, Merits},
|
passive::{FactionUpgrades, Merits},
|
||||||
player::{
|
player::{
|
||||||
Attacker, BodyPart, ChooseWeapon, CombatTurns, Current, CurrentTarget, Defeated,
|
Attacker, BodyPart, ChooseWeapon, CombatTurns, Current, CurrentTarget, Defeated, Defender,
|
||||||
Defender, FightEndType, Level, MaxHealth, PartDamageBonus, Player, PlayerStrategy,
|
FightEndType, Level, MaxHealth, PartDamageBonus, Player, PlayerStrategy, Weapons,
|
||||||
Weapons,
|
|
||||||
},
|
},
|
||||||
stat::{
|
stat::{
|
||||||
AmmoControl, Clips, CritRate, DamageBonus, Defence, Dexterity, EffectiveStat, Health,
|
AmmoControl, Clips, CritRate, DamageBonus, Defence, Dexterity, EffectiveStat, Health,
|
||||||
SimpleStatBundle, SimpleStatEffective, Speed, Strength, WeaponAccuracy,
|
SimpleStatBundle, SimpleStatEffective, Speed, Strength, WeaponAccuracy,
|
||||||
},
|
},
|
||||||
weapon::{
|
weapon::{
|
||||||
Ammo, DamageStat, NeedsReload, NonTargeted, RateOfFire, Usable, Uses, Weapon,
|
Ammo, DamageStat, NeedsReload, NonTargeted, RateOfFire, Usable, Uses, Weapon, WeaponSlot,
|
||||||
WeaponSlot,
|
|
||||||
},
|
},
|
||||||
},
|
|
||||||
hierarchy::Children,
|
|
||||||
};
|
};
|
||||||
use rand::Rng as _;
|
use rand::Rng as _;
|
||||||
|
|
||||||
|
|
@ -33,12 +28,12 @@ use crate::{
|
||||||
pub mod stats;
|
pub mod stats;
|
||||||
pub mod status_effect;
|
pub mod status_effect;
|
||||||
|
|
||||||
fn select_weapon(
|
fn select_weapon<'a>(
|
||||||
weapons: &Weapons,
|
weapons: &Weapons,
|
||||||
slot: WeaponSlot,
|
slot: WeaponSlot,
|
||||||
reload: bool,
|
reload: bool,
|
||||||
usable_q: &Query<(Has<NeedsReload>, Option<&Children>), With<Usable>>,
|
usable_q: &'a Query<(Has<NeedsReload>, Option<&Children>), With<Usable>>,
|
||||||
) -> Option<(Entity, Option<Children>)> {
|
) -> Option<(Entity, Option<&'a Children>)> {
|
||||||
let id = match slot {
|
let id = match slot {
|
||||||
WeaponSlot::Primary => weapons.primary?,
|
WeaponSlot::Primary => weapons.primary?,
|
||||||
WeaponSlot::Secondary => weapons.secondary?,
|
WeaponSlot::Secondary => weapons.secondary?,
|
||||||
|
|
@ -53,7 +48,7 @@ fn select_weapon(
|
||||||
if !reload && needs_reload {
|
if !reload && needs_reload {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
Some((id, children.cloned()))
|
Some((id, children))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -155,7 +150,7 @@ pub fn pick_action(
|
||||||
let target = target_q.single().unwrap();
|
let target = target_q.single().unwrap();
|
||||||
|
|
||||||
if let Some(children) = children {
|
if let Some(children) = children {
|
||||||
for effect in weapon_trigger_q.iter_many(children.get()) {
|
for effect in weapon_trigger_q.iter_many(children) {
|
||||||
effect.trigger(&mut effects, current, target);
|
effect.trigger(&mut effects, current, target);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -357,7 +352,7 @@ pub fn use_damaging_weapon(
|
||||||
|
|
||||||
let mut dmg_bonus = dmg_bonus + p_dmg_bonus;
|
let mut dmg_bonus = dmg_bonus + p_dmg_bonus;
|
||||||
|
|
||||||
for part_bonus in part_bonus_q.iter_many(children.get()) {
|
for part_bonus in part_bonus_q.iter_many(children) {
|
||||||
if let Some(bonus) = part_bonus.dmg_bonus(body_part) {
|
if let Some(bonus) = part_bonus.dmg_bonus(body_part) {
|
||||||
dmg_bonus.value += bonus;
|
dmg_bonus.value += bonus;
|
||||||
}
|
}
|
||||||
|
|
@ -378,7 +373,7 @@ pub fn use_damaging_weapon(
|
||||||
metrics.record_histogram(Some(weapon), "dmg", dmg);
|
metrics.record_histogram(Some(weapon), "dmg", dmg);
|
||||||
|
|
||||||
if dmg > 0 {
|
if dmg > 0 {
|
||||||
for effect in damage_proc_q.iter_many(children.get()) {
|
for effect in damage_proc_q.iter_many(children) {
|
||||||
match *effect {
|
match *effect {
|
||||||
DamageProcEffect::MultiTurn { value, bonus } => {
|
DamageProcEffect::MultiTurn { value, bonus } => {
|
||||||
if multi_attack_proc.is_some() {
|
if multi_attack_proc.is_some() {
|
||||||
|
|
|
||||||
|
|
@ -1,21 +1,18 @@
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
use bevy_ecs::prelude::*;
|
use bevy_ecs::prelude::*;
|
||||||
use proxisim_models::{
|
use proxisim_models::bundle::stat::{
|
||||||
bundle::stat::{
|
|
||||||
AdditiveBonus, AdditiveBonuses, AmmoControl, BaselineStat, ClipSize, Clips, CritRate,
|
AdditiveBonus, AdditiveBonuses, AmmoControl, BaselineStat, ClipSize, Clips, CritRate,
|
||||||
DamageBonus, Defence, Dexterity, EffectiveStat, Health, MultiplicativeBonus,
|
DamageBonus, Defence, Dexterity, EffectiveStat, Health, MultiplicativeBonus,
|
||||||
MultiplicativeBonuses, SimpleStatBonus, SimpleStatEffective, SimpleStatMarker,
|
MultiplicativeBonuses, SimpleStatBonus, SimpleStatEffective, SimpleStatMarker,
|
||||||
SimpleStatSnapshot, Speed, StatMarker, StatSnapshot, Strength, WeaponAccuracy,
|
SimpleStatSnapshot, Speed, StatMarker, StatSnapshot, Strength, WeaponAccuracy,
|
||||||
},
|
|
||||||
hierarchy::Parent,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::Stages;
|
use crate::Stages;
|
||||||
|
|
||||||
fn add_additive_bonus<Stat: StatMarker>(
|
fn add_additive_bonus<Stat: StatMarker>(
|
||||||
In(entities): In<Vec<Entity>>,
|
In(entities): In<Vec<Entity>>,
|
||||||
effect_q: Query<(&AdditiveBonus<Stat>, &Parent)>,
|
effect_q: Query<(&AdditiveBonus<Stat>, &ChildOf)>,
|
||||||
mut stat_q: Query<(
|
mut stat_q: Query<(
|
||||||
&BaselineStat<Stat>,
|
&BaselineStat<Stat>,
|
||||||
&mut AdditiveBonuses<Stat>,
|
&mut AdditiveBonuses<Stat>,
|
||||||
|
|
@ -24,7 +21,7 @@ fn add_additive_bonus<Stat: StatMarker>(
|
||||||
)>,
|
)>,
|
||||||
) {
|
) {
|
||||||
for (bonus, player) in effect_q.iter_many(entities) {
|
for (bonus, player) in effect_q.iter_many(entities) {
|
||||||
let (baseline, mut add, mult, mut eff) = stat_q.get_mut(player.get()).unwrap();
|
let (baseline, mut add, mult, mut eff) = stat_q.get_mut(player.parent()).unwrap();
|
||||||
add.factor += bonus.value;
|
add.factor += bonus.value;
|
||||||
eff.value = baseline.value * add.factor * mult.factor;
|
eff.value = baseline.value * add.factor * mult.factor;
|
||||||
}
|
}
|
||||||
|
|
@ -32,7 +29,7 @@ fn add_additive_bonus<Stat: StatMarker>(
|
||||||
|
|
||||||
fn revert_additive_bonus<Stat: StatMarker>(
|
fn revert_additive_bonus<Stat: StatMarker>(
|
||||||
In(entities): In<Vec<Entity>>,
|
In(entities): In<Vec<Entity>>,
|
||||||
effect_q: Query<(&AdditiveBonus<Stat>, &Parent)>,
|
effect_q: Query<(&AdditiveBonus<Stat>, &ChildOf)>,
|
||||||
mut stat_q: Query<(
|
mut stat_q: Query<(
|
||||||
&BaselineStat<Stat>,
|
&BaselineStat<Stat>,
|
||||||
&mut AdditiveBonuses<Stat>,
|
&mut AdditiveBonuses<Stat>,
|
||||||
|
|
@ -41,7 +38,7 @@ fn revert_additive_bonus<Stat: StatMarker>(
|
||||||
)>,
|
)>,
|
||||||
) {
|
) {
|
||||||
for (bonus, player) in effect_q.iter_many(entities) {
|
for (bonus, player) in effect_q.iter_many(entities) {
|
||||||
let (baseline, mut add, mult, mut eff) = stat_q.get_mut(player.get()).unwrap();
|
let (baseline, mut add, mult, mut eff) = stat_q.get_mut(player.parent()).unwrap();
|
||||||
add.factor -= bonus.value;
|
add.factor -= bonus.value;
|
||||||
eff.value = baseline.value * add.factor * mult.factor;
|
eff.value = baseline.value * add.factor * mult.factor;
|
||||||
}
|
}
|
||||||
|
|
@ -49,7 +46,7 @@ fn revert_additive_bonus<Stat: StatMarker>(
|
||||||
|
|
||||||
fn add_multiplicative_bonus<Stat: StatMarker>(
|
fn add_multiplicative_bonus<Stat: StatMarker>(
|
||||||
In(entities): In<Vec<Entity>>,
|
In(entities): In<Vec<Entity>>,
|
||||||
effect_q: Query<(&MultiplicativeBonus<Stat>, &Parent)>,
|
effect_q: Query<(&MultiplicativeBonus<Stat>, &ChildOf)>,
|
||||||
mut stat_q: Query<(
|
mut stat_q: Query<(
|
||||||
&BaselineStat<Stat>,
|
&BaselineStat<Stat>,
|
||||||
&AdditiveBonuses<Stat>,
|
&AdditiveBonuses<Stat>,
|
||||||
|
|
@ -58,7 +55,7 @@ fn add_multiplicative_bonus<Stat: StatMarker>(
|
||||||
)>,
|
)>,
|
||||||
) {
|
) {
|
||||||
for (bonus, player) in effect_q.iter_many(entities) {
|
for (bonus, player) in effect_q.iter_many(entities) {
|
||||||
let (baseline, add, mut mult, mut eff) = stat_q.get_mut(player.get()).unwrap();
|
let (baseline, add, mut mult, mut eff) = stat_q.get_mut(player.parent()).unwrap();
|
||||||
mult.factor *= bonus.value;
|
mult.factor *= bonus.value;
|
||||||
eff.value = baseline.value * add.factor * mult.factor;
|
eff.value = baseline.value * add.factor * mult.factor;
|
||||||
}
|
}
|
||||||
|
|
@ -66,7 +63,7 @@ fn add_multiplicative_bonus<Stat: StatMarker>(
|
||||||
|
|
||||||
fn revert_multiplicative_bonus<Stat: StatMarker>(
|
fn revert_multiplicative_bonus<Stat: StatMarker>(
|
||||||
In(entities): In<Vec<Entity>>,
|
In(entities): In<Vec<Entity>>,
|
||||||
effect_q: Query<(&MultiplicativeBonus<Stat>, &Parent)>,
|
effect_q: Query<(&MultiplicativeBonus<Stat>, &ChildOf)>,
|
||||||
mut stat_q: Query<(
|
mut stat_q: Query<(
|
||||||
&BaselineStat<Stat>,
|
&BaselineStat<Stat>,
|
||||||
&AdditiveBonuses<Stat>,
|
&AdditiveBonuses<Stat>,
|
||||||
|
|
@ -75,7 +72,7 @@ fn revert_multiplicative_bonus<Stat: StatMarker>(
|
||||||
)>,
|
)>,
|
||||||
) {
|
) {
|
||||||
for (bonus, player) in effect_q.iter_many(entities) {
|
for (bonus, player) in effect_q.iter_many(entities) {
|
||||||
let (baseline, add, mut mult, mut eff) = stat_q.get_mut(player.get()).unwrap();
|
let (baseline, add, mut mult, mut eff) = stat_q.get_mut(player.parent()).unwrap();
|
||||||
mult.factor /= bonus.value;
|
mult.factor /= bonus.value;
|
||||||
eff.value = baseline.value * add.factor * mult.factor;
|
eff.value = baseline.value * add.factor * mult.factor;
|
||||||
}
|
}
|
||||||
|
|
@ -117,22 +114,22 @@ fn restore_stats<Stat: StatMarker>(
|
||||||
|
|
||||||
fn apply_simple_stat_bonus<Stat: SimpleStatMarker>(
|
fn apply_simple_stat_bonus<Stat: SimpleStatMarker>(
|
||||||
In(entities): In<Vec<Entity>>,
|
In(entities): In<Vec<Entity>>,
|
||||||
effect_q: Query<(&SimpleStatBonus<Stat>, &Parent)>,
|
effect_q: Query<(&SimpleStatBonus<Stat>, &ChildOf)>,
|
||||||
mut stat_q: Query<&mut SimpleStatEffective<Stat>>,
|
mut stat_q: Query<&mut SimpleStatEffective<Stat>>,
|
||||||
) {
|
) {
|
||||||
for (bonus, target) in effect_q.iter_many(&entities) {
|
for (bonus, target) in effect_q.iter_many(&entities) {
|
||||||
let mut effective = stat_q.get_mut(target.get()).unwrap();
|
let mut effective = stat_q.get_mut(target.parent()).unwrap();
|
||||||
effective.value = Stat::apply_bonus(effective.value, bonus.value);
|
effective.value = Stat::apply_bonus(effective.value, bonus.value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn revert_simple_stat_bonus<Stat: SimpleStatMarker>(
|
fn revert_simple_stat_bonus<Stat: SimpleStatMarker>(
|
||||||
In(entities): In<Vec<Entity>>,
|
In(entities): In<Vec<Entity>>,
|
||||||
effect_q: Query<(&SimpleStatBonus<Stat>, &Parent)>,
|
effect_q: Query<(&SimpleStatBonus<Stat>, &ChildOf)>,
|
||||||
mut stat_q: Query<&mut SimpleStatEffective<Stat>>,
|
mut stat_q: Query<&mut SimpleStatEffective<Stat>>,
|
||||||
) {
|
) {
|
||||||
for (bonus, target) in effect_q.iter_many(entities) {
|
for (bonus, target) in effect_q.iter_many(entities) {
|
||||||
let mut effective = stat_q.get_mut(target.get()).unwrap();
|
let mut effective = stat_q.get_mut(target.parent()).unwrap();
|
||||||
effective.value = Stat::revert_bonus(effective.value, bonus.value);
|
effective.value = Stat::revert_bonus(effective.value, bonus.value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,8 @@
|
||||||
use std::{collections::VecDeque, marker::PhantomData};
|
use std::{collections::VecDeque, marker::PhantomData};
|
||||||
|
|
||||||
use bevy_ecs::prelude::*;
|
use bevy_ecs::prelude::*;
|
||||||
use proxisim_models::{
|
use proxisim_models::bundle::stat::{
|
||||||
bundle::stat::{
|
|
||||||
AdditiveBonus, Defence, Dexterity, MultiplicativeBonus, Speed, StatMarker, Strength,
|
AdditiveBonus, Defence, Dexterity, MultiplicativeBonus, Speed, StatMarker, Strength,
|
||||||
},
|
|
||||||
hierarchy::Parent,
|
|
||||||
};
|
};
|
||||||
use rand::Rng as _;
|
use rand::Rng as _;
|
||||||
|
|
||||||
|
|
@ -345,7 +342,7 @@ impl AdditiveStatusEffectMarker<2> for Frozen {
|
||||||
|
|
||||||
fn apply_additive_status_effect<const N: usize, M: AdditiveStatusEffectMarker<N>>(
|
fn apply_additive_status_effect<const N: usize, M: AdditiveStatusEffectMarker<N>>(
|
||||||
In(entities): In<Vec<Entity>>,
|
In(entities): In<Vec<Entity>>,
|
||||||
effect_q: Query<(Entity, &Parent, &AdditiveStatusEffect<N, M>)>,
|
effect_q: Query<(Entity, &ChildOf, &AdditiveStatusEffect<N, M>)>,
|
||||||
mut parent_q: Query<Option<&mut StatusEffectStack<M>>>,
|
mut parent_q: Query<Option<&mut StatusEffectStack<M>>>,
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
mut effects: Effects,
|
mut effects: Effects,
|
||||||
|
|
@ -353,15 +350,15 @@ fn apply_additive_status_effect<const N: usize, M: AdditiveStatusEffectMarker<N>
|
||||||
) {
|
) {
|
||||||
for (entity, player, effect) in effect_q.iter_many(entities) {
|
for (entity, player, effect) in effect_q.iter_many(entities) {
|
||||||
log!(logger, "apply_status_effect", {
|
log!(logger, "apply_status_effect", {
|
||||||
recipient: player.get(),
|
recipient: player.parent(),
|
||||||
effect: std::any::type_name::<M>(),
|
effect: std::any::type_name::<M>(),
|
||||||
});
|
});
|
||||||
|
|
||||||
let stack = parent_q.get_mut(player.get()).unwrap();
|
let stack = parent_q.get_mut(player.parent()).unwrap();
|
||||||
|
|
||||||
let new_effects = <M::AffectedStats as Stats<N>>::spawn_additive_effects(
|
let new_effects = <M::AffectedStats as Stats<N>>::spawn_additive_effects(
|
||||||
&mut effects,
|
&mut effects,
|
||||||
player.get(),
|
player.parent(),
|
||||||
M::factor() * (1.0 + effect.extra_effectiveness),
|
M::factor() * (1.0 + effect.extra_effectiveness),
|
||||||
std::any::type_name::<M>(),
|
std::any::type_name::<M>(),
|
||||||
);
|
);
|
||||||
|
|
@ -389,13 +386,13 @@ fn apply_additive_status_effect<const N: usize, M: AdditiveStatusEffectMarker<N>
|
||||||
|
|
||||||
fn remove_additive_status_effect<const N: usize, M: AdditiveStatusEffectMarker<N>>(
|
fn remove_additive_status_effect<const N: usize, M: AdditiveStatusEffectMarker<N>>(
|
||||||
In(entities): In<Vec<Entity>>,
|
In(entities): In<Vec<Entity>>,
|
||||||
effect_q: Query<(Entity, &Parent)>,
|
effect_q: Query<(Entity, &ChildOf)>,
|
||||||
mut parent_q: Query<Option<&mut StatusEffectStack<M>>>,
|
mut parent_q: Query<Option<&mut StatusEffectStack<M>>>,
|
||||||
linked_q: Query<&LinkedComponents<N>>,
|
linked_q: Query<&LinkedComponents<N>>,
|
||||||
mut effects: Effects,
|
mut effects: Effects,
|
||||||
) {
|
) {
|
||||||
for (effect, player) in effect_q.iter_many(entities) {
|
for (effect, player) in effect_q.iter_many(entities) {
|
||||||
if let Some(mut stack) = parent_q.get_mut(player.get()).unwrap()
|
if let Some(mut stack) = parent_q.get_mut(player.parent()).unwrap()
|
||||||
&& stack.effects.front() == Some(&effect)
|
&& stack.effects.front() == Some(&effect)
|
||||||
{
|
{
|
||||||
stack.effects.pop_front();
|
stack.effects.pop_front();
|
||||||
|
|
@ -412,8 +409,8 @@ fn remove_additive_status_effect<const N: usize, M: AdditiveStatusEffectMarker<N
|
||||||
fn apply_temp_debuff_effect<Temp: DebuffingTempMarker>(
|
fn apply_temp_debuff_effect<Temp: DebuffingTempMarker>(
|
||||||
In(entities): In<Vec<Entity>>,
|
In(entities): In<Vec<Entity>>,
|
||||||
mut rng: ResMut<Rng>,
|
mut rng: ResMut<Rng>,
|
||||||
temp_q: Query<(Entity, &Parent, &AssociatedWeapon)>,
|
temp_q: Query<(Entity, &ChildOf, &AssociatedWeapon)>,
|
||||||
weapon_q: Query<&Parent>,
|
weapon_q: Query<&ChildOf>,
|
||||||
mut parent_q: Query<(
|
mut parent_q: Query<(
|
||||||
Option<&mut StatusEffectStack<Temp>>,
|
Option<&mut StatusEffectStack<Temp>>,
|
||||||
Has<TempDebuffImmunity<Temp>>,
|
Has<TempDebuffImmunity<Temp>>,
|
||||||
|
|
@ -422,14 +419,14 @@ fn apply_temp_debuff_effect<Temp: DebuffingTempMarker>(
|
||||||
mut logger: Logger,
|
mut logger: Logger,
|
||||||
) {
|
) {
|
||||||
for (effect, player, weapon) in temp_q.iter_many(entities) {
|
for (effect, player, weapon) in temp_q.iter_many(entities) {
|
||||||
let (stack, immunity) = parent_q.get_mut(player.get()).unwrap();
|
let (stack, immunity) = parent_q.get_mut(player.parent()).unwrap();
|
||||||
let user = weapon_q.get(weapon.0).unwrap();
|
let user = weapon_q.get(weapon.0).unwrap();
|
||||||
if immunity {
|
if immunity {
|
||||||
commands.entity(effect).despawn();
|
commands.entity(effect).despawn();
|
||||||
commands.entity(player.get()).remove_child(effect);
|
commands.entity(player.parent()).remove_child(effect);
|
||||||
log!(logger, "used_debuff_temp", {
|
log!(logger, "used_debuff_temp", {
|
||||||
actor: user.get(),
|
actor: user.parent(),
|
||||||
recipient: player.get(),
|
recipient: player.parent(),
|
||||||
weapon: weapon.0,
|
weapon: weapon.0,
|
||||||
immune: true,
|
immune: true,
|
||||||
});
|
});
|
||||||
|
|
@ -447,7 +444,7 @@ fn apply_temp_debuff_effect<Temp: DebuffingTempMarker>(
|
||||||
|
|
||||||
let bonus = effects.spawn(
|
let bonus = effects.spawn(
|
||||||
MultiplicativeBonus::<Temp::Stat>::new(std::any::type_name::<Temp>(), effective_factor),
|
MultiplicativeBonus::<Temp::Stat>::new(std::any::type_name::<Temp>(), effective_factor),
|
||||||
player.get(),
|
player.parent(),
|
||||||
);
|
);
|
||||||
|
|
||||||
if let Some(mut stack) = stack {
|
if let Some(mut stack) = stack {
|
||||||
|
|
@ -456,7 +453,7 @@ fn apply_temp_debuff_effect<Temp: DebuffingTempMarker>(
|
||||||
stack.effects.push_back(effect);
|
stack.effects.push_back(effect);
|
||||||
} else {
|
} else {
|
||||||
commands
|
commands
|
||||||
.entity(player.get())
|
.entity(player.parent())
|
||||||
.insert(StatusEffectStack::<Temp> {
|
.insert(StatusEffectStack::<Temp> {
|
||||||
effects: VecDeque::from([effect]),
|
effects: VecDeque::from([effect]),
|
||||||
bonus,
|
bonus,
|
||||||
|
|
@ -465,8 +462,8 @@ fn apply_temp_debuff_effect<Temp: DebuffingTempMarker>(
|
||||||
}
|
}
|
||||||
|
|
||||||
log!(logger, "used_debuff_temp", {
|
log!(logger, "used_debuff_temp", {
|
||||||
actor: user.get(),
|
actor: user.parent(),
|
||||||
recipient: player.get(),
|
recipient: player.parent(),
|
||||||
weapon: weapon.0,
|
weapon: weapon.0,
|
||||||
immune: false,
|
immune: false,
|
||||||
});
|
});
|
||||||
|
|
@ -475,14 +472,14 @@ fn apply_temp_debuff_effect<Temp: DebuffingTempMarker>(
|
||||||
|
|
||||||
fn remove_temp_debuff_effect<Temp: DebuffingTempMarker>(
|
fn remove_temp_debuff_effect<Temp: DebuffingTempMarker>(
|
||||||
In(entities): In<Vec<Entity>>,
|
In(entities): In<Vec<Entity>>,
|
||||||
temp_q: Query<&Parent>,
|
temp_q: Query<&ChildOf>,
|
||||||
mut parent_q: Query<(&mut StatusEffectStack<Temp>, Has<TempDebuffImmunity<Temp>>)>,
|
mut parent_q: Query<(&mut StatusEffectStack<Temp>, Has<TempDebuffImmunity<Temp>>)>,
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
_logger: Logger,
|
_logger: Logger,
|
||||||
mut effects: Effects,
|
mut effects: Effects,
|
||||||
) {
|
) {
|
||||||
for player in temp_q.iter_many(entities) {
|
for player in temp_q.iter_many(entities) {
|
||||||
let (mut stack, immunity) = parent_q.get_mut(player.get()).unwrap();
|
let (mut stack, immunity) = parent_q.get_mut(player.parent()).unwrap();
|
||||||
if immunity {
|
if immunity {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
@ -501,13 +498,13 @@ fn remove_temp_debuff_effect<Temp: DebuffingTempMarker>(
|
||||||
std::any::type_name::<Temp>(),
|
std::any::type_name::<Temp>(),
|
||||||
effective_factor,
|
effective_factor,
|
||||||
),
|
),
|
||||||
player.get(),
|
player.parent(),
|
||||||
);
|
);
|
||||||
|
|
||||||
stack.effects.pop_front();
|
stack.effects.pop_front();
|
||||||
} else {
|
} else {
|
||||||
commands
|
commands
|
||||||
.entity(player.get())
|
.entity(player.parent())
|
||||||
.remove::<StatusEffectStack<Temp>>();
|
.remove::<StatusEffectStack<Temp>>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,11 @@
|
||||||
use bevy_ecs::prelude::*;
|
use bevy_ecs::prelude::*;
|
||||||
use proxisim_models::{
|
use proxisim_models::bundle::{
|
||||||
bundle::{
|
|
||||||
bonus::{BonusPartDamageBonus, BonusValue, WeaponBonusType},
|
bonus::{BonusPartDamageBonus, BonusValue, WeaponBonusType},
|
||||||
player::PartDamageBonus,
|
player::PartDamageBonus,
|
||||||
stat::{
|
stat::{
|
||||||
AdditiveBonus, AmmoControl, Clips, CritRate, DamageBonus, SimpleStatBonus,
|
AdditiveBonus, AmmoControl, Clips, CritRate, DamageBonus, SimpleStatBonus,
|
||||||
SimpleStatEffective, Speed, Strength, WeaponAccuracy,
|
SimpleStatEffective, Speed, Strength, WeaponAccuracy,
|
||||||
},
|
},
|
||||||
},
|
|
||||||
hierarchy::{HierarchyBuilder, Parent},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
|
@ -197,7 +194,7 @@ impl BonusPartDamageBonus {
|
||||||
} */
|
} */
|
||||||
|
|
||||||
pub(crate) fn prepare_bonuses(
|
pub(crate) fn prepare_bonuses(
|
||||||
bonus_q: Query<(&Parent, &WeaponBonusType, &BonusValue)>,
|
bonus_q: Query<(&ChildOf, &WeaponBonusType, &BonusValue)>,
|
||||||
clips_q: Query<&SimpleStatEffective<Clips>>,
|
clips_q: Query<&SimpleStatEffective<Clips>>,
|
||||||
mut effects: Effects,
|
mut effects: Effects,
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
|
|
@ -207,227 +204,227 @@ pub(crate) fn prepare_bonuses(
|
||||||
WeaponBonusType::Berserk => {
|
WeaponBonusType::Berserk => {
|
||||||
effects.spawn(
|
effects.spawn(
|
||||||
SimpleStatBonus::<DamageBonus>::new("beserk", value.0 / 100.0),
|
SimpleStatBonus::<DamageBonus>::new("beserk", value.0 / 100.0),
|
||||||
weapon.get(),
|
weapon.parent(),
|
||||||
);
|
);
|
||||||
effects.spawn(
|
effects.spawn(
|
||||||
SimpleStatBonus::<WeaponAccuracy>::new("beserk", -value.0 / 2.0 / 50.0),
|
SimpleStatBonus::<WeaponAccuracy>::new("beserk", -value.0 / 2.0 / 50.0),
|
||||||
weapon.get(),
|
weapon.parent(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
WeaponBonusType::Conserve => {
|
WeaponBonusType::Conserve => {
|
||||||
effects.spawn(
|
effects.spawn(
|
||||||
SimpleStatBonus::<AmmoControl>::new("conserve", value.0 / 100.0),
|
SimpleStatBonus::<AmmoControl>::new("conserve", value.0 / 100.0),
|
||||||
weapon.get(),
|
weapon.parent(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
WeaponBonusType::Expose => {
|
WeaponBonusType::Expose => {
|
||||||
effects.spawn(
|
effects.spawn(
|
||||||
SimpleStatBonus::<CritRate>::new("expose", (value.0 / 0.5) as u16),
|
SimpleStatBonus::<CritRate>::new("expose", (value.0 / 0.5) as u16),
|
||||||
weapon.get(),
|
weapon.parent(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
WeaponBonusType::Grace => {
|
WeaponBonusType::Grace => {
|
||||||
effects.spawn(
|
effects.spawn(
|
||||||
SimpleStatBonus::<DamageBonus>::new("grace", -value.0 / 2.0 / 100.0),
|
SimpleStatBonus::<DamageBonus>::new("grace", -value.0 / 2.0 / 100.0),
|
||||||
weapon.get(),
|
weapon.parent(),
|
||||||
);
|
);
|
||||||
effects.spawn(
|
effects.spawn(
|
||||||
SimpleStatBonus::<WeaponAccuracy>::new("grace", value.0 / 50.0),
|
SimpleStatBonus::<WeaponAccuracy>::new("grace", value.0 / 50.0),
|
||||||
weapon.get(),
|
weapon.parent(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
WeaponBonusType::Powerful => {
|
WeaponBonusType::Powerful => {
|
||||||
effects.spawn(
|
effects.spawn(
|
||||||
SimpleStatBonus::<DamageBonus>::new("powerful", value.0 / 100.0),
|
SimpleStatBonus::<DamageBonus>::new("powerful", value.0 / 100.0),
|
||||||
weapon.get(),
|
weapon.parent(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
WeaponBonusType::Specialist => {
|
WeaponBonusType::Specialist => {
|
||||||
effects.spawn(
|
effects.spawn(
|
||||||
SimpleStatBonus::<DamageBonus>::new("specialist", value.0 / 100.0),
|
SimpleStatBonus::<DamageBonus>::new("specialist", value.0 / 100.0),
|
||||||
weapon.get(),
|
weapon.parent(),
|
||||||
);
|
);
|
||||||
|
|
||||||
if let Ok(clips) = clips_q.get(weapon.get()) {
|
if let Ok(clips) = clips_q.get(weapon.parent()) {
|
||||||
effects.spawn(
|
effects.spawn(
|
||||||
SimpleStatBonus::<Clips>::new("specialist", -(clips.value as i16)),
|
SimpleStatBonus::<Clips>::new("specialist", -(clips.value as i16)),
|
||||||
weapon.get(),
|
weapon.parent(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
WeaponBonusType::Empower => {
|
WeaponBonusType::Empower => {
|
||||||
commands
|
commands
|
||||||
.spawn(TurnTriggeredEffect::Bonus {
|
.entity(weapon.parent())
|
||||||
|
.with_child(TurnTriggeredEffect::Bonus {
|
||||||
value: value.0,
|
value: value.0,
|
||||||
bonus: TurnTriggeredBonus::Empower,
|
bonus: TurnTriggeredBonus::Empower,
|
||||||
})
|
});
|
||||||
.set_parent(weapon.get());
|
|
||||||
}
|
}
|
||||||
WeaponBonusType::Quicken => {
|
WeaponBonusType::Quicken => {
|
||||||
commands
|
commands
|
||||||
.spawn(TurnTriggeredEffect::Bonus {
|
.entity(weapon.parent())
|
||||||
|
.with_child(TurnTriggeredEffect::Bonus {
|
||||||
value: value.0,
|
value: value.0,
|
||||||
bonus: TurnTriggeredBonus::Quicken,
|
bonus: TurnTriggeredBonus::Quicken,
|
||||||
})
|
});
|
||||||
.set_parent(weapon.get());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
WeaponBonusType::Assassinate => {
|
WeaponBonusType::Assassinate => {
|
||||||
commands
|
commands
|
||||||
.spawn(FirstTurnEffect::Bonus {
|
.entity(weapon.parent())
|
||||||
|
.with_child(FirstTurnEffect::Bonus {
|
||||||
value: value.0,
|
value: value.0,
|
||||||
bonus: FirstTurnBonus::Assassinate,
|
bonus: FirstTurnBonus::Assassinate,
|
||||||
})
|
});
|
||||||
.set_parent(weapon.get());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
WeaponBonusType::Blindfire => {
|
WeaponBonusType::Blindfire => {
|
||||||
commands
|
commands
|
||||||
.spawn(DamageProcEffect::MultiTurn {
|
.entity(weapon.parent())
|
||||||
|
.with_child(DamageProcEffect::MultiTurn {
|
||||||
value: value.0,
|
value: value.0,
|
||||||
bonus: MultiTurnBonus::Blindfire,
|
bonus: MultiTurnBonus::Blindfire,
|
||||||
})
|
});
|
||||||
.set_parent(weapon.get());
|
|
||||||
}
|
}
|
||||||
WeaponBonusType::Fury => {
|
WeaponBonusType::Fury => {
|
||||||
commands
|
commands
|
||||||
.spawn(DamageProcEffect::MultiTurn {
|
.entity(weapon.parent())
|
||||||
|
.with_child(DamageProcEffect::MultiTurn {
|
||||||
value: value.0,
|
value: value.0,
|
||||||
bonus: MultiTurnBonus::Fury,
|
bonus: MultiTurnBonus::Fury,
|
||||||
})
|
});
|
||||||
.set_parent(weapon.get());
|
|
||||||
}
|
}
|
||||||
WeaponBonusType::Rage => {
|
WeaponBonusType::Rage => {
|
||||||
commands
|
commands
|
||||||
.spawn(DamageProcEffect::MultiTurn {
|
.entity(weapon.parent())
|
||||||
|
.with_child(DamageProcEffect::MultiTurn {
|
||||||
value: value.0,
|
value: value.0,
|
||||||
bonus: MultiTurnBonus::Rage,
|
bonus: MultiTurnBonus::Rage,
|
||||||
})
|
});
|
||||||
.set_parent(weapon.get());
|
|
||||||
}
|
}
|
||||||
WeaponBonusType::DoubleTap => {
|
WeaponBonusType::DoubleTap => {
|
||||||
commands
|
commands
|
||||||
.spawn(DamageProcEffect::MultiTurn {
|
.entity(weapon.parent())
|
||||||
|
.with_child(DamageProcEffect::MultiTurn {
|
||||||
value: value.0,
|
value: value.0,
|
||||||
bonus: MultiTurnBonus::DoubleTap,
|
bonus: MultiTurnBonus::DoubleTap,
|
||||||
})
|
});
|
||||||
.set_parent(weapon.get());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
WeaponBonusType::Achilles => {
|
WeaponBonusType::Achilles => {
|
||||||
commands
|
commands
|
||||||
.spawn(PartDamageBonus::WeaponBonus {
|
.entity(weapon.parent())
|
||||||
|
.with_child(PartDamageBonus::WeaponBonus {
|
||||||
value: value.0 / 100.0,
|
value: value.0 / 100.0,
|
||||||
bonus: BonusPartDamageBonus::Achilles,
|
bonus: BonusPartDamageBonus::Achilles,
|
||||||
})
|
});
|
||||||
.set_parent(weapon.get());
|
|
||||||
}
|
}
|
||||||
WeaponBonusType::Cupid => {
|
WeaponBonusType::Cupid => {
|
||||||
commands
|
commands
|
||||||
.spawn(PartDamageBonus::WeaponBonus {
|
.entity(weapon.parent())
|
||||||
|
.with_child(PartDamageBonus::WeaponBonus {
|
||||||
value: value.0 / 100.0,
|
value: value.0 / 100.0,
|
||||||
bonus: BonusPartDamageBonus::Cupid,
|
bonus: BonusPartDamageBonus::Cupid,
|
||||||
})
|
});
|
||||||
.set_parent(weapon.get());
|
|
||||||
}
|
}
|
||||||
WeaponBonusType::Crusher => {
|
WeaponBonusType::Crusher => {
|
||||||
commands
|
commands
|
||||||
.spawn(PartDamageBonus::WeaponBonus {
|
.entity(weapon.parent())
|
||||||
|
.with_child(PartDamageBonus::WeaponBonus {
|
||||||
value: value.0 / 100.0,
|
value: value.0 / 100.0,
|
||||||
bonus: BonusPartDamageBonus::Crusher,
|
bonus: BonusPartDamageBonus::Crusher,
|
||||||
})
|
});
|
||||||
.set_parent(weapon.get());
|
|
||||||
}
|
}
|
||||||
WeaponBonusType::Deadeye => {
|
WeaponBonusType::Deadeye => {
|
||||||
commands
|
commands
|
||||||
.spawn(PartDamageBonus::WeaponBonus {
|
.entity(weapon.parent())
|
||||||
|
.with_child(PartDamageBonus::WeaponBonus {
|
||||||
value: value.0 / 100.0,
|
value: value.0 / 100.0,
|
||||||
bonus: BonusPartDamageBonus::Deadeye,
|
bonus: BonusPartDamageBonus::Deadeye,
|
||||||
})
|
});
|
||||||
.set_parent(weapon.get());
|
|
||||||
}
|
}
|
||||||
WeaponBonusType::Throttle => {
|
WeaponBonusType::Throttle => {
|
||||||
commands
|
commands
|
||||||
.spawn(PartDamageBonus::WeaponBonus {
|
.entity(weapon.parent())
|
||||||
|
.with_child(PartDamageBonus::WeaponBonus {
|
||||||
value: value.0 / 100.0,
|
value: value.0 / 100.0,
|
||||||
bonus: BonusPartDamageBonus::Throttle,
|
bonus: BonusPartDamageBonus::Throttle,
|
||||||
})
|
});
|
||||||
.set_parent(weapon.get());
|
|
||||||
}
|
}
|
||||||
WeaponBonusType::Roshambo => {
|
WeaponBonusType::Roshambo => {
|
||||||
commands
|
commands
|
||||||
.spawn(PartDamageBonus::WeaponBonus {
|
.entity(weapon.parent())
|
||||||
|
.with_child(PartDamageBonus::WeaponBonus {
|
||||||
value: value.0 / 100.0,
|
value: value.0 / 100.0,
|
||||||
bonus: BonusPartDamageBonus::Roshambo,
|
bonus: BonusPartDamageBonus::Roshambo,
|
||||||
})
|
});
|
||||||
.set_parent(weapon.get());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
WeaponBonusType::Cripple => {
|
WeaponBonusType::Cripple => {
|
||||||
commands
|
commands
|
||||||
.spawn(DamageProcEffect::OpponentEffect {
|
.entity(weapon.parent())
|
||||||
|
.with_child(DamageProcEffect::OpponentEffect {
|
||||||
value: value.0,
|
value: value.0,
|
||||||
bonus: OpponentStatusEffect::Cripple,
|
bonus: OpponentStatusEffect::Cripple,
|
||||||
})
|
});
|
||||||
.set_parent(weapon.get());
|
|
||||||
}
|
}
|
||||||
WeaponBonusType::Demoralise => {
|
WeaponBonusType::Demoralise => {
|
||||||
commands
|
commands
|
||||||
.spawn(DamageProcEffect::OpponentEffect {
|
.entity(weapon.parent())
|
||||||
|
.with_child(DamageProcEffect::OpponentEffect {
|
||||||
value: value.0,
|
value: value.0,
|
||||||
bonus: OpponentStatusEffect::Demoralise,
|
bonus: OpponentStatusEffect::Demoralise,
|
||||||
})
|
});
|
||||||
.set_parent(weapon.get());
|
|
||||||
}
|
}
|
||||||
WeaponBonusType::Freeze => {
|
WeaponBonusType::Freeze => {
|
||||||
commands
|
commands
|
||||||
.spawn(DamageProcEffect::OpponentEffect {
|
.entity(weapon.parent())
|
||||||
|
.with_child(DamageProcEffect::OpponentEffect {
|
||||||
value: value.0,
|
value: value.0,
|
||||||
bonus: OpponentStatusEffect::Freeze,
|
bonus: OpponentStatusEffect::Freeze,
|
||||||
})
|
});
|
||||||
.set_parent(weapon.get());
|
|
||||||
}
|
}
|
||||||
WeaponBonusType::Slow => {
|
WeaponBonusType::Slow => {
|
||||||
commands
|
commands
|
||||||
.spawn(DamageProcEffect::OpponentEffect {
|
.entity(weapon.parent())
|
||||||
|
.with_child(DamageProcEffect::OpponentEffect {
|
||||||
value: value.0,
|
value: value.0,
|
||||||
bonus: OpponentStatusEffect::Slow,
|
bonus: OpponentStatusEffect::Slow,
|
||||||
})
|
});
|
||||||
.set_parent(weapon.get());
|
|
||||||
}
|
}
|
||||||
WeaponBonusType::Toxin => {
|
WeaponBonusType::Toxin => {
|
||||||
commands
|
commands
|
||||||
.spawn(DamageProcEffect::OpponentEffect {
|
.entity(weapon.parent())
|
||||||
|
.with_child(DamageProcEffect::OpponentEffect {
|
||||||
value: value.0,
|
value: value.0,
|
||||||
bonus: OpponentStatusEffect::Toxin,
|
bonus: OpponentStatusEffect::Toxin,
|
||||||
})
|
});
|
||||||
.set_parent(weapon.get());
|
|
||||||
}
|
}
|
||||||
WeaponBonusType::Weaken => {
|
WeaponBonusType::Weaken => {
|
||||||
commands
|
commands
|
||||||
.spawn(DamageProcEffect::OpponentEffect {
|
.entity(weapon.parent())
|
||||||
|
.with_child(DamageProcEffect::OpponentEffect {
|
||||||
value: value.0,
|
value: value.0,
|
||||||
bonus: OpponentStatusEffect::Weaken,
|
bonus: OpponentStatusEffect::Weaken,
|
||||||
})
|
});
|
||||||
.set_parent(weapon.get());
|
|
||||||
}
|
}
|
||||||
WeaponBonusType::Wither => {
|
WeaponBonusType::Wither => {
|
||||||
commands
|
commands
|
||||||
.spawn(DamageProcEffect::OpponentEffect {
|
.entity(weapon.parent())
|
||||||
|
.with_child(DamageProcEffect::OpponentEffect {
|
||||||
value: value.0,
|
value: value.0,
|
||||||
bonus: OpponentStatusEffect::Wither,
|
bonus: OpponentStatusEffect::Wither,
|
||||||
})
|
});
|
||||||
.set_parent(weapon.get());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
WeaponBonusType::Motivate => {
|
WeaponBonusType::Motivate => {
|
||||||
commands
|
commands
|
||||||
.spawn(DamageProcEffect::SelfEffect {
|
.entity(weapon.parent())
|
||||||
|
.with_child(DamageProcEffect::SelfEffect {
|
||||||
value: value.0,
|
value: value.0,
|
||||||
bonus: SelfStatusEffect::Motivate,
|
bonus: SelfStatusEffect::Motivate,
|
||||||
})
|
});
|
||||||
.set_parent(weapon.get());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val => unimplemented!("{val:?}"),
|
val => unimplemented!("{val:?}"),
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
use bevy_ecs::prelude::*;
|
use bevy_ecs::prelude::*;
|
||||||
use proxisim_models::{
|
use proxisim_models::bundle::{
|
||||||
bundle::{
|
|
||||||
passive::{Education, EducationPartDamageBonus, FactionUpgrades, Merits},
|
passive::{Education, EducationPartDamageBonus, FactionUpgrades, Merits},
|
||||||
player::{Current, PartDamageBonus, Weapons},
|
player::{Current, PartDamageBonus, Weapons},
|
||||||
stat::{
|
stat::{
|
||||||
|
|
@ -11,15 +10,13 @@ use proxisim_models::{
|
||||||
Ammo, EquippedMods, Experience, Japanese, NeedsReload, Usable, Weapon, WeaponCategory,
|
Ammo, EquippedMods, Experience, Japanese, NeedsReload, Usable, Weapon, WeaponCategory,
|
||||||
WeaponMod, WeaponSlot,
|
WeaponMod, WeaponSlot,
|
||||||
},
|
},
|
||||||
},
|
|
||||||
hierarchy::{HierarchyBuilder, Parent},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
Stages,
|
||||||
effect::{Effects, TurnLimitedEffect},
|
effect::{Effects, TurnLimitedEffect},
|
||||||
log,
|
log,
|
||||||
log::Logger,
|
log::Logger,
|
||||||
Stages,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use self::bonus::{
|
use self::bonus::{
|
||||||
|
|
@ -157,25 +154,6 @@ pub enum DamageProcEffect {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_owner(weapons_q: Query<(Entity, &Weapons)>, mut commands: Commands) {
|
|
||||||
for (player, weapons) in weapons_q.iter() {
|
|
||||||
if let Some(primary) = weapons.primary {
|
|
||||||
commands.entity(primary).set_parent(player);
|
|
||||||
}
|
|
||||||
if let Some(secondary) = weapons.secondary {
|
|
||||||
commands.entity(secondary).set_parent(player);
|
|
||||||
}
|
|
||||||
if let Some(melee) = weapons.melee {
|
|
||||||
commands.entity(melee).set_parent(player);
|
|
||||||
}
|
|
||||||
if let Some(temp) = weapons.temporary {
|
|
||||||
commands.entity(temp).set_parent(player);
|
|
||||||
}
|
|
||||||
commands.entity(weapons.fists).set_parent(player);
|
|
||||||
commands.entity(weapons.kick).set_parent(player);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn apply_passives(
|
fn apply_passives(
|
||||||
weapon_q: Query<(
|
weapon_q: Query<(
|
||||||
Entity,
|
Entity,
|
||||||
|
|
@ -184,7 +162,7 @@ fn apply_passives(
|
||||||
&WeaponCategory,
|
&WeaponCategory,
|
||||||
&WeaponSlot,
|
&WeaponSlot,
|
||||||
Has<Japanese>,
|
Has<Japanese>,
|
||||||
&Parent,
|
&ChildOf,
|
||||||
)>,
|
)>,
|
||||||
player_q: Query<(&Merits, &Education, &FactionUpgrades)>,
|
player_q: Query<(&Merits, &Education, &FactionUpgrades)>,
|
||||||
mut effects: Effects,
|
mut effects: Effects,
|
||||||
|
|
@ -331,8 +309,8 @@ fn apply_passives(
|
||||||
weapon,
|
weapon,
|
||||||
);
|
);
|
||||||
commands
|
commands
|
||||||
.spawn(TurnTriggeredEffect::Mod(TurnTriggeredMod::Bipod))
|
.entity(weapon)
|
||||||
.set_parent(weapon);
|
.with_child(TurnTriggeredEffect::Mod(TurnTriggeredMod::Bipod));
|
||||||
}
|
}
|
||||||
WeaponMod::Tripod => {
|
WeaponMod::Tripod => {
|
||||||
effects.spawn(
|
effects.spawn(
|
||||||
|
|
@ -340,40 +318,38 @@ fn apply_passives(
|
||||||
weapon,
|
weapon,
|
||||||
);
|
);
|
||||||
commands
|
commands
|
||||||
.spawn(TurnTriggeredEffect::Mod(TurnTriggeredMod::Tripod))
|
.entity(weapon)
|
||||||
.set_parent(weapon);
|
.with_child(TurnTriggeredEffect::Mod(TurnTriggeredMod::Tripod));
|
||||||
}
|
}
|
||||||
WeaponMod::SmallLight => {
|
WeaponMod::SmallLight => {
|
||||||
commands
|
commands
|
||||||
.spawn(TurnTriggeredEffect::Mod(TurnTriggeredMod::SmallLight))
|
.entity(weapon)
|
||||||
.set_parent(weapon);
|
.with_child(TurnTriggeredEffect::Mod(TurnTriggeredMod::SmallLight));
|
||||||
}
|
}
|
||||||
WeaponMod::PrecisionLight => {
|
WeaponMod::PrecisionLight => {
|
||||||
commands
|
commands
|
||||||
.spawn(TurnTriggeredEffect::Mod(TurnTriggeredMod::PrecisionLight))
|
.entity(weapon)
|
||||||
.set_parent(weapon);
|
.with_child(TurnTriggeredEffect::Mod(TurnTriggeredMod::PrecisionLight));
|
||||||
}
|
}
|
||||||
WeaponMod::TacticalIlluminator => {
|
WeaponMod::TacticalIlluminator => {
|
||||||
commands
|
commands.entity(weapon).with_child(TurnTriggeredEffect::Mod(
|
||||||
.spawn(TurnTriggeredEffect::Mod(
|
|
||||||
TurnTriggeredMod::TacticalIlluminator,
|
TurnTriggeredMod::TacticalIlluminator,
|
||||||
))
|
));
|
||||||
.set_parent(weapon);
|
|
||||||
}
|
}
|
||||||
WeaponMod::AdjustableTrigger => {
|
WeaponMod::AdjustableTrigger => {
|
||||||
commands
|
commands
|
||||||
.spawn(FirstTurnEffect::Mod(FirstTurnMod::AdjustableTrigger))
|
.entity(weapon)
|
||||||
.set_parent(weapon);
|
.with_child(FirstTurnEffect::Mod(FirstTurnMod::AdjustableTrigger));
|
||||||
}
|
}
|
||||||
WeaponMod::HairTrigger => {
|
WeaponMod::HairTrigger => {
|
||||||
commands
|
commands
|
||||||
.spawn(FirstTurnEffect::Mod(FirstTurnMod::HairTrigger))
|
.entity(weapon)
|
||||||
.set_parent(weapon);
|
.with_child(FirstTurnEffect::Mod(FirstTurnMod::HairTrigger));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let (merits, education, faction) = player_q.get(player.get()).unwrap();
|
let (merits, education, faction) = player_q.get(player.parent()).unwrap();
|
||||||
|
|
||||||
let (mastery, edu_acc) = match cat {
|
let (mastery, edu_acc) = match cat {
|
||||||
WeaponCategory::HeavyArtillery => (
|
WeaponCategory::HeavyArtillery => (
|
||||||
|
|
@ -445,10 +421,10 @@ fn apply_passives(
|
||||||
|
|
||||||
if education.bio2380 {
|
if education.bio2380 {
|
||||||
commands
|
commands
|
||||||
.spawn(PartDamageBonus::Education(
|
.entity(weapon)
|
||||||
|
.with_child(PartDamageBonus::Education(
|
||||||
EducationPartDamageBonus::Bio2380,
|
EducationPartDamageBonus::Bio2380,
|
||||||
))
|
));
|
||||||
.set_parent(weapon);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if mastery > 0 {
|
if mastery > 0 {
|
||||||
|
|
@ -490,7 +466,7 @@ fn reload_weapon(
|
||||||
mut weapon_q: Query<
|
mut weapon_q: Query<
|
||||||
(
|
(
|
||||||
Entity,
|
Entity,
|
||||||
&Parent,
|
&ChildOf,
|
||||||
&mut Ammo,
|
&mut Ammo,
|
||||||
&mut SimpleStatEffective<Clips>,
|
&mut SimpleStatEffective<Clips>,
|
||||||
&SimpleStatEffective<ClipSize>,
|
&SimpleStatEffective<ClipSize>,
|
||||||
|
|
@ -505,7 +481,7 @@ fn reload_weapon(
|
||||||
clips.value -= 1;
|
clips.value -= 1;
|
||||||
|
|
||||||
log!(logger, "reload_weapon", {
|
log!(logger, "reload_weapon", {
|
||||||
actor: player.get(),
|
actor: player.parent(),
|
||||||
weapon
|
weapon
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -530,18 +506,17 @@ fn restore_ammo(
|
||||||
}
|
}
|
||||||
|
|
||||||
fn apply_first_turn_effects(
|
fn apply_first_turn_effects(
|
||||||
effect_q: Query<(&Parent, &FirstTurnEffect)>,
|
effect_q: Query<(&ChildOf, &FirstTurnEffect)>,
|
||||||
player_q: Query<&Parent>,
|
player_q: Query<&ChildOf>,
|
||||||
mut effects: Effects,
|
mut effects: Effects,
|
||||||
) {
|
) {
|
||||||
for (weapon, effect) in effect_q.iter() {
|
for (weapon, effect) in effect_q.iter() {
|
||||||
let player = player_q.get(weapon.get()).unwrap();
|
let player = player_q.get(weapon.parent()).unwrap();
|
||||||
effect.spawn(&mut effects, weapon.get(), player.get());
|
effect.spawn(&mut effects, weapon.parent(), player.parent());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn configure(stages: &mut Stages) {
|
pub(crate) fn configure(stages: &mut Stages) {
|
||||||
stages.equip.add_systems(set_owner);
|
|
||||||
// running this in the snapshot layer ensures that the stat increases aren't restored at the
|
// running this in the snapshot layer ensures that the stat increases aren't restored at the
|
||||||
// end of the run
|
// end of the run
|
||||||
stages.snapshot.add_systems(apply_first_turn_effects);
|
stages.snapshot.add_systems(apply_first_turn_effects);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue