using Microsoft.EntityFrameworkCore; using RadicadeServer.DB; using RadicadeServer.RecNet.Leveling; using RadicadeServer.RecNet.Progression; using RadicadeServer.RecNet.Royale; using RadicadeServer.Utils; namespace RadicadeServer.API.Royale { public static class RoyaleShared { public static readonly string[] RankNames = { "Recruit", "Cadet", "Private", "Corporal", "Sergeant", "Lieutenant", "Captain", "Major", "Colonel", "General" }; public static int RankIdxForLevel(int level) => Math.Clamp((level - 1) / 5, 0, RankNames.Length - 1); public static (long current, long next) XpThresholds(List map, int level) { long cumulative = 0; long current = 0; long next = 0; foreach (var entry in map.OrderBy(x => x.Level)) { if (entry.Level <= 0) continue; if (entry.Level <= level) { cumulative += entry.RequiredXp; current = cumulative; } else { if (next == 0) next = cumulative + entry.RequiredXp; break; } } if (next == 0) next = current; return (current, next); } public static RoyaleProgressDTO BuildProgress(ProgressionData data) { var map = LevelUpGiftService.ParseMap(); int level = LevelUpGiftService.DisplayLevel(data.Level); var (current, next) = XpThresholds(map, level); int rankIdx = RankIdxForLevel(level); long totalXp = level >= LevelUpGiftService.MaxLevel ? next : data.XP; return new RoyaleProgressDTO { TotalXP = totalXp, Level = level, RankIdx = rankIdx, RankName = RankNames[rankIdx], CurrentLevelXPThreshold = current, NextLevelXPThreshold = next, NextLevelAcornReward = Math.Max(10, level * 5) }; } public static async Task AwardXpAsync( RecDBContext db, long playerId, int xp, string description, List awardStrings) { var progression = await db.Progression.FirstOrDefaultAsync(x => x.PlayerId == playerId); if (progression == null) { progression = new ProgressionData { PlayerId = playerId }; db.Progression.Add(progression); } if (xp <= 0) { await db.SaveChangesAsync(); return BuildProgress(progression); } int granted = (int)Math.Min(xp, int.MaxValue); int oldLevel = progression.Level; progression.XP = (int)Math.Min(progression.XP + granted, int.MaxValue); progression.RecordXpGrant(granted); await LevelUpGiftService.DeliverLevelUpGiftsAsync(db, playerId, recomputeFromXp: true, fromLevel: oldLevel, notify: true); await db.SaveChangesAsync(); if (granted > 0 && awardStrings.Count == 0) awardStrings.Add($"{description}: +{granted} XP"); if (granted > 0) await RoomProgressionService.SendProgressionLevelUpdateAsync(db, playerId, progression); return BuildProgress(progression); } } }