fixed first round effect and migrated logging
This commit is contained in:
parent
b45d04b872
commit
e7d6b74aab
10 changed files with 539 additions and 222 deletions
|
|
@ -3,9 +3,15 @@ use bevy_ecs::prelude::*;
|
|||
use crate::{
|
||||
effect::{Effects, TurnLimitedEffect},
|
||||
hierarchy::{HierarchyBuilder, Parent},
|
||||
player::stats::{
|
||||
AdditiveBonus, AmmoControl, Clips, CritRate, DamageBonus, SimpleStatBonus,
|
||||
SimpleStatEffective, Speed, Strength, WeaponAccuracy,
|
||||
player::{
|
||||
stats::{
|
||||
AdditiveBonus, AmmoControl, Clips, CritRate, DamageBonus, SimpleStatBonus,
|
||||
SimpleStatEffective, Speed, Strength, WeaponAccuracy,
|
||||
},
|
||||
status_effect::{
|
||||
AdditiveStatusEffect, Crippled, Demoralise, Frozen, Motivate, Slow, Weakened, Withered,
|
||||
},
|
||||
BodyPart, PartDamageBonus,
|
||||
},
|
||||
Stages,
|
||||
};
|
||||
|
|
@ -155,6 +161,117 @@ impl MultiTurnBonus {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub enum OpponentStatusEffect {
|
||||
Cripple,
|
||||
// TODO: implement for group fights
|
||||
Demoralise,
|
||||
Freeze,
|
||||
Slow,
|
||||
Toxin,
|
||||
Weaken,
|
||||
Wither,
|
||||
}
|
||||
|
||||
impl OpponentStatusEffect {
|
||||
pub fn spawn(self, target: Entity, effects: &mut Effects, rng: &mut impl rand::Rng) {
|
||||
match self {
|
||||
Self::Cripple => {
|
||||
effects.spawn(AdditiveStatusEffect::<1, Crippled>::default(), target);
|
||||
}
|
||||
Self::Demoralise => {
|
||||
effects.spawn(AdditiveStatusEffect::<4, Demoralise>::default(), target);
|
||||
}
|
||||
Self::Freeze => {
|
||||
effects.spawn(AdditiveStatusEffect::<2, Frozen>::default(), target);
|
||||
}
|
||||
Self::Slow => {
|
||||
effects.spawn(AdditiveStatusEffect::<1, Slow>::default(), target);
|
||||
}
|
||||
Self::Toxin => match rng.gen_range(0..4) {
|
||||
0 => OpponentStatusEffect::Cripple.spawn(target, effects, rng),
|
||||
1 => OpponentStatusEffect::Slow.spawn(target, effects, rng),
|
||||
2 => OpponentStatusEffect::Weaken.spawn(target, effects, rng),
|
||||
_ => OpponentStatusEffect::Wither.spawn(target, effects, rng),
|
||||
},
|
||||
Self::Weaken => {
|
||||
effects.spawn(AdditiveStatusEffect::<1, Weakened>::default(), target);
|
||||
}
|
||||
Self::Wither => {
|
||||
effects.spawn(AdditiveStatusEffect::<1, Withered>::default(), target);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub enum SelfStatusEffect {
|
||||
Motivate,
|
||||
}
|
||||
|
||||
impl SelfStatusEffect {
|
||||
pub fn spawn(self, current: Entity, effects: &mut Effects) {
|
||||
match self {
|
||||
Self::Motivate => {
|
||||
effects.spawn(AdditiveStatusEffect::<4, Motivate>::default(), current);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub enum BonusPartDamageBonus {
|
||||
Achilles,
|
||||
Crusher,
|
||||
Cupid,
|
||||
Deadeye,
|
||||
Roshambo,
|
||||
Throttle,
|
||||
}
|
||||
|
||||
impl BonusPartDamageBonus {
|
||||
pub fn dmg_bonus(self, part: BodyPart, value: f32) -> Option<f32> {
|
||||
match self {
|
||||
Self::Achilles => match part {
|
||||
BodyPart::LeftFoot | BodyPart::RightFoot => Some(value),
|
||||
_ => None,
|
||||
},
|
||||
Self::Crusher => {
|
||||
if part == BodyPart::Head {
|
||||
Some(value)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
Self::Cupid => {
|
||||
if part == BodyPart::Heart {
|
||||
Some(value)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
Self::Deadeye => match part {
|
||||
BodyPart::Head | BodyPart::Heart | BodyPart::Throat => Some(value),
|
||||
_ => None,
|
||||
},
|
||||
Self::Roshambo => {
|
||||
if part == BodyPart::Groin {
|
||||
Some(value)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
Self::Throttle => {
|
||||
if part == BodyPart::Throat {
|
||||
Some(value)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn prepare_bonuses(
|
||||
bonus_q: Query<(
|
||||
&Parent,
|
||||
|
|
@ -278,6 +395,121 @@ pub(crate) fn prepare_bonuses(
|
|||
.set_parent(weapon.get());
|
||||
}
|
||||
|
||||
WeaponBonus::Achilles => {
|
||||
commands
|
||||
.spawn(PartDamageBonus::WeaponBonus {
|
||||
value: value.0 / 100.0,
|
||||
bonus: BonusPartDamageBonus::Achilles,
|
||||
})
|
||||
.set_parent(weapon.get());
|
||||
}
|
||||
WeaponBonus::Cupid => {
|
||||
commands
|
||||
.spawn(PartDamageBonus::WeaponBonus {
|
||||
value: value.0 / 100.0,
|
||||
bonus: BonusPartDamageBonus::Cupid,
|
||||
})
|
||||
.set_parent(weapon.get());
|
||||
}
|
||||
WeaponBonus::Crusher => {
|
||||
commands
|
||||
.spawn(PartDamageBonus::WeaponBonus {
|
||||
value: value.0 / 100.0,
|
||||
bonus: BonusPartDamageBonus::Crusher,
|
||||
})
|
||||
.set_parent(weapon.get());
|
||||
}
|
||||
WeaponBonus::Deadeye => {
|
||||
commands
|
||||
.spawn(PartDamageBonus::WeaponBonus {
|
||||
value: value.0 / 100.0,
|
||||
bonus: BonusPartDamageBonus::Deadeye,
|
||||
})
|
||||
.set_parent(weapon.get());
|
||||
}
|
||||
WeaponBonus::Throttle => {
|
||||
commands
|
||||
.spawn(PartDamageBonus::WeaponBonus {
|
||||
value: value.0 / 100.0,
|
||||
bonus: BonusPartDamageBonus::Throttle,
|
||||
})
|
||||
.set_parent(weapon.get());
|
||||
}
|
||||
WeaponBonus::Roshambo => {
|
||||
commands
|
||||
.spawn(PartDamageBonus::WeaponBonus {
|
||||
value: value.0 / 100.0,
|
||||
bonus: BonusPartDamageBonus::Roshambo,
|
||||
})
|
||||
.set_parent(weapon.get());
|
||||
}
|
||||
|
||||
WeaponBonus::Cripple => {
|
||||
commands
|
||||
.spawn(DamageProcEffect::OpponentEffect {
|
||||
value: value.0,
|
||||
bonus: OpponentStatusEffect::Cripple,
|
||||
})
|
||||
.set_parent(weapon.get());
|
||||
}
|
||||
WeaponBonus::Demoralise => {
|
||||
commands
|
||||
.spawn(DamageProcEffect::OpponentEffect {
|
||||
value: value.0,
|
||||
bonus: OpponentStatusEffect::Demoralise,
|
||||
})
|
||||
.set_parent(weapon.get());
|
||||
}
|
||||
WeaponBonus::Freeze => {
|
||||
commands
|
||||
.spawn(DamageProcEffect::OpponentEffect {
|
||||
value: value.0,
|
||||
bonus: OpponentStatusEffect::Freeze,
|
||||
})
|
||||
.set_parent(weapon.get());
|
||||
}
|
||||
WeaponBonus::Slow => {
|
||||
commands
|
||||
.spawn(DamageProcEffect::OpponentEffect {
|
||||
value: value.0,
|
||||
bonus: OpponentStatusEffect::Slow,
|
||||
})
|
||||
.set_parent(weapon.get());
|
||||
}
|
||||
WeaponBonus::Toxin => {
|
||||
commands
|
||||
.spawn(DamageProcEffect::OpponentEffect {
|
||||
value: value.0,
|
||||
bonus: OpponentStatusEffect::Toxin,
|
||||
})
|
||||
.set_parent(weapon.get());
|
||||
}
|
||||
WeaponBonus::Weaken => {
|
||||
commands
|
||||
.spawn(DamageProcEffect::OpponentEffect {
|
||||
value: value.0,
|
||||
bonus: OpponentStatusEffect::Weaken,
|
||||
})
|
||||
.set_parent(weapon.get());
|
||||
}
|
||||
WeaponBonus::Wither => {
|
||||
commands
|
||||
.spawn(DamageProcEffect::OpponentEffect {
|
||||
value: value.0,
|
||||
bonus: OpponentStatusEffect::Wither,
|
||||
})
|
||||
.set_parent(weapon.get());
|
||||
}
|
||||
|
||||
WeaponBonus::Motivate => {
|
||||
commands
|
||||
.spawn(DamageProcEffect::SelfEffect {
|
||||
value: value.0,
|
||||
bonus: SelfStatusEffect::Motivate,
|
||||
})
|
||||
.set_parent(weapon.get());
|
||||
}
|
||||
|
||||
val => unimplemented!("{val:?}"),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,22 +1,24 @@
|
|||
use bevy_ecs::prelude::*;
|
||||
use macros::LogMessage;
|
||||
|
||||
use crate::{
|
||||
effect::{Effects, TurnLimitedEffect},
|
||||
hierarchy::{HierarchyBuilder, Parent},
|
||||
log,
|
||||
log::Logger,
|
||||
passives::{Education, FactionUpgrades, Merits},
|
||||
passives::{Education, EducationPartDamageBonus, FactionUpgrades, Merits},
|
||||
player::{
|
||||
stats::{
|
||||
AdditiveBonus, AmmoControl, ClipSize, Clips, CritRate, DamageBonus, Dexterity,
|
||||
SimpleStatBonus, SimpleStatBundle, SimpleStatEffective, WeaponAccuracy,
|
||||
},
|
||||
Current, Weapons,
|
||||
Current, PartDamageBonus, Weapons,
|
||||
},
|
||||
Id, Name, Stages,
|
||||
};
|
||||
|
||||
use self::bonus::{FirstTurnBonus, MultiTurnBonus, TurnTriggeredBonus};
|
||||
use self::bonus::{
|
||||
FirstTurnBonus, MultiTurnBonus, OpponentStatusEffect, SelfStatusEffect, TurnTriggeredBonus,
|
||||
};
|
||||
|
||||
pub mod bonus;
|
||||
pub mod temp;
|
||||
|
|
@ -58,7 +60,7 @@ pub enum WeaponCategory {
|
|||
Smg,
|
||||
Shotgun,
|
||||
Pistol,
|
||||
Club,
|
||||
Clubbing,
|
||||
Piercing,
|
||||
Slashing,
|
||||
Mechanical,
|
||||
|
|
@ -110,7 +112,7 @@ pub enum WeaponMod {
|
|||
FullChoke,
|
||||
RecoilPad,
|
||||
StandardBrake,
|
||||
HeavyDutyBreak,
|
||||
HeavyDutyBrake,
|
||||
TacticalBrake,
|
||||
SmallLight,
|
||||
PrecisionLight,
|
||||
|
|
@ -220,11 +222,6 @@ pub enum FirstTurnEffect {
|
|||
Bonus { value: f32, bonus: FirstTurnBonus },
|
||||
}
|
||||
|
||||
#[derive(Component)]
|
||||
pub enum DamageProcEffect {
|
||||
MultiTurn { value: f32, bonus: MultiTurnBonus },
|
||||
}
|
||||
|
||||
impl FirstTurnEffect {
|
||||
fn spawn(&self, effects: &mut Effects, weapon: Entity, owner: Entity) {
|
||||
match self {
|
||||
|
|
@ -234,31 +231,28 @@ impl FirstTurnEffect {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Component)]
|
||||
pub enum DamageProcEffect {
|
||||
MultiTurn {
|
||||
value: f32,
|
||||
bonus: MultiTurnBonus,
|
||||
},
|
||||
OpponentEffect {
|
||||
value: f32,
|
||||
bonus: OpponentStatusEffect,
|
||||
},
|
||||
SelfEffect {
|
||||
value: f32,
|
||||
bonus: SelfStatusEffect,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Component)]
|
||||
pub struct EquippedMods(pub Vec<WeaponMod>);
|
||||
|
||||
#[derive(Component)]
|
||||
pub struct Experience(pub f32);
|
||||
|
||||
#[derive(LogMessage)]
|
||||
pub struct ReloadWeapon {
|
||||
#[log(player)]
|
||||
pub actor: Entity,
|
||||
#[log(weapon)]
|
||||
pub weapon: Entity,
|
||||
}
|
||||
|
||||
#[derive(LogMessage)]
|
||||
pub struct MissTarget {
|
||||
#[log(player)]
|
||||
pub actor: Entity,
|
||||
#[log(player)]
|
||||
pub recipient: Entity,
|
||||
#[log(weapon)]
|
||||
pub weapon: Entity,
|
||||
pub rounds: Option<u16>,
|
||||
}
|
||||
|
||||
#[derive(Bundle)]
|
||||
pub struct WeaponBundle {
|
||||
pub usable: Usable,
|
||||
|
|
@ -514,7 +508,7 @@ fn apply_passives(
|
|||
weapon,
|
||||
);
|
||||
}
|
||||
WeaponMod::HeavyDutyBreak => {
|
||||
WeaponMod::HeavyDutyBrake => {
|
||||
effects.spawn(
|
||||
SimpleStatBonus::<WeaponAccuracy>::new("heavy duty brake", 1.25 / 50.0),
|
||||
weapon,
|
||||
|
|
@ -595,7 +589,7 @@ fn apply_passives(
|
|||
merits.pistol_mastery,
|
||||
education.cbt2840.then_some("CBT2840"),
|
||||
),
|
||||
WeaponCategory::Club => (merits.club_mastery, None),
|
||||
WeaponCategory::Clubbing => (merits.club_mastery, None),
|
||||
WeaponCategory::Piercing => (merits.piercing_mastery, None),
|
||||
WeaponCategory::Slashing => (merits.slashing_mastery, None),
|
||||
WeaponCategory::Mechanical => (merits.mechanical_mastery, None),
|
||||
|
|
@ -644,6 +638,14 @@ fn apply_passives(
|
|||
effects.spawn(SimpleStatBonus::<DamageBonus>::new("HIS2160", 0.10), weapon);
|
||||
}
|
||||
|
||||
if education.bio2380 {
|
||||
commands
|
||||
.spawn(PartDamageBonus::Education(
|
||||
EducationPartDamageBonus::Bio2380,
|
||||
))
|
||||
.set_parent(weapon);
|
||||
}
|
||||
|
||||
if mastery > 0 {
|
||||
effects.spawn(
|
||||
SimpleStatBonus::<WeaponAccuracy>::new("mastery", (mastery as f32) * 0.2 / 50.0),
|
||||
|
|
@ -697,9 +699,9 @@ fn reload_weapon(
|
|||
ammo.0 = clip_size.value;
|
||||
clips.value -= 1;
|
||||
|
||||
logger.log(|| ReloadWeapon {
|
||||
log!(logger, "reload_weapon", {
|
||||
actor: player.get(),
|
||||
weapon,
|
||||
weapon
|
||||
});
|
||||
|
||||
commands.entity(weapon).remove::<NeedsReload>();
|
||||
|
|
@ -735,12 +737,10 @@ fn apply_first_turn_effects(
|
|||
|
||||
pub(crate) fn configure(stages: &mut Stages) {
|
||||
stages.equip.add_systems(set_owner);
|
||||
stages.pre_fight.add_systems((
|
||||
apply_passives,
|
||||
apply_first_turn_effects
|
||||
.after(apply_passives)
|
||||
.after(bonus::prepare_bonuses),
|
||||
));
|
||||
// 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);
|
||||
stages.pre_fight.add_systems(apply_passives);
|
||||
stages.turn.add_systems(reload_weapon);
|
||||
stages.post_turn.add_systems(unset_current);
|
||||
stages
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue