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 bevy_ecs::{entity::Entity, world::World};
|
||||
use bevy_ecs::{prelude::*, relationship::RelatedSpawner};
|
||||
use strum::Display;
|
||||
|
||||
use crate::{
|
||||
|
|
@ -186,8 +186,8 @@ impl ArmourDto {
|
|||
.collect()
|
||||
}
|
||||
|
||||
pub fn spawn(self, world: &mut World) -> Entity {
|
||||
let mut commands = world.spawn(draw_id());
|
||||
pub fn spawn(self, spawner: &mut RelatedSpawner<'_, ChildOf>) -> Entity {
|
||||
let mut commands = spawner.spawn(draw_id());
|
||||
|
||||
commands.insert((
|
||||
Name(self.name.to_string()),
|
||||
|
|
|
|||
|
|
@ -52,19 +52,6 @@ pub struct PlayerDto {
|
|||
|
||||
impl PlayerDto {
|
||||
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());
|
||||
|
||||
commands.insert((
|
||||
|
|
@ -85,22 +72,48 @@ impl PlayerDto {
|
|||
faction,
|
||||
});
|
||||
|
||||
commands.insert(Weapons {
|
||||
primary,
|
||||
secondary,
|
||||
melee,
|
||||
temporary,
|
||||
kick,
|
||||
fists,
|
||||
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,
|
||||
secondary,
|
||||
melee,
|
||||
temporary,
|
||||
kick,
|
||||
fists,
|
||||
});
|
||||
});
|
||||
if let Some(weapons) = weapons {
|
||||
commands.insert(weapons);
|
||||
}
|
||||
|
||||
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,
|
||||
head,
|
||||
legs,
|
||||
feet,
|
||||
hands,
|
||||
})
|
||||
});
|
||||
|
||||
commands.insert(PlayerArmour {
|
||||
torso,
|
||||
head,
|
||||
legs,
|
||||
feet,
|
||||
hands,
|
||||
});
|
||||
if let Some(armour) = armour {
|
||||
commands.insert(armour);
|
||||
}
|
||||
|
||||
commands
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use std::borrow::Cow;
|
||||
|
||||
use bevy_ecs::prelude::*;
|
||||
use bevy_ecs::{prelude::*, relationship::RelatedSpawner};
|
||||
|
||||
use crate::{
|
||||
bundle::{
|
||||
|
|
@ -252,8 +252,8 @@ impl WeaponDto {
|
|||
})
|
||||
}
|
||||
|
||||
pub fn spawn(self, world: &mut World) -> Entity {
|
||||
let mut commands = world.spawn(draw_id());
|
||||
pub fn spawn(self, spawner: &mut RelatedSpawner<'_, ChildOf>) -> Entity {
|
||||
let mut commands = spawner.spawn(draw_id());
|
||||
|
||||
let verb = match self.kind {
|
||||
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 dto;
|
||||
// pub mod hierarchy;
|
||||
|
|
|
|||
|
|
@ -1,18 +1,15 @@
|
|||
use bevy_ecs::prelude::*;
|
||||
use proxisim_models::{
|
||||
bundle::armour::{
|
||||
ArmourBodyPart, ArmourBodyPartSlot, ArmourBodyParts, ArmourCoverage, ArmourValue,
|
||||
ArmourVec, BodyPartCoverage, Immunities, Immunity, PlayerArmour,
|
||||
},
|
||||
hierarchy::HierarchyBuilder,
|
||||
use proxisim_models::bundle::armour::{
|
||||
ArmourBodyPart, ArmourBodyPartSlot, ArmourBodyParts, ArmourCoverage, ArmourValue, ArmourVec,
|
||||
BodyPartCoverage, Immunities, Immunity, PlayerArmour,
|
||||
};
|
||||
use strum::IntoEnumIterator;
|
||||
|
||||
use crate::{
|
||||
Stages,
|
||||
player::status_effect::{
|
||||
ConcussionGrenade, FlashGrenade, PepperSpray, TearGas, TempDebuffImmunity,
|
||||
},
|
||||
Stages,
|
||||
};
|
||||
|
||||
fn generate_body_parts(
|
||||
|
|
@ -24,7 +21,7 @@ fn generate_body_parts(
|
|||
let mut parts = ArmourVec::<ArmourBodyPart>::default();
|
||||
|
||||
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 {
|
||||
let mut player = commands.entity(player);
|
||||
|
|
|
|||
|
|
@ -1,10 +1,7 @@
|
|||
use std::{any::TypeId, collections::HashMap, sync::Mutex};
|
||||
|
||||
use bevy_ecs::{prelude::*, system::SystemParam};
|
||||
use proxisim_models::{
|
||||
bundle::player::{Current, Defender, Player},
|
||||
hierarchy::{HierarchyBuilder, Parent},
|
||||
};
|
||||
use proxisim_models::bundle::player::{Current, Defender, Player};
|
||||
|
||||
use crate::Stages;
|
||||
|
||||
|
|
@ -77,13 +74,9 @@ impl<'w, 's> Effects<'w, 's> {
|
|||
) -> Entity {
|
||||
let id = self.registry.type_map.get(&TypeId::of::<T>()).unwrap();
|
||||
|
||||
let spawned_effect = self
|
||||
.commands
|
||||
.spawn(effect)
|
||||
.insert(*id)
|
||||
.insert(addins)
|
||||
.set_parent(to)
|
||||
.id();
|
||||
let spawned_effect = self.commands.spawn(effect).insert(*id).insert(addins).id();
|
||||
|
||||
self.commands.entity(to).add_child(spawned_effect);
|
||||
|
||||
self.scheduled
|
||||
.create
|
||||
|
|
@ -202,7 +195,7 @@ pub(crate) fn run_effects(world: &mut World) {
|
|||
};
|
||||
|
||||
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.despawn(entity);
|
||||
}
|
||||
|
|
@ -277,12 +270,12 @@ fn mark_permanent_effects(effect_q: Query<Entity, With<EffectId>>, mut commands:
|
|||
}
|
||||
|
||||
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,
|
||||
) {
|
||||
for (effect, target) in effect_q.iter() {
|
||||
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 proxisim_models::{
|
||||
bundle::{
|
||||
Id, Name,
|
||||
player::{Attacker, Player},
|
||||
weapon::Weapon,
|
||||
Id, Name,
|
||||
},
|
||||
dto::metrics::EntityInfo,
|
||||
hierarchy::Parent,
|
||||
};
|
||||
|
||||
use crate::Stages;
|
||||
|
|
@ -18,7 +17,7 @@ pub struct EntityRegistry(pub HashMap<Entity, EntityInfo>);
|
|||
|
||||
fn read_entities(
|
||||
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>,
|
||||
) {
|
||||
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() {
|
||||
let (_, _, player_id, _) = player_q.get(player.get()).unwrap();
|
||||
let (_, _, player_id, _) = player_q.get(player.parent()).unwrap();
|
||||
registry.0.insert(
|
||||
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
|
||||
}
|
||||
}
|
||||
21
src/log.rs
21
src/log.rs
|
|
@ -1,16 +1,13 @@
|
|||
use std::sync::Mutex;
|
||||
|
||||
use bevy_ecs::{prelude::*, query::QuerySingleError, system::SystemParam};
|
||||
use proxisim_models::{
|
||||
bundle::{
|
||||
stat::{
|
||||
AdditiveBonus, BaselineStat, ClipSize, Clips, CritRate, DamageBonus, Defence,
|
||||
Dexterity, EffectiveStat, MultiplicativeBonus, SimpleStatBaseline, SimpleStatBonus,
|
||||
SimpleStatEffective, SimpleStatMarker, Speed, StatMarker, Strength, WeaponAccuracy,
|
||||
},
|
||||
weapon::WeaponVerb,
|
||||
use proxisim_models::bundle::{
|
||||
stat::{
|
||||
AdditiveBonus, BaselineStat, ClipSize, Clips, CritRate, DamageBonus, Defence, Dexterity,
|
||||
EffectiveStat, MultiplicativeBonus, SimpleStatBaseline, SimpleStatBonus,
|
||||
SimpleStatEffective, SimpleStatMarker, Speed, StatMarker, Strength, WeaponAccuracy,
|
||||
},
|
||||
hierarchy::Children,
|
||||
weapon::WeaponVerb,
|
||||
};
|
||||
|
||||
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() {
|
||||
let effects_add: Vec<_> = add_q
|
||||
.iter_many(children.get())
|
||||
.iter_many(children)
|
||||
.map(|bonus| (bonus.label, 100.0 * bonus.value))
|
||||
.collect();
|
||||
let effects_mult: Vec<_> = mult_q
|
||||
.iter_many(children.get())
|
||||
.iter_many(children)
|
||||
.map(|bonus| (bonus.label, 100.0 * bonus.value))
|
||||
.collect();
|
||||
|
||||
|
|
@ -570,7 +567,7 @@ fn log_simple_stat_changes<Stat: SimpleStatMarker>(
|
|||
{
|
||||
for (target, baseline, effective, children) in stat_q.iter() {
|
||||
let bonuses: Vec<_> = bonus_q
|
||||
.iter_many(children.get())
|
||||
.iter_many(children)
|
||||
.map(|bonus| (bonus.label, Stat::denormalise_bonus(bonus.value)))
|
||||
.collect();
|
||||
|
||||
|
|
|
|||
|
|
@ -1,23 +1,18 @@
|
|||
use bevy_ecs::prelude::*;
|
||||
use proxisim_models::{
|
||||
bundle::{
|
||||
armour::{ArmourBodyPart, ArmourBodyParts},
|
||||
passive::{FactionUpgrades, Merits},
|
||||
player::{
|
||||
Attacker, BodyPart, ChooseWeapon, CombatTurns, Current, CurrentTarget, Defeated,
|
||||
Defender, FightEndType, Level, MaxHealth, PartDamageBonus, Player, PlayerStrategy,
|
||||
Weapons,
|
||||
},
|
||||
stat::{
|
||||
AmmoControl, Clips, CritRate, DamageBonus, Defence, Dexterity, EffectiveStat, Health,
|
||||
SimpleStatBundle, SimpleStatEffective, Speed, Strength, WeaponAccuracy,
|
||||
},
|
||||
weapon::{
|
||||
Ammo, DamageStat, NeedsReload, NonTargeted, RateOfFire, Usable, Uses, Weapon,
|
||||
WeaponSlot,
|
||||
},
|
||||
use proxisim_models::bundle::{
|
||||
armour::{ArmourBodyPart, ArmourBodyParts},
|
||||
passive::{FactionUpgrades, Merits},
|
||||
player::{
|
||||
Attacker, BodyPart, ChooseWeapon, CombatTurns, Current, CurrentTarget, Defeated, Defender,
|
||||
FightEndType, Level, MaxHealth, PartDamageBonus, Player, PlayerStrategy, Weapons,
|
||||
},
|
||||
stat::{
|
||||
AmmoControl, Clips, CritRate, DamageBonus, Defence, Dexterity, EffectiveStat, Health,
|
||||
SimpleStatBundle, SimpleStatEffective, Speed, Strength, WeaponAccuracy,
|
||||
},
|
||||
weapon::{
|
||||
Ammo, DamageStat, NeedsReload, NonTargeted, RateOfFire, Usable, Uses, Weapon, WeaponSlot,
|
||||
},
|
||||
hierarchy::Children,
|
||||
};
|
||||
use rand::Rng as _;
|
||||
|
||||
|
|
@ -33,12 +28,12 @@ use crate::{
|
|||
pub mod stats;
|
||||
pub mod status_effect;
|
||||
|
||||
fn select_weapon(
|
||||
fn select_weapon<'a>(
|
||||
weapons: &Weapons,
|
||||
slot: WeaponSlot,
|
||||
reload: bool,
|
||||
usable_q: &Query<(Has<NeedsReload>, Option<&Children>), With<Usable>>,
|
||||
) -> Option<(Entity, Option<Children>)> {
|
||||
usable_q: &'a Query<(Has<NeedsReload>, Option<&Children>), With<Usable>>,
|
||||
) -> Option<(Entity, Option<&'a Children>)> {
|
||||
let id = match slot {
|
||||
WeaponSlot::Primary => weapons.primary?,
|
||||
WeaponSlot::Secondary => weapons.secondary?,
|
||||
|
|
@ -53,7 +48,7 @@ fn select_weapon(
|
|||
if !reload && needs_reload {
|
||||
None
|
||||
} else {
|
||||
Some((id, children.cloned()))
|
||||
Some((id, children))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -155,7 +150,7 @@ pub fn pick_action(
|
|||
let target = target_q.single().unwrap();
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
@ -357,7 +352,7 @@ pub fn use_damaging_weapon(
|
|||
|
||||
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) {
|
||||
dmg_bonus.value += bonus;
|
||||
}
|
||||
|
|
@ -378,7 +373,7 @@ pub fn use_damaging_weapon(
|
|||
metrics.record_histogram(Some(weapon), "dmg", dmg);
|
||||
|
||||
if dmg > 0 {
|
||||
for effect in damage_proc_q.iter_many(children.get()) {
|
||||
for effect in damage_proc_q.iter_many(children) {
|
||||
match *effect {
|
||||
DamageProcEffect::MultiTurn { value, bonus } => {
|
||||
if multi_attack_proc.is_some() {
|
||||
|
|
|
|||
|
|
@ -1,21 +1,18 @@
|
|||
use std::marker::PhantomData;
|
||||
|
||||
use bevy_ecs::prelude::*;
|
||||
use proxisim_models::{
|
||||
bundle::stat::{
|
||||
AdditiveBonus, AdditiveBonuses, AmmoControl, BaselineStat, ClipSize, Clips, CritRate,
|
||||
DamageBonus, Defence, Dexterity, EffectiveStat, Health, MultiplicativeBonus,
|
||||
MultiplicativeBonuses, SimpleStatBonus, SimpleStatEffective, SimpleStatMarker,
|
||||
SimpleStatSnapshot, Speed, StatMarker, StatSnapshot, Strength, WeaponAccuracy,
|
||||
},
|
||||
hierarchy::Parent,
|
||||
use proxisim_models::bundle::stat::{
|
||||
AdditiveBonus, AdditiveBonuses, AmmoControl, BaselineStat, ClipSize, Clips, CritRate,
|
||||
DamageBonus, Defence, Dexterity, EffectiveStat, Health, MultiplicativeBonus,
|
||||
MultiplicativeBonuses, SimpleStatBonus, SimpleStatEffective, SimpleStatMarker,
|
||||
SimpleStatSnapshot, Speed, StatMarker, StatSnapshot, Strength, WeaponAccuracy,
|
||||
};
|
||||
|
||||
use crate::Stages;
|
||||
|
||||
fn add_additive_bonus<Stat: StatMarker>(
|
||||
In(entities): In<Vec<Entity>>,
|
||||
effect_q: Query<(&AdditiveBonus<Stat>, &Parent)>,
|
||||
effect_q: Query<(&AdditiveBonus<Stat>, &ChildOf)>,
|
||||
mut stat_q: Query<(
|
||||
&BaselineStat<Stat>,
|
||||
&mut AdditiveBonuses<Stat>,
|
||||
|
|
@ -24,7 +21,7 @@ fn add_additive_bonus<Stat: StatMarker>(
|
|||
)>,
|
||||
) {
|
||||
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;
|
||||
eff.value = baseline.value * add.factor * mult.factor;
|
||||
}
|
||||
|
|
@ -32,7 +29,7 @@ fn add_additive_bonus<Stat: StatMarker>(
|
|||
|
||||
fn revert_additive_bonus<Stat: StatMarker>(
|
||||
In(entities): In<Vec<Entity>>,
|
||||
effect_q: Query<(&AdditiveBonus<Stat>, &Parent)>,
|
||||
effect_q: Query<(&AdditiveBonus<Stat>, &ChildOf)>,
|
||||
mut stat_q: Query<(
|
||||
&BaselineStat<Stat>,
|
||||
&mut AdditiveBonuses<Stat>,
|
||||
|
|
@ -41,7 +38,7 @@ fn revert_additive_bonus<Stat: StatMarker>(
|
|||
)>,
|
||||
) {
|
||||
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;
|
||||
eff.value = baseline.value * add.factor * mult.factor;
|
||||
}
|
||||
|
|
@ -49,7 +46,7 @@ fn revert_additive_bonus<Stat: StatMarker>(
|
|||
|
||||
fn add_multiplicative_bonus<Stat: StatMarker>(
|
||||
In(entities): In<Vec<Entity>>,
|
||||
effect_q: Query<(&MultiplicativeBonus<Stat>, &Parent)>,
|
||||
effect_q: Query<(&MultiplicativeBonus<Stat>, &ChildOf)>,
|
||||
mut stat_q: Query<(
|
||||
&BaselineStat<Stat>,
|
||||
&AdditiveBonuses<Stat>,
|
||||
|
|
@ -58,7 +55,7 @@ fn add_multiplicative_bonus<Stat: StatMarker>(
|
|||
)>,
|
||||
) {
|
||||
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;
|
||||
eff.value = baseline.value * add.factor * mult.factor;
|
||||
}
|
||||
|
|
@ -66,7 +63,7 @@ fn add_multiplicative_bonus<Stat: StatMarker>(
|
|||
|
||||
fn revert_multiplicative_bonus<Stat: StatMarker>(
|
||||
In(entities): In<Vec<Entity>>,
|
||||
effect_q: Query<(&MultiplicativeBonus<Stat>, &Parent)>,
|
||||
effect_q: Query<(&MultiplicativeBonus<Stat>, &ChildOf)>,
|
||||
mut stat_q: Query<(
|
||||
&BaselineStat<Stat>,
|
||||
&AdditiveBonuses<Stat>,
|
||||
|
|
@ -75,7 +72,7 @@ fn revert_multiplicative_bonus<Stat: StatMarker>(
|
|||
)>,
|
||||
) {
|
||||
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;
|
||||
eff.value = baseline.value * add.factor * mult.factor;
|
||||
}
|
||||
|
|
@ -117,22 +114,22 @@ fn restore_stats<Stat: StatMarker>(
|
|||
|
||||
fn apply_simple_stat_bonus<Stat: SimpleStatMarker>(
|
||||
In(entities): In<Vec<Entity>>,
|
||||
effect_q: Query<(&SimpleStatBonus<Stat>, &Parent)>,
|
||||
effect_q: Query<(&SimpleStatBonus<Stat>, &ChildOf)>,
|
||||
mut stat_q: Query<&mut SimpleStatEffective<Stat>>,
|
||||
) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
fn revert_simple_stat_bonus<Stat: SimpleStatMarker>(
|
||||
In(entities): In<Vec<Entity>>,
|
||||
effect_q: Query<(&SimpleStatBonus<Stat>, &Parent)>,
|
||||
effect_q: Query<(&SimpleStatBonus<Stat>, &ChildOf)>,
|
||||
mut stat_q: Query<&mut SimpleStatEffective<Stat>>,
|
||||
) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,8 @@
|
|||
use std::{collections::VecDeque, marker::PhantomData};
|
||||
|
||||
use bevy_ecs::prelude::*;
|
||||
use proxisim_models::{
|
||||
bundle::stat::{
|
||||
AdditiveBonus, Defence, Dexterity, MultiplicativeBonus, Speed, StatMarker, Strength,
|
||||
},
|
||||
hierarchy::Parent,
|
||||
use proxisim_models::bundle::stat::{
|
||||
AdditiveBonus, Defence, Dexterity, MultiplicativeBonus, Speed, StatMarker, Strength,
|
||||
};
|
||||
use rand::Rng as _;
|
||||
|
||||
|
|
@ -345,7 +342,7 @@ impl AdditiveStatusEffectMarker<2> for Frozen {
|
|||
|
||||
fn apply_additive_status_effect<const N: usize, M: AdditiveStatusEffectMarker<N>>(
|
||||
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 commands: Commands,
|
||||
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) {
|
||||
log!(logger, "apply_status_effect", {
|
||||
recipient: player.get(),
|
||||
recipient: player.parent(),
|
||||
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(
|
||||
&mut effects,
|
||||
player.get(),
|
||||
player.parent(),
|
||||
M::factor() * (1.0 + effect.extra_effectiveness),
|
||||
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>>(
|
||||
In(entities): In<Vec<Entity>>,
|
||||
effect_q: Query<(Entity, &Parent)>,
|
||||
effect_q: Query<(Entity, &ChildOf)>,
|
||||
mut parent_q: Query<Option<&mut StatusEffectStack<M>>>,
|
||||
linked_q: Query<&LinkedComponents<N>>,
|
||||
mut effects: Effects,
|
||||
) {
|
||||
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.pop_front();
|
||||
|
|
@ -412,8 +409,8 @@ fn remove_additive_status_effect<const N: usize, M: AdditiveStatusEffectMarker<N
|
|||
fn apply_temp_debuff_effect<Temp: DebuffingTempMarker>(
|
||||
In(entities): In<Vec<Entity>>,
|
||||
mut rng: ResMut<Rng>,
|
||||
temp_q: Query<(Entity, &Parent, &AssociatedWeapon)>,
|
||||
weapon_q: Query<&Parent>,
|
||||
temp_q: Query<(Entity, &ChildOf, &AssociatedWeapon)>,
|
||||
weapon_q: Query<&ChildOf>,
|
||||
mut parent_q: Query<(
|
||||
Option<&mut StatusEffectStack<Temp>>,
|
||||
Has<TempDebuffImmunity<Temp>>,
|
||||
|
|
@ -422,14 +419,14 @@ fn apply_temp_debuff_effect<Temp: DebuffingTempMarker>(
|
|||
mut logger: Logger,
|
||||
) {
|
||||
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();
|
||||
if immunity {
|
||||
commands.entity(effect).despawn();
|
||||
commands.entity(player.get()).remove_child(effect);
|
||||
commands.entity(player.parent()).remove_child(effect);
|
||||
log!(logger, "used_debuff_temp", {
|
||||
actor: user.get(),
|
||||
recipient: player.get(),
|
||||
actor: user.parent(),
|
||||
recipient: player.parent(),
|
||||
weapon: weapon.0,
|
||||
immune: true,
|
||||
});
|
||||
|
|
@ -447,7 +444,7 @@ fn apply_temp_debuff_effect<Temp: DebuffingTempMarker>(
|
|||
|
||||
let bonus = effects.spawn(
|
||||
MultiplicativeBonus::<Temp::Stat>::new(std::any::type_name::<Temp>(), effective_factor),
|
||||
player.get(),
|
||||
player.parent(),
|
||||
);
|
||||
|
||||
if let Some(mut stack) = stack {
|
||||
|
|
@ -456,7 +453,7 @@ fn apply_temp_debuff_effect<Temp: DebuffingTempMarker>(
|
|||
stack.effects.push_back(effect);
|
||||
} else {
|
||||
commands
|
||||
.entity(player.get())
|
||||
.entity(player.parent())
|
||||
.insert(StatusEffectStack::<Temp> {
|
||||
effects: VecDeque::from([effect]),
|
||||
bonus,
|
||||
|
|
@ -465,8 +462,8 @@ fn apply_temp_debuff_effect<Temp: DebuffingTempMarker>(
|
|||
}
|
||||
|
||||
log!(logger, "used_debuff_temp", {
|
||||
actor: user.get(),
|
||||
recipient: player.get(),
|
||||
actor: user.parent(),
|
||||
recipient: player.parent(),
|
||||
weapon: weapon.0,
|
||||
immune: false,
|
||||
});
|
||||
|
|
@ -475,14 +472,14 @@ fn apply_temp_debuff_effect<Temp: DebuffingTempMarker>(
|
|||
|
||||
fn remove_temp_debuff_effect<Temp: DebuffingTempMarker>(
|
||||
In(entities): In<Vec<Entity>>,
|
||||
temp_q: Query<&Parent>,
|
||||
temp_q: Query<&ChildOf>,
|
||||
mut parent_q: Query<(&mut StatusEffectStack<Temp>, Has<TempDebuffImmunity<Temp>>)>,
|
||||
mut commands: Commands,
|
||||
_logger: Logger,
|
||||
mut effects: Effects,
|
||||
) {
|
||||
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 {
|
||||
continue;
|
||||
}
|
||||
|
|
@ -501,13 +498,13 @@ fn remove_temp_debuff_effect<Temp: DebuffingTempMarker>(
|
|||
std::any::type_name::<Temp>(),
|
||||
effective_factor,
|
||||
),
|
||||
player.get(),
|
||||
player.parent(),
|
||||
);
|
||||
|
||||
stack.effects.pop_front();
|
||||
} else {
|
||||
commands
|
||||
.entity(player.get())
|
||||
.entity(player.parent())
|
||||
.remove::<StatusEffectStack<Temp>>();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,14 +1,11 @@
|
|||
use bevy_ecs::prelude::*;
|
||||
use proxisim_models::{
|
||||
bundle::{
|
||||
bonus::{BonusPartDamageBonus, BonusValue, WeaponBonusType},
|
||||
player::PartDamageBonus,
|
||||
stat::{
|
||||
AdditiveBonus, AmmoControl, Clips, CritRate, DamageBonus, SimpleStatBonus,
|
||||
SimpleStatEffective, Speed, Strength, WeaponAccuracy,
|
||||
},
|
||||
use proxisim_models::bundle::{
|
||||
bonus::{BonusPartDamageBonus, BonusValue, WeaponBonusType},
|
||||
player::PartDamageBonus,
|
||||
stat::{
|
||||
AdditiveBonus, AmmoControl, Clips, CritRate, DamageBonus, SimpleStatBonus,
|
||||
SimpleStatEffective, Speed, Strength, WeaponAccuracy,
|
||||
},
|
||||
hierarchy::{HierarchyBuilder, Parent},
|
||||
};
|
||||
|
||||
use crate::{
|
||||
|
|
@ -197,7 +194,7 @@ impl BonusPartDamageBonus {
|
|||
} */
|
||||
|
||||
pub(crate) fn prepare_bonuses(
|
||||
bonus_q: Query<(&Parent, &WeaponBonusType, &BonusValue)>,
|
||||
bonus_q: Query<(&ChildOf, &WeaponBonusType, &BonusValue)>,
|
||||
clips_q: Query<&SimpleStatEffective<Clips>>,
|
||||
mut effects: Effects,
|
||||
mut commands: Commands,
|
||||
|
|
@ -207,227 +204,227 @@ pub(crate) fn prepare_bonuses(
|
|||
WeaponBonusType::Berserk => {
|
||||
effects.spawn(
|
||||
SimpleStatBonus::<DamageBonus>::new("beserk", value.0 / 100.0),
|
||||
weapon.get(),
|
||||
weapon.parent(),
|
||||
);
|
||||
effects.spawn(
|
||||
SimpleStatBonus::<WeaponAccuracy>::new("beserk", -value.0 / 2.0 / 50.0),
|
||||
weapon.get(),
|
||||
weapon.parent(),
|
||||
);
|
||||
}
|
||||
WeaponBonusType::Conserve => {
|
||||
effects.spawn(
|
||||
SimpleStatBonus::<AmmoControl>::new("conserve", value.0 / 100.0),
|
||||
weapon.get(),
|
||||
weapon.parent(),
|
||||
);
|
||||
}
|
||||
WeaponBonusType::Expose => {
|
||||
effects.spawn(
|
||||
SimpleStatBonus::<CritRate>::new("expose", (value.0 / 0.5) as u16),
|
||||
weapon.get(),
|
||||
weapon.parent(),
|
||||
);
|
||||
}
|
||||
WeaponBonusType::Grace => {
|
||||
effects.spawn(
|
||||
SimpleStatBonus::<DamageBonus>::new("grace", -value.0 / 2.0 / 100.0),
|
||||
weapon.get(),
|
||||
weapon.parent(),
|
||||
);
|
||||
effects.spawn(
|
||||
SimpleStatBonus::<WeaponAccuracy>::new("grace", value.0 / 50.0),
|
||||
weapon.get(),
|
||||
weapon.parent(),
|
||||
);
|
||||
}
|
||||
WeaponBonusType::Powerful => {
|
||||
effects.spawn(
|
||||
SimpleStatBonus::<DamageBonus>::new("powerful", value.0 / 100.0),
|
||||
weapon.get(),
|
||||
weapon.parent(),
|
||||
);
|
||||
}
|
||||
WeaponBonusType::Specialist => {
|
||||
effects.spawn(
|
||||
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(
|
||||
SimpleStatBonus::<Clips>::new("specialist", -(clips.value as i16)),
|
||||
weapon.get(),
|
||||
weapon.parent(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
WeaponBonusType::Empower => {
|
||||
commands
|
||||
.spawn(TurnTriggeredEffect::Bonus {
|
||||
.entity(weapon.parent())
|
||||
.with_child(TurnTriggeredEffect::Bonus {
|
||||
value: value.0,
|
||||
bonus: TurnTriggeredBonus::Empower,
|
||||
})
|
||||
.set_parent(weapon.get());
|
||||
});
|
||||
}
|
||||
WeaponBonusType::Quicken => {
|
||||
commands
|
||||
.spawn(TurnTriggeredEffect::Bonus {
|
||||
.entity(weapon.parent())
|
||||
.with_child(TurnTriggeredEffect::Bonus {
|
||||
value: value.0,
|
||||
bonus: TurnTriggeredBonus::Quicken,
|
||||
})
|
||||
.set_parent(weapon.get());
|
||||
});
|
||||
}
|
||||
|
||||
WeaponBonusType::Assassinate => {
|
||||
commands
|
||||
.spawn(FirstTurnEffect::Bonus {
|
||||
.entity(weapon.parent())
|
||||
.with_child(FirstTurnEffect::Bonus {
|
||||
value: value.0,
|
||||
bonus: FirstTurnBonus::Assassinate,
|
||||
})
|
||||
.set_parent(weapon.get());
|
||||
});
|
||||
}
|
||||
|
||||
WeaponBonusType::Blindfire => {
|
||||
commands
|
||||
.spawn(DamageProcEffect::MultiTurn {
|
||||
.entity(weapon.parent())
|
||||
.with_child(DamageProcEffect::MultiTurn {
|
||||
value: value.0,
|
||||
bonus: MultiTurnBonus::Blindfire,
|
||||
})
|
||||
.set_parent(weapon.get());
|
||||
});
|
||||
}
|
||||
WeaponBonusType::Fury => {
|
||||
commands
|
||||
.spawn(DamageProcEffect::MultiTurn {
|
||||
.entity(weapon.parent())
|
||||
.with_child(DamageProcEffect::MultiTurn {
|
||||
value: value.0,
|
||||
bonus: MultiTurnBonus::Fury,
|
||||
})
|
||||
.set_parent(weapon.get());
|
||||
});
|
||||
}
|
||||
WeaponBonusType::Rage => {
|
||||
commands
|
||||
.spawn(DamageProcEffect::MultiTurn {
|
||||
.entity(weapon.parent())
|
||||
.with_child(DamageProcEffect::MultiTurn {
|
||||
value: value.0,
|
||||
bonus: MultiTurnBonus::Rage,
|
||||
})
|
||||
.set_parent(weapon.get());
|
||||
});
|
||||
}
|
||||
WeaponBonusType::DoubleTap => {
|
||||
commands
|
||||
.spawn(DamageProcEffect::MultiTurn {
|
||||
.entity(weapon.parent())
|
||||
.with_child(DamageProcEffect::MultiTurn {
|
||||
value: value.0,
|
||||
bonus: MultiTurnBonus::DoubleTap,
|
||||
})
|
||||
.set_parent(weapon.get());
|
||||
});
|
||||
}
|
||||
|
||||
WeaponBonusType::Achilles => {
|
||||
commands
|
||||
.spawn(PartDamageBonus::WeaponBonus {
|
||||
.entity(weapon.parent())
|
||||
.with_child(PartDamageBonus::WeaponBonus {
|
||||
value: value.0 / 100.0,
|
||||
bonus: BonusPartDamageBonus::Achilles,
|
||||
})
|
||||
.set_parent(weapon.get());
|
||||
});
|
||||
}
|
||||
WeaponBonusType::Cupid => {
|
||||
commands
|
||||
.spawn(PartDamageBonus::WeaponBonus {
|
||||
.entity(weapon.parent())
|
||||
.with_child(PartDamageBonus::WeaponBonus {
|
||||
value: value.0 / 100.0,
|
||||
bonus: BonusPartDamageBonus::Cupid,
|
||||
})
|
||||
.set_parent(weapon.get());
|
||||
});
|
||||
}
|
||||
WeaponBonusType::Crusher => {
|
||||
commands
|
||||
.spawn(PartDamageBonus::WeaponBonus {
|
||||
.entity(weapon.parent())
|
||||
.with_child(PartDamageBonus::WeaponBonus {
|
||||
value: value.0 / 100.0,
|
||||
bonus: BonusPartDamageBonus::Crusher,
|
||||
})
|
||||
.set_parent(weapon.get());
|
||||
});
|
||||
}
|
||||
WeaponBonusType::Deadeye => {
|
||||
commands
|
||||
.spawn(PartDamageBonus::WeaponBonus {
|
||||
.entity(weapon.parent())
|
||||
.with_child(PartDamageBonus::WeaponBonus {
|
||||
value: value.0 / 100.0,
|
||||
bonus: BonusPartDamageBonus::Deadeye,
|
||||
})
|
||||
.set_parent(weapon.get());
|
||||
});
|
||||
}
|
||||
WeaponBonusType::Throttle => {
|
||||
commands
|
||||
.spawn(PartDamageBonus::WeaponBonus {
|
||||
.entity(weapon.parent())
|
||||
.with_child(PartDamageBonus::WeaponBonus {
|
||||
value: value.0 / 100.0,
|
||||
bonus: BonusPartDamageBonus::Throttle,
|
||||
})
|
||||
.set_parent(weapon.get());
|
||||
});
|
||||
}
|
||||
WeaponBonusType::Roshambo => {
|
||||
commands
|
||||
.spawn(PartDamageBonus::WeaponBonus {
|
||||
.entity(weapon.parent())
|
||||
.with_child(PartDamageBonus::WeaponBonus {
|
||||
value: value.0 / 100.0,
|
||||
bonus: BonusPartDamageBonus::Roshambo,
|
||||
})
|
||||
.set_parent(weapon.get());
|
||||
});
|
||||
}
|
||||
|
||||
WeaponBonusType::Cripple => {
|
||||
commands
|
||||
.spawn(DamageProcEffect::OpponentEffect {
|
||||
.entity(weapon.parent())
|
||||
.with_child(DamageProcEffect::OpponentEffect {
|
||||
value: value.0,
|
||||
bonus: OpponentStatusEffect::Cripple,
|
||||
})
|
||||
.set_parent(weapon.get());
|
||||
});
|
||||
}
|
||||
WeaponBonusType::Demoralise => {
|
||||
commands
|
||||
.spawn(DamageProcEffect::OpponentEffect {
|
||||
.entity(weapon.parent())
|
||||
.with_child(DamageProcEffect::OpponentEffect {
|
||||
value: value.0,
|
||||
bonus: OpponentStatusEffect::Demoralise,
|
||||
})
|
||||
.set_parent(weapon.get());
|
||||
});
|
||||
}
|
||||
WeaponBonusType::Freeze => {
|
||||
commands
|
||||
.spawn(DamageProcEffect::OpponentEffect {
|
||||
.entity(weapon.parent())
|
||||
.with_child(DamageProcEffect::OpponentEffect {
|
||||
value: value.0,
|
||||
bonus: OpponentStatusEffect::Freeze,
|
||||
})
|
||||
.set_parent(weapon.get());
|
||||
});
|
||||
}
|
||||
WeaponBonusType::Slow => {
|
||||
commands
|
||||
.spawn(DamageProcEffect::OpponentEffect {
|
||||
.entity(weapon.parent())
|
||||
.with_child(DamageProcEffect::OpponentEffect {
|
||||
value: value.0,
|
||||
bonus: OpponentStatusEffect::Slow,
|
||||
})
|
||||
.set_parent(weapon.get());
|
||||
});
|
||||
}
|
||||
WeaponBonusType::Toxin => {
|
||||
commands
|
||||
.spawn(DamageProcEffect::OpponentEffect {
|
||||
.entity(weapon.parent())
|
||||
.with_child(DamageProcEffect::OpponentEffect {
|
||||
value: value.0,
|
||||
bonus: OpponentStatusEffect::Toxin,
|
||||
})
|
||||
.set_parent(weapon.get());
|
||||
});
|
||||
}
|
||||
WeaponBonusType::Weaken => {
|
||||
commands
|
||||
.spawn(DamageProcEffect::OpponentEffect {
|
||||
.entity(weapon.parent())
|
||||
.with_child(DamageProcEffect::OpponentEffect {
|
||||
value: value.0,
|
||||
bonus: OpponentStatusEffect::Weaken,
|
||||
})
|
||||
.set_parent(weapon.get());
|
||||
});
|
||||
}
|
||||
WeaponBonusType::Wither => {
|
||||
commands
|
||||
.spawn(DamageProcEffect::OpponentEffect {
|
||||
.entity(weapon.parent())
|
||||
.with_child(DamageProcEffect::OpponentEffect {
|
||||
value: value.0,
|
||||
bonus: OpponentStatusEffect::Wither,
|
||||
})
|
||||
.set_parent(weapon.get());
|
||||
});
|
||||
}
|
||||
|
||||
WeaponBonusType::Motivate => {
|
||||
commands
|
||||
.spawn(DamageProcEffect::SelfEffect {
|
||||
.entity(weapon.parent())
|
||||
.with_child(DamageProcEffect::SelfEffect {
|
||||
value: value.0,
|
||||
bonus: SelfStatusEffect::Motivate,
|
||||
})
|
||||
.set_parent(weapon.get());
|
||||
});
|
||||
}
|
||||
|
||||
val => unimplemented!("{val:?}"),
|
||||
|
|
|
|||
|
|
@ -1,25 +1,22 @@
|
|||
use bevy_ecs::prelude::*;
|
||||
use proxisim_models::{
|
||||
bundle::{
|
||||
passive::{Education, EducationPartDamageBonus, FactionUpgrades, Merits},
|
||||
player::{Current, PartDamageBonus, Weapons},
|
||||
stat::{
|
||||
AdditiveBonus, AmmoControl, ClipSize, Clips, CritRate, DamageBonus, Dexterity,
|
||||
SimpleStatBonus, SimpleStatEffective, WeaponAccuracy,
|
||||
},
|
||||
weapon::{
|
||||
Ammo, EquippedMods, Experience, Japanese, NeedsReload, Usable, Weapon, WeaponCategory,
|
||||
WeaponMod, WeaponSlot,
|
||||
},
|
||||
use proxisim_models::bundle::{
|
||||
passive::{Education, EducationPartDamageBonus, FactionUpgrades, Merits},
|
||||
player::{Current, PartDamageBonus, Weapons},
|
||||
stat::{
|
||||
AdditiveBonus, AmmoControl, ClipSize, Clips, CritRate, DamageBonus, Dexterity,
|
||||
SimpleStatBonus, SimpleStatEffective, WeaponAccuracy,
|
||||
},
|
||||
weapon::{
|
||||
Ammo, EquippedMods, Experience, Japanese, NeedsReload, Usable, Weapon, WeaponCategory,
|
||||
WeaponMod, WeaponSlot,
|
||||
},
|
||||
hierarchy::{HierarchyBuilder, Parent},
|
||||
};
|
||||
|
||||
use crate::{
|
||||
Stages,
|
||||
effect::{Effects, TurnLimitedEffect},
|
||||
log,
|
||||
log::Logger,
|
||||
Stages,
|
||||
};
|
||||
|
||||
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(
|
||||
weapon_q: Query<(
|
||||
Entity,
|
||||
|
|
@ -184,7 +162,7 @@ fn apply_passives(
|
|||
&WeaponCategory,
|
||||
&WeaponSlot,
|
||||
Has<Japanese>,
|
||||
&Parent,
|
||||
&ChildOf,
|
||||
)>,
|
||||
player_q: Query<(&Merits, &Education, &FactionUpgrades)>,
|
||||
mut effects: Effects,
|
||||
|
|
@ -331,8 +309,8 @@ fn apply_passives(
|
|||
weapon,
|
||||
);
|
||||
commands
|
||||
.spawn(TurnTriggeredEffect::Mod(TurnTriggeredMod::Bipod))
|
||||
.set_parent(weapon);
|
||||
.entity(weapon)
|
||||
.with_child(TurnTriggeredEffect::Mod(TurnTriggeredMod::Bipod));
|
||||
}
|
||||
WeaponMod::Tripod => {
|
||||
effects.spawn(
|
||||
|
|
@ -340,40 +318,38 @@ fn apply_passives(
|
|||
weapon,
|
||||
);
|
||||
commands
|
||||
.spawn(TurnTriggeredEffect::Mod(TurnTriggeredMod::Tripod))
|
||||
.set_parent(weapon);
|
||||
.entity(weapon)
|
||||
.with_child(TurnTriggeredEffect::Mod(TurnTriggeredMod::Tripod));
|
||||
}
|
||||
WeaponMod::SmallLight => {
|
||||
commands
|
||||
.spawn(TurnTriggeredEffect::Mod(TurnTriggeredMod::SmallLight))
|
||||
.set_parent(weapon);
|
||||
.entity(weapon)
|
||||
.with_child(TurnTriggeredEffect::Mod(TurnTriggeredMod::SmallLight));
|
||||
}
|
||||
WeaponMod::PrecisionLight => {
|
||||
commands
|
||||
.spawn(TurnTriggeredEffect::Mod(TurnTriggeredMod::PrecisionLight))
|
||||
.set_parent(weapon);
|
||||
.entity(weapon)
|
||||
.with_child(TurnTriggeredEffect::Mod(TurnTriggeredMod::PrecisionLight));
|
||||
}
|
||||
WeaponMod::TacticalIlluminator => {
|
||||
commands
|
||||
.spawn(TurnTriggeredEffect::Mod(
|
||||
TurnTriggeredMod::TacticalIlluminator,
|
||||
))
|
||||
.set_parent(weapon);
|
||||
commands.entity(weapon).with_child(TurnTriggeredEffect::Mod(
|
||||
TurnTriggeredMod::TacticalIlluminator,
|
||||
));
|
||||
}
|
||||
WeaponMod::AdjustableTrigger => {
|
||||
commands
|
||||
.spawn(FirstTurnEffect::Mod(FirstTurnMod::AdjustableTrigger))
|
||||
.set_parent(weapon);
|
||||
.entity(weapon)
|
||||
.with_child(FirstTurnEffect::Mod(FirstTurnMod::AdjustableTrigger));
|
||||
}
|
||||
WeaponMod::HairTrigger => {
|
||||
commands
|
||||
.spawn(FirstTurnEffect::Mod(FirstTurnMod::HairTrigger))
|
||||
.set_parent(weapon);
|
||||
.entity(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 {
|
||||
WeaponCategory::HeavyArtillery => (
|
||||
|
|
@ -445,10 +421,10 @@ fn apply_passives(
|
|||
|
||||
if education.bio2380 {
|
||||
commands
|
||||
.spawn(PartDamageBonus::Education(
|
||||
.entity(weapon)
|
||||
.with_child(PartDamageBonus::Education(
|
||||
EducationPartDamageBonus::Bio2380,
|
||||
))
|
||||
.set_parent(weapon);
|
||||
));
|
||||
}
|
||||
|
||||
if mastery > 0 {
|
||||
|
|
@ -490,7 +466,7 @@ fn reload_weapon(
|
|||
mut weapon_q: Query<
|
||||
(
|
||||
Entity,
|
||||
&Parent,
|
||||
&ChildOf,
|
||||
&mut Ammo,
|
||||
&mut SimpleStatEffective<Clips>,
|
||||
&SimpleStatEffective<ClipSize>,
|
||||
|
|
@ -505,7 +481,7 @@ fn reload_weapon(
|
|||
clips.value -= 1;
|
||||
|
||||
log!(logger, "reload_weapon", {
|
||||
actor: player.get(),
|
||||
actor: player.parent(),
|
||||
weapon
|
||||
});
|
||||
|
||||
|
|
@ -530,18 +506,17 @@ fn restore_ammo(
|
|||
}
|
||||
|
||||
fn apply_first_turn_effects(
|
||||
effect_q: Query<(&Parent, &FirstTurnEffect)>,
|
||||
player_q: Query<&Parent>,
|
||||
effect_q: Query<(&ChildOf, &FirstTurnEffect)>,
|
||||
player_q: Query<&ChildOf>,
|
||||
mut effects: Effects,
|
||||
) {
|
||||
for (weapon, effect) in effect_q.iter() {
|
||||
let player = player_q.get(weapon.get()).unwrap();
|
||||
effect.spawn(&mut effects, weapon.get(), player.get());
|
||||
let player = player_q.get(weapon.parent()).unwrap();
|
||||
effect.spawn(&mut effects, weapon.parent(), player.parent());
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
// end of the run
|
||||
stages.snapshot.add_systems(apply_first_turn_effects);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue