From 37b2c085557a65815353f6e054ea2e29977fbdc6 Mon Sep 17 00:00:00 2001 From: "Torsten Schulz (local)" Date: Mon, 8 Dec 2025 11:23:34 +0100 Subject: [PATCH] Add new event effects and implement regional changes: Introduced HouseQualityChange and updated StorageCapacityChange effects in EventsWorker. Implemented regional handling for storage capacity and house quality changes during events, enhancing gameplay dynamics and event impact. Improved logging for affected stocks and houses during changes. --- src/worker/events.rs | 284 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 276 insertions(+), 8 deletions(-) diff --git a/src/worker/events.rs b/src/worker/events.rs index b27d665..ffdfd10 100644 --- a/src/worker/events.rs +++ b/src/worker/events.rs @@ -49,6 +49,8 @@ pub enum EventEffect { storage_destruction_min_percent: f64, storage_destruction_max_percent: f64, }, + /// Änderung der Hausqualität (in Punkten, kann negativ sein) + HouseQualityChange { probability: f64, min_change: i32, max_change: i32 }, } /// Definition eines zufälligen Ereignisses @@ -154,6 +156,12 @@ impl EventsWorker { storage_destruction_min_percent: 0.0, storage_destruction_max_percent: 10.0, }, + // Verbleibende Lager können durch den Sturm beschädigt werden und Kapazität verlieren + EventEffect::StorageCapacityChange { + probability: 0.7, // 70% Chance, dass verbleibende Lager beschädigt werden + min_percent: -10.0, + max_percent: -3.0, + }, ], }, RandomEvent { @@ -200,9 +208,12 @@ impl EventsWorker { storage_destruction_min_percent: 0.0, storage_destruction_max_percent: 50.0, }, - // Für alle anderen Lagerarten: nur Lagerbestand kann zerstört werden - // (storage_destruction_max_percent = 0.0 bedeutet keine Lager-Zerstörung) - // Hinweis: Weitere Stock-Typen können hier hinzugefügt werden + // Verbleibende Lager können durch das Feuer beschädigt werden und Kapazität verlieren + EventEffect::StorageCapacityChange { + probability: 0.8, // 80% Chance, dass verbleibende Lager beschädigt werden + min_percent: -15.0, + max_percent: -5.0, + }, ], }, RandomEvent { @@ -283,6 +294,33 @@ impl EventsWorker { }, ], }, + RandomEvent { + id: "earthquake".to_string(), + probability_per_minute: 0.001, // 0.1% pro Minute (sehr selten) + event_type: EventType::Regional, + title: "Erdbeben".to_string(), + description: "Ein Erdbeben hat die Region erschüttert.".to_string(), + effects: vec![ + EventEffect::CharacterHealthChange { + probability: 0.3, // 30% Chance auf Gesundheitsschäden (geringe Wahrscheinlichkeit) + min_change: -20, + max_change: -5, + }, + EventEffect::CharacterDeath { + probability: 0.05, // 5% Chance auf Tod (sehr geringe Wahrscheinlichkeit) + }, + EventEffect::StorageCapacityChange { + probability: 1.0, // Alle Lager werden beschädigt + min_percent: -20.0, + max_percent: -5.0, + }, + EventEffect::HouseQualityChange { + probability: 1.0, // Alle Häuser werden beschädigt + min_change: -15, + max_change: -5, + }, + ], + }, ] } @@ -782,6 +820,46 @@ impl EventsWorker { } } } + EventEffect::StorageCapacityChange { + probability, + min_percent, + max_percent, + } => { + if effect_roll < *probability { + if let Ok(affected_stocks) = Self::apply_regional_storage_capacity_change( + &mut conn, + region_id, + *min_percent, + *max_percent, + rng, + ) { + effect_results.push(json!({ + "type": "storage_capacity_change", + "affected_stocks": affected_stocks, + })); + } + } + } + EventEffect::HouseQualityChange { + probability, + min_change, + max_change, + } => { + if effect_roll < *probability { + if let Ok(affected_houses) = Self::apply_regional_house_quality_change( + &mut conn, + region_id, + *min_change, + *max_change, + rng, + ) { + effect_results.push(json!({ + "type": "house_quality_change", + "affected_houses": affected_houses, + })); + } + } + } _ => { eprintln!( "[EventsWorker] Effekt {:?} wird für regionale Ereignisse noch nicht unterstützt", @@ -856,19 +934,209 @@ impl EventsWorker { } fn apply_storage_capacity_change( - _conn: &mut DbConnection, + conn: &mut DbConnection, user_id: i32, percent_change: f64, ) -> Result<(), DbError> { - // TODO: Implementierung für Lagerkapazitätsänderung - // Dies könnte eine temporäre Modifikation sein oder eine permanente Änderung + // Hole alle Stocks des Spielers + const QUERY_GET_USER_STOCKS: &str = r#" + SELECT s.id AS stock_id, s.quantity AS current_capacity + FROM falukant_data.stock s + JOIN falukant_data.branch b ON s.branch_id = b.id + WHERE b.falukant_user_id = $1; + "#; + + conn.prepare("get_user_stocks_capacity", QUERY_GET_USER_STOCKS)?; + let stock_rows = conn.execute("get_user_stocks_capacity", &[&user_id])?; + + if stock_rows.is_empty() { + eprintln!( + "[EventsWorker] Keine Stocks für Spieler {} gefunden", + user_id + ); + return Ok(()); + } + + // Reduziere die Kapazität aller Stocks + const QUERY_UPDATE_STOCK_CAPACITY: &str = r#" + UPDATE falukant_data.stock + SET quantity = GREATEST(1, ROUND(quantity * (1 + $1 / 100.0))) + WHERE id = $2; + "#; + + conn.prepare("update_stock_capacity", QUERY_UPDATE_STOCK_CAPACITY)?; + + let mut affected_stocks = 0; + for row in stock_rows { + let stock_id: Option = row + .get("stock_id") + .and_then(|v| v.parse::().ok()); + + let stock_id = match stock_id { + Some(id) => id, + None => continue, + }; + + let current_capacity: i32 = row + .get("current_capacity") + .and_then(|v| v.parse::().ok()) + .unwrap_or(0); + + if current_capacity > 0 { + conn.execute("update_stock_capacity", &[&percent_change, &stock_id])?; + affected_stocks += 1; + } + } + eprintln!( - "[EventsWorker] Lagerkapazitätsänderung für Spieler {}: {:.2}% (noch nicht implementiert)", - user_id, percent_change + "[EventsWorker] Lagerkapazitätsänderung für Spieler {}: {:.2}% bei {} Stocks", + user_id, percent_change, affected_stocks ); + Ok(()) } + fn apply_regional_storage_capacity_change( + conn: &mut DbConnection, + region_id: i32, + min_percent: f64, + max_percent: f64, + rng: &mut impl Rng, + ) -> Result { + // Hole alle Stocks in der Region + const QUERY_GET_REGION_STOCKS: &str = r#" + SELECT s.id AS stock_id, s.quantity AS current_capacity + FROM falukant_data.stock s + JOIN falukant_data.branch b ON s.branch_id = b.id + WHERE b.region_id = $1; + "#; + + conn.prepare("get_region_stocks_capacity", QUERY_GET_REGION_STOCKS)?; + let stock_rows = conn.execute("get_region_stocks_capacity", &[®ion_id])?; + + if stock_rows.is_empty() { + eprintln!( + "[EventsWorker] Keine Stocks in Region {} gefunden", + region_id + ); + return Ok(0); + } + + // Berechne die prozentuale Änderung + let percent_change = rng.gen_range(min_percent..=max_percent); + + // Reduziere die Kapazität aller Stocks + const QUERY_UPDATE_STOCK_CAPACITY_REGIONAL: &str = r#" + UPDATE falukant_data.stock + SET quantity = GREATEST(1, ROUND(quantity * (1 + $1 / 100.0))) + WHERE id = $2; + "#; + + conn.prepare("update_stock_capacity_regional", QUERY_UPDATE_STOCK_CAPACITY_REGIONAL)?; + + let mut affected_stocks = 0; + for row in stock_rows { + let stock_id: Option = row + .get("stock_id") + .and_then(|v| v.parse::().ok()); + + let stock_id = match stock_id { + Some(id) => id, + None => continue, + }; + + let current_capacity: i32 = row + .get("current_capacity") + .and_then(|v| v.parse::().ok()) + .unwrap_or(0); + + if current_capacity > 0 { + conn.execute("update_stock_capacity_regional", &[&percent_change, &stock_id])?; + affected_stocks += 1; + } + } + + eprintln!( + "[EventsWorker] Regionale Lagerkapazitätsänderung für Region {}: {:.2}% bei {} Stocks", + region_id, percent_change, affected_stocks + ); + + Ok(affected_stocks) + } + + fn apply_regional_house_quality_change( + conn: &mut DbConnection, + region_id: i32, + min_change: i32, + max_change: i32, + rng: &mut impl Rng, + ) -> Result { + // Hole alle Häuser in der Region + const QUERY_GET_REGION_HOUSES: &str = r#" + SELECT uh.id AS house_id, + uh.roof_condition, + uh.floor_condition, + uh.wall_condition, + uh.window_condition + FROM falukant_data.user_house uh + JOIN falukant_data.character c ON c.user_id = uh.user_id + WHERE c.region_id = $1 + AND uh.house_type_id NOT IN ( + SELECT id + FROM falukant_type.house h + WHERE h.label_tr = 'under_bridge' + ); + "#; + + conn.prepare("get_region_houses", QUERY_GET_REGION_HOUSES)?; + let house_rows = conn.execute("get_region_houses", &[®ion_id])?; + + if house_rows.is_empty() { + eprintln!( + "[EventsWorker] Keine Häuser in Region {} gefunden", + region_id + ); + return Ok(0); + } + + // Berechne die Änderung + let quality_change = rng.gen_range(min_change..=max_change); + + // Reduziere die Qualität aller Häuser + const QUERY_UPDATE_HOUSE_QUALITY: &str = r#" + UPDATE falukant_data.user_house + SET roof_condition = GREATEST(0, LEAST(100, roof_condition + $1)), + floor_condition = GREATEST(0, LEAST(100, floor_condition + $1)), + wall_condition = GREATEST(0, LEAST(100, wall_condition + $1)), + window_condition = GREATEST(0, LEAST(100, window_condition + $1)) + WHERE id = $2; + "#; + + conn.prepare("update_house_quality", QUERY_UPDATE_HOUSE_QUALITY)?; + + let mut affected_houses = 0; + for row in house_rows { + let house_id: Option = row + .get("house_id") + .and_then(|v| v.parse::().ok()); + + let house_id = match house_id { + Some(id) => id, + None => continue, + }; + + conn.execute("update_house_quality", &[&quality_change, &house_id])?; + affected_houses += 1; + } + + eprintln!( + "[EventsWorker] Regionale Hausqualitätsänderung für Region {}: {} Punkte bei {} Häusern", + region_id, quality_change, affected_houses + ); + + Ok(affected_houses) + } + fn apply_weather_change( conn: &mut DbConnection, region_id: i32,