More cosmetics (rank-gated) + steeper level curve capped at 100
Cosmetics — many new variants, the rarer ones gated behind higher ranks: - Card backs: +midnight/jade/onyx (buy) + crimson/aurora/obsidian/imperial (earned by wins/rating up to Master). Card fronts: +sunset/velvet/onyx (buy) + goldleaf/crystal/imperial (earned). - Titles: +marksman, untouchable, sweeper, ruler, platinum_star, diamond_ace, immortal, the_one (gated by kots/streak/shutouts/hakem/rating/level/wins), mirrored on the server so live games grant them. - Avatars: list expanded + rank/wins-earned tier (robot/wizard/ninja/king/ genie/crown) via new ownedAvatarIds(); profile picker shows earned ones, shop sells the priced ones. - Stickers: new Persian-text stamp pack (کوت! / دمت گرم / باریکلا / آخه؟) plus a rank-earned Victory pack (بردیم!/حکم) — new inline-SVG art. Leveling: XP per level now grows (100*l + 15*l²) so each level is harder; higher leagues grant more XP (×1.5 at 500 stake, ×2 at 1000) so you progress by playing up. Hard cap at level 100. Mirrored in server Gamification (XpForLevel/MatchXp/ AddXp). Sim now tops out lower (level 20 vs 35 over 500 matches) as intended. Verified: tsc + next build + dotnet build clean; sim passes; images rebuilt :1500/:1505. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -38,9 +38,14 @@ public static class Gamification
|
||||
return (s.Won ? s.Stake : -s.Stake) + kot;
|
||||
}
|
||||
|
||||
public static int XpForLevel(int level) => 100 * level;
|
||||
public static int MatchXp(MatchSummaryDto s) =>
|
||||
40 + (s.Won ? 80 : 0) + s.TricksWon * 5 + (s.KotFor ? 30 : 0);
|
||||
public const int MaxLevel = 100;
|
||||
public static int XpForLevel(int level) => 100 * level + 15 * level * level;
|
||||
private static double LeagueXpFactor(int stake) => stake >= 1000 ? 2.0 : stake >= 500 ? 1.5 : 1.0;
|
||||
public static int MatchXp(MatchSummaryDto s)
|
||||
{
|
||||
int b = 40 + (s.Won ? 80 : 0) + s.TricksWon * 5 + (s.KotFor ? 30 : 0);
|
||||
return (int)Math.Round(b * LeagueXpFactor(s.Stake));
|
||||
}
|
||||
|
||||
// metric: wins|kotsFor|bestWinStreak|shutoutWins|games|tricks|level ; ratingFloor>0 = rank ach.
|
||||
private record AchDef(string Id, string? Metric, int RatingFloor, int Goal, int Coin, string NameFa, string NameEn, string Icon);
|
||||
@@ -102,8 +107,12 @@ public static class Gamification
|
||||
new("novice", "تازهکار", "Novice"), new("winner", "برنده", "Winner"),
|
||||
new("expert", "خبره", "Expert"), new("kot_master", "استاد کُت", "Kot Master"),
|
||||
new("professional", "حرفهای", "Professional"), new("veteran", "کهنهکار", "Veteran"),
|
||||
new("captain", "کاپیتان", "Captain"), new("champion", "قهرمان", "Champion"),
|
||||
new("leader", "فرمانده", "Leader"), new("legend", "اسطوره", "Legend"),
|
||||
new("captain", "کاپیتان", "Captain"), new("marksman", "کماندار", "Marksman"),
|
||||
new("untouchable", "شکستناپذیر", "Untouchable"), new("sweeper", "جاروکش", "Sweeper"),
|
||||
new("ruler", "فرمانروا", "Ruler"), new("champion", "قهرمان", "Champion"),
|
||||
new("platinum_star", "ستاره پلاتین", "Platinum Star"), new("leader", "فرمانده", "Leader"),
|
||||
new("diamond_ace", "آس الماس", "Diamond Ace"), new("immortal", "جاودانه", "Immortal"),
|
||||
new("the_one", "یگانه", "The One"), new("legend", "اسطوره", "Legend"),
|
||||
};
|
||||
|
||||
private static bool TitleUnlocked(string id, StatsDto st, int rating, int level) => id switch
|
||||
@@ -115,8 +124,16 @@ public static class Gamification
|
||||
"professional" => st.Wins >= 50,
|
||||
"veteran" => level >= 30,
|
||||
"captain" => st.Wins >= 100,
|
||||
"marksman" => st.KotsFor >= 50,
|
||||
"untouchable" => st.BestWinStreak >= 10,
|
||||
"sweeper" => st.ShutoutWins >= 10,
|
||||
"ruler" => st.HakemRounds >= 50,
|
||||
"champion" => rating >= 1300,
|
||||
"platinum_star" => rating >= 1500,
|
||||
"leader" => st.Wins >= 250,
|
||||
"diamond_ace" => rating >= 1700,
|
||||
"immortal" => level >= 50,
|
||||
"the_one" => st.Wins >= 500,
|
||||
"legend" => rating >= 1900,
|
||||
_ => false,
|
||||
};
|
||||
@@ -125,7 +142,8 @@ public static class Gamification
|
||||
{
|
||||
bool up = false;
|
||||
xp += gain;
|
||||
while (xp >= XpForLevel(level)) { xp -= XpForLevel(level); level++; up = true; }
|
||||
while (level < MaxLevel && xp >= XpForLevel(level)) { xp -= XpForLevel(level); level++; up = true; }
|
||||
if (level >= MaxLevel) { level = MaxLevel; xp = Math.Min(xp, XpForLevel(MaxLevel)); }
|
||||
return (level, xp, up);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user