Add random heir fallback logic in EventsWorker: Implement a new SQL query to select a random NPC heir from the same region when no children are available. Enhance error handling to log cases where no heir is found, ensuring better user feedback and maintaining character associations. Update UserCharacterWorker to utilize this new logic for heir assignment.

This commit is contained in:
Torsten Schulz (local)
2026-01-07 10:14:24 +01:00
parent b7eafe28a1
commit f96e474f32
3 changed files with 76 additions and 8 deletions

View File

@@ -45,6 +45,7 @@ use crate::worker::sql::{
QUERY_DELETE_CHILD_RELATION,
QUERY_DELETE_CHARACTER,
QUERY_GET_HEIR,
QUERY_GET_RANDOM_HEIR_FROM_REGION,
QUERY_SET_CHARACTER_USER,
QUERY_CLEAR_CHARACTER_USER,
QUERY_GET_CURRENT_MONEY,
@@ -1589,17 +1590,27 @@ impl EventsWorker {
.and_then(|r| r.get("child_character_id"))
.and_then(|v| v.parse::<i32>().ok());
// Kein Kind als Erbe vorhanden? Dann fallback: zufälliger NPC-Character aus der Region,
// Alter 1014 Tage.
let heir_id = match heir_id {
Some(id) if id > 0 => id,
_ => {
// Kein Erbe gefunden - Vermögen geht verloren
conn.prepare("random_heir_region", QUERY_GET_RANDOM_HEIR_FROM_REGION)?;
let rows = conn.execute("random_heir_region", &[&deceased_character_id])?;
rows.first()
.and_then(|r| r.get("child_character_id"))
.and_then(|v| v.parse::<i32>().ok())
.unwrap_or(0)
}
};
if heir_id <= 0 {
eprintln!(
"[EventsWorker] Kein Erbe für Charakter {} gefunden, Vermögen geht verloren",
deceased_character_id
"[EventsWorker] Kein Erbe für Charakter {} gefunden (weder Kind noch Fallback in Region). User {} hat danach keinen Character.",
deceased_character_id, falukant_user_id
);
return Ok(());
}
};
// 2) Wichtig: erst die alte User-Zuordnung am verstorbenen Charakter lösen.
// Falls es einen Unique-Constraint auf `character.user_id` gibt, würde das

View File

@@ -1351,6 +1351,31 @@ pub const QUERY_RANDOM_HEIR: &str = r#"
chosen.child_character_id;
"#;
// Fallback-Erbe: Wenn ein Spieler-Character ohne Kinder stirbt, suchen wir einen zufälligen
// NPC-Character in derselben Region (Alter 1014 Tage) und übergeben ihm die user_id.
pub const QUERY_GET_RANDOM_HEIR_FROM_REGION: &str = r#"
SELECT ch.id AS child_character_id
FROM falukant_data.character ch
WHERE ch.user_id IS NULL
AND ch.health > 0
AND ch.id <> $1
AND ch.region_id = (
SELECT region_id
FROM falukant_data.character
WHERE id = $1
)
-- Alter zwischen 10 und 14 Tagen: birthdate in [now-14d, now-10d]
AND ch.birthdate <= NOW() - INTERVAL '10 days'
AND ch.birthdate >= NOW() - INTERVAL '14 days'
AND ch.title_of_nobility = (
SELECT id
FROM falukant_type.title
WHERE label_tr = 'noncivil'
)
ORDER BY RANDOM()
LIMIT 1;
"#;
pub const QUERY_UPDATE_USER_MONEY: &str = r#"
UPDATE falukant_data.falukant_user
SET money = $1,
@@ -1600,8 +1625,16 @@ pub const QUERY_GET_FINISHED_PRODUCTIONS: &str = r#"
ON p.product_id = pr.id
JOIN falukant_data.branch br
ON p.branch_id = br.id
JOIN falukant_data.character c
ON c.user_id = br.falukant_user_id
-- Es kann vorkommen, dass ein User temporär keinen zugeordneten Character hat
-- (z.B. nach Tod/Erbe). Produktionen sollen trotzdem abschließen.
-- LATERAL verhindert Duplikate, falls ein User mehrere Characters hat.
LEFT JOIN LATERAL (
SELECT c.id, c.user_id
FROM falukant_data.character c
WHERE c.user_id = br.falukant_user_id
ORDER BY c.updated_at DESC NULLS LAST, c.id DESC
LIMIT 1
) c ON TRUE
LEFT JOIN falukant_data.knowledge k
ON p.product_id = k.product_id
AND k.character_id = c.id

View File

@@ -28,6 +28,7 @@ use crate::worker::sql::{
QUERY_COUNT_CHILDREN,
QUERY_GET_HEIR,
QUERY_RANDOM_HEIR,
QUERY_GET_RANDOM_HEIR_FROM_REGION,
QUERY_SET_CHARACTER_USER,
QUERY_CLEAR_CHARACTER_USER,
QUERY_UPDATE_USER_MONEY,
@@ -608,6 +609,12 @@ impl UserCharacterWorker {
new_money = self.calculate_new_money(falukant_user_id, heir_id > 0)?;
}
// Wenn es gar keine Kinder gibt, nimm einen zufälligen NPC in der Region (Alter 1014 Tage).
if heir_id < 1 {
heir_id = self.get_random_heir_from_region(character_id)?;
new_money = self.calculate_new_money(falukant_user_id, heir_id > 0)?;
}
if heir_id > 0 {
// Erst die alte Zuordnung lösen (Unique-Constraint safety), dann den Erben zuweisen.
self.clear_character_user(character_id)?;
@@ -669,6 +676,23 @@ impl UserCharacterWorker {
.unwrap_or(-1))
}
fn get_random_heir_from_region(&mut self, deceased_character_id: i32) -> Result<i32, DbError> {
let mut conn = self
.base
.pool
.get()
.map_err(|e| DbError::new(format!("DB-Verbindung fehlgeschlagen: {e}")))?;
conn.prepare("random_heir_region", QUERY_GET_RANDOM_HEIR_FROM_REGION)?;
let rows = conn.execute("random_heir_region", &[&deceased_character_id])?;
Ok(rows
.first()
.and_then(|r| r.get("child_character_id"))
.and_then(|v| v.parse::<i32>().ok())
.unwrap_or(-1))
}
fn set_new_character(
&mut self,
falukant_user_id: i32,