fixed first round effect and migrated logging

This commit is contained in:
TotallyNot 2024-01-08 19:37:48 +01:00
parent b45d04b872
commit e7d6b74aab
10 changed files with 539 additions and 222 deletions

View file

@ -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:?}"),
}
}

View file

@ -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