diff --git a/src/worker/events.rs b/src/worker/events.rs index 4339970..5bc84c7 100644 --- a/src/worker/events.rs +++ b/src/worker/events.rs @@ -703,19 +703,12 @@ impl EventsWorker { } }; + // Nur NPC-Kinder werden vom Kindstod getroffen; user_id ist bei NPCs None let user_id: Option = rows .first() .and_then(|r| r.get("user_id")) .and_then(|v| v.parse::().ok()); - let user_id = match user_id { - Some(id) => id, - None => { - eprintln!("[EventsWorker] Kein user_id für Kind {} gefunden", character_id); - return Ok(()); - } - }; - // Wende Effekte an (in diesem Fall nur CharacterDeath) let mut effect_results = Vec::new(); for effect in &event.effects { @@ -740,32 +733,32 @@ impl EventsWorker { } } - // Schreibe Benachrichtigung in die Datenbank mit Event-Details - let notification_json = serde_json::json!({ - "tr": format!("random_event.{}", event.id), - "event_id": event.id, - "event_type": "personal", - "character_id": character_id, - "effects": effect_results - }); - Self::notify_user(pool, broker, user_id, ¬ification_json.to_string())?; + // Nur Spieler benachrichtigen (NPC-Kindstod hat keinen user_id) + if let Some(uid) = user_id { + let notification_json = serde_json::json!({ + "tr": format!("random_event.{}", event.id), + "event_id": event.id, + "event_type": "personal", + "character_id": character_id, + "effects": effect_results + }); + Self::notify_user(pool, broker, uid, ¬ification_json.to_string())?; - // Sende Benachrichtigung über WebSocket - let notification = json!({ - "event": "random_event", - "event_id": event.id, - "event_type": "personal", - "user_id": user_id, - "character_id": character_id, - "title": event.title, - "description": event.description, - "effects": effect_results - }); - - broker.publish(notification.to_string()); + let notification = json!({ + "event": "random_event", + "event_id": event.id, + "event_type": "personal", + "user_id": uid, + "character_id": character_id, + "title": event.title, + "description": event.description, + "effects": effect_results + }); + broker.publish(notification.to_string()); + } eprintln!( - "[EventsWorker] Plötzlicher Kindstod für Charakter {} (Spieler {}) verarbeitet", - character_id, user_id + "[EventsWorker] Plötzlicher Kindstod für Charakter {} verarbeitet", + character_id ); Ok(()) @@ -1295,8 +1288,8 @@ impl EventsWorker { min_change: i32, max_change: i32, rng: &mut impl Rng, - pool: &ConnectionPool, - broker: &MessageBroker, + _pool: &ConnectionPool, + _broker: &MessageBroker, ) -> Result<(i32, i32), DbError> { // Hole einen zufälligen Charakter des Spielers conn.prepare("get_random_character", QUERY_GET_RANDOM_CHARACTER)?; @@ -1322,19 +1315,13 @@ impl EventsWorker { .unwrap_or(100); let health_change = rng.gen_range(min_change..=max_change); - let new_health = (current_health + health_change).clamp(0, 100); + // Durch Unfälle/Krankheiten soll Gesundheit von Spieler-Charakteren nicht auf 0 fallen + let new_health = (current_health + health_change).clamp(1, 100); // Update Gesundheit conn.prepare("update_health", QUERY_UPDATE_HEALTH)?; conn.execute("update_health", &[&new_health, &character_id])?; - // Bei Health <= 0 sofort Tod prüfen und verarbeiten - if new_health <= 0 { - if let Err(e) = Self::handle_character_death(pool, broker, character_id) { - eprintln!("[EventsWorker] handle_character_death nach Health-Update: {e}"); - } - } - Ok((character_id, health_change)) } @@ -1400,7 +1387,16 @@ impl EventsWorker { .unwrap_or(100); let health_change = rng.gen_range(min_change..=max_change); - let new_health = (current_health + health_change).clamp(0, 100); + let user_id: Option = row + .get("user_id") + .and_then(|v| v.parse::().ok()); + // Durch Unfälle/Krankheiten soll Gesundheit von Spieler-Charakteren nicht auf 0 fallen + let new_health_raw = (current_health + health_change).clamp(0, 100); + let new_health = if user_id.is_some() { + new_health_raw.max(1) + } else { + new_health_raw + }; // Update Gesundheit conn.prepare("update_health_regional", QUERY_UPDATE_HEALTH)?; @@ -1444,7 +1440,14 @@ impl EventsWorker { None => continue, }; - // Verwende die existierende Logik zum Löschen von Charakteren + let user_id: Option = row + .get("user_id") + .and_then(|v| v.parse::().ok()); + // Nur NPCs (user_id IS NULL) von regionalem Tod betroffen + if user_id.is_some() { + continue; + } + if Self::handle_character_death(pool, broker, character_id).is_ok() { dead_characters.push(character_id); } diff --git a/src/worker/sql.rs b/src/worker/sql.rs index 9a06469..013d627 100644 --- a/src/worker/sql.rs +++ b/src/worker/sql.rs @@ -18,10 +18,11 @@ pub const QUERY_GET_RANDOM_USER: &str = r#" SELECT id FROM falukant_data.falukant_user ORDER BY RANDOM() LIMIT 1; "#; +/// Nur NPC-Kleinkinder (user_id IS NULL); Spieler-Charaktere sind von plötzlichem Kindstod ausgenommen. pub const QUERY_GET_RANDOM_INFANT: &str = r#" SELECT c.id AS character_id, c.user_id, CURRENT_DATE - c.birthdate::date AS age_days FROM falukant_data."character" c -WHERE c.user_id IS NOT NULL AND c.health > 0 AND CURRENT_DATE - c.birthdate::date <= 730 +WHERE c.user_id IS NULL AND c.health > 0 AND CURRENT_DATE - c.birthdate::date <= 730 ORDER BY RANDOM() LIMIT 1; "#; @@ -522,7 +523,7 @@ UPDATE falukant_data."character" SET health = $1 WHERE id = $2; "#; pub const QUERY_GET_REGION_CHARACTERS: &str = r#" -SELECT id, health FROM falukant_data."character" WHERE region_id = $1 AND health > 0; +SELECT id, health, user_id FROM falukant_data."character" WHERE region_id = $1 AND health > 0; "#; pub const QUERY_DELETE_DIRECTOR: &str = r#" @@ -605,6 +606,7 @@ pub const QUERY_GET_USERS_TO_UPDATE: &str = r#" WHERE user_id IS NOT NULL; "#; +/// Spieler-Charaktere mit Health <= 0 werden periodisch zum Tod verarbeitet. pub const QUERY_GET_CHARACTERS_ZERO_HEALTH: &str = r#" SELECT id FROM falukant_data."character" WHERE user_id IS NOT NULL AND health <= 0;