query("SELECT * FROM sp_seasons WHERE active=1 ORDER BY id DESC LIMIT 1")->fetch(); } catch (\Throwable $e) { $season = null; // sp_* Tabellen existieren noch nicht -> einfach nichts tun } return $season ?: null; } function sp_level_for_xp($pdo, $seasonId, $xp) { $s = $pdo->prepare("SELECT COUNT(*) FROM sp_levels WHERE season_id=? AND xp_required<=?"); $s->execute([$seasonId, $xp]); return max(1, (int)$s->fetchColumn()); } // Vergibt Season-XP an eine Persona. Erkennt Level-Ups automatisch und // schreibt dafuer einen kleinen NSZ-Boost-Drip gut (5 pro Level-Aufstieg). // Still-scheitern (nie fatal) -> ein fehlendes sp_-Schema legt keinen // anderen Endpunkt lahm. function sp_add_xp($pdo, $personaId, $amount, $reason = '') { $amount = (int)$amount; if ($amount <= 0 || !$personaId) return; $season = sp_active_season($pdo); if (!$season) return; $seasonId = (int)$season['id']; try { $pdo->exec("CREATE TABLE IF NOT EXISTS sp_xp_log ( id INT AUTO_INCREMENT PRIMARY KEY, player_id INT NOT NULL, season_id INT NOT NULL, amount INT NOT NULL, reason VARCHAR(120), created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP)"); $pdo->beginTransaction(); $s = $pdo->prepare("SELECT xp, premium_owned FROM sp_player_season WHERE player_id=? AND season_id=? FOR UPDATE"); $s->execute([$personaId, $seasonId]); $row = $s->fetch(); $oldXp = $row ? (int)$row['xp'] : 0; // Premium-Spur = 2x XP auf ALLE Season-Pass-XP-Vergaben if ($row && (int)$row['premium_owned'] === 1) $amount *= 2; if (!$row) { $pdo->prepare("INSERT INTO sp_player_season (player_id, season_id, xp) VALUES (?,?,?)") ->execute([$personaId, $seasonId, $amount]); } else { $pdo->prepare("UPDATE sp_player_season SET xp = xp + ? WHERE player_id=? AND season_id=?") ->execute([$amount, $personaId, $seasonId]); } $newXp = $oldXp + $amount; $pdo->prepare("INSERT INTO sp_xp_log (player_id, season_id, amount, reason) VALUES (?,?,?,?)") ->execute([$personaId, $seasonId, $amount, $reason]); // Level-Up erkennen -> automatischen NSZ-Boost-Drip gutschreiben (5 pro Level) // NSZ Boost = das ECHTE persona.boost-Feld (Umbenennung von "SpeedBoost" im Spiel) - // KEINE eigene Zaehlung mehr, damit Web und Client denselben Wert sehen. $oldLevel = sp_level_for_xp($pdo, $seasonId, $oldXp); $newLevel = sp_level_for_xp($pdo, $seasonId, $newXp); if ($newLevel > $oldLevel) { $gain = ($newLevel - $oldLevel) * 5; $pdo->prepare("UPDATE persona SET boost = boost + ? WHERE id=?")->execute([$gain, $personaId]); } $pdo->commit(); } catch (\Throwable $e) { if ($pdo->inTransaction()) $pdo->rollBack(); // bewusst still: Season-Pass-XP darf niemals ein Gameplay-Feature abschiessen } }