Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 13 additions & 6 deletions src-tauri/crates/olm_core/src/training.rs
Original file line number Diff line number Diff line change
Expand Up @@ -856,7 +856,10 @@ pub fn process_scrim_block(game: &mut Game, weekday_num: u32) -> bool {
/// weekly schedule) give full condition recovery with no training cost.
/// Scrims focus can gain extra efficiency from stronger weekly scrim opponents.
/// `weekday_num` is 0=Mon .. 6=Sun (chrono Weekday::num_days_from_monday()).
pub fn process_training(game: &mut Game, weekday_num: u32) {
/// `is_matchday` — when true, skips attribute-gain training and applies only
/// a partial condition recovery so condition does not steadily drain to 0 %
/// over the course of a split.
pub fn process_training(game: &mut Game, weekday_num: u32, is_matchday: bool) {
let manager_team_id = game.manager.team_id.clone();
let rival_player_ids: Vec<String> = game
.players
Expand Down Expand Up @@ -949,7 +952,7 @@ pub fn process_training(game: &mut Game, weekday_num: u32) {
.unwrap_or(&plan.default_focus);

// On rest days or recovery-focused plans: no training cost
let condition_cost: u8 = if !is_training_day {
let condition_cost: u8 = if !is_training_day || is_matchday {
0
} else {
match (player_focus, &plan.intensity) {
Expand All @@ -961,14 +964,18 @@ pub fn process_training(game: &mut Game, weekday_num: u32) {
};

// Recovery amount: rest days get boosted recovery (like mental reset days)
let recovery_base: f64 = if !is_training_day {
// On matchdays we apply a partial recovery (≈60 % of a rest day) so that
// condition does not steadily drain to 0 % over the course of a split.
let recovery_base: f64 = if is_matchday {
4.2 * plan.bonus.physio_mult * plan.medical_facility_mult
} else if !is_training_day {
7.0 * plan.bonus.physio_mult * plan.medical_facility_mult
} else {
match player_focus {
TrainingFocus::MentalResetRecovery => {
9.0 * plan.bonus.physio_mult * plan.medical_facility_mult
}
_ => 3.0 * plan.bonus.physio_mult * plan.medical_facility_mult,
_ => 5.0 * plan.bonus.physio_mult * plan.medical_facility_mult,
}
};

Expand All @@ -981,8 +988,8 @@ pub fn process_training(game: &mut Game, weekday_num: u32) {
let condition_rec = recovery_factor_from_condition(player.condition);
let fitness_rec = recovery_factor_from_fitness(player.fitness);

// On rest days: only recovery, no attribute gains
if !is_training_day {
// On rest days or matchdays: only recovery, no attribute gains
if !is_training_day || is_matchday {
let stamina_factor = player.attributes.mental_resilience as f64 / 100.0;
let recovery = (recovery_base
* (0.5 + stamina_factor * 0.5)
Expand Down
12 changes: 10 additions & 2 deletions src-tauri/crates/olm_core/src/turn/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,13 @@ where
info!("[turn] process_day {}: matchday", today);
simulate_matchday_with_capture(game, &today, on_capture);
maybe_schedule_playoffs(game);
// Apply partial condition recovery even on matchdays so that player
// condition does not steadily drain to 0 % over the course of a split.
let weekday_num = game.clock.current_date.weekday().num_days_from_monday();
training::process_training(game, weekday_num, true);
} else {
let weekday_num = game.clock.current_date.weekday().num_days_from_monday();
training::process_training(game, weekday_num);
training::process_training(game, weekday_num, false);
training::check_squad_fitness_warnings(game);
}

Expand Down Expand Up @@ -126,6 +130,11 @@ pub fn finish_live_match_day(game: &mut Game) {
news::generate_weekly_digest_news(game, &today);
news::generate_pre_match_messages(game, &today);

// Apply partial condition recovery (matchday rate) so live-match
// days also restore some condition instead of only draining it.
let weekday_num = game.clock.current_date.weekday().num_days_from_monday();
training::process_training(game, weekday_num, true);

crate::firing::check_manager_firing(game);
crate::job_offers::check_job_offers(game);
potential::process_potential_research(game);
Expand All @@ -135,7 +144,6 @@ pub fn finish_live_match_day(game: &mut Game) {
game.day_phase = crate::game::DayPhase::Morning;
crate::season_context::refresh_game_context(game);
}

// ---------------------------------------------------------------------------
// Domain → Engine type conversion
// ---------------------------------------------------------------------------
Expand Down
9 changes: 7 additions & 2 deletions src-tauri/crates/olm_core/src/turn/post_match.rs
Original file line number Diff line number Diff line change
Expand Up @@ -825,8 +825,13 @@ fn deplete_match_stamina(game: &mut Game, team_id: &str, report: &crate::engine:
}
let minutes_factor = minutes as f64 / 90.0;
let stamina_factor = player.attributes.mental_resilience as f64 / 100.0;
let base_depletion = 40.0 * (1.0 - stamina_factor * 0.4);
let depletion = (base_depletion * minutes_factor) as u8;

// Randomised per-player depletion between 15-30 base.
// This replaces the old fixed 40, which was so aggressive that
// condition hit 0% midway through the split with no way to recover.
let random_base = 15.0 + rand::random::<f64>() * 15.0; // 15.0 – 30.0
let base_depletion = random_base * (1.0 - stamina_factor * 0.25);
let depletion = (base_depletion * minutes_factor).ceil() as u8;
player.condition = player.condition.saturating_sub(depletion);

if minutes >= 60 {
Expand Down