This commit is contained in:
TotallyNot 2025-11-03 16:36:45 +01:00
parent e7d6b74aab
commit 35413b563c
Signed by: pyrite
GPG key ID: 7F1BA9170CD35D15
33 changed files with 10238 additions and 1891 deletions

View file

@ -1,102 +1,26 @@
use bevy_ecs::prelude::*;
use crate::{
effect::{Effects, TurnLimitedEffect},
hierarchy::{HierarchyBuilder, Parent},
player::{
stats::{
use proxisim_models::{
bundle::{
bonus::{BonusPartDamageBonus, BonusValue, WeaponBonusType},
player::PartDamageBonus,
stat::{
AdditiveBonus, AmmoControl, Clips, CritRate, DamageBonus, SimpleStatBonus,
SimpleStatEffective, Speed, Strength, WeaponAccuracy,
},
status_effect::{
AdditiveStatusEffect, Crippled, Demoralise, Frozen, Motivate, Slow, Weakened, Withered,
},
BodyPart, PartDamageBonus,
},
hierarchy::{HierarchyBuilder, Parent},
};
use crate::{
Stages,
effect::{Effects, TurnLimitedEffect},
player::status_effect::{
AdditiveStatusEffect, Crippled, Demoralise, Frozen, Motivate, Slow, Weakened, Withered,
},
};
use super::{DamageProcEffect, FirstTurnEffect, TurnTriggeredEffect};
#[derive(Component, Debug, Clone, Copy)]
#[cfg_attr(feature = "json", derive(serde::Deserialize))]
#[cfg_attr(feature = "json", serde(rename_all = "snake_case"))]
pub enum WeaponBonus {
// Weapon passives
Berserk,
Conserve,
Expose,
Grace,
Powerful,
Specialist,
// Turn triggered passives
Empower,
Quicken,
// First turn effects
Assassinate,
// Additive status effects triggered by damaging hits
Cripple,
Demoralise,
Freeze,
Motivate,
Slow,
Toxin,
Weaken,
Wither,
// DOT status effects
Bleed,
Burning,
Lacerate,
Poison,
SevereBurning,
// Other status effects
Eviscerate,
Paralyse,
Schock,
Stun,
// Multi attack bonuses
Blindfire,
Fury,
DoubleTap,
Rage,
// Body part multipliers
Achilles,
Crusher,
Cupid,
Deadeye,
Roshambo,
Throttle,
// Attack nullification types
Homerun,
Parry,
}
#[derive(Component)]
pub struct BonusValue(f32);
#[derive(Bundle)]
pub struct WeaponBonusBundle {
pub bonus: WeaponBonus,
pub value: BonusValue,
}
impl WeaponBonusBundle {
pub fn new(bonus: WeaponBonus, value: f32) -> Self {
Self {
bonus,
value: BonusValue(value),
}
}
}
#[derive(Clone, Copy)]
pub enum TurnTriggeredBonus {
Empower,
@ -188,7 +112,7 @@ impl OpponentStatusEffect {
Self::Slow => {
effects.spawn(AdditiveStatusEffect::<1, Slow>::default(), target);
}
Self::Toxin => match rng.gen_range(0..4) {
Self::Toxin => match rng.random_range(0..4) {
0 => OpponentStatusEffect::Cripple.spawn(target, effects, rng),
1 => OpponentStatusEffect::Slow.spawn(target, effects, rng),
2 => OpponentStatusEffect::Weaken.spawn(target, effects, rng),
@ -219,7 +143,7 @@ impl SelfStatusEffect {
}
}
#[derive(Clone, Copy)]
/* #[derive(Clone, Copy)]
pub enum BonusPartDamageBonus {
Achilles,
Crusher,
@ -270,21 +194,17 @@ impl BonusPartDamageBonus {
}
}
}
}
} */
pub(crate) fn prepare_bonuses(
bonus_q: Query<(
&Parent,
&WeaponBonus,
&BonusValue,
Option<&SimpleStatEffective<Clips>>,
)>,
bonus_q: Query<(&Parent, &WeaponBonusType, &BonusValue)>,
clips_q: Query<&SimpleStatEffective<Clips>>,
mut effects: Effects,
mut commands: Commands,
) {
for (weapon, bonus, value, clips) in bonus_q.iter() {
for (weapon, bonus, value) in bonus_q.iter() {
match bonus {
WeaponBonus::Berserk => {
WeaponBonusType::Berserk => {
effects.spawn(
SimpleStatBonus::<DamageBonus>::new("beserk", value.0 / 100.0),
weapon.get(),
@ -294,19 +214,19 @@ pub(crate) fn prepare_bonuses(
weapon.get(),
);
}
WeaponBonus::Conserve => {
WeaponBonusType::Conserve => {
effects.spawn(
SimpleStatBonus::<AmmoControl>::new("conserve", value.0 / 100.0),
weapon.get(),
);
}
WeaponBonus::Expose => {
WeaponBonusType::Expose => {
effects.spawn(
SimpleStatBonus::<CritRate>::new("expose", (value.0 / 0.5) as u16),
weapon.get(),
);
}
WeaponBonus::Grace => {
WeaponBonusType::Grace => {
effects.spawn(
SimpleStatBonus::<DamageBonus>::new("grace", -value.0 / 2.0 / 100.0),
weapon.get(),
@ -316,27 +236,27 @@ pub(crate) fn prepare_bonuses(
weapon.get(),
);
}
WeaponBonus::Powerful => {
WeaponBonusType::Powerful => {
effects.spawn(
SimpleStatBonus::<DamageBonus>::new("powerful", value.0 / 100.0),
weapon.get(),
);
}
WeaponBonus::Specialist => {
WeaponBonusType::Specialist => {
effects.spawn(
SimpleStatBonus::<DamageBonus>::new("specialist", value.0 / 100.0),
weapon.get(),
);
effects.spawn(
SimpleStatBonus::<Clips>::new(
"specialist",
-clips.map(|c| c.value as i16).unwrap_or_default(),
),
weapon.get(),
);
if let Ok(clips) = clips_q.get(weapon.get()) {
effects.spawn(
SimpleStatBonus::<Clips>::new("specialist", -(clips.value as i16)),
weapon.get(),
);
}
}
WeaponBonus::Empower => {
WeaponBonusType::Empower => {
commands
.spawn(TurnTriggeredEffect::Bonus {
value: value.0,
@ -344,7 +264,7 @@ pub(crate) fn prepare_bonuses(
})
.set_parent(weapon.get());
}
WeaponBonus::Quicken => {
WeaponBonusType::Quicken => {
commands
.spawn(TurnTriggeredEffect::Bonus {
value: value.0,
@ -353,7 +273,7 @@ pub(crate) fn prepare_bonuses(
.set_parent(weapon.get());
}
WeaponBonus::Assassinate => {
WeaponBonusType::Assassinate => {
commands
.spawn(FirstTurnEffect::Bonus {
value: value.0,
@ -362,7 +282,7 @@ pub(crate) fn prepare_bonuses(
.set_parent(weapon.get());
}
WeaponBonus::Blindfire => {
WeaponBonusType::Blindfire => {
commands
.spawn(DamageProcEffect::MultiTurn {
value: value.0,
@ -370,7 +290,7 @@ pub(crate) fn prepare_bonuses(
})
.set_parent(weapon.get());
}
WeaponBonus::Fury => {
WeaponBonusType::Fury => {
commands
.spawn(DamageProcEffect::MultiTurn {
value: value.0,
@ -378,7 +298,7 @@ pub(crate) fn prepare_bonuses(
})
.set_parent(weapon.get());
}
WeaponBonus::Rage => {
WeaponBonusType::Rage => {
commands
.spawn(DamageProcEffect::MultiTurn {
value: value.0,
@ -386,7 +306,7 @@ pub(crate) fn prepare_bonuses(
})
.set_parent(weapon.get());
}
WeaponBonus::DoubleTap => {
WeaponBonusType::DoubleTap => {
commands
.spawn(DamageProcEffect::MultiTurn {
value: value.0,
@ -395,7 +315,7 @@ pub(crate) fn prepare_bonuses(
.set_parent(weapon.get());
}
WeaponBonus::Achilles => {
WeaponBonusType::Achilles => {
commands
.spawn(PartDamageBonus::WeaponBonus {
value: value.0 / 100.0,
@ -403,7 +323,7 @@ pub(crate) fn prepare_bonuses(
})
.set_parent(weapon.get());
}
WeaponBonus::Cupid => {
WeaponBonusType::Cupid => {
commands
.spawn(PartDamageBonus::WeaponBonus {
value: value.0 / 100.0,
@ -411,7 +331,7 @@ pub(crate) fn prepare_bonuses(
})
.set_parent(weapon.get());
}
WeaponBonus::Crusher => {
WeaponBonusType::Crusher => {
commands
.spawn(PartDamageBonus::WeaponBonus {
value: value.0 / 100.0,
@ -419,7 +339,7 @@ pub(crate) fn prepare_bonuses(
})
.set_parent(weapon.get());
}
WeaponBonus::Deadeye => {
WeaponBonusType::Deadeye => {
commands
.spawn(PartDamageBonus::WeaponBonus {
value: value.0 / 100.0,
@ -427,7 +347,7 @@ pub(crate) fn prepare_bonuses(
})
.set_parent(weapon.get());
}
WeaponBonus::Throttle => {
WeaponBonusType::Throttle => {
commands
.spawn(PartDamageBonus::WeaponBonus {
value: value.0 / 100.0,
@ -435,7 +355,7 @@ pub(crate) fn prepare_bonuses(
})
.set_parent(weapon.get());
}
WeaponBonus::Roshambo => {
WeaponBonusType::Roshambo => {
commands
.spawn(PartDamageBonus::WeaponBonus {
value: value.0 / 100.0,
@ -444,7 +364,7 @@ pub(crate) fn prepare_bonuses(
.set_parent(weapon.get());
}
WeaponBonus::Cripple => {
WeaponBonusType::Cripple => {
commands
.spawn(DamageProcEffect::OpponentEffect {
value: value.0,
@ -452,7 +372,7 @@ pub(crate) fn prepare_bonuses(
})
.set_parent(weapon.get());
}
WeaponBonus::Demoralise => {
WeaponBonusType::Demoralise => {
commands
.spawn(DamageProcEffect::OpponentEffect {
value: value.0,
@ -460,7 +380,7 @@ pub(crate) fn prepare_bonuses(
})
.set_parent(weapon.get());
}
WeaponBonus::Freeze => {
WeaponBonusType::Freeze => {
commands
.spawn(DamageProcEffect::OpponentEffect {
value: value.0,
@ -468,7 +388,7 @@ pub(crate) fn prepare_bonuses(
})
.set_parent(weapon.get());
}
WeaponBonus::Slow => {
WeaponBonusType::Slow => {
commands
.spawn(DamageProcEffect::OpponentEffect {
value: value.0,
@ -476,7 +396,7 @@ pub(crate) fn prepare_bonuses(
})
.set_parent(weapon.get());
}
WeaponBonus::Toxin => {
WeaponBonusType::Toxin => {
commands
.spawn(DamageProcEffect::OpponentEffect {
value: value.0,
@ -484,7 +404,7 @@ pub(crate) fn prepare_bonuses(
})
.set_parent(weapon.get());
}
WeaponBonus::Weaken => {
WeaponBonusType::Weaken => {
commands
.spawn(DamageProcEffect::OpponentEffect {
value: value.0,
@ -492,7 +412,7 @@ pub(crate) fn prepare_bonuses(
})
.set_parent(weapon.get());
}
WeaponBonus::Wither => {
WeaponBonusType::Wither => {
commands
.spawn(DamageProcEffect::OpponentEffect {
value: value.0,
@ -501,7 +421,7 @@ pub(crate) fn prepare_bonuses(
.set_parent(weapon.get());
}
WeaponBonus::Motivate => {
WeaponBonusType::Motivate => {
commands
.spawn(DamageProcEffect::SelfEffect {
value: value.0,

View file

@ -1,19 +1,25 @@
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,
},
},
hierarchy::{HierarchyBuilder, Parent},
};
use crate::{
effect::{Effects, TurnLimitedEffect},
hierarchy::{HierarchyBuilder, Parent},
log,
log::Logger,
passives::{Education, EducationPartDamageBonus, FactionUpgrades, Merits},
player::{
stats::{
AdditiveBonus, AmmoControl, ClipSize, Clips, CritRate, DamageBonus, Dexterity,
SimpleStatBonus, SimpleStatBundle, SimpleStatEffective, WeaponAccuracy,
},
Current, PartDamageBonus, Weapons,
},
Id, Name, Stages,
Stages,
};
use self::bonus::{
@ -23,102 +29,6 @@ use self::bonus::{
pub mod bonus;
pub mod temp;
#[derive(Component)]
pub struct Usable;
#[derive(Component)]
pub struct Weapon;
#[derive(Component, Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "json", derive(serde::Deserialize))]
#[cfg_attr(feature = "json", serde(rename_all = "snake_case"))]
pub enum WeaponSlot {
Primary,
Secondary,
Melee,
Temporary,
Fists,
Kick,
}
#[derive(Component, Debug, Clone, Copy)]
pub enum WeaponVerb {
Hit,
Kicked,
Fired,
Threw,
Exploded,
}
#[derive(Component, Clone, Copy)]
#[cfg_attr(feature = "json", derive(serde::Deserialize))]
#[cfg_attr(feature = "json", serde(rename_all = "snake_case"))]
pub enum WeaponCategory {
HeavyArtillery,
MachineGun,
Rifle,
Smg,
Shotgun,
Pistol,
Clubbing,
Piercing,
Slashing,
Mechanical,
Temporary,
HandToHand,
}
#[derive(Component, Debug)]
pub struct DamageStat(pub f32);
#[derive(Component)]
pub struct Japanese;
#[derive(Component)]
pub struct Ammo(pub u16);
#[derive(Component)]
pub struct RateOfFire(pub [u16; 2]);
#[derive(Component)]
pub struct NeedsReload;
#[derive(Clone, Copy)]
#[cfg_attr(feature = "json", derive(serde::Deserialize))]
#[cfg_attr(feature = "json", serde(rename_all = "snake_case"))]
pub enum WeaponMod {
ReflexSight,
HolographicSight,
AcogSight,
ThermalSight,
Laser1mw,
Laser5mw,
Laser30mw,
Laser100mw,
SmallSuppressor,
StandardSuppressor,
LargeSuppressor,
ExtendedMags,
HighCapacityMags,
ExtraClip,
ExtraClip2,
AdjustableTrigger,
HairTrigger,
Bipod,
Tripod,
CustomGrip,
SkeetChoke,
ImprovedChoke,
FullChoke,
RecoilPad,
StandardBrake,
HeavyDutyBrake,
TacticalBrake,
SmallLight,
PrecisionLight,
TacticalIlluminator,
}
#[derive(Clone, Copy)]
pub enum TurnTriggeredMod {
Bipod,
@ -247,109 +157,6 @@ pub enum DamageProcEffect {
},
}
#[derive(Component)]
pub struct EquippedMods(pub Vec<WeaponMod>);
#[derive(Component)]
pub struct Experience(pub f32);
#[derive(Bundle)]
pub struct WeaponBundle {
pub usable: Usable,
pub weapon: Weapon,
pub name: Name,
pub id: Id,
pub verb: WeaponVerb,
pub slot: WeaponSlot,
}
#[derive(Bundle)]
pub struct DamagingWeaponBundle {
pub crit_rate: SimpleStatBundle<CritRate>,
pub dmg: DamageStat,
pub acc: SimpleStatBundle<WeaponAccuracy>,
pub dmg_bonus: SimpleStatBundle<DamageBonus>,
pub equipped_mods: EquippedMods,
pub experience: Experience,
pub category: WeaponCategory,
}
#[derive(Bundle)]
pub struct AmmoWeaponBundle {
pub ammo: Ammo,
pub clips: SimpleStatBundle<Clips>,
pub clip_size: SimpleStatBundle<ClipSize>,
pub rate_of_fire: RateOfFire,
pub ammo_control: SimpleStatBundle<AmmoControl>,
}
impl WeaponBundle {
pub fn new(name: String, id: usize, verb: WeaponVerb, slot: WeaponSlot) -> Self {
Self {
usable: Usable,
weapon: Weapon,
name: Name(name),
id: Id(id),
verb,
slot,
}
}
pub fn fists(id: usize) -> Self {
Self::new("Fists".to_owned(), id, WeaponVerb::Hit, WeaponSlot::Fists)
}
pub fn kick(id: usize) -> Self {
Self::new("Kick".to_owned(), id, WeaponVerb::Kicked, WeaponSlot::Kick)
}
}
impl DamagingWeaponBundle {
pub fn new(
dmg: f32,
acc: f32,
mods: Vec<WeaponMod>,
exp: f32,
category: WeaponCategory,
) -> Self {
Self {
crit_rate: SimpleStatBundle::new(0),
dmg: DamageStat(dmg / 10.0),
acc: SimpleStatBundle::new((acc - 50.0) / 50.0),
dmg_bonus: SimpleStatBundle::new(1.0),
equipped_mods: EquippedMods(mods),
experience: Experience(exp),
category,
}
}
pub fn fists() -> Self {
// NOTE: The accuracy value is taken from the attack page. The damage value here differs
// from the one in Proxima's simulator, but in some quick tests 10.0 proofed to be a better fit
// This might have changed in the weapon damage update
Self::new(10.0, 50.0, Vec::default(), 0.0, WeaponCategory::HandToHand)
}
pub fn kick() -> Self {
// NOTE: The accuracy value is taken from the attack page. The damage value here differs
// from the one in Proxima's simulator, but in some quick tests 30.0 proofed to be a better fit
// This might have changed in the weapon damage update
Self::new(30.0, 40.0, Vec::default(), 0.0, WeaponCategory::HandToHand)
}
}
impl AmmoWeaponBundle {
pub fn new(clips: u16, clip_size: u16, rof: [u16; 2]) -> Self {
Self {
ammo: Ammo(clip_size),
clips: SimpleStatBundle::new(clips - 1),
clip_size: SimpleStatBundle::new(clip_size),
rate_of_fire: RateOfFire(rof),
ammo_control: SimpleStatBundle::new(0.0),
}
}
}
fn set_owner(weapons_q: Query<(Entity, &Weapons)>, mut commands: Commands) {
for (player, weapons) in weapons_q.iter() {
if let Some(primary) = weapons.primary {
@ -364,10 +171,8 @@ fn set_owner(weapons_q: Query<(Entity, &Weapons)>, mut commands: Commands) {
if let Some(temp) = weapons.temporary {
commands.entity(temp).set_parent(player);
}
commands.entity(weapons.fists.unwrap()).set_parent(player);
if let Some(kick) = weapons.kick {
commands.entity(kick).set_parent(player);
}
commands.entity(weapons.fists).set_parent(player);
commands.entity(weapons.kick).set_parent(player);
}
}

View file

@ -1,202 +1,33 @@
use bevy_ecs::prelude::*;
use strum::Display;
use crate::{
effect::Effects,
player::{
status_effect::{
ConcussionGrenade, FlashGrenade, PepperSpray, Sand, SmokeGrenade, TearGas,
TempDebuffEffect,
},
Current, CurrentTarget,
},
Stages,
use proxisim_models::bundle::{
player::{Current, CurrentTarget, Player},
weapon::{BuffingTemp, DebuffingTemp, Usable, Uses},
};
use super::{DamagingWeaponBundle, Usable, WeaponBundle, WeaponCategory, WeaponSlot, WeaponVerb};
#[derive(Component, Default)]
pub struct NonTargeted;
#[derive(Component, Default)]
pub struct Temporary;
#[derive(Component)]
pub struct Uses(pub u16);
impl Default for Uses {
fn default() -> Self {
Self(1)
}
}
use crate::{
Stages,
effect::Effects,
log,
log::Logger,
player::status_effect::{
AdditiveStatusEffect, ConcussionGrenade, FlashGrenade, Hardened, Hastened, PepperSpray,
Sharpened, SmokeGrenade, Strengthened, TearGas, TempDebuffEffect,
},
};
#[derive(Component)]
pub struct AssociatedWeapon(pub Entity);
#[derive(Component, Debug, Clone, Copy, Display)]
pub enum DebuffingTemp {
TearGas,
SmokeGrenade,
PepperSpray,
ConcussionGrenade,
FlashGrenade,
Sand,
}
#[derive(Bundle, Default)]
pub struct TemporaryBundle {
pub temporary: Temporary,
pub uses: Uses,
}
#[derive(Debug, Clone, Copy)]
#[cfg_attr(feature = "json", derive(serde::Deserialize))]
pub enum Temp {
Heg,
NailBomb,
Grenade,
Fireworks,
ClaymoreMine,
TearGas,
SmokeGrenade,
PepperSpray,
ConcussionGrenade,
FlashGrenade,
Sand,
}
impl Temp {
pub fn spawn(self, world: &mut World, id: usize) -> EntityWorldMut<'_> {
match self {
Self::Heg => world.spawn((
WeaponBundle::new(
"HEG".to_owned(),
id,
WeaponVerb::Exploded,
WeaponSlot::Temporary,
),
DamagingWeaponBundle::new(90.00, 116.00, vec![], 0.0, WeaponCategory::Temporary),
TemporaryBundle::default(),
NonTargeted,
)),
Self::NailBomb => world.spawn((
WeaponBundle::new(
"Nail Bomb".to_owned(),
id,
WeaponVerb::Exploded,
WeaponSlot::Temporary,
),
DamagingWeaponBundle::new(99.00, 106.00, vec![], 0.0, WeaponCategory::Temporary),
TemporaryBundle::default(),
NonTargeted,
)),
Self::Grenade => world.spawn((
WeaponBundle::new(
"Grenade".to_owned(),
id,
WeaponVerb::Exploded,
WeaponSlot::Temporary,
),
DamagingWeaponBundle::new(86.00, 106.00, vec![], 0.0, WeaponCategory::Temporary),
TemporaryBundle::default(),
NonTargeted,
)),
Self::Fireworks => world.spawn((
WeaponBundle::new(
"Fireworks".to_owned(),
id,
WeaponVerb::Exploded,
WeaponSlot::Temporary,
),
DamagingWeaponBundle::new(45.00, 34.00, vec![], 0.0, WeaponCategory::Temporary),
TemporaryBundle::default(),
NonTargeted,
)),
Self::ClaymoreMine => world.spawn((
WeaponBundle::new(
"Claymore Mine".to_owned(),
id,
WeaponVerb::Exploded,
WeaponSlot::Temporary,
),
DamagingWeaponBundle::new(83.00, 27.00, vec![], 0.0, WeaponCategory::Temporary),
TemporaryBundle::default(),
NonTargeted,
)),
Self::TearGas => world.spawn((
WeaponBundle::new(
"Tear Gas".to_owned(),
id,
WeaponVerb::Exploded,
WeaponSlot::Temporary,
),
TemporaryBundle::default(),
DebuffingTemp::TearGas,
)),
Self::SmokeGrenade => world.spawn((
WeaponBundle::new(
"Smoke Grenade".to_owned(),
id,
WeaponVerb::Exploded,
WeaponSlot::Temporary,
),
TemporaryBundle::default(),
DebuffingTemp::SmokeGrenade,
)),
Self::PepperSpray => world.spawn((
WeaponBundle::new(
"Pepper Spray".to_owned(),
id,
WeaponVerb::Exploded,
WeaponSlot::Temporary,
),
TemporaryBundle::default(),
DebuffingTemp::PepperSpray,
)),
Self::ConcussionGrenade => world.spawn((
WeaponBundle::new(
"Concussion Grenade".to_owned(),
id,
WeaponVerb::Exploded,
WeaponSlot::Temporary,
),
TemporaryBundle::default(),
DebuffingTemp::ConcussionGrenade,
)),
Self::FlashGrenade => world.spawn((
WeaponBundle::new(
"Flash Grenade".to_owned(),
id,
WeaponVerb::Exploded,
WeaponSlot::Temporary,
),
TemporaryBundle::default(),
DebuffingTemp::FlashGrenade,
)),
Self::Sand => world.spawn((
WeaponBundle::new(
"Sand".to_owned(),
id,
WeaponVerb::Exploded,
WeaponSlot::Temporary,
),
TemporaryBundle::default(),
DebuffingTemp::Sand,
)),
}
}
}
fn use_debuffing_temp(
mut temp_q: Query<(Entity, &DebuffingTemp, &mut Uses), With<Current>>,
target_q: Query<Entity, With<CurrentTarget>>,
mut effects: Effects,
mut commands: Commands,
) {
let Ok((weapon, temp, mut uses)) = temp_q.get_single_mut() else {
let Ok((weapon, temp, mut uses)) = temp_q.single_mut() else {
return;
};
let target = target_q.single();
let target = target_q.single().unwrap();
match temp {
DebuffingTemp::TearGas => effects.spawn_and_insert(
@ -224,13 +55,54 @@ fn use_debuffing_temp(
target,
AssociatedWeapon(weapon),
),
DebuffingTemp::Sand => effects.spawn_and_insert(
TempDebuffEffect::<Sand>::default(),
target,
};
uses.0 -= 1;
if uses.0 == 0 {
commands.entity(weapon).remove::<Usable>();
}
}
fn use_buffing_temp(
mut temp_q: Query<(Entity, &BuffingTemp, &mut Uses), With<Current>>,
current_q: Query<Entity, (With<Current>, With<Player>)>,
mut effects: Effects,
mut commands: Commands,
mut logger: Logger,
) {
let Ok((weapon, temp, mut uses)) = temp_q.single_mut() else {
return;
};
let current = current_q.single().unwrap();
match temp {
BuffingTemp::Serotonin => effects.spawn_and_insert(
AdditiveStatusEffect::<1, Hardened>::default(),
current,
AssociatedWeapon(weapon),
),
BuffingTemp::Tyrosine => effects.spawn_and_insert(
AdditiveStatusEffect::<1, Sharpened>::default(),
current,
AssociatedWeapon(weapon),
),
BuffingTemp::Melatonin => effects.spawn_and_insert(
AdditiveStatusEffect::<1, Hastened>::default(),
current,
AssociatedWeapon(weapon),
),
BuffingTemp::Epinephrine => effects.spawn_and_insert(
AdditiveStatusEffect::<1, Strengthened>::default(),
current,
AssociatedWeapon(weapon),
),
};
log!(logger, "used_buff_temp", {
actor: current,
weapon: weapon,
});
uses.0 -= 1;
if uses.0 == 0 {
commands.entity(weapon).remove::<Usable>();
@ -245,5 +117,6 @@ fn restore_uses(mut uses_q: Query<&mut Uses>) {
pub(crate) fn configure(stages: &mut Stages) {
stages.turn.add_systems(use_debuffing_temp);
stages.turn.add_systems(use_buffing_temp);
stages.restore.add_systems(restore_uses);
}